8383#include <linux/blkdev.h>
8484#include <linux/backing-dev.h>
8585#include <linux/init.h>
86- #include <linux/parser.h>
86+ #include <linux/fs_context.h>
87+ #include <linux/fs_parser.h>
8788#include <linux/buffer_head.h>
8889#include <linux/vfs.h>
8990#include <linux/log2.h>
90- #include <linux/mount.h>
9191#include <linux/seq_file.h>
9292#include <linux/iversion.h>
9393
@@ -342,120 +342,74 @@ void ufs_warning (struct super_block * sb, const char * function,
342342 va_end (args );
343343}
344344
345- enum {
346- Opt_type_old = UFS_MOUNT_UFSTYPE_OLD ,
347- Opt_type_sunx86 = UFS_MOUNT_UFSTYPE_SUNx86 ,
348- Opt_type_sun = UFS_MOUNT_UFSTYPE_SUN ,
349- Opt_type_sunos = UFS_MOUNT_UFSTYPE_SUNOS ,
350- Opt_type_44bsd = UFS_MOUNT_UFSTYPE_44BSD ,
351- Opt_type_ufs2 = UFS_MOUNT_UFSTYPE_UFS2 ,
352- Opt_type_hp = UFS_MOUNT_UFSTYPE_HP ,
353- Opt_type_nextstepcd = UFS_MOUNT_UFSTYPE_NEXTSTEP_CD ,
354- Opt_type_nextstep = UFS_MOUNT_UFSTYPE_NEXTSTEP ,
355- Opt_type_openstep = UFS_MOUNT_UFSTYPE_OPENSTEP ,
356- Opt_onerror_panic = UFS_MOUNT_ONERROR_PANIC ,
357- Opt_onerror_lock = UFS_MOUNT_ONERROR_LOCK ,
358- Opt_onerror_umount = UFS_MOUNT_ONERROR_UMOUNT ,
359- Opt_onerror_repair = UFS_MOUNT_ONERROR_REPAIR ,
360- Opt_err
345+ enum { Opt_type , Opt_onerror };
346+
347+ static const struct constant_table ufs_param_ufstype [] = {
348+ {"old" , UFS_MOUNT_UFSTYPE_OLD },
349+ {"sunx86" , UFS_MOUNT_UFSTYPE_SUNx86 },
350+ {"sun" , UFS_MOUNT_UFSTYPE_SUN },
351+ {"sunos" , UFS_MOUNT_UFSTYPE_SUNOS },
352+ {"44bsd" , UFS_MOUNT_UFSTYPE_44BSD },
353+ {"ufs2" , UFS_MOUNT_UFSTYPE_UFS2 },
354+ {"5xbsd" , UFS_MOUNT_UFSTYPE_UFS2 },
355+ {"hp" , UFS_MOUNT_UFSTYPE_HP },
356+ {"nextstep-cd" , UFS_MOUNT_UFSTYPE_NEXTSTEP_CD },
357+ {"nextstep" , UFS_MOUNT_UFSTYPE_NEXTSTEP },
358+ {"openstep" , UFS_MOUNT_UFSTYPE_OPENSTEP },
359+ {}
361360};
362361
363- static const match_table_t tokens = {
364- {Opt_type_old , "ufstype=old" },
365- {Opt_type_sunx86 , "ufstype=sunx86" },
366- {Opt_type_sun , "ufstype=sun" },
367- {Opt_type_sunos , "ufstype=sunos" },
368- {Opt_type_44bsd , "ufstype=44bsd" },
369- {Opt_type_ufs2 , "ufstype=ufs2" },
370- {Opt_type_ufs2 , "ufstype=5xbsd" },
371- {Opt_type_hp , "ufstype=hp" },
372- {Opt_type_nextstepcd , "ufstype=nextstep-cd" },
373- {Opt_type_nextstep , "ufstype=nextstep" },
374- {Opt_type_openstep , "ufstype=openstep" },
375- /*end of possible ufs types */
376- {Opt_onerror_panic , "onerror=panic" },
377- {Opt_onerror_lock , "onerror=lock" },
378- {Opt_onerror_umount , "onerror=umount" },
379- {Opt_onerror_repair , "onerror=repair" },
380- {Opt_err , NULL }
362+ static const struct constant_table ufs_param_onerror [] = {
363+ {"panic" , UFS_MOUNT_ONERROR_PANIC },
364+ {"lock" , UFS_MOUNT_ONERROR_LOCK },
365+ {"umount" , UFS_MOUNT_ONERROR_UMOUNT },
366+ {"repair" , UFS_MOUNT_ONERROR_REPAIR },
367+ {}
381368};
382369
383- static int ufs_parse_options (char * options , unsigned * flavour , unsigned * on_err , bool remount )
370+ static const struct fs_parameter_spec ufs_param_spec [] = {
371+ fsparam_enum ("ufstype" , Opt_type , ufs_param_ufstype ),
372+ fsparam_enum ("onerror" , Opt_onerror , ufs_param_onerror ),
373+ {}
374+ };
375+
376+ struct ufs_fs_context {
377+ unsigned int flavour , on_err ;
378+ };
379+
380+ static int ufs_parse_param (struct fs_context * fc , struct fs_parameter * param )
384381{
385- char * p ;
386-
382+ struct ufs_fs_context * ctx = fc -> fs_private ;
383+ struct fs_parse_result result ;
384+ int opt ;
385+
387386 UFSD ("ENTER\n" );
388-
389- if (!options )
390- return 1 ;
391-
392- while ((p = strsep (& options , "," )) != NULL ) {
393- substring_t args [MAX_OPT_ARGS ];
394- int token ;
395- unsigned int old = * flavour ;
396- if (!* p )
397- continue ;
398387
399- token = match_token (p , tokens , args );
400- switch (token ) {
401- case Opt_type_old :
402- * flavour = UFS_MOUNT_UFSTYPE_OLD ;
403- break ;
404- case Opt_type_sunx86 :
405- * flavour = UFS_MOUNT_UFSTYPE_SUNx86 ;
406- break ;
407- case Opt_type_sun :
408- * flavour = UFS_MOUNT_UFSTYPE_SUN ;
409- break ;
410- case Opt_type_sunos :
411- * flavour = UFS_MOUNT_UFSTYPE_SUNOS ;
412- break ;
413- case Opt_type_44bsd :
414- * flavour = UFS_MOUNT_UFSTYPE_44BSD ;
415- break ;
416- case Opt_type_ufs2 :
417- * flavour = UFS_MOUNT_UFSTYPE_UFS2 ;
418- break ;
419- case Opt_type_hp :
420- * flavour = UFS_MOUNT_UFSTYPE_HP ;
421- break ;
422- case Opt_type_nextstepcd :
423- * flavour = UFS_MOUNT_UFSTYPE_NEXTSTEP_CD ;
424- break ;
425- case Opt_type_nextstep :
426- * flavour = UFS_MOUNT_UFSTYPE_NEXTSTEP ;
427- break ;
428- case Opt_type_openstep :
429- * flavour = UFS_MOUNT_UFSTYPE_OPENSTEP ;
430- break ;
431- case Opt_onerror_panic :
432- * on_err = UFS_MOUNT_ONERROR_PANIC ;
433- break ;
434- case Opt_onerror_lock :
435- * on_err = UFS_MOUNT_ONERROR_LOCK ;
436- break ;
437- case Opt_onerror_umount :
438- * on_err = UFS_MOUNT_ONERROR_UMOUNT ;
439- break ;
440- case Opt_onerror_repair :
441- * on_err = UFS_MOUNT_ONERROR_REPAIR ;
442- pr_err ("Unable to do repair on error, will lock lock instead\n" );
443- break ;
444- default :
445- pr_err ("Invalid option: \"%s\" or missing value\n" , p );
388+ opt = fs_parse (fc , ufs_param_spec , param , & result );
389+ if (opt < 0 )
390+ return opt ;
391+
392+ switch (opt ) {
393+ case Opt_type :
394+ if (ctx -> flavour == result .uint_32 ) /* no-op */
446395 return 0 ;
447- }
448- if (* flavour == old )
449- continue ;
450- if (!old )
451- continue ;
452- if (remount )
396+ if (fc -> purpose == FS_CONTEXT_FOR_RECONFIGURE ) {
453397 pr_err ("ufstype can't be changed during remount\n" );
454- else
398+ return - EINVAL ;
399+ }
400+ if (!ctx -> flavour ) {
455401 pr_err ("conflicting ufstype options\n" );
456- return 0 ;
402+ return - EINVAL ;
403+ }
404+ ctx -> flavour = result .uint_32 ;
405+ break ;
406+ case Opt_onerror :
407+ ctx -> on_err = result .uint_32 ;
408+ break ;
409+ default :
410+ return - EINVAL ;
457411 }
458- return 1 ;
412+ return 0 ;
459413}
460414
461415/*
@@ -760,8 +714,10 @@ static u64 ufs_max_bytes(struct super_block *sb)
760714 return res << uspi -> s_bshift ;
761715}
762716
763- static int ufs_fill_super (struct super_block * sb , void * data , int silent )
717+ static int ufs_fill_super (struct super_block * sb , struct fs_context * fc )
764718{
719+ struct ufs_fs_context * ctx = fc -> fs_private ;
720+ int silent = fc -> sb_flags & SB_SILENT ;
765721 struct ufs_sb_info * sbi ;
766722 struct ufs_sb_private_info * uspi ;
767723 struct ufs_super_block_first * usb1 ;
@@ -799,16 +755,10 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
799755 mutex_init (& sbi -> s_lock );
800756 spin_lock_init (& sbi -> work_lock );
801757 INIT_DELAYED_WORK (& sbi -> sync_work , delayed_sync_fs );
802- /*
803- * Set default mount options
804- * Parse mount options
805- */
806- sbi -> s_flavour = 0 ;
807- sbi -> s_on_err = UFS_MOUNT_ONERROR_LOCK ;
808- if (!ufs_parse_options (data , & sbi -> s_flavour , & sbi -> s_on_err , false)) {
809- pr_err ("wrong mount options\n" );
810- goto failed ;
811- }
758+
759+ sbi -> s_flavour = ctx -> flavour ;
760+ sbi -> s_on_err = ctx -> on_err ;
761+
812762 if (!sbi -> s_flavour ) {
813763 if (!silent )
814764 pr_err ("You didn't specify the type of your ufs filesystem\n\n"
@@ -1286,13 +1236,15 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
12861236 return - ENOMEM ;
12871237}
12881238
1289- static int ufs_remount (struct super_block * sb , int * mount_flags , char * data )
1239+ static int ufs_reconfigure (struct fs_context * fc )
12901240{
12911241 struct ufs_sb_private_info * uspi ;
12921242 struct ufs_super_block_first * usb1 ;
12931243 struct ufs_super_block_third * usb3 ;
1294- unsigned on_err , ufstype ;
1295- unsigned flags ;
1244+ struct ufs_fs_context * ctx = fc -> fs_private ;
1245+ struct super_block * sb = fc -> root -> d_sb ;
1246+ unsigned int ufstype ;
1247+ unsigned int flags ;
12961248
12971249 sync_filesystem (sb );
12981250 mutex_lock (& UFS_SB (sb )-> s_lock );
@@ -1301,27 +1253,18 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
13011253 usb1 = ubh_get_usb_first (uspi );
13021254 usb3 = ubh_get_usb_third (uspi );
13031255
1304- /*
1305- * Allow the "check" option to be passed as a remount option.
1306- * It is not possible to change ufstype option during remount
1307- */
13081256 ufstype = UFS_SB (sb )-> s_flavour ;
1309- on_err = UFS_MOUNT_ONERROR_LOCK ;
1310- if (!ufs_parse_options (data , & ufstype , & on_err , true)) {
1311- mutex_unlock (& UFS_SB (sb )-> s_lock );
1312- return - EINVAL ;
1313- }
13141257
1315- if ((bool )(* mount_flags & SB_RDONLY ) == sb_rdonly (sb )) {
1316- UFS_SB (sb )-> s_on_err = on_err ;
1258+ if ((bool )(fc -> sb_flags & SB_RDONLY ) == sb_rdonly (sb )) {
1259+ UFS_SB (sb )-> s_on_err = ctx -> on_err ;
13171260 mutex_unlock (& UFS_SB (sb )-> s_lock );
13181261 return 0 ;
13191262 }
13201263
13211264 /*
13221265 * fs was mouted as rw, remounting ro
13231266 */
1324- if (* mount_flags & SB_RDONLY ) {
1267+ if (fc -> sb_flags & SB_RDONLY ) {
13251268 ufs_put_super_internal (sb );
13261269 usb1 -> fs_time = ufs_get_seconds (sb );
13271270 if ((flags & UFS_ST_MASK ) == UFS_ST_SUN
@@ -1357,7 +1300,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
13571300 sb -> s_flags &= ~SB_RDONLY ;
13581301#endif
13591302 }
1360- UFS_SB (sb )-> s_on_err = on_err ;
1303+ UFS_SB (sb )-> s_on_err = ctx -> on_err ;
13611304 mutex_unlock (& UFS_SB (sb )-> s_lock );
13621305 return 0 ;
13631306}
@@ -1366,18 +1309,18 @@ static int ufs_show_options(struct seq_file *seq, struct dentry *root)
13661309{
13671310 struct ufs_sb_info * sbi = UFS_SB (root -> d_sb );
13681311 unsigned mval = sbi -> s_flavour ;
1369- const struct match_token * tp = tokens ;
1312+ const struct constant_table * tp ;
13701313
1371- while (tp -> token != Opt_onerror_panic && tp -> token != mval )
1314+ tp = ufs_param_ufstype ;
1315+ while (tp -> value && tp -> value != mval )
13721316 ++ tp ;
1373- BUG_ON (tp -> token == Opt_onerror_panic );
1374- seq_printf (seq , ",%s" , tp -> pattern );
1317+ seq_printf (seq , ",ufstype=%s" , tp -> name );
13751318
1319+ tp = ufs_param_onerror ;
13761320 mval = sbi -> s_on_err ;
1377- while (tp -> token != Opt_err && tp -> token != mval )
1321+ while (tp -> value && tp -> value != mval )
13781322 ++ tp ;
1379- BUG_ON (tp -> token == Opt_err );
1380- seq_printf (seq , ",%s" , tp -> pattern );
1323+ seq_printf (seq , ",onerror=%s" , tp -> name );
13811324
13821325 return 0 ;
13831326}
@@ -1471,21 +1414,57 @@ static const struct super_operations ufs_super_ops = {
14711414 .put_super = ufs_put_super ,
14721415 .sync_fs = ufs_sync_fs ,
14731416 .statfs = ufs_statfs ,
1474- .remount_fs = ufs_remount ,
14751417 .show_options = ufs_show_options ,
14761418};
14771419
1478- static struct dentry * ufs_mount (struct file_system_type * fs_type ,
1479- int flags , const char * dev_name , void * data )
1420+ static int ufs_get_tree (struct fs_context * fc )
14801421{
1481- return mount_bdev (fs_type , flags , dev_name , data , ufs_fill_super );
1422+ return get_tree_bdev (fc , ufs_fill_super );
1423+ }
1424+
1425+ static void ufs_free_fc (struct fs_context * fc )
1426+ {
1427+ kfree (fc -> fs_private );
1428+ }
1429+
1430+ static const struct fs_context_operations ufs_context_ops = {
1431+ .parse_param = ufs_parse_param ,
1432+ .get_tree = ufs_get_tree ,
1433+ .reconfigure = ufs_reconfigure ,
1434+ .free = ufs_free_fc ,
1435+ };
1436+
1437+ static int ufs_init_fs_context (struct fs_context * fc )
1438+ {
1439+ struct ufs_fs_context * ctx ;
1440+
1441+ ctx = kzalloc (sizeof (* ctx ), GFP_KERNEL );
1442+ if (!ctx )
1443+ return - ENOMEM ;
1444+
1445+ if (fc -> purpose == FS_CONTEXT_FOR_RECONFIGURE ) {
1446+ struct super_block * sb = fc -> root -> d_sb ;
1447+ struct ufs_sb_info * sbi = UFS_SB (sb );
1448+
1449+ ctx -> flavour = sbi -> s_flavour ;
1450+ ctx -> on_err = sbi -> s_on_err ;
1451+ } else {
1452+ ctx -> flavour = 0 ;
1453+ ctx -> on_err = UFS_MOUNT_ONERROR_LOCK ;
1454+ }
1455+
1456+ fc -> fs_private = ctx ;
1457+ fc -> ops = & ufs_context_ops ;
1458+
1459+ return 0 ;
14821460}
14831461
14841462static struct file_system_type ufs_fs_type = {
14851463 .owner = THIS_MODULE ,
14861464 .name = "ufs" ,
1487- .mount = ufs_mount ,
14881465 .kill_sb = kill_block_super ,
1466+ .init_fs_context = ufs_init_fs_context ,
1467+ .parameters = ufs_param_spec ,
14891468 .fs_flags = FS_REQUIRES_DEV ,
14901469};
14911470MODULE_ALIAS_FS ("ufs" );
0 commit comments