diff --git a/include/sys/zfs_znode.h b/include/sys/zfs_znode.h index 356092169a..4dbecb4b5e 100644 --- a/include/sys/zfs_znode.h +++ b/include/sys/zfs_znode.h @@ -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 *, diff --git a/module/zfs/zfs_vfsops.c b/module/zfs/zfs_vfsops.c index ef433125a1..4545c20e24 100644 --- a/module/zfs/zfs_vfsops.c +++ b/module/zfs/zfs_vfsops.c @@ -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); } diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index b666ee39cc..e5e187b15a 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -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); } diff --git a/module/zfs/zfs_znode.c b/module/zfs/zfs_znode.c index 7823bc5e74..0ae16448f1 100644 --- a/module/zfs/zfs_znode.c +++ b/module/zfs/zfs_znode.c @@ -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); }