On Tue, 2019-11-05 at 07:23 -0800, Darrick J. Wong wrote: > On Tue, Nov 05, 2019 at 11:00:36AM +0800, Ian Kent wrote: > > On Mon, 2019-11-04 at 14:53 -0800, Darrick J. Wong wrote: > > > On Mon, Nov 04, 2019 at 06:55:44PM +0800, Ian Kent wrote: > > > > Define the struct fs_parameter_spec table that's used by the > > > > new > > > > mount-api for options parsing. > > > > > > > > Create the various fs context operations methods and define the > > > > fs_context_operations struct. > > > > > > > > Create the fs context initialization method and update the > > > > struct > > > > file_system_type to utilize it. The initialization function is > > > > responsible for working storage initialization, allocation and > > > > initialization of file system private information storage and > > > > for > > > > setting the operations in the fs context. > > > > > > > > Also set struct file_system_type .parameters to the newly > > > > defined > > > > struct fs_parameter_spec options parsing table for use by the > > > > fs > > > > context methods and remove unused code. > > > > > > > > Signed-off-by: Ian Kent <raven@xxxxxxxxxx> > > > > --- > > > > fs/xfs/xfs_super.c | 408 ++++++++++++++++++++++------------ > > > > ---- > > > > -------------- > > > > 1 file changed, 171 insertions(+), 237 deletions(-) > > > > > > > > diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c > > > > index 62dfc678c415..2d4edaaf934e 100644 > > > > --- a/fs/xfs/xfs_super.c > > > > +++ b/fs/xfs/xfs_super.c > > > > @@ -37,7 +37,8 @@ > > > > #include "xfs_reflink.h" > > > > > > > > #include <linux/magic.h> > > > > -#include <linux/parser.h> > > > > +#include <linux/fs_context.h> > > > > +#include <linux/fs_parser.h> > > > > > > > > static const struct super_operations xfs_super_operations; > > > > > > > > @@ -58,55 +59,57 @@ enum { > > > > Opt_filestreams, Opt_quota, Opt_noquota, Opt_usrquota, > > > > Opt_grpquota, > > > > Opt_prjquota, Opt_uquota, Opt_gquota, Opt_pquota, > > > > Opt_uqnoenforce, Opt_gqnoenforce, Opt_pqnoenforce, > > > > Opt_qnoenforce, > > > > - Opt_discard, Opt_nodiscard, Opt_dax, Opt_err, > > > > + Opt_discard, Opt_nodiscard, Opt_dax, > > > > }; > > > > > > > > -static const match_table_t tokens = { > > > > - {Opt_logbufs, "logbufs=%u"}, /* number of XFS log > > > > buffers */ > > > > - {Opt_logbsize, "logbsize=%s"}, /* size of XFS log > > > > buffers > > > > */ > > > > - {Opt_logdev, "logdev=%s"}, /* log device */ > > > > - {Opt_rtdev, "rtdev=%s"}, /* realtime I/O device > > > > */ > > > > - {Opt_wsync, "wsync"}, /* safe-mode nfs > > > > compatible mount > > > > */ > > > > - {Opt_noalign, "noalign"}, /* turn off stripe > > > > alignment */ > > > > - {Opt_swalloc, "swalloc"}, /* turn on stripe width > > > > allocation */ > > > > - {Opt_sunit, "sunit=%u"}, /* data volume stripe > > > > unit */ > > > > - {Opt_swidth, "swidth=%u"}, /* data volume stripe > > > > width > > > > */ > > > > - {Opt_nouuid, "nouuid"}, /* ignore filesystem > > > > UUID > > > > */ > > > > - {Opt_grpid, "grpid"}, /* group-ID from parent > > > > directory > > > > */ > > > > - {Opt_nogrpid, "nogrpid"}, /* group-ID from > > > > current > > > > process */ > > > > - {Opt_bsdgroups, "bsdgroups"}, /* group-ID from parent > > > > directory */ > > > > - {Opt_sysvgroups,"sysvgroups"}, /* group-ID from > > > > current > > > > process */ > > > > - {Opt_allocsize, "allocsize=%s"},/* preferred allocation > > > > size */ > > > > - {Opt_norecovery,"norecovery"}, /* don't run XFS > > > > recovery > > > > */ > > > > - {Opt_inode64, "inode64"}, /* inodes can be > > > > allocated > > > > anywhere */ > > > > - {Opt_inode32, "inode32"}, /* inode allocation > > > > limited to > > > > - * XFS_MAXINUMBER_32 */ > > > > - {Opt_ikeep, "ikeep"}, /* do not free empty > > > > inode clusters > > > > */ > > > > - {Opt_noikeep, "noikeep"}, /* free empty inode > > > > clusters */ > > > > - {Opt_largeio, "largeio"}, /* report large I/O > > > > sizes > > > > in stat() */ > > > > - {Opt_nolargeio, "nolargeio"}, /* do not report large > > > > I/O > > > > sizes > > > > - * in stat(). */ > > > > - {Opt_attr2, "attr2"}, /* do use attr2 > > > > attribute format */ > > > > - {Opt_noattr2, "noattr2"}, /* do not use attr2 > > > > attribute format */ > > > > - {Opt_filestreams,"filestreams"},/* use filestreams > > > > allocator */ > > > > - {Opt_quota, "quota"}, /* disk quotas (user) > > > > */ > > > > - {Opt_noquota, "noquota"}, /* no quotas */ > > > > - {Opt_usrquota, "usrquota"}, /* user quota enabled > > > > */ > > > > - {Opt_grpquota, "grpquota"}, /* group quota enabled > > > > */ > > > > - {Opt_prjquota, "prjquota"}, /* project quota > > > > enabled */ > > > > - {Opt_uquota, "uquota"}, /* user quota (IRIX > > > > variant) */ > > > > - {Opt_gquota, "gquota"}, /* group quota (IRIX > > > > variant) */ > > > > - {Opt_pquota, "pquota"}, /* project quota (IRIX > > > > variant) */ > > > > - {Opt_uqnoenforce,"uqnoenforce"},/* user quota limit > > > > enforcement > > > > */ > > > > - {Opt_gqnoenforce,"gqnoenforce"},/* group quota limit > > > > enforcement */ > > > > - {Opt_pqnoenforce,"pqnoenforce"},/* project quota limit > > > > enforcement */ > > > > - {Opt_qnoenforce, "qnoenforce"}, /* same as uqnoenforce > > > > */ > > > > - {Opt_discard, "discard"}, /* Discard unused > > > > blocks */ > > > > - {Opt_nodiscard, "nodiscard"}, /* Do not discard > > > > unused > > > > blocks */ > > > > - {Opt_dax, "dax"}, /* Enable direct access > > > > to bdev > > > > pages */ > > > > - {Opt_err, NULL}, > > > > +static const struct fs_parameter_spec xfs_param_specs[] = { > > > > + fsparam_u32("logbufs", Opt_logbufs), > > > > + fsparam_string("logbsize", Opt_logbsize), > > > > + fsparam_string("logdev", Opt_logdev), > > > > + fsparam_string("rtdev", Opt_rtdev), > > > > + fsparam_flag("wsync", Opt_wsync), > > > > + fsparam_flag("noalign", Opt_noalign), > > > > + fsparam_flag("swalloc", Opt_swalloc), > > > > + fsparam_u32("sunit", Opt_sunit), > > > > + fsparam_u32("swidth", Opt_swidth), > > > > + fsparam_flag("nouuid", Opt_nouuid), > > > > + fsparam_flag("grpid", Opt_grpid), > > > > + fsparam_flag("nogrpid", Opt_nogrpid), > > > > + fsparam_flag("bsdgroups", Opt_bsdgroups), > > > > + fsparam_flag("sysvgroups", Opt_sysvgroups), > > > > + fsparam_string("allocsize", Opt_allocsize), > > > > + fsparam_flag("norecovery", Opt_norecovery), > > > > + fsparam_flag("inode64", Opt_inode64), > > > > + fsparam_flag("inode32", Opt_inode32), > > > > + fsparam_flag("ikeep", Opt_ikeep), > > > > + fsparam_flag("noikeep", Opt_noikeep), > > > > + fsparam_flag("largeio", Opt_largeio), > > > > + fsparam_flag("nolargeio", Opt_nolargeio), > > > > + fsparam_flag("attr2", Opt_attr2), > > > > + fsparam_flag("noattr2", Opt_noattr2), > > > > + fsparam_flag("filestreams", Opt_filestreams), > > > > + fsparam_flag("quota", Opt_quota), > > > > + fsparam_flag("noquota", Opt_noquota), > > > > + fsparam_flag("usrquota", Opt_usrquota), > > > > + fsparam_flag("grpquota", Opt_grpquota), > > > > + fsparam_flag("prjquota", Opt_prjquota), > > > > + fsparam_flag("uquota", Opt_uquota), > > > > + fsparam_flag("gquota", Opt_gquota), > > > > + fsparam_flag("pquota", Opt_pquota), > > > > + fsparam_flag("uqnoenforce", Opt_uqnoenforce), > > > > + fsparam_flag("gqnoenforce", Opt_gqnoenforce), > > > > + fsparam_flag("pqnoenforce", Opt_pqnoenforce), > > > > + fsparam_flag("qnoenforce", Opt_qnoenforce), > > > > + fsparam_flag("discard", Opt_discard), > > > > + fsparam_flag("nodiscard", Opt_nodiscard), > > > > + fsparam_flag("dax", Opt_dax), > > > > + {} > > > > }; > > > > > > > > +static const struct fs_parameter_description xfs_fs_parameters > > > > = { > > > > + .name = "xfs", > > > > + .specs = xfs_param_specs, > > > > +}; > > > > > > > > static int > > > > suffix_kstrtoint( > > > > @@ -143,55 +146,42 @@ suffix_kstrtoint( > > > > return ret; > > > > } > > > > > > > > -static int > > > > -match_kstrtoint( > > > > - const substring_t *s, > > > > - unsigned int base, > > > > - int *res) > > > > -{ > > > > - const char *value; > > > > - int ret; > > > > - > > > > - value = match_strdup(s); > > > > - if (!value) > > > > - return -ENOMEM; > > > > - ret = suffix_kstrtoint(value, base, res); > > > > - kfree(value); > > > > - return ret; > > > > -} > > > > - > > > > static int > > > > xfs_fc_parse_param( > > > > > > This is the only function where mp->m_super can be NULL, correct? > > > > Yep. > > > > > If so, I'll add a comment to that effect, and, > > > Reviewed-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > > > Thanks, much appreciated. > > > > > (for this and patch 12.) > > > > > > Will throw this at a testing cloud and see what happens... > > > > It's seems ok when I run it against xfstests but I'm not as > > familiar > > with what to expect as you would be, I'm interested to hear how it > > goes, ;) > > Looked like it ran just fine. > > > I noticed a significant change in test run times with the latest > > for-next but there was also an xfstests update so I'm not sure > > what caused it. Some test run times went up by 8 to 10 or more > > times, which seemed like a big change, possibly a regression. > > Hmm, I haven't seen any such regression; it still takes ~3h to run > all > the non-dangerous tests. Ok, it must be my setup then. Thought I'd mention it just in case there was something wrong. Ian > > --D > > > Ian > > > > > --D > > > > > > > - int token, > > > > - char *p, > > > > - substring_t *args, > > > > - struct xfs_mount *mp) > > > > + struct fs_context *fc, > > > > + struct fs_parameter *param) > > > > { > > > > + struct xfs_mount *mp = fc->s_fs_info; > > > > + struct fs_parse_result result; > > > > int size = 0; > > > > + int opt; > > > > + > > > > + opt = fs_parse(fc, &xfs_fs_parameters, param, &result); > > > > + if (opt < 0) > > > > + return opt; > > > > > > > > - switch (token) { > > > > + switch (opt) { > > > > case Opt_logbufs: > > > > - if (match_int(args, &mp->m_logbufs)) > > > > - return -EINVAL; > > > > + mp->m_logbufs = result.uint_32; > > > > return 0; > > > > case Opt_logbsize: > > > > - if (match_kstrtoint(args, 10, &mp->m_logbsize)) > > > > + if (suffix_kstrtoint(param->string, 10, &mp- > > > > > m_logbsize)) > > > > return -EINVAL; > > > > return 0; > > > > case Opt_logdev: > > > > kfree(mp->m_logname); > > > > - mp->m_logname = match_strdup(args); > > > > + mp->m_logname = kstrdup(param->string, > > > > GFP_KERNEL); > > > > if (!mp->m_logname) > > > > return -ENOMEM; > > > > return 0; > > > > case Opt_rtdev: > > > > kfree(mp->m_rtname); > > > > - mp->m_rtname = match_strdup(args); > > > > + mp->m_rtname = kstrdup(param->string, > > > > GFP_KERNEL); > > > > if (!mp->m_rtname) > > > > return -ENOMEM; > > > > return 0; > > > > case Opt_allocsize: > > > > - if (match_kstrtoint(args, 10, &size)) > > > > + if (suffix_kstrtoint(param->string, 10, &size)) > > > > return -EINVAL; > > > > mp->m_allocsize_log = ffs(size) - 1; > > > > mp->m_flags |= XFS_MOUNT_ALLOCSIZE; > > > > @@ -217,12 +207,10 @@ xfs_fc_parse_param( > > > > mp->m_flags |= XFS_MOUNT_SWALLOC; > > > > return 0; > > > > case Opt_sunit: > > > > - if (match_int(args, &mp->m_dalign)) > > > > - return -EINVAL; > > > > + mp->m_dalign = result.uint_32; > > > > return 0; > > > > case Opt_swidth: > > > > - if (match_int(args, &mp->m_swidth)) > > > > - return -EINVAL; > > > > + mp->m_swidth = result.uint_32; > > > > return 0; > > > > case Opt_inode32: > > > > mp->m_flags |= XFS_MOUNT_SMALL_INUMS; > > > > @@ -301,7 +289,7 @@ xfs_fc_parse_param( > > > > return 0; > > > > #endif > > > > default: > > > > - xfs_warn(mp, "unknown mount option [%s].", p); > > > > + xfs_warn(mp, "unknown mount option [%s].", > > > > param->key); > > > > return -EINVAL; > > > > } > > > > > > > > @@ -376,62 +364,6 @@ xfs_fc_validate_params( > > > > return 0; > > > > } > > > > > > > > -/* > > > > - * This function fills in xfs_mount_t fields based on mount > > > > args. > > > > - * Note: the superblock has _not_ yet been read in. > > > > - * > > > > - * Note that this function leaks the various device name > > > > allocations on > > > > - * failure. The caller takes care of them. > > > > - * > > > > - * *sb is const because this is also used to test options on > > > > the > > > > remount > > > > - * path, and we don't want this to have any side effects at > > > > remount time. > > > > - * Today this function does not change *sb, but just to > > > > future- > > > > proof... > > > > - */ > > > > -static int > > > > -xfs_parseargs( > > > > - struct xfs_mount *mp, > > > > - char *options) > > > > -{ > > > > - const struct super_block *sb = mp->m_super; > > > > - char *p; > > > > - substring_t args[MAX_OPT_ARGS]; > > > > - > > > > - /* > > > > - * Copy binary VFS mount flags we are interested in. > > > > - */ > > > > - if (sb_rdonly(sb)) > > > > - mp->m_flags |= XFS_MOUNT_RDONLY; > > > > - if (sb->s_flags & SB_DIRSYNC) > > > > - mp->m_flags |= XFS_MOUNT_DIRSYNC; > > > > - if (sb->s_flags & SB_SYNCHRONOUS) > > > > - mp->m_flags |= XFS_MOUNT_WSYNC; > > > > - > > > > - /* > > > > - * These can be overridden by the mount option parsing. > > > > - */ > > > > - mp->m_logbufs = -1; > > > > - mp->m_logbsize = -1; > > > > - mp->m_allocsize_log = 16; /* 64k */ > > > > - > > > > - if (!options) > > > > - return 0; > > > > - > > > > - while ((p = strsep(&options, ",")) != NULL) { > > > > - int token; > > > > - int ret; > > > > - > > > > - if (!*p) > > > > - continue; > > > > - > > > > - token = match_token(p, tokens, args); > > > > - ret = xfs_fc_parse_param(token, p, args, mp); > > > > - if (ret) > > > > - return ret; > > > > - } > > > > - > > > > - return xfs_fc_validate_params(mp); > > > > -} > > > > - > > > > struct proc_xfs_info { > > > > uint64_t flag; > > > > char *str; > > > > @@ -1207,25 +1139,6 @@ xfs_quiesce_attr( > > > > xfs_log_quiesce(mp); > > > > } > > > > > > > > -STATIC int > > > > -xfs_test_remount_options( > > > > - struct super_block *sb, > > > > - char *options) > > > > -{ > > > > - int error = 0; > > > > - struct xfs_mount *tmp_mp; > > > > - > > > > - tmp_mp = kmem_zalloc(sizeof(*tmp_mp), KM_MAYFAIL); > > > > - if (!tmp_mp) > > > > - return -ENOMEM; > > > > - > > > > - tmp_mp->m_super = sb; > > > > - error = xfs_parseargs(tmp_mp, options); > > > > - xfs_mount_free(tmp_mp); > > > > - > > > > - return error; > > > > -} > > > > - > > > > static int > > > > xfs_remount_rw( > > > > struct xfs_mount *mp) > > > > @@ -1329,76 +1242,57 @@ xfs_remount_ro( > > > > return 0; > > > > } > > > > > > > > -STATIC int > > > > -xfs_fs_remount( > > > > - struct super_block *sb, > > > > - int *flags, > > > > - char *options) > > > > +/* > > > > + * Logically we would return an error here to prevent users > > > > from > > > > believing > > > > + * they might have changed mount options using remount which > > > > can't > > > > be changed. > > > > + * > > > > + * But unfortunately mount(8) adds all options from mtab and > > > > fstab > > > > to the mount > > > > + * arguments in some cases so we can't blindly reject options, > > > > but > > > > have to > > > > + * check for each specified option if it actually differs from > > > > the > > > > currently > > > > + * set option and only reject it if that's the case. > > > > + * > > > > + * Until that is implemented we return success for every > > > > remount > > > > request, and > > > > + * silently ignore all options that we can't actually change. > > > > + */ > > > > +static int > > > > +xfs_fc_reconfigure( > > > > + struct fs_context *fc) > > > > { > > > > - struct xfs_mount *mp = XFS_M(sb); > > > > + struct xfs_mount *mp = XFS_M(fc->root->d_sb); > > > > + struct xfs_mount *new_mp = fc->s_fs_info; > > > > xfs_sb_t *sbp = &mp->m_sb; > > > > - substring_t args[MAX_OPT_ARGS]; > > > > - char *p; > > > > + int flags = fc->sb_flags; > > > > int error; > > > > > > > > - /* First, check for complete junk; i.e. invalid options > > > > */ > > > > - error = xfs_test_remount_options(sb, options); > > > > + error = xfs_fc_validate_params(new_mp); > > > > if (error) > > > > return error; > > > > > > > > - sync_filesystem(sb); > > > > - while ((p = strsep(&options, ",")) != NULL) { > > > > - int token; > > > > - > > > > - if (!*p) > > > > - continue; > > > > - > > > > - token = match_token(p, tokens, args); > > > > - switch (token) { > > > > - case Opt_inode64: > > > > - mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS; > > > > - mp->m_maxagi = xfs_set_inode_alloc(mp, > > > > sbp- > > > > > sb_agcount); > > > > - break; > > > > - case Opt_inode32: > > > > - mp->m_flags |= XFS_MOUNT_SMALL_INUMS; > > > > - mp->m_maxagi = xfs_set_inode_alloc(mp, > > > > sbp- > > > > > sb_agcount); > > > > - break; > > > > - default: > > > > - /* > > > > - * Logically we would return an error > > > > here to > > > > prevent > > > > - * users from believing they might have > > > > changed > > > > - * mount options using remount which > > > > can't be > > > > changed. > > > > - * > > > > - * But unfortunately mount(8) adds all > > > > options > > > > from > > > > - * mtab and fstab to the mount > > > > arguments in > > > > some cases > > > > - * so we can't blindly reject options, > > > > but have > > > > to > > > > - * check for each specified option if > > > > it > > > > actually > > > > - * differs from the currently set > > > > option and > > > > only > > > > - * reject it if that's the case. > > > > - * > > > > - * Until that is implemented we return > > > > success > > > > for > > > > - * every remount request, and silently > > > > ignore > > > > all > > > > - * options that we can't actually > > > > change. > > > > - */ > > > > -#if 0 > > > > - xfs_info(mp, > > > > - "mount option \"%s\" not supported for > > > > remount", p); > > > > - return -EINVAL; > > > > -#else > > > > - break; > > > > -#endif > > > > - } > > > > + sync_filesystem(mp->m_super); > > > > + > > > > + /* inode32 -> inode64 */ > > > > + if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && > > > > + !(new_mp->m_flags & XFS_MOUNT_SMALL_INUMS)) { > > > > + mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS; > > > > + mp->m_maxagi = xfs_set_inode_alloc(mp, sbp- > > > > > sb_agcount); > > > > + } > > > > + > > > > + /* inode64 -> inode32 */ > > > > + if (!(mp->m_flags & XFS_MOUNT_SMALL_INUMS) && > > > > + (new_mp->m_flags & XFS_MOUNT_SMALL_INUMS)) { > > > > + mp->m_flags |= XFS_MOUNT_SMALL_INUMS; > > > > + mp->m_maxagi = xfs_set_inode_alloc(mp, sbp- > > > > > sb_agcount); > > > > } > > > > > > > > /* ro -> rw */ > > > > - if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & > > > > SB_RDONLY)) > > > > { > > > > + if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(flags & > > > > SB_RDONLY)) { > > > > error = xfs_remount_rw(mp); > > > > if (error) > > > > return error; > > > > } > > > > > > > > /* rw -> ro */ > > > > - if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (*flags & > > > > SB_RDONLY)) > > > > { > > > > + if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (flags & > > > > SB_RDONLY)) { > > > > error = xfs_remount_ro(mp); > > > > if (error) > > > > return error; > > > > @@ -1588,28 +1482,18 @@ xfs_mount_alloc(void) > > > > return mp; > > > > } > > > > > > > > - > > > > -STATIC int > > > > -xfs_fs_fill_super( > > > > +static int > > > > +xfs_fc_fill_super( > > > > struct super_block *sb, > > > > - void *data, > > > > - int silent) > > > > + struct fs_context *fc) > > > > { > > > > + struct xfs_mount *mp = sb->s_fs_info; > > > > struct inode *root; > > > > - struct xfs_mount *mp = NULL; > > > > int flags = 0, error = -ENOMEM; > > > > > > > > - /* > > > > - * allocate mp and do all low-level struct > > > > initializations > > > > before we > > > > - * attach it to the super > > > > - */ > > > > - mp = xfs_mount_alloc(); > > > > - if (!mp) > > > > - goto out; > > > > mp->m_super = sb; > > > > - sb->s_fs_info = mp; > > > > > > > > - error = xfs_parseargs(mp, (char *)data); > > > > + error = xfs_fc_validate_params(mp); > > > > if (error) > > > > goto out_free_names; > > > > > > > > @@ -1633,7 +1517,7 @@ xfs_fs_fill_super( > > > > msleep(xfs_globals.mount_delay * 1000); > > > > } > > > > > > > > - if (silent) > > > > + if (fc->sb_flags & SB_SILENT) > > > > flags |= XFS_MFSI_QUIET; > > > > > > > > error = xfs_open_devices(mp); > > > > @@ -1778,7 +1662,6 @@ xfs_fs_fill_super( > > > > out_free_names: > > > > sb->s_fs_info = NULL; > > > > xfs_mount_free(mp); > > > > - out: > > > > return error; > > > > > > > > out_unmount: > > > > @@ -1787,6 +1670,13 @@ xfs_fs_fill_super( > > > > goto out_free_sb; > > > > } > > > > > > > > +static int > > > > +xfs_fc_get_tree( > > > > + struct fs_context *fc) > > > > +{ > > > > + return get_tree_bdev(fc, xfs_fc_fill_super); > > > > +} > > > > + > > > > STATIC void > > > > xfs_fs_put_super( > > > > struct super_block *sb) > > > > @@ -1811,16 +1701,6 @@ xfs_fs_put_super( > > > > xfs_mount_free(mp); > > > > } > > > > > > > > -STATIC struct dentry * > > > > -xfs_fs_mount( > > > > - struct file_system_type *fs_type, > > > > - int flags, > > > > - const char *dev_name, > > > > - void *data) > > > > -{ > > > > - return mount_bdev(fs_type, flags, dev_name, data, > > > > xfs_fs_fill_super); > > > > -} > > > > - > > > > static long > > > > xfs_fs_nr_cached_objects( > > > > struct super_block *sb, > > > > @@ -1850,16 +1730,70 @@ static const struct super_operations > > > > xfs_super_operations = { > > > > .freeze_fs = xfs_fs_freeze, > > > > .unfreeze_fs = xfs_fs_unfreeze, > > > > .statfs = xfs_fs_statfs, > > > > - .remount_fs = xfs_fs_remount, > > > > .show_options = xfs_fs_show_options, > > > > .nr_cached_objects = xfs_fs_nr_cached_objects, > > > > .free_cached_objects = xfs_fs_free_cached_objects, > > > > }; > > > > > > > > +static void xfs_fc_free( > > > > + struct fs_context *fc) > > > > +{ > > > > + struct xfs_mount *mp = fc->s_fs_info; > > > > + > > > > + /* > > > > + * mp is stored in the fs_context when it is > > > > initialized. > > > > + * mp is transferred to the superblock on a successful > > > > mount, > > > > + * but if an error occurs before the transfer we have > > > > to free > > > > + * it here. > > > > + */ > > > > + if (mp) > > > > + xfs_mount_free(mp); > > > > +} > > > > + > > > > +static const struct fs_context_operations xfs_context_ops = { > > > > + .parse_param = xfs_fc_parse_param, > > > > + .get_tree = xfs_fc_get_tree, > > > > + .reconfigure = xfs_fc_reconfigure, > > > > + .free = xfs_fc_free, > > > > +}; > > > > + > > > > +static int xfs_init_fs_context( > > > > + struct fs_context *fc) > > > > +{ > > > > + struct xfs_mount *mp; > > > > + > > > > + mp = xfs_mount_alloc(); > > > > + if (!mp) > > > > + return -ENOMEM; > > > > + > > > > + /* > > > > + * These can be overridden by the mount option parsing. > > > > + */ > > > > + mp->m_logbufs = -1; > > > > + mp->m_logbsize = -1; > > > > + mp->m_allocsize_log = 16; /* 64k */ > > > > + > > > > + /* > > > > + * Copy binary VFS mount flags we are interested in. > > > > + */ > > > > + if (fc->sb_flags & SB_RDONLY) > > > > + mp->m_flags |= XFS_MOUNT_RDONLY; > > > > + if (fc->sb_flags & SB_DIRSYNC) > > > > + mp->m_flags |= XFS_MOUNT_DIRSYNC; > > > > + if (fc->sb_flags & SB_SYNCHRONOUS) > > > > + mp->m_flags |= XFS_MOUNT_WSYNC; > > > > + > > > > + fc->s_fs_info = mp; > > > > + fc->ops = &xfs_context_ops; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > static struct file_system_type xfs_fs_type = { > > > > .owner = THIS_MODULE, > > > > .name = "xfs", > > > > - .mount = xfs_fs_mount, > > > > + .init_fs_context = xfs_init_fs_context, > > > > + .parameters = &xfs_fs_parameters, > > > > .kill_sb = kill_block_super, > > > > .fs_flags = FS_REQUIRES_DEV, > > > > }; > > > >