summaryrefslogtreecommitdiffstats
path: root/module/zfs/zfs_znode.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/zfs_znode.c')
-rw-r--r--module/zfs/zfs_znode.c156
1 files changed, 87 insertions, 69 deletions
diff --git a/module/zfs/zfs_znode.c b/module/zfs/zfs_znode.c
index f3662e272..39b2ba07a 100644
--- a/module/zfs/zfs_znode.c
+++ b/module/zfs/zfs_znode.c
@@ -492,6 +492,90 @@ zfs_inode_set_ops(zfs_sb_t *zsb, struct inode *ip)
}
}
+void
+zfs_set_inode_flags(znode_t *zp, struct inode *ip)
+{
+ /*
+ * Linux and Solaris have different sets of file attributes, so we
+ * restrict this conversion to the intersection of the two.
+ */
+
+ if (zp->z_pflags & ZFS_IMMUTABLE)
+ ip->i_flags |= S_IMMUTABLE;
+ else
+ ip->i_flags &= ~S_IMMUTABLE;
+
+ if (zp->z_pflags & ZFS_APPENDONLY)
+ ip->i_flags |= S_APPEND;
+ else
+ ip->i_flags &= ~S_APPEND;
+}
+
+/*
+ * Update the embedded inode given the znode. We should work toward
+ * eliminating this function as soon as possible by removing values
+ * which are duplicated between the znode and inode. If the generic
+ * inode has the correct field it should be used, and the ZFS code
+ * updated to access the inode. This can be done incrementally.
+ */
+static void
+zfs_inode_update_impl(znode_t *zp, boolean_t new)
+{
+ zfs_sb_t *zsb;
+ struct inode *ip;
+ uint32_t blksize;
+ u_longlong_t i_blocks;
+ uint64_t atime[2], mtime[2], ctime[2];
+
+ ASSERT(zp != NULL);
+ zsb = ZTOZSB(zp);
+ ip = ZTOI(zp);
+
+ /* Skip .zfs control nodes which do not exist on disk. */
+ if (zfsctl_is_node(ip))
+ return;
+
+ sa_lookup(zp->z_sa_hdl, SA_ZPL_ATIME(zsb), &atime, 16);
+ sa_lookup(zp->z_sa_hdl, SA_ZPL_MTIME(zsb), &mtime, 16);
+ sa_lookup(zp->z_sa_hdl, SA_ZPL_CTIME(zsb), &ctime, 16);
+
+ dmu_object_size_from_db(sa_get_db(zp->z_sa_hdl), &blksize, &i_blocks);
+
+ spin_lock(&ip->i_lock);
+ ip->i_generation = zp->z_gen;
+ ip->i_uid = SUID_TO_KUID(zp->z_uid);
+ ip->i_gid = SGID_TO_KGID(zp->z_gid);
+ set_nlink(ip, zp->z_links);
+ ip->i_mode = zp->z_mode;
+ zfs_set_inode_flags(zp, ip);
+ ip->i_blkbits = SPA_MINBLOCKSHIFT;
+ ip->i_blocks = i_blocks;
+
+ /*
+ * Only read atime from SA if we are newly created inode (or rezget),
+ * otherwise i_atime might be dirty.
+ */
+ if (new)
+ ZFS_TIME_DECODE(&ip->i_atime, atime);
+ ZFS_TIME_DECODE(&ip->i_mtime, mtime);
+ ZFS_TIME_DECODE(&ip->i_ctime, ctime);
+
+ i_size_write(ip, zp->z_size);
+ spin_unlock(&ip->i_lock);
+}
+
+static void
+zfs_inode_update_new(znode_t *zp)
+{
+ zfs_inode_update_impl(zp, B_TRUE);
+}
+
+void
+zfs_inode_update(znode_t *zp)
+{
+ zfs_inode_update_impl(zp, B_FALSE);
+}
+
/*
* Construct a znode+inode and initialize.
*
@@ -567,7 +651,7 @@ zfs_znode_alloc(zfs_sb_t *zsb, dmu_buf_t *db, int blksz,
}
ip->i_ino = obj;
- zfs_inode_update(zp);
+ zfs_inode_update_new(zp);
zfs_inode_set_ops(zsb, ip);
/*
@@ -594,73 +678,6 @@ error:
return (NULL);
}
-void
-zfs_set_inode_flags(znode_t *zp, struct inode *ip)
-{
- /*
- * Linux and Solaris have different sets of file attributes, so we
- * restrict this conversion to the intersection of the two.
- */
-
- if (zp->z_pflags & ZFS_IMMUTABLE)
- ip->i_flags |= S_IMMUTABLE;
- else
- ip->i_flags &= ~S_IMMUTABLE;
-
- if (zp->z_pflags & ZFS_APPENDONLY)
- ip->i_flags |= S_APPEND;
- else
- ip->i_flags &= ~S_APPEND;
-}
-
-/*
- * Update the embedded inode given the znode. We should work toward
- * eliminating this function as soon as possible by removing values
- * which are duplicated between the znode and inode. If the generic
- * inode has the correct field it should be used, and the ZFS code
- * updated to access the inode. This can be done incrementally.
- */
-void
-zfs_inode_update(znode_t *zp)
-{
- zfs_sb_t *zsb;
- struct inode *ip;
- uint32_t blksize;
- u_longlong_t i_blocks;
- uint64_t atime[2], mtime[2], ctime[2];
-
- ASSERT(zp != NULL);
- zsb = ZTOZSB(zp);
- ip = ZTOI(zp);
-
- /* Skip .zfs control nodes which do not exist on disk. */
- if (zfsctl_is_node(ip))
- return;
-
- sa_lookup(zp->z_sa_hdl, SA_ZPL_ATIME(zsb), &atime, 16);
- sa_lookup(zp->z_sa_hdl, SA_ZPL_MTIME(zsb), &mtime, 16);
- sa_lookup(zp->z_sa_hdl, SA_ZPL_CTIME(zsb), &ctime, 16);
-
- dmu_object_size_from_db(sa_get_db(zp->z_sa_hdl), &blksize, &i_blocks);
-
- spin_lock(&ip->i_lock);
- ip->i_generation = zp->z_gen;
- ip->i_uid = SUID_TO_KUID(zp->z_uid);
- ip->i_gid = SGID_TO_KGID(zp->z_gid);
- set_nlink(ip, zp->z_links);
- ip->i_mode = zp->z_mode;
- zfs_set_inode_flags(zp, ip);
- ip->i_blkbits = SPA_MINBLOCKSHIFT;
- ip->i_blocks = i_blocks;
-
- ZFS_TIME_DECODE(&ip->i_atime, atime);
- ZFS_TIME_DECODE(&ip->i_mtime, mtime);
- ZFS_TIME_DECODE(&ip->i_ctime, ctime);
-
- i_size_write(ip, zp->z_size);
- spin_unlock(&ip->i_lock);
-}
-
/*
* Safely mark an inode dirty. Inodes which are part of a read-only
* file system or snapshot may not be dirtied.
@@ -1220,7 +1237,8 @@ zfs_rezget(znode_t *zp)
zp->z_unlinked = (zp->z_links == 0);
zp->z_blksz = doi.doi_data_block_size;
- zfs_inode_update(zp);
+ zp->z_atime_dirty = 0;
+ zfs_inode_update_new(zp);
zfs_znode_hold_exit(zsb, zh);