From 03f9ba9d990efb911026ebee0902671915db01a3 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 15 Mar 2011 12:03:42 -0700 Subject: [PATCH] Register .sync_fs handler Register the missing .sync_fs handler. This is a noop in most cases because the usual requirement is that sync just be initiated. As part of the DMU's normal transaction processing txgs will be frequently synced. However, when the 'wait' flag is set the requirement is that .sync_fs must not return until the data is safe on disk. With the addition of the .sync_fs handler this is now properly implemented. --- include/sys/zfs_znode.h | 2 +- module/zfs/zfs_vfsops.c | 18 +++++++++++------- module/zfs/zpl_super.c | 16 +++++++++++++++- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/include/sys/zfs_znode.h b/include/sys/zfs_znode.h index 4e0b611..b028e2e 100644 --- a/include/sys/zfs_znode.h +++ b/include/sys/zfs_znode.h @@ -323,7 +323,7 @@ extern void zfs_zinactive(znode_t *); extern void zfs_znode_delete(znode_t *, dmu_tx_t *); extern void zfs_remove_op_tables(void); extern int zfs_create_op_tables(void); -extern int zfs_sync(zfs_sb_t *, short, cred_t *); +extern int zfs_sync(struct super_block *, int, cred_t *); 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); diff --git a/module/zfs/zfs_vfsops.c b/module/zfs/zfs_vfsops.c index ea7e9ce..1e8e6af 100644 --- a/module/zfs/zfs_vfsops.c +++ b/module/zfs/zfs_vfsops.c @@ -69,8 +69,10 @@ /*ARGSUSED*/ int -zfs_sync(zfs_sb_t *zsb, short flag, cred_t *cr) +zfs_sync(struct super_block *sb, int wait, cred_t *cr) { + zfs_sb_t *zsb = sb->s_fs_info; + /* * Data integrity is job one. We don't want a compromised kernel * writing to the storage pool, so we never sync during panic. @@ -78,6 +80,13 @@ zfs_sync(zfs_sb_t *zsb, short flag, cred_t *cr) if (unlikely(oops_in_progress)) return (0); + /* + * Semantically, the only requirement is that the sync be initiated. + * The DMU syncs out txgs frequently, so there's nothing to do. + */ + if (!wait) + return (0); + if (zsb != NULL) { /* * Sync a specific filesystem. @@ -87,19 +96,14 @@ zfs_sync(zfs_sb_t *zsb, short flag, cred_t *cr) ZFS_ENTER(zsb); dp = dmu_objset_pool(zsb->z_os); -#ifdef HAVE_SHUTDOWN /* * If the system is shutting down, then skip any * filesystems which may exist on a suspended pool. - * - * XXX: This can be implemented using the Linux reboot - * notifiers: {un}register_reboot_notifier(). */ - if (sys_shutdown && spa_suspended(dp->dp_spa)) { + if (spa_suspended(dp->dp_spa)) { ZFS_EXIT(zsb); return (0); } -#endif /* HAVE_SHUTDOWN */ if (zsb->z_log != NULL) zil_commit(zsb->z_log, 0); diff --git a/module/zfs/zpl_super.c b/module/zfs/zpl_super.c index 0417ce2..73e5268 100644 --- a/module/zfs/zpl_super.c +++ b/module/zfs/zpl_super.c @@ -105,6 +105,20 @@ zpl_put_super(struct super_block *sb) } static int +zpl_sync_fs(struct super_block *sb, int wait) +{ + cred_t *cr; + int error; + + cr = (cred_t *)get_current_cred(); + error = -zfs_sync(sb, wait, cr); + put_cred(cr); + ASSERT3S(error, <=, 0); + + return (error); +} + +static int zpl_statfs(struct dentry *dentry, struct kstatfs *statp) { int error; @@ -179,7 +193,7 @@ const struct super_operations zpl_super_operations = { #endif /* HAVE_EVICT_INODE */ .put_super = zpl_put_super, .write_super = NULL, - .sync_fs = NULL, + .sync_fs = zpl_sync_fs, .freeze_fs = NULL, .unfreeze_fs = NULL, .statfs = zpl_statfs, -- 1.8.3.1