summaryrefslogtreecommitdiffstats
path: root/module/zfs/zfs_vfsops.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/zfs_vfsops.c')
-rw-r--r--module/zfs/zfs_vfsops.c85
1 files changed, 69 insertions, 16 deletions
diff --git a/module/zfs/zfs_vfsops.c b/module/zfs/zfs_vfsops.c
index f94073cbb..9ee7b2e8a 100644
--- a/module/zfs/zfs_vfsops.c
+++ b/module/zfs/zfs_vfsops.c
@@ -262,11 +262,22 @@ zfs_register_callbacks(zfs_sb_t *zsb)
{
struct dsl_dataset *ds = NULL;
objset_t *os = zsb->z_os;
- boolean_t do_readonly = B_FALSE;
+ zfs_mntopts_t *zmo = zsb->z_mntopts;
int error = 0;
- if (zfs_is_readonly(zsb) || !spa_writeable(dmu_objset_spa(os)))
- do_readonly = B_TRUE;
+ ASSERT(zsb);
+ ASSERT(zmo);
+
+ /*
+ * The act of registering our callbacks will destroy any mount
+ * options we may have. In order to enable temporary overrides
+ * of mount options, we stash away the current values and
+ * restore them after we register the callbacks.
+ */
+ if (zfs_is_readonly(zsb) || !spa_writeable(dmu_objset_spa(os))) {
+ zmo->z_do_readonly = B_TRUE;
+ zmo->z_readonly = B_TRUE;
+ }
/*
* Register property callbacks.
@@ -307,8 +318,25 @@ zfs_register_callbacks(zfs_sb_t *zsb)
if (error)
goto unregister;
- if (do_readonly)
- readonly_changed_cb(zsb, B_TRUE);
+ /*
+ * Invoke our callbacks to restore temporary mount options.
+ */
+ if (zmo->z_do_readonly)
+ readonly_changed_cb(zsb, zmo->z_readonly);
+ if (zmo->z_do_setuid)
+ setuid_changed_cb(zsb, zmo->z_setuid);
+ if (zmo->z_do_exec)
+ exec_changed_cb(zsb, zmo->z_exec);
+ if (zmo->z_do_devices)
+ devices_changed_cb(zsb, zmo->z_devices);
+ if (zmo->z_do_xattr)
+ xattr_changed_cb(zsb, zmo->z_xattr);
+ if (zmo->z_do_atime)
+ atime_changed_cb(zsb, zmo->z_atime);
+ if (zmo->z_do_relatime)
+ relatime_changed_cb(zsb, zmo->z_relatime);
+ if (zmo->z_do_nbmand)
+ nbmand_changed_cb(zsb, zmo->z_nbmand);
return (0);
@@ -642,8 +670,26 @@ zfs_owner_overquota(zfs_sb_t *zsb, znode_t *zp, boolean_t isgroup)
}
EXPORT_SYMBOL(zfs_owner_overquota);
+zfs_mntopts_t *
+zfs_mntopts_alloc(void)
+{
+ return (kmem_zalloc(sizeof (zfs_mntopts_t), KM_SLEEP));
+}
+
+void
+zfs_mntopts_free(zfs_mntopts_t *zmo)
+{
+ if (zmo->z_osname)
+ strfree(zmo->z_osname);
+
+ if (zmo->z_mntpoint)
+ strfree(zmo->z_mntpoint);
+
+ kmem_free(zmo, sizeof (zfs_mntopts_t));
+}
+
int
-zfs_sb_create(const char *osname, zfs_sb_t **zsbp)
+zfs_sb_create(const char *osname, zfs_mntopts_t *zmo, zfs_sb_t **zsbp)
{
objset_t *os;
zfs_sb_t *zsb;
@@ -664,6 +710,11 @@ zfs_sb_create(const char *osname, zfs_sb_t **zsbp)
}
/*
+ * Optional temporary mount options, free'd in zfs_sb_free().
+ */
+ zsb->z_mntopts = (zmo ? zmo : zfs_mntopts_alloc());
+
+ /*
* Initialize the zfs-specific filesystem structure.
* Should probably make this a kmem cache, shuffle fields,
* and just bzero up to z_hold_mtx[].
@@ -892,6 +943,7 @@ zfs_sb_free(zfs_sb_t *zsb)
for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
mutex_destroy(&zsb->z_hold_mtx[i]);
vmem_free(zsb->z_hold_mtx, sizeof (kmutex_t) * ZFS_OBJ_MTX_SZ);
+ zfs_mntopts_free(zsb->z_mntopts);
kmem_free(zsb, sizeof (zfs_sb_t));
}
EXPORT_SYMBOL(zfs_sb_free);
@@ -1310,16 +1362,15 @@ atomic_long_t zfs_bdi_seq = ATOMIC_LONG_INIT(0);
#endif
int
-zfs_domount(struct super_block *sb, void *data, int silent)
+zfs_domount(struct super_block *sb, zfs_mntopts_t *zmo, int silent)
{
- zpl_mount_data_t *zmd = data;
- const char *osname = zmd->z_osname;
+ const char *osname = zmo->z_osname;
zfs_sb_t *zsb;
struct inode *root_inode;
uint64_t recordsize;
int error;
- error = zfs_sb_create(osname, &zsb);
+ error = zfs_sb_create(osname, zmo, &zsb);
if (error)
return (error);
@@ -1462,13 +1513,15 @@ zfs_umount(struct super_block *sb)
EXPORT_SYMBOL(zfs_umount);
int
-zfs_remount(struct super_block *sb, int *flags, char *data)
+zfs_remount(struct super_block *sb, int *flags, zfs_mntopts_t *zmo)
{
- /*
- * All namespace flags (MNT_*) and super block flags (MS_*) will
- * be handled by the Linux VFS. Only handle custom options here.
- */
- return (0);
+ zfs_sb_t *zsb = sb->s_fs_info;
+ int error;
+
+ zfs_unregister_callbacks(zsb);
+ error = zfs_register_callbacks(zsb);
+
+ return (error);
}
EXPORT_SYMBOL(zfs_remount);