@@ -244,7 +244,6 @@ static void ovl_free_fs(struct ovl_fs *ofs)
244244 kfree (ofs -> config .lowerdir );
245245 kfree (ofs -> config .upperdir );
246246 kfree (ofs -> config .workdir );
247- kfree (ofs -> config .redirect_mode );
248247 if (ofs -> creator_cred )
249248 put_cred (ofs -> creator_cred );
250249 kfree (ofs );
@@ -330,9 +329,24 @@ static bool ovl_force_readonly(struct ovl_fs *ofs)
330329 return (!ovl_upper_mnt (ofs ) || !ofs -> workdir );
331330}
332331
333- static const char * ovl_redirect_mode_def (void )
332+ static const struct constant_table ovl_parameter_redirect_dir [] = {
333+ { "off" , OVL_REDIRECT_OFF },
334+ { "follow" , OVL_REDIRECT_FOLLOW },
335+ { "nofollow" , OVL_REDIRECT_NOFOLLOW },
336+ { "on" , OVL_REDIRECT_ON },
337+ {}
338+ };
339+
340+ static const char * ovl_redirect_mode (struct ovl_config * config )
334341{
335- return ovl_redirect_dir_def ? "on" : "off" ;
342+ return ovl_parameter_redirect_dir [config -> redirect_mode ].name ;
343+ }
344+
345+ static int ovl_redirect_mode_def (void )
346+ {
347+ return ovl_redirect_dir_def ? OVL_REDIRECT_ON :
348+ ovl_redirect_always_follow ? OVL_REDIRECT_FOLLOW :
349+ OVL_REDIRECT_NOFOLLOW ;
336350}
337351
338352static const struct constant_table ovl_parameter_xino [] = {
@@ -372,8 +386,9 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
372386 }
373387 if (ofs -> config .default_permissions )
374388 seq_puts (m , ",default_permissions" );
375- if (strcmp (ofs -> config .redirect_mode , ovl_redirect_mode_def ()) != 0 )
376- seq_printf (m , ",redirect_dir=%s" , ofs -> config .redirect_mode );
389+ if (ofs -> config .redirect_mode != ovl_redirect_mode_def ())
390+ seq_printf (m , ",redirect_dir=%s" ,
391+ ovl_redirect_mode (& ofs -> config ));
377392 if (ofs -> config .index != ovl_index_def )
378393 seq_printf (m , ",index=%s" , ofs -> config .index ? "on" : "off" );
379394 if (!ofs -> config .uuid )
@@ -431,7 +446,10 @@ enum {
431446 OPT_UPPERDIR ,
432447 OPT_WORKDIR ,
433448 OPT_DEFAULT_PERMISSIONS ,
434- OPT_REDIRECT_DIR ,
449+ OPT_REDIRECT_DIR_ON ,
450+ OPT_REDIRECT_DIR_OFF ,
451+ OPT_REDIRECT_DIR_FOLLOW ,
452+ OPT_REDIRECT_DIR_NOFOLLOW ,
435453 OPT_INDEX_ON ,
436454 OPT_INDEX_OFF ,
437455 OPT_UUID_ON ,
@@ -453,7 +471,10 @@ static const match_table_t ovl_tokens = {
453471 {OPT_UPPERDIR , "upperdir=%s" },
454472 {OPT_WORKDIR , "workdir=%s" },
455473 {OPT_DEFAULT_PERMISSIONS , "default_permissions" },
456- {OPT_REDIRECT_DIR , "redirect_dir=%s" },
474+ {OPT_REDIRECT_DIR_ON , "redirect_dir=on" },
475+ {OPT_REDIRECT_DIR_OFF , "redirect_dir=off" },
476+ {OPT_REDIRECT_DIR_FOLLOW , "redirect_dir=follow" },
477+ {OPT_REDIRECT_DIR_NOFOLLOW , "redirect_dir=nofollow" },
457478 {OPT_INDEX_ON , "index=on" },
458479 {OPT_INDEX_OFF , "index=off" },
459480 {OPT_USERXATTR , "userxattr" },
@@ -493,40 +514,12 @@ static char *ovl_next_opt(char **s)
493514 return sbegin ;
494515}
495516
496- static int ovl_parse_redirect_mode (struct ovl_config * config , const char * mode )
497- {
498- if (strcmp (mode , "on" ) == 0 ) {
499- config -> redirect_dir = true;
500- /*
501- * Does not make sense to have redirect creation without
502- * redirect following.
503- */
504- config -> redirect_follow = true;
505- } else if (strcmp (mode , "follow" ) == 0 ) {
506- config -> redirect_follow = true;
507- } else if (strcmp (mode , "off" ) == 0 ) {
508- if (ovl_redirect_always_follow )
509- config -> redirect_follow = true;
510- } else if (strcmp (mode , "nofollow" ) != 0 ) {
511- pr_err ("bad mount option \"redirect_dir=%s\"\n" ,
512- mode );
513- return - EINVAL ;
514- }
515-
516- return 0 ;
517- }
518-
519517static int ovl_parse_opt (char * opt , struct ovl_config * config )
520518{
521519 char * p ;
522- int err ;
523520 bool metacopy_opt = false, redirect_opt = false;
524521 bool nfs_export_opt = false, index_opt = false;
525522
526- config -> redirect_mode = kstrdup (ovl_redirect_mode_def (), GFP_KERNEL );
527- if (!config -> redirect_mode )
528- return - ENOMEM ;
529-
530523 while ((p = ovl_next_opt (& opt )) != NULL ) {
531524 int token ;
532525 substring_t args [MAX_OPT_ARGS ];
@@ -561,11 +554,25 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
561554 config -> default_permissions = true;
562555 break ;
563556
564- case OPT_REDIRECT_DIR :
565- kfree (config -> redirect_mode );
566- config -> redirect_mode = match_strdup (& args [0 ]);
567- if (!config -> redirect_mode )
568- return - ENOMEM ;
557+ case OPT_REDIRECT_DIR_ON :
558+ config -> redirect_mode = OVL_REDIRECT_ON ;
559+ redirect_opt = true;
560+ break ;
561+
562+ case OPT_REDIRECT_DIR_OFF :
563+ config -> redirect_mode = ovl_redirect_always_follow ?
564+ OVL_REDIRECT_FOLLOW :
565+ OVL_REDIRECT_NOFOLLOW ;
566+ redirect_opt = true;
567+ break ;
568+
569+ case OPT_REDIRECT_DIR_FOLLOW :
570+ config -> redirect_mode = OVL_REDIRECT_FOLLOW ;
571+ redirect_opt = true;
572+ break ;
573+
574+ case OPT_REDIRECT_DIR_NOFOLLOW :
575+ config -> redirect_mode = OVL_REDIRECT_NOFOLLOW ;
569576 redirect_opt = true;
570577 break ;
571578
@@ -654,22 +661,18 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
654661 config -> ovl_volatile = false;
655662 }
656663
657- err = ovl_parse_redirect_mode (config , config -> redirect_mode );
658- if (err )
659- return err ;
660-
661664 /*
662665 * This is to make the logic below simpler. It doesn't make any other
663- * difference, since config-> redirect_dir is only used for upper.
666+ * difference, since redirect_dir=on is only used for upper.
664667 */
665- if (!config -> upperdir && config -> redirect_follow )
666- config -> redirect_dir = true ;
668+ if (!config -> upperdir && config -> redirect_mode == OVL_REDIRECT_FOLLOW )
669+ config -> redirect_mode = OVL_REDIRECT_ON ;
667670
668671 /* Resolve metacopy -> redirect_dir dependency */
669- if (config -> metacopy && ! config -> redirect_dir ) {
672+ if (config -> metacopy && config -> redirect_mode != OVL_REDIRECT_ON ) {
670673 if (metacopy_opt && redirect_opt ) {
671674 pr_err ("conflicting options: metacopy=on,redirect_dir=%s\n" ,
672- config -> redirect_mode );
675+ ovl_redirect_mode ( config ) );
673676 return - EINVAL ;
674677 }
675678 if (redirect_opt ) {
@@ -678,17 +681,18 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
678681 * in this conflict.
679682 */
680683 pr_info ("disabling metacopy due to redirect_dir=%s\n" ,
681- config -> redirect_mode );
684+ ovl_redirect_mode ( config ) );
682685 config -> metacopy = false;
683686 } else {
684687 /* Automatically enable redirect otherwise. */
685- config -> redirect_follow = config -> redirect_dir = true ;
688+ config -> redirect_mode = OVL_REDIRECT_ON ;
686689 }
687690 }
688691
689692 /* Resolve nfs_export -> index dependency */
690693 if (config -> nfs_export && !config -> index ) {
691- if (!config -> upperdir && config -> redirect_follow ) {
694+ if (!config -> upperdir &&
695+ config -> redirect_mode != OVL_REDIRECT_NOFOLLOW ) {
692696 pr_info ("NFS export requires \"redirect_dir=nofollow\" on non-upper mount, falling back to nfs_export=off.\n" );
693697 config -> nfs_export = false;
694698 } else if (nfs_export_opt && index_opt ) {
@@ -733,9 +737,10 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
733737
734738 /* Resolve userxattr -> !redirect && !metacopy dependency */
735739 if (config -> userxattr ) {
736- if (config -> redirect_follow && redirect_opt ) {
740+ if (redirect_opt &&
741+ config -> redirect_mode != OVL_REDIRECT_NOFOLLOW ) {
737742 pr_err ("conflicting options: userxattr,redirect_dir=%s\n" ,
738- config -> redirect_mode );
743+ ovl_redirect_mode ( config ) );
739744 return - EINVAL ;
740745 }
741746 if (config -> metacopy && metacopy_opt ) {
@@ -748,7 +753,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
748753 * options must be explicitly enabled if used together with
749754 * userxattr.
750755 */
751- config -> redirect_dir = config -> redirect_follow = false ;
756+ config -> redirect_mode = OVL_REDIRECT_NOFOLLOW ;
752757 config -> metacopy = false;
753758 }
754759
@@ -1332,10 +1337,17 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
13321337 if (err ) {
13331338 pr_warn ("failed to set xattr on upper\n" );
13341339 ofs -> noxattr = true;
1335- if (ofs -> config .index || ofs -> config .metacopy ) {
1336- ofs -> config .index = false;
1340+ if (ovl_redirect_follow (ofs )) {
1341+ ofs -> config .redirect_mode = OVL_REDIRECT_NOFOLLOW ;
1342+ pr_warn ("...falling back to redirect_dir=nofollow.\n" );
1343+ }
1344+ if (ofs -> config .metacopy ) {
13371345 ofs -> config .metacopy = false;
1338- pr_warn ("...falling back to index=off,metacopy=off.\n" );
1346+ pr_warn ("...falling back to metacopy=off.\n" );
1347+ }
1348+ if (ofs -> config .index ) {
1349+ ofs -> config .index = false;
1350+ pr_warn ("...falling back to index=off.\n" );
13391351 }
13401352 /*
13411353 * xattr support is required for persistent st_ino.
@@ -1963,6 +1975,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
19631975 if (!cred )
19641976 goto out_err ;
19651977
1978+ ofs -> config .redirect_mode = ovl_redirect_mode_def ();
19661979 ofs -> config .index = ovl_index_def ;
19671980 ofs -> config .uuid = true;
19681981 ofs -> config .nfs_export = ovl_nfs_export_def ;
0 commit comments