diff --git a/include/sys/zfs_vfsops.h b/include/sys/zfs_vfsops.h index a208bc1f8..aeecc472d 100644 --- a/include/sys/zfs_vfsops.h +++ b/include/sys/zfs_vfsops.h @@ -41,33 +41,43 @@ extern "C" { typedef struct zfsvfs zfsvfs_t; struct znode; -typedef struct zfs_mntopts { - char *z_osname; /* Objset name */ - char *z_mntpoint; /* Primary mount point */ - uint64_t z_xattr; - boolean_t z_readonly; - boolean_t z_do_readonly; - boolean_t z_setuid; - boolean_t z_do_setuid; - boolean_t z_exec; - boolean_t z_do_exec; - boolean_t z_devices; - boolean_t z_do_devices; - boolean_t z_do_xattr; - boolean_t z_atime; - boolean_t z_do_atime; - boolean_t z_relatime; - boolean_t z_do_relatime; - boolean_t z_nbmand; - boolean_t z_do_nbmand; -} zfs_mntopts_t; +/* + * This structure emulates the vfs_t from other platforms. It's purpose + * is to faciliate the handling of mount options and minimize structural + * differences between the platforms. + */ +typedef struct vfs { + struct zfsvfs *vfs_data; + char *vfs_mntpoint; /* Primary mount point */ + uint64_t vfs_xattr; + boolean_t vfs_readonly; + boolean_t vfs_do_readonly; + boolean_t vfs_setuid; + boolean_t vfs_do_setuid; + boolean_t vfs_exec; + boolean_t vfs_do_exec; + boolean_t vfs_devices; + boolean_t vfs_do_devices; + boolean_t vfs_do_xattr; + boolean_t vfs_atime; + boolean_t vfs_do_atime; + boolean_t vfs_relatime; + boolean_t vfs_do_relatime; + boolean_t vfs_nbmand; + boolean_t vfs_do_nbmand; +} vfs_t; + +typedef struct zfs_mnt { + const char *mnt_osname; /* Objset name */ + char *mnt_data; /* Raw mount options */ +} zfs_mnt_t; struct zfsvfs { + vfs_t *z_vfs; /* generic fs struct */ struct super_block *z_sb; /* generic super_block */ struct backing_dev_info z_bdi; /* generic backing dev info */ struct zfsvfs *z_parent; /* parent fs */ objset_t *z_os; /* objset reference */ - zfs_mntopts_t *z_mntopts; /* passed mount options */ uint64_t z_flags; /* super_block flags */ uint64_t z_root; /* id of root znode */ uint64_t z_unlinkedobj; /* id of unlinked zapobj */ @@ -193,17 +203,15 @@ extern boolean_t zfs_fuid_overquota(zfsvfs_t *zfsvfs, boolean_t isgroup, extern boolean_t zfs_fuid_overobjquota(zfsvfs_t *zfsvfs, boolean_t isgroup, uint64_t fuid); extern int zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers); -extern int zfsvfs_create(const char *name, zfs_mntopts_t *zmo, zfsvfs_t **zfvp); +extern int zfsvfs_create(const char *name, zfsvfs_t **zfvp); extern void zfsvfs_free(zfsvfs_t *zfsvfs); extern int zfs_check_global_label(const char *dsname, const char *hexsl); extern boolean_t zfs_is_readonly(zfsvfs_t *zfsvfs); -extern zfs_mntopts_t *zfs_mntopts_alloc(void); -extern void zfs_mntopts_free(zfs_mntopts_t *zmo); -extern int zfs_domount(struct super_block *sb, zfs_mntopts_t *zmo, int silent); +extern int zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent); extern void zfs_preumount(struct super_block *sb); extern int zfs_umount(struct super_block *sb); -extern int zfs_remount(struct super_block *sb, int *flags, zfs_mntopts_t *zmo); +extern int zfs_remount(struct super_block *sb, int *flags, zfs_mnt_t *zm); extern int zfs_statvfs(struct dentry *dentry, struct kstatfs *statp); extern int zfs_vget(struct super_block *sb, struct inode **ipp, fid_t *fidp); extern int zfs_prune(struct super_block *sb, unsigned long nr_to_scan, diff --git a/module/zfs/zfs_ctldir.c b/module/zfs/zfs_ctldir.c index 5d713f6d7..eea1bb2e8 100644 --- a/module/zfs/zfs_ctldir.c +++ b/module/zfs/zfs_ctldir.c @@ -746,7 +746,7 @@ zfsctl_snapshot_path_objset(zfsvfs_t *zfsvfs, uint64_t objsetid, uint64_t id, pos = 0; int error = 0; - if (zfsvfs->z_mntopts->z_mntpoint == NULL) + if (zfsvfs->z_vfs->vfs_mntpoint == NULL) return (ENOENT); cookie = spl_fstrans_mark(); @@ -767,7 +767,7 @@ zfsctl_snapshot_path_objset(zfsvfs_t *zfsvfs, uint64_t objsetid, memset(full_path, 0, path_len); snprintf(full_path, path_len - 1, "%s/.zfs/snapshot/%s", - zfsvfs->z_mntopts->z_mntpoint, snapname); + zfsvfs->z_vfs->vfs_mntpoint, snapname); out: kmem_free(snapname, ZFS_MAX_DATASET_NAME_LEN); spl_fstrans_unmark(cookie); diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index e89306a59..6df61fecb 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -1431,7 +1431,7 @@ zfsvfs_hold(const char *name, void *tag, zfsvfs_t **zfvp, boolean_t writer) int error = 0; if (getzfsvfs(name, zfvp) != 0) - error = zfsvfs_create(name, NULL, zfvp); + error = zfsvfs_create(name, zfvp); if (error == 0) { rrm_enter(&(*zfvp)->z_teardown_lock, (writer) ? RW_WRITER : RW_READER, tag); diff --git a/module/zfs/zfs_vfsops.c b/module/zfs/zfs_vfsops.c index c55c50088..9f01d30d3 100644 --- a/module/zfs/zfs_vfsops.c +++ b/module/zfs/zfs_vfsops.c @@ -68,6 +68,200 @@ #include #include "zfs_comutil.h" +enum { + TOKEN_RO, + TOKEN_RW, + TOKEN_SETUID, + TOKEN_NOSETUID, + TOKEN_EXEC, + TOKEN_NOEXEC, + TOKEN_DEVICES, + TOKEN_NODEVICES, + TOKEN_DIRXATTR, + TOKEN_SAXATTR, + TOKEN_XATTR, + TOKEN_NOXATTR, + TOKEN_ATIME, + TOKEN_NOATIME, + TOKEN_RELATIME, + TOKEN_NORELATIME, + TOKEN_NBMAND, + TOKEN_NONBMAND, + TOKEN_MNTPOINT, + TOKEN_LAST, +}; + +static const match_table_t zpl_tokens = { + { TOKEN_RO, MNTOPT_RO }, + { TOKEN_RW, MNTOPT_RW }, + { TOKEN_SETUID, MNTOPT_SETUID }, + { TOKEN_NOSETUID, MNTOPT_NOSETUID }, + { TOKEN_EXEC, MNTOPT_EXEC }, + { TOKEN_NOEXEC, MNTOPT_NOEXEC }, + { TOKEN_DEVICES, MNTOPT_DEVICES }, + { TOKEN_NODEVICES, MNTOPT_NODEVICES }, + { TOKEN_DIRXATTR, MNTOPT_DIRXATTR }, + { TOKEN_SAXATTR, MNTOPT_SAXATTR }, + { TOKEN_XATTR, MNTOPT_XATTR }, + { TOKEN_NOXATTR, MNTOPT_NOXATTR }, + { TOKEN_ATIME, MNTOPT_ATIME }, + { TOKEN_NOATIME, MNTOPT_NOATIME }, + { TOKEN_RELATIME, MNTOPT_RELATIME }, + { TOKEN_NORELATIME, MNTOPT_NORELATIME }, + { TOKEN_NBMAND, MNTOPT_NBMAND }, + { TOKEN_NONBMAND, MNTOPT_NONBMAND }, + { TOKEN_MNTPOINT, MNTOPT_MNTPOINT "=%s" }, + { TOKEN_LAST, NULL }, +}; + +static void +zfsvfs_vfs_free(vfs_t *vfsp) +{ + if (vfsp != NULL) { + if (vfsp->vfs_mntpoint != NULL) + strfree(vfsp->vfs_mntpoint); + + kmem_free(vfsp, sizeof (vfs_t)); + } +} + +static int +zfsvfs_parse_option(char *option, int token, substring_t *args, vfs_t *vfsp) +{ + switch (token) { + case TOKEN_RO: + vfsp->vfs_readonly = B_TRUE; + vfsp->vfs_do_readonly = B_TRUE; + break; + case TOKEN_RW: + vfsp->vfs_readonly = B_FALSE; + vfsp->vfs_do_readonly = B_TRUE; + break; + case TOKEN_SETUID: + vfsp->vfs_setuid = B_TRUE; + vfsp->vfs_do_setuid = B_TRUE; + break; + case TOKEN_NOSETUID: + vfsp->vfs_setuid = B_FALSE; + vfsp->vfs_do_setuid = B_TRUE; + break; + case TOKEN_EXEC: + vfsp->vfs_exec = B_TRUE; + vfsp->vfs_do_exec = B_TRUE; + break; + case TOKEN_NOEXEC: + vfsp->vfs_exec = B_FALSE; + vfsp->vfs_do_exec = B_TRUE; + break; + case TOKEN_DEVICES: + vfsp->vfs_devices = B_TRUE; + vfsp->vfs_do_devices = B_TRUE; + break; + case TOKEN_NODEVICES: + vfsp->vfs_devices = B_FALSE; + vfsp->vfs_do_devices = B_TRUE; + break; + case TOKEN_DIRXATTR: + vfsp->vfs_xattr = ZFS_XATTR_DIR; + vfsp->vfs_do_xattr = B_TRUE; + break; + case TOKEN_SAXATTR: + vfsp->vfs_xattr = ZFS_XATTR_SA; + vfsp->vfs_do_xattr = B_TRUE; + break; + case TOKEN_XATTR: + vfsp->vfs_xattr = ZFS_XATTR_DIR; + vfsp->vfs_do_xattr = B_TRUE; + break; + case TOKEN_NOXATTR: + vfsp->vfs_xattr = ZFS_XATTR_OFF; + vfsp->vfs_do_xattr = B_TRUE; + break; + case TOKEN_ATIME: + vfsp->vfs_atime = B_TRUE; + vfsp->vfs_do_atime = B_TRUE; + break; + case TOKEN_NOATIME: + vfsp->vfs_atime = B_FALSE; + vfsp->vfs_do_atime = B_TRUE; + break; + case TOKEN_RELATIME: + vfsp->vfs_relatime = B_TRUE; + vfsp->vfs_do_relatime = B_TRUE; + break; + case TOKEN_NORELATIME: + vfsp->vfs_relatime = B_FALSE; + vfsp->vfs_do_relatime = B_TRUE; + break; + case TOKEN_NBMAND: + vfsp->vfs_nbmand = B_TRUE; + vfsp->vfs_do_nbmand = B_TRUE; + break; + case TOKEN_NONBMAND: + vfsp->vfs_nbmand = B_FALSE; + vfsp->vfs_do_nbmand = B_TRUE; + break; + case TOKEN_MNTPOINT: + vfsp->vfs_mntpoint = match_strdup(&args[0]); + if (vfsp->vfs_mntpoint == NULL) + return (SET_ERROR(ENOMEM)); + + break; + default: + break; + } + + return (0); +} + +/* + * Parse the raw mntopts and return a vfs_t describing the options. + */ +static int +zfsvfs_parse_options(char *mntopts, vfs_t **vfsp) +{ + vfs_t *tmp_vfsp; + int error; + + tmp_vfsp = kmem_zalloc(sizeof (vfs_t), KM_SLEEP); + + if (mntopts != NULL) { + substring_t args[MAX_OPT_ARGS]; + char *tmp_mntopts, *p, *t; + int token; + + tmp_mntopts = t = strdup(mntopts); + if (tmp_mntopts == NULL) + return (SET_ERROR(ENOMEM)); + + while ((p = strsep(&t, ",")) != NULL) { + if (!*p) + continue; + + args[0].to = args[0].from = NULL; + token = match_token(p, zpl_tokens, args); + error = zfsvfs_parse_option(p, token, args, tmp_vfsp); + if (error) { + strfree(tmp_mntopts); + zfsvfs_vfs_free(tmp_vfsp); + return (error); + } + } + + strfree(tmp_mntopts); + } + + *vfsp = tmp_vfsp; + + return (0); +} + +boolean_t +zfs_is_readonly(zfsvfs_t *zfsvfs) +{ + return (!!(zfsvfs->z_sb->s_flags & MS_RDONLY)); +} + /*ARGSUSED*/ int zfs_sync(struct super_block *sb, int wait, cred_t *cr) @@ -122,12 +316,6 @@ zfs_sync(struct super_block *sb, int wait, cred_t *cr) return (0); } -boolean_t -zfs_is_readonly(zfsvfs_t *zfsvfs) -{ - return (!!(zfsvfs->z_sb->s_flags & MS_RDONLY)); -} - static void atime_changed_cb(void *arg, uint64_t newval) { @@ -255,16 +443,18 @@ acl_inherit_changed_cb(void *arg, uint64_t newval) ((zfsvfs_t *)arg)->z_acl_inherit = newval; } -int -zfs_register_callbacks(zfsvfs_t *zfsvfs) +static int +zfs_register_callbacks(vfs_t *vfsp) { struct dsl_dataset *ds = NULL; - objset_t *os = zfsvfs->z_os; - zfs_mntopts_t *zmo = zfsvfs->z_mntopts; + objset_t *os = NULL; + zfsvfs_t *zfsvfs = NULL; int error = 0; + ASSERT(vfsp); + zfsvfs = vfsp->vfs_data; ASSERT(zfsvfs); - ASSERT(zmo); + os = zfsvfs->z_os; /* * The act of registering our callbacks will destroy any mount @@ -273,8 +463,8 @@ zfs_register_callbacks(zfsvfs_t *zfsvfs) * restore them after we register the callbacks. */ if (zfs_is_readonly(zfsvfs) || !spa_writeable(dmu_objset_spa(os))) { - zmo->z_do_readonly = B_TRUE; - zmo->z_readonly = B_TRUE; + vfsp->vfs_do_readonly = B_TRUE; + vfsp->vfs_readonly = B_TRUE; } /* @@ -320,22 +510,22 @@ zfs_register_callbacks(zfsvfs_t *zfsvfs) /* * Invoke our callbacks to restore temporary mount options. */ - if (zmo->z_do_readonly) - readonly_changed_cb(zfsvfs, zmo->z_readonly); - if (zmo->z_do_setuid) - setuid_changed_cb(zfsvfs, zmo->z_setuid); - if (zmo->z_do_exec) - exec_changed_cb(zfsvfs, zmo->z_exec); - if (zmo->z_do_devices) - devices_changed_cb(zfsvfs, zmo->z_devices); - if (zmo->z_do_xattr) - xattr_changed_cb(zfsvfs, zmo->z_xattr); - if (zmo->z_do_atime) - atime_changed_cb(zfsvfs, zmo->z_atime); - if (zmo->z_do_relatime) - relatime_changed_cb(zfsvfs, zmo->z_relatime); - if (zmo->z_do_nbmand) - nbmand_changed_cb(zfsvfs, zmo->z_nbmand); + if (vfsp->vfs_do_readonly) + readonly_changed_cb(zfsvfs, vfsp->vfs_readonly); + if (vfsp->vfs_do_setuid) + setuid_changed_cb(zfsvfs, vfsp->vfs_setuid); + if (vfsp->vfs_do_exec) + exec_changed_cb(zfsvfs, vfsp->vfs_exec); + if (vfsp->vfs_do_devices) + devices_changed_cb(zfsvfs, vfsp->vfs_devices); + if (vfsp->vfs_do_xattr) + xattr_changed_cb(zfsvfs, vfsp->vfs_xattr); + if (vfsp->vfs_do_atime) + atime_changed_cb(zfsvfs, vfsp->vfs_atime); + if (vfsp->vfs_do_relatime) + relatime_changed_cb(zfsvfs, vfsp->vfs_relatime); + if (vfsp->vfs_do_nbmand) + nbmand_changed_cb(zfsvfs, vfsp->vfs_nbmand); return (0); @@ -708,26 +898,8 @@ zfs_owner_overquota(zfsvfs_t *zfsvfs, znode_t *zp, boolean_t isgroup) return (zfs_fuid_overquota(zfsvfs, isgroup, fuid)); } -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 -zfsvfs_create(const char *osname, zfs_mntopts_t *zmo, zfsvfs_t **zfvp) +zfsvfs_create(const char *osname, zfsvfs_t **zfvp) { objset_t *os; zfsvfs_t *zfsvfs; @@ -737,23 +909,21 @@ zfsvfs_create(const char *osname, zfs_mntopts_t *zmo, zfsvfs_t **zfvp) zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP); - /* - * Optional temporary mount options, free'd in zfsvfs_free(). - */ - zfsvfs->z_mntopts = (zmo ? zmo : zfs_mntopts_alloc()); - /* * We claim to always be readonly so we can open snapshots; * other ZPL code will prevent us from writing to snapshots. */ error = dmu_objset_own(osname, DMU_OST_ZFS, B_TRUE, zfsvfs, &os); - if (error) - goto out_zmo; + if (error) { + kmem_free(zfsvfs, sizeof (zfsvfs_t)); + return (error); + } /* * Initialize the zfs-specific filesystem structure. * Should probably make this a kmem cache, shuffle fields. */ + zfsvfs->z_vfs = NULL; zfsvfs->z_sb = NULL; zfsvfs->z_parent = zfsvfs; zfsvfs->z_max_blksz = SPA_OLD_MAXBLOCKSIZE; @@ -889,9 +1059,7 @@ zfsvfs_create(const char *osname, zfs_mntopts_t *zmo, zfsvfs_t **zfvp) out: dmu_objset_disown(os, zfsvfs); -out_zmo: *zfvp = NULL; - zfs_mntopts_free(zfsvfs->z_mntopts); kmem_free(zfsvfs, sizeof (zfsvfs_t)); return (error); } @@ -901,7 +1069,7 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting) { int error; - error = zfs_register_callbacks(zfsvfs); + error = zfs_register_callbacks(zfsvfs->z_vfs); if (error) return (error); @@ -997,7 +1165,7 @@ zfsvfs_free(zfsvfs_t *zfsvfs) } vmem_free(zfsvfs->z_hold_trees, sizeof (avl_tree_t) * size); vmem_free(zfsvfs->z_hold_locks, sizeof (kmutex_t) * size); - zfs_mntopts_free(zfsvfs->z_mntopts); + zfsvfs_vfs_free(zfsvfs->z_vfs); kmem_free(zfsvfs, sizeof (zfsvfs_t)); } @@ -1380,22 +1548,30 @@ atomic_long_t zfs_bdi_seq = ATOMIC_LONG_INIT(0); #endif int -zfs_domount(struct super_block *sb, zfs_mntopts_t *zmo, int silent) +zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent) { - const char *osname = zmo->z_osname; - zfsvfs_t *zfsvfs; + const char *osname = zm->mnt_osname; struct inode *root_inode; uint64_t recordsize; - int error; + int error = 0; + zfsvfs_t *zfsvfs; - error = zfsvfs_create(osname, zmo, &zfsvfs); + ASSERT(zm); + ASSERT(osname); + + error = zfsvfs_create(osname, &zfsvfs); if (error) return (error); + error = zfsvfs_parse_options(zm->mnt_data, &zfsvfs->z_vfs); + if (error) + goto out; + if ((error = dsl_prop_get_integer(osname, "recordsize", &recordsize, NULL))) goto out; + zfsvfs->z_vfs->vfs_data = zfsvfs; zfsvfs->z_sb = sb; sb->s_fs_info = zfsvfs; sb->s_magic = ZFS_SUPER_MAGIC; @@ -1555,13 +1731,22 @@ zfs_umount(struct super_block *sb) } int -zfs_remount(struct super_block *sb, int *flags, zfs_mntopts_t *zmo) +zfs_remount(struct super_block *sb, int *flags, zfs_mnt_t *zm) { zfsvfs_t *zfsvfs = sb->s_fs_info; + vfs_t *vfsp; int error; + error = zfsvfs_parse_options(zm->mnt_data, &vfsp); + if (error) + return (error); + zfs_unregister_callbacks(zfsvfs); - error = zfs_register_callbacks(zfsvfs); + zfsvfs_vfs_free(zfsvfs->z_vfs); + + vfsp->vfs_data = zfsvfs; + zfsvfs->z_vfs = vfsp; + (void) zfs_register_callbacks(vfsp); return (error); } diff --git a/module/zfs/zpl_super.c b/module/zfs/zpl_super.c index 16017ff44..b6ef60277 100644 --- a/module/zfs/zpl_super.c +++ b/module/zfs/zpl_super.c @@ -184,211 +184,15 @@ zpl_statfs(struct dentry *dentry, struct kstatfs *statp) return (error); } -enum { - TOKEN_RO, - TOKEN_RW, - TOKEN_SETUID, - TOKEN_NOSETUID, - TOKEN_EXEC, - TOKEN_NOEXEC, - TOKEN_DEVICES, - TOKEN_NODEVICES, - TOKEN_DIRXATTR, - TOKEN_SAXATTR, - TOKEN_XATTR, - TOKEN_NOXATTR, - TOKEN_ATIME, - TOKEN_NOATIME, - TOKEN_RELATIME, - TOKEN_NORELATIME, - TOKEN_NBMAND, - TOKEN_NONBMAND, - TOKEN_MNTPOINT, - TOKEN_LAST, -}; - -static const match_table_t zpl_tokens = { - { TOKEN_RO, MNTOPT_RO }, - { TOKEN_RW, MNTOPT_RW }, - { TOKEN_SETUID, MNTOPT_SETUID }, - { TOKEN_NOSETUID, MNTOPT_NOSETUID }, - { TOKEN_EXEC, MNTOPT_EXEC }, - { TOKEN_NOEXEC, MNTOPT_NOEXEC }, - { TOKEN_DEVICES, MNTOPT_DEVICES }, - { TOKEN_NODEVICES, MNTOPT_NODEVICES }, - { TOKEN_DIRXATTR, MNTOPT_DIRXATTR }, - { TOKEN_SAXATTR, MNTOPT_SAXATTR }, - { TOKEN_XATTR, MNTOPT_XATTR }, - { TOKEN_NOXATTR, MNTOPT_NOXATTR }, - { TOKEN_ATIME, MNTOPT_ATIME }, - { TOKEN_NOATIME, MNTOPT_NOATIME }, - { TOKEN_RELATIME, MNTOPT_RELATIME }, - { TOKEN_NORELATIME, MNTOPT_NORELATIME }, - { TOKEN_NBMAND, MNTOPT_NBMAND }, - { TOKEN_NONBMAND, MNTOPT_NONBMAND }, - { TOKEN_MNTPOINT, MNTOPT_MNTPOINT "=%s" }, - { TOKEN_LAST, NULL }, -}; - -static int -zpl_parse_option(char *option, int token, substring_t *args, zfs_mntopts_t *zmo) -{ - switch (token) { - case TOKEN_RO: - zmo->z_readonly = B_TRUE; - zmo->z_do_readonly = B_TRUE; - break; - case TOKEN_RW: - zmo->z_readonly = B_FALSE; - zmo->z_do_readonly = B_TRUE; - break; - case TOKEN_SETUID: - zmo->z_setuid = B_TRUE; - zmo->z_do_setuid = B_TRUE; - break; - case TOKEN_NOSETUID: - zmo->z_setuid = B_FALSE; - zmo->z_do_setuid = B_TRUE; - break; - case TOKEN_EXEC: - zmo->z_exec = B_TRUE; - zmo->z_do_exec = B_TRUE; - break; - case TOKEN_NOEXEC: - zmo->z_exec = B_FALSE; - zmo->z_do_exec = B_TRUE; - break; - case TOKEN_DEVICES: - zmo->z_devices = B_TRUE; - zmo->z_do_devices = B_TRUE; - break; - case TOKEN_NODEVICES: - zmo->z_devices = B_FALSE; - zmo->z_do_devices = B_TRUE; - break; - case TOKEN_DIRXATTR: - zmo->z_xattr = ZFS_XATTR_DIR; - zmo->z_do_xattr = B_TRUE; - break; - case TOKEN_SAXATTR: - zmo->z_xattr = ZFS_XATTR_SA; - zmo->z_do_xattr = B_TRUE; - break; - case TOKEN_XATTR: - zmo->z_xattr = ZFS_XATTR_DIR; - zmo->z_do_xattr = B_TRUE; - break; - case TOKEN_NOXATTR: - zmo->z_xattr = ZFS_XATTR_OFF; - zmo->z_do_xattr = B_TRUE; - break; - case TOKEN_ATIME: - zmo->z_atime = B_TRUE; - zmo->z_do_atime = B_TRUE; - break; - case TOKEN_NOATIME: - zmo->z_atime = B_FALSE; - zmo->z_do_atime = B_TRUE; - break; - case TOKEN_RELATIME: - zmo->z_relatime = B_TRUE; - zmo->z_do_relatime = B_TRUE; - break; - case TOKEN_NORELATIME: - zmo->z_relatime = B_FALSE; - zmo->z_do_relatime = B_TRUE; - break; - case TOKEN_NBMAND: - zmo->z_nbmand = B_TRUE; - zmo->z_do_nbmand = B_TRUE; - break; - case TOKEN_NONBMAND: - zmo->z_nbmand = B_FALSE; - zmo->z_do_nbmand = B_TRUE; - break; - case TOKEN_MNTPOINT: - zmo->z_mntpoint = match_strdup(&args[0]); - if (zmo->z_mntpoint == NULL) - return (-ENOMEM); - - break; - default: - break; - } - - return (0); -} - -/* - * Parse the mntopts string storing the results in provided zmo argument. - * If an error occurs the zmo argument will not be modified. The caller - * needs to set isremount when recycling an existing zfs_mntopts_t. - */ -static int -zpl_parse_options(char *osname, char *mntopts, zfs_mntopts_t *zmo, - boolean_t isremount) -{ - zfs_mntopts_t *tmp_zmo; - int error; - - tmp_zmo = zfs_mntopts_alloc(); - tmp_zmo->z_osname = strdup(osname); - - if (mntopts) { - substring_t args[MAX_OPT_ARGS]; - char *tmp_mntopts, *p, *t; - int token; - - t = tmp_mntopts = strdup(mntopts); - - while ((p = strsep(&t, ",")) != NULL) { - if (!*p) - continue; - - args[0].to = args[0].from = NULL; - token = match_token(p, zpl_tokens, args); - error = zpl_parse_option(p, token, args, tmp_zmo); - if (error) { - zfs_mntopts_free(tmp_zmo); - strfree(tmp_mntopts); - return (error); - } - } - - strfree(tmp_mntopts); - } - - if (isremount == B_TRUE) { - if (zmo->z_osname) - strfree(zmo->z_osname); - - if (zmo->z_mntpoint) - strfree(zmo->z_mntpoint); - } else { - ASSERT3P(zmo->z_osname, ==, NULL); - ASSERT3P(zmo->z_mntpoint, ==, NULL); - } - - memcpy(zmo, tmp_zmo, sizeof (zfs_mntopts_t)); - kmem_free(tmp_zmo, sizeof (zfs_mntopts_t)); - - return (0); -} - static int zpl_remount_fs(struct super_block *sb, int *flags, char *data) { - zfsvfs_t *zfsvfs = sb->s_fs_info; + zfs_mnt_t zm = { .mnt_osname = NULL, .mnt_data = data }; fstrans_cookie_t cookie; int error; - error = zpl_parse_options(zfsvfs->z_mntopts->z_osname, data, - zfsvfs->z_mntopts, B_TRUE); - if (error) - return (error); - cookie = spl_fstrans_mark(); - error = -zfs_remount(sb, flags, zfsvfs->z_mntopts); + error = -zfs_remount(sb, flags, &zm); spl_fstrans_unmark(cookie); ASSERT3S(error, <=, 0); @@ -432,12 +236,12 @@ zpl_show_options(struct seq_file *seq, struct vfsmount *vfsp) static int zpl_fill_super(struct super_block *sb, void *data, int silent) { - zfs_mntopts_t *zmo = (zfs_mntopts_t *)data; + zfs_mnt_t *zm = (zfs_mnt_t *)data; fstrans_cookie_t cookie; int error; cookie = spl_fstrans_mark(); - error = -zfs_domount(sb, zmo, silent); + error = -zfs_domount(sb, zm, silent); spl_fstrans_unmark(cookie); ASSERT3S(error, <=, 0); @@ -449,32 +253,18 @@ static struct dentry * zpl_mount(struct file_system_type *fs_type, int flags, const char *osname, void *data) { - zfs_mntopts_t *zmo = zfs_mntopts_alloc(); - int error; + zfs_mnt_t zm = { .mnt_osname = osname, .mnt_data = data }; - error = zpl_parse_options((char *)osname, (char *)data, zmo, B_FALSE); - if (error) { - zfs_mntopts_free(zmo); - return (ERR_PTR(error)); - } - - return (mount_nodev(fs_type, flags, zmo, zpl_fill_super)); + return (mount_nodev(fs_type, flags, &zm, zpl_fill_super)); } #else static int zpl_get_sb(struct file_system_type *fs_type, int flags, const char *osname, void *data, struct vfsmount *mnt) { - zfs_mntopts_t *zmo = zfs_mntopts_alloc(); - int error; + zfs_mnt_t zm = { .mnt_osname = osname, .mnt_data = data }; - error = zpl_parse_options((char *)osname, (char *)data, zmo, B_FALSE); - if (error) { - zfs_mntopts_free(zmo); - return (error); - } - - return (get_sb_nodev(fs_type, flags, zmo, zpl_fill_super, mnt)); + return (get_sb_nodev(fs_type, flags, &zm, zpl_fill_super, mnt)); } #endif /* HAVE_MOUNT_NODEV */