]> granicus.if.org Git - zfs/commitdiff
VFS: Add zfs_inode_update() helper
authorBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 5 Jan 2011 22:27:30 +0000 (14:27 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 10 Feb 2011 17:27:20 +0000 (09:27 -0800)
For the moment we have left ZFS unchanged and it updates many values
as part of the znode.  However, some of these values should be set
in the inode.  For the moment this is handled by adding a function
called zfs_inode_update() which updates the inode based on the znode.

This is considered a workaround until we can systematically go
through the ZFS code and have it directly update the inode.  At
which point zfs_update_inode() can be dropped entirely.  Keeping
two copies of the same data isn't only inefficient it's a breeding
ground for bugs.

include/sys/zfs_znode.h
module/zfs/zfs_vfsops.c
module/zfs/zfs_vnops.c
module/zfs/zfs_znode.c

index 356092169acbab8432a489ccf8b8b264fdd89ff4..4dbecb4b5e9a566ca1c0a0e121aa5313d99bec17 100644 (file)
@@ -326,6 +326,7 @@ extern dev_t        zfs_cmpldev(uint64_t);
 extern int     zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value);
 extern int     zfs_get_stats(objset_t *os, nvlist_t *nv);
 extern void    zfs_znode_dmu_fini(znode_t *);
+extern void    zfs_inode_update(znode_t *);
 
 extern void zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
     znode_t *dzp, znode_t *zp, char *name, vsecattr_t *, zfs_fuid_info_t *,
index ef433125a1ec6042610589f59cfe7227b9d1400d..4545c20e24d8f9e613515b85667d201ce9ad26ba 100644 (file)
@@ -1942,6 +1942,9 @@ zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
        }
 
        *vpp = ZTOV(zp);
+       if (*vpp)
+               zfs_inode_update(VTOZ(*vpp));
+
        ZFS_EXIT(zfsvfs);
        return (0);
 }
index b666ee39ccbe78732d929240b70f61875713f044..e5e187b15a45a898e07e7da933ebd897057f3f5c 100644 (file)
@@ -564,6 +564,7 @@ out:
        zfs_range_unlock(rl);
 
        ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
+       zfs_inode_update(zp);
        ZFS_EXIT(zfsvfs);
        return (error);
 }
@@ -938,6 +939,7 @@ again:
            zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, zp->z_id);
 
+       zfs_inode_update(zp);
        ZFS_EXIT(zfsvfs);
        return (0);
 }
@@ -1266,8 +1268,12 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
        }
 
        error = zfs_dirlook(zdp, nm, vpp, flags, direntflags, realpnp);
-       if (error == 0)
+       if (error == 0) {
+               if (*vpp)
+                       zfs_inode_update(VTOZ(*vpp));
+
                error = specvp_check(vpp, cr);
+       }
 
        ZFS_EXIT(zfsvfs);
        return (error);
@@ -1523,6 +1529,8 @@ out:
                if (zp)
                        VN_RELE(ZTOV(zp));
        } else {
+               zfs_inode_update(dzp);
+               zfs_inode_update(zp);
                *vpp = ZTOV(zp);
                error = specvp_check(vpp, cr);
        }
@@ -1753,6 +1761,10 @@ out:
                pn_free(realnmp);
 
        zfs_dirent_unlock(dl);
+       zfs_inode_update(dzp);
+       zfs_inode_update(zp);
+       if (xzp)
+               zfs_inode_update(xzp);
 
        if (!delete_now)
                VN_RELE(vp);
@@ -1945,6 +1957,8 @@ top:
        if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
 
+       zfs_inode_update(dzp);
+       zfs_inode_update(zp);
        ZFS_EXIT(zfsvfs);
        return (0);
 }
@@ -2074,6 +2088,8 @@ out:
        if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
 
+       zfs_inode_update(dzp);
+       zfs_inode_update(zp);
        ZFS_EXIT(zfsvfs);
        return (error);
 }
@@ -3227,6 +3243,7 @@ out:
        } else {
                err2 = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
                dmu_tx_commit(tx);
+                zfs_inode_update(zp);
        }
 
 out2:
@@ -3674,13 +3691,19 @@ out:
        zfs_dirent_unlock(sdl);
        zfs_dirent_unlock(tdl);
 
+       zfs_inode_update(sdzp);
        if (sdzp == tdzp)
                rw_exit(&sdzp->z_name_lock);
 
+       if (sdzp != tdzp)
+               zfs_inode_update(tdzp);
 
+       zfs_inode_update(szp);
        VN_RELE(ZTOV(szp));
-       if (tzp)
+       if (tzp) {
+               zfs_inode_update(tzp);
                VN_RELE(ZTOV(tzp));
+       }
 
        if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
@@ -3828,6 +3851,9 @@ top:
                txtype |= TX_CI;
        zfs_log_symlink(zilog, tx, txtype, dzp, zp, name, link);
 
+       zfs_inode_update(dzp);
+       zfs_inode_update(zp);
+
        zfs_acl_ids_free(&acl_ids);
 
        dmu_tx_commit(tx);
@@ -3882,6 +3908,7 @@ zfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr, caller_context_t *ct)
 
        ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
 
+       zfs_inode_update(zp);
        ZFS_EXIT(zfsvfs);
        return (error);
 }
@@ -4037,6 +4064,8 @@ top:
        if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
 
+       zfs_inode_update(dzp);
+       zfs_inode_update(szp);
        ZFS_EXIT(zfsvfs);
        return (error);
 }
index 7823bc5e74c9a34245751bfcd8d44bec1bdb210f..0ae16448f1b6bbd9d8980cb4d7ee348aff75dd0a 100644 (file)
@@ -521,6 +521,47 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
        return (zp);
 }
 
+/*
+ * 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)
+{
+       zfsvfs_t        *zfsvfs;
+       struct inode    *inode;
+       uint32_t        blksize;
+       uint64_t        atime[2], mtime[2], ctime[2];
+
+       ASSERT(zp != NULL);
+       zfsvfs = zp->z_zfsvfs;
+       inode = ZTOI(zp);
+
+       sa_lookup(zp->z_sa_hdl, SA_ZPL_ATIME(zfsvfs), &atime, 16);
+       sa_lookup(zp->z_sa_hdl, SA_ZPL_MTIME(zfsvfs), &mtime, 16);
+       sa_lookup(zp->z_sa_hdl, SA_ZPL_CTIME(zfsvfs), &ctime, 16);
+
+       spin_lock(&inode->i_lock);
+       inode->i_generation = zp->z_gen;
+       inode->i_uid = zp->z_uid;
+       inode->i_gid = zp->z_gid;
+       inode->i_nlink = zp->z_links;
+       inode->i_mode = zp->z_mode;
+       inode->i_blkbits = SPA_MINBLOCKSHIFT;
+       dmu_object_size_from_db(sa_get_db(zp->z_sa_hdl), &blksize,
+           (u_longlong_t *)&inode->i_blocks);
+
+       ZFS_TIME_DECODE(&inode->i_atime, atime);
+       ZFS_TIME_DECODE(&inode->i_mtime, mtime);
+       ZFS_TIME_DECODE(&inode->i_ctime, ctime);
+
+       i_size_write(inode, zp->z_size);
+       spin_unlock(&inode->i_lock);
+}
+
 static uint64_t empty_xattr;
 static uint64_t pad[4];
 static zfs_acl_phys_t acl_phys;
@@ -1534,6 +1575,7 @@ log:
        zfs_log_truncate(zilog, tx, TX_TRUNCATE, zp, off, len);
 
        dmu_tx_commit(tx);
+       zfs_inode_update(zp);
        return (0);
 }