diff options
Diffstat (limited to 'module/zfs')
-rw-r--r-- | module/zfs/zfs_vnops.c | 73 | ||||
-rw-r--r-- | module/zfs/zpl_super.c | 21 |
2 files changed, 71 insertions, 23 deletions
diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index 415ba7191..8ec4db26f 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -218,32 +218,11 @@ zfs_close(struct inode *ip, int flag, cred_t *cr) { znode_t *zp = ITOZ(ip); zfs_sb_t *zsb = ITOZSB(ip); - int error = 0; ZFS_ENTER(zsb); ZFS_VERIFY_ZP(zp); /* - * When closing an mmap()'ed file ensure the inode atime, mtime, and - * ctime are written to disk. These values may have been updated in - * memory by filemap_page_mkwrite() bit are not yet reflected in the - * znode since writepage() may occur after the close. - */ - if (zp->z_is_mapped) { - vattr_t *vap; - - vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); - vap->va_mask = ATTR_ATIME | ATTR_MTIME | ATTR_CTIME; - vap->va_atime = ip->i_atime; - vap->va_mtime = ip->i_mtime; - vap->va_ctime = ip->i_ctime; - - error = zfs_setattr(ip, vap, 0, cr); - - kmem_free(vap, sizeof(vattr_t)); - } - - /* * Zero the synchronous opens in the znode. Under Linux the * zfs_close() hook is not symmetric with zfs_open(), it is * only called once when the last reference is dropped. @@ -256,7 +235,7 @@ zfs_close(struct inode *ip, int flag, cred_t *cr) VERIFY(zfs_vscan(ip, cr, 1) == 0); ZFS_EXIT(zsb); - return (error); + return (0); } EXPORT_SYMBOL(zfs_close); @@ -3920,6 +3899,56 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc) return (err); } +/* + * Update the system attributes when the inode has been dirtied. For the + * moment we're conservative and only update the atime, mtime, and ctime. + */ +int +zfs_dirty_inode(struct inode *ip, int flags) +{ + znode_t *zp = ITOZ(ip); + zfs_sb_t *zsb = ITOZSB(ip); + dmu_tx_t *tx; + uint64_t atime[2], mtime[2], ctime[2]; + sa_bulk_attr_t bulk[3]; + int error; + int cnt = 0; + + ZFS_ENTER(zsb); + ZFS_VERIFY_ZP(zp); + + tx = dmu_tx_create(zsb->z_os); + + dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); + zfs_sa_upgrade_txholds(tx, zp); + + error = dmu_tx_assign(tx, TXG_WAIT); + if (error) { + dmu_tx_abort(tx); + goto out; + } + + mutex_enter(&zp->z_lock); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_ATIME(zsb), NULL, &atime, 16); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MTIME(zsb), NULL, &mtime, 16); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(zsb), NULL, &ctime, 16); + + /* Preserve the mtime and ctime provided by the inode */ + ZFS_TIME_ENCODE(&ip->i_atime, atime); + ZFS_TIME_ENCODE(&ip->i_mtime, mtime); + ZFS_TIME_ENCODE(&ip->i_ctime, ctime); + zp->z_atime_dirty = 0; + + error = sa_bulk_update(zp->z_sa_hdl, bulk, cnt, tx); + mutex_exit(&zp->z_lock); + + dmu_tx_commit(tx); +out: + ZFS_EXIT(zsb); + return (error); +} +EXPORT_SYMBOL(zfs_dirty_inode); + /*ARGSUSED*/ void zfs_inactive(struct inode *ip) diff --git a/module/zfs/zpl_super.c b/module/zfs/zpl_super.c index fd4f691e1..d4d4e1b67 100644 --- a/module/zfs/zpl_super.c +++ b/module/zfs/zpl_super.c @@ -49,6 +49,25 @@ zpl_inode_destroy(struct inode *ip) } /* + * Called from __mark_inode_dirty() to reflect that something in the + * inode has changed. We use it to ensure the znode system attributes + * are always strictly update to date with respect to the inode. + */ +#ifdef HAVE_DIRTY_INODE_WITH_FLAGS +static void +zpl_dirty_inode(struct inode *ip, int flags) +{ + zfs_dirty_inode(ip, flags); +} +#else +static void +zpl_dirty_inode(struct inode *ip) +{ + zfs_dirty_inode(ip, 0); +} +#endif /* HAVE_DIRTY_INODE_WITH_FLAGS */ + +/* * When ->drop_inode() is called its return value indicates if the * inode should be evicted from the inode cache. If the inode is * unhashed and has no links the default policy is to evict it @@ -306,7 +325,7 @@ zpl_free_cached_objects(struct super_block *sb, int nr_to_scan) const struct super_operations zpl_super_operations = { .alloc_inode = zpl_inode_alloc, .destroy_inode = zpl_inode_destroy, - .dirty_inode = NULL, + .dirty_inode = zpl_dirty_inode, .write_inode = NULL, .drop_inode = NULL, #ifdef HAVE_EVICT_INODE |