]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - fs/xfs/xfs_super.c
Merge branch 'xfs-misc-fixes-4.6-3' into for-next
[mirror_ubuntu-bionic-kernel.git] / fs / xfs / xfs_super.c
index 3bd2027a7ea65cb1c1a7e94004e71578ead6a907..d760934109b5d628891ea3e91fa1a9e3f68ec36b 100644 (file)
@@ -66,83 +66,85 @@ static struct kset *xfs_kset;               /* top-level xfs sysfs dir */
 static struct xfs_kobj xfs_dbg_kobj;   /* global debug sysfs attrs */
 #endif
 
-#define MNTOPT_LOGBUFS "logbufs"       /* number of XFS log buffers */
-#define MNTOPT_LOGBSIZE        "logbsize"      /* size of XFS log buffers */
-#define MNTOPT_LOGDEV  "logdev"        /* log device */
-#define MNTOPT_RTDEV   "rtdev"         /* realtime I/O device */
-#define MNTOPT_BIOSIZE "biosize"       /* log2 of preferred buffered io size */
-#define MNTOPT_WSYNC   "wsync"         /* safe-mode nfs compatible mount */
-#define MNTOPT_NOALIGN "noalign"       /* turn off stripe alignment */
-#define MNTOPT_SWALLOC "swalloc"       /* turn on stripe width allocation */
-#define MNTOPT_SUNIT   "sunit"         /* data volume stripe unit */
-#define MNTOPT_SWIDTH  "swidth"        /* data volume stripe width */
-#define MNTOPT_NOUUID  "nouuid"        /* ignore filesystem UUID */
-#define MNTOPT_MTPT    "mtpt"          /* filesystem mount point */
-#define MNTOPT_GRPID   "grpid"         /* group-ID from parent directory */
-#define MNTOPT_NOGRPID "nogrpid"       /* group-ID from current process */
-#define MNTOPT_BSDGROUPS    "bsdgroups"    /* group-ID from parent directory */
-#define MNTOPT_SYSVGROUPS   "sysvgroups"   /* group-ID from current process */
-#define MNTOPT_ALLOCSIZE    "allocsize"    /* preferred allocation size */
-#define MNTOPT_NORECOVERY   "norecovery"   /* don't run XFS recovery */
-#define MNTOPT_BARRIER "barrier"       /* use writer barriers for log write and
-                                        * unwritten extent conversion */
-#define MNTOPT_NOBARRIER "nobarrier"   /* .. disable */
-#define MNTOPT_64BITINODE   "inode64"  /* inodes can be allocated anywhere */
-#define MNTOPT_32BITINODE   "inode32"  /* inode allocation limited to
-                                        * XFS_MAXINUMBER_32 */
-#define MNTOPT_IKEEP   "ikeep"         /* do not free empty inode clusters */
-#define MNTOPT_NOIKEEP "noikeep"       /* free empty inode clusters */
-#define MNTOPT_LARGEIO    "largeio"    /* report large I/O sizes in stat() */
-#define MNTOPT_NOLARGEIO   "nolargeio" /* do not report large I/O sizes
-                                        * in stat(). */
-#define MNTOPT_ATTR2   "attr2"         /* do use attr2 attribute format */
-#define MNTOPT_NOATTR2 "noattr2"       /* do not use attr2 attribute format */
-#define MNTOPT_FILESTREAM  "filestreams" /* use filestreams allocator */
-#define MNTOPT_QUOTA   "quota"         /* disk quotas (user) */
-#define MNTOPT_NOQUOTA "noquota"       /* no quotas */
-#define MNTOPT_USRQUOTA        "usrquota"      /* user quota enabled */
-#define MNTOPT_GRPQUOTA        "grpquota"      /* group quota enabled */
-#define MNTOPT_PRJQUOTA        "prjquota"      /* project quota enabled */
-#define MNTOPT_UQUOTA  "uquota"        /* user quota (IRIX variant) */
-#define MNTOPT_GQUOTA  "gquota"        /* group quota (IRIX variant) */
-#define MNTOPT_PQUOTA  "pquota"        /* project quota (IRIX variant) */
-#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
-#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
-#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
-#define MNTOPT_QUOTANOENF  "qnoenforce"        /* same as uqnoenforce */
-#define MNTOPT_DISCARD    "discard"    /* Discard unused blocks */
-#define MNTOPT_NODISCARD   "nodiscard" /* Do not discard unused blocks */
-
-#define MNTOPT_DAX     "dax"           /* Enable direct access to bdev pages */
-
 /*
  * Table driven mount option parser.
- *
- * Currently only used for remount, but it will be used for mount
- * in the future, too.
  */
 enum {
-       Opt_barrier,
-       Opt_nobarrier,
-       Opt_inode64,
-       Opt_inode32,
-       Opt_err
+       Opt_logbufs, Opt_logbsize, Opt_logdev, Opt_rtdev, Opt_biosize,
+       Opt_wsync, Opt_noalign, Opt_swalloc, Opt_sunit, Opt_swidth, Opt_nouuid,
+       Opt_mtpt, Opt_grpid, Opt_nogrpid, Opt_bsdgroups, Opt_sysvgroups,
+       Opt_allocsize, Opt_norecovery, Opt_barrier, Opt_nobarrier,
+       Opt_inode64, Opt_inode32, Opt_ikeep, Opt_noikeep,
+       Opt_largeio, Opt_nolargeio, Opt_attr2, Opt_noattr2, 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,
 };
 
 static const match_table_t tokens = {
-       {Opt_barrier, "barrier"},
-       {Opt_nobarrier, "nobarrier"},
-       {Opt_inode64, "inode64"},
-       {Opt_inode32, "inode32"},
-       {Opt_err, NULL}
+       {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_biosize,   "biosize=%u"},  /* log2 of preferred buffered io size */
+       {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_mtpt,      "mtpt"},        /* filesystem mount point */
+       {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_barrier,   "barrier"},     /* use writer barriers for log write and
+                                        * unwritten extent conversion */
+       {Opt_nobarrier, "nobarrier"},   /* .. disable */
+       {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 int
-suffix_kstrtoint(char *s, unsigned int base, int *res)
+suffix_kstrtoint(const substring_t *s, unsigned int base, int *res)
 {
        int     last, shift_left_factor = 0, _res;
-       char    *value = s;
+       char    *value;
+       int     ret = 0;
+
+       value = match_strdup(s);
+       if (!value)
+               return -ENOMEM;
 
        last = strlen(value) - 1;
        if (value[last] == 'K' || value[last] == 'k') {
@@ -158,10 +160,11 @@ suffix_kstrtoint(char *s, unsigned int base, int *res)
                value[last] = '\0';
        }
 
-       if (kstrtoint(s, base, &_res))
-               return -EINVAL;
+       if (kstrtoint(value, base, &_res))
+               ret = -EINVAL;
+       kfree(value);
        *res = _res << shift_left_factor;
-       return 0;
+       return ret;
 }
 
 /*
@@ -170,14 +173,19 @@ suffix_kstrtoint(char *s, unsigned int base, int *res)
  *
  * 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)
 {
-       struct super_block      *sb = mp->m_super;
-       char                    *this_char, *value;
+       const struct super_block *sb = mp->m_super;
+       char                    *p;
+       substring_t             args[MAX_OPT_ARGS];
        int                     dsunit = 0;
        int                     dswidth = 0;
        int                     iosize = 0;
@@ -218,152 +226,152 @@ xfs_parseargs(
        if (!options)
                goto done;
 
-       while ((this_char = strsep(&options, ",")) != NULL) {
-               if (!*this_char)
+       while ((p = strsep(&options, ",")) != NULL) {
+               int             token;
+
+               if (!*p)
                        continue;
-               if ((value = strchr(this_char, '=')) != NULL)
-                       *value++ = 0;
 
-               if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
-                       if (!value || !*value) {
-                               xfs_warn(mp, "%s option requires an argument",
-                                       this_char);
-                               return -EINVAL;
-                       }
-                       if (kstrtoint(value, 10, &mp->m_logbufs))
-                               return -EINVAL;
-               } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
-                       if (!value || !*value) {
-                               xfs_warn(mp, "%s option requires an argument",
-                                       this_char);
-                               return -EINVAL;
-                       }
-                       if (suffix_kstrtoint(value, 10, &mp->m_logbsize))
+               token = match_token(p, tokens, args);
+               switch (token) {
+               case Opt_logbufs:
+                       if (match_int(args, &mp->m_logbufs))
                                return -EINVAL;
-               } else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
-                       if (!value || !*value) {
-                               xfs_warn(mp, "%s option requires an argument",
-                                       this_char);
+                       break;
+               case Opt_logbsize:
+                       if (suffix_kstrtoint(args, 10, &mp->m_logbsize))
                                return -EINVAL;
-                       }
-                       mp->m_logname = kstrndup(value, MAXNAMELEN, GFP_KERNEL);
+                       break;
+               case Opt_logdev:
+                       mp->m_logname = match_strdup(args);
                        if (!mp->m_logname)
                                return -ENOMEM;
-               } else if (!strcmp(this_char, MNTOPT_MTPT)) {
-                       xfs_warn(mp, "%s option not allowed on this system",
-                               this_char);
+                       break;
+               case Opt_mtpt:
+                       xfs_warn(mp, "%s option not allowed on this system", p);
                        return -EINVAL;
-               } else if (!strcmp(this_char, MNTOPT_RTDEV)) {
-                       if (!value || !*value) {
-                               xfs_warn(mp, "%s option requires an argument",
-                                       this_char);
-                               return -EINVAL;
-                       }
-                       mp->m_rtname = kstrndup(value, MAXNAMELEN, GFP_KERNEL);
+               case Opt_rtdev:
+                       mp->m_rtname = match_strdup(args);
                        if (!mp->m_rtname)
                                return -ENOMEM;
-               } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE) ||
-                          !strcmp(this_char, MNTOPT_BIOSIZE)) {
-                       if (!value || !*value) {
-                               xfs_warn(mp, "%s option requires an argument",
-                                       this_char);
-                               return -EINVAL;
-                       }
-                       if (suffix_kstrtoint(value, 10, &iosize))
+                       break;
+               case Opt_allocsize:
+               case Opt_biosize:
+                       if (suffix_kstrtoint(args, 10, &iosize))
                                return -EINVAL;
                        iosizelog = ffs(iosize) - 1;
-               } else if (!strcmp(this_char, MNTOPT_GRPID) ||
-                          !strcmp(this_char, MNTOPT_BSDGROUPS)) {
+                       break;
+               case Opt_grpid:
+               case Opt_bsdgroups:
                        mp->m_flags |= XFS_MOUNT_GRPID;
-               } else if (!strcmp(this_char, MNTOPT_NOGRPID) ||
-                          !strcmp(this_char, MNTOPT_SYSVGROUPS)) {
+                       break;
+               case Opt_nogrpid:
+               case Opt_sysvgroups:
                        mp->m_flags &= ~XFS_MOUNT_GRPID;
-               } else if (!strcmp(this_char, MNTOPT_WSYNC)) {
+                       break;
+               case Opt_wsync:
                        mp->m_flags |= XFS_MOUNT_WSYNC;
-               } else if (!strcmp(this_char, MNTOPT_NORECOVERY)) {
+                       break;
+               case Opt_norecovery:
                        mp->m_flags |= XFS_MOUNT_NORECOVERY;
-               } else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
+                       break;
+               case Opt_noalign:
                        mp->m_flags |= XFS_MOUNT_NOALIGN;
-               } else if (!strcmp(this_char, MNTOPT_SWALLOC)) {
+                       break;
+               case Opt_swalloc:
                        mp->m_flags |= XFS_MOUNT_SWALLOC;
-               } else if (!strcmp(this_char, MNTOPT_SUNIT)) {
-                       if (!value || !*value) {
-                               xfs_warn(mp, "%s option requires an argument",
-                                       this_char);
-                               return -EINVAL;
-                       }
-                       if (kstrtoint(value, 10, &dsunit))
-                               return -EINVAL;
-               } else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
-                       if (!value || !*value) {
-                               xfs_warn(mp, "%s option requires an argument",
-                                       this_char);
+                       break;
+               case Opt_sunit:
+                       if (match_int(args, &dsunit))
                                return -EINVAL;
-                       }
-                       if (kstrtoint(value, 10, &dswidth))
+                       break;
+               case Opt_swidth:
+                       if (match_int(args, &dswidth))
                                return -EINVAL;
-               } else if (!strcmp(this_char, MNTOPT_32BITINODE)) {
+                       break;
+               case Opt_inode32:
                        mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
-               } else if (!strcmp(this_char, MNTOPT_64BITINODE)) {
+                       break;
+               case Opt_inode64:
                        mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS;
-               } else if (!strcmp(this_char, MNTOPT_NOUUID)) {
+                       break;
+               case Opt_nouuid:
                        mp->m_flags |= XFS_MOUNT_NOUUID;
-               } else if (!strcmp(this_char, MNTOPT_BARRIER)) {
+                       break;
+               case Opt_barrier:
                        mp->m_flags |= XFS_MOUNT_BARRIER;
-               } else if (!strcmp(this_char, MNTOPT_NOBARRIER)) {
+                       break;
+               case Opt_nobarrier:
                        mp->m_flags &= ~XFS_MOUNT_BARRIER;
-               } else if (!strcmp(this_char, MNTOPT_IKEEP)) {
+                       break;
+               case Opt_ikeep:
                        mp->m_flags |= XFS_MOUNT_IKEEP;
-               } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
+                       break;
+               case Opt_noikeep:
                        mp->m_flags &= ~XFS_MOUNT_IKEEP;
-               } else if (!strcmp(this_char, MNTOPT_LARGEIO)) {
+                       break;
+               case Opt_largeio:
                        mp->m_flags &= ~XFS_MOUNT_COMPAT_IOSIZE;
-               } else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) {
+                       break;
+               case Opt_nolargeio:
                        mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;
-               } else if (!strcmp(this_char, MNTOPT_ATTR2)) {
+                       break;
+               case Opt_attr2:
                        mp->m_flags |= XFS_MOUNT_ATTR2;
-               } else if (!strcmp(this_char, MNTOPT_NOATTR2)) {
+                       break;
+               case Opt_noattr2:
                        mp->m_flags &= ~XFS_MOUNT_ATTR2;
                        mp->m_flags |= XFS_MOUNT_NOATTR2;
-               } else if (!strcmp(this_char, MNTOPT_FILESTREAM)) {
+                       break;
+               case Opt_filestreams:
                        mp->m_flags |= XFS_MOUNT_FILESTREAMS;
-               } else if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
+                       break;
+               case Opt_noquota:
                        mp->m_qflags &= ~XFS_ALL_QUOTA_ACCT;
                        mp->m_qflags &= ~XFS_ALL_QUOTA_ENFD;
                        mp->m_qflags &= ~XFS_ALL_QUOTA_ACTIVE;
-               } else if (!strcmp(this_char, MNTOPT_QUOTA) ||
-                          !strcmp(this_char, MNTOPT_UQUOTA) ||
-                          !strcmp(this_char, MNTOPT_USRQUOTA)) {
+                       break;
+               case Opt_quota:
+               case Opt_uquota:
+               case Opt_usrquota:
                        mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE |
                                         XFS_UQUOTA_ENFD);
-               } else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
-                          !strcmp(this_char, MNTOPT_UQUOTANOENF)) {
+                       break;
+               case Opt_qnoenforce:
+               case Opt_uqnoenforce:
                        mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
                        mp->m_qflags &= ~XFS_UQUOTA_ENFD;
-               } else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
-                          !strcmp(this_char, MNTOPT_PRJQUOTA)) {
+                       break;
+               case Opt_pquota:
+               case Opt_prjquota:
                        mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE |
                                         XFS_PQUOTA_ENFD);
-               } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
+                       break;
+               case Opt_pqnoenforce:
                        mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
                        mp->m_qflags &= ~XFS_PQUOTA_ENFD;
-               } else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
-                          !strcmp(this_char, MNTOPT_GRPQUOTA)) {
+               case Opt_gquota:
+               case Opt_grpquota:
                        mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE |
                                         XFS_GQUOTA_ENFD);
-               } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
+                       break;
+               case Opt_gqnoenforce:
                        mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
                        mp->m_qflags &= ~XFS_GQUOTA_ENFD;
-               } else if (!strcmp(this_char, MNTOPT_DISCARD)) {
+                       break;
+               case Opt_discard:
                        mp->m_flags |= XFS_MOUNT_DISCARD;
-               } else if (!strcmp(this_char, MNTOPT_NODISCARD)) {
+                       break;
+               case Opt_nodiscard:
                        mp->m_flags &= ~XFS_MOUNT_DISCARD;
+                       break;
 #ifdef CONFIG_FS_DAX
-               } else if (!strcmp(this_char, MNTOPT_DAX)) {
+               case Opt_dax:
                        mp->m_flags |= XFS_MOUNT_DAX;
+                       break;
 #endif
-               } else {
-                       xfs_warn(mp, "unknown mount option [%s].", this_char);
+               default:
+                       xfs_warn(mp, "unknown mount option [%s].", p);
                        return -EINVAL;
                }
        }
@@ -462,25 +470,25 @@ xfs_showargs(
 {
        static struct proc_xfs_info xfs_info_set[] = {
                /* the few simple ones we can get from the mount struct */
-               { XFS_MOUNT_IKEEP,              "," MNTOPT_IKEEP },
-               { XFS_MOUNT_WSYNC,              "," MNTOPT_WSYNC },
-               { XFS_MOUNT_NOALIGN,            "," MNTOPT_NOALIGN },
-               { XFS_MOUNT_SWALLOC,            "," MNTOPT_SWALLOC },
-               { XFS_MOUNT_NOUUID,             "," MNTOPT_NOUUID },
-               { XFS_MOUNT_NORECOVERY,         "," MNTOPT_NORECOVERY },
-               { XFS_MOUNT_ATTR2,              "," MNTOPT_ATTR2 },
-               { XFS_MOUNT_FILESTREAMS,        "," MNTOPT_FILESTREAM },
-               { XFS_MOUNT_GRPID,              "," MNTOPT_GRPID },
-               { XFS_MOUNT_DISCARD,            "," MNTOPT_DISCARD },
-               { XFS_MOUNT_SMALL_INUMS,        "," MNTOPT_32BITINODE },
-               { XFS_MOUNT_DAX,                "," MNTOPT_DAX },
+               { XFS_MOUNT_IKEEP,              ",ikeep" },
+               { XFS_MOUNT_WSYNC,              ",wsync" },
+               { XFS_MOUNT_NOALIGN,            ",noalign" },
+               { XFS_MOUNT_SWALLOC,            ",swalloc" },
+               { XFS_MOUNT_NOUUID,             ",nouuid" },
+               { XFS_MOUNT_NORECOVERY,         ",norecovery" },
+               { XFS_MOUNT_ATTR2,              ",attr2" },
+               { XFS_MOUNT_FILESTREAMS,        ",filestreams" },
+               { XFS_MOUNT_GRPID,              ",grpid" },
+               { XFS_MOUNT_DISCARD,            ",discard" },
+               { XFS_MOUNT_SMALL_INUMS,        ",inode32" },
+               { XFS_MOUNT_DAX,                ",dax" },
                { 0, NULL }
        };
        static struct proc_xfs_info xfs_info_unset[] = {
                /* the few simple ones we can get from the mount struct */
-               { XFS_MOUNT_COMPAT_IOSIZE,      "," MNTOPT_LARGEIO },
-               { XFS_MOUNT_BARRIER,            "," MNTOPT_NOBARRIER },
-               { XFS_MOUNT_SMALL_INUMS,        "," MNTOPT_64BITINODE },
+               { XFS_MOUNT_COMPAT_IOSIZE,      ",largeio" },
+               { XFS_MOUNT_BARRIER,            ",nobarrier" },
+               { XFS_MOUNT_SMALL_INUMS,        ",inode64" },
                { 0, NULL }
        };
        struct proc_xfs_info    *xfs_infop;
@@ -495,46 +503,46 @@ xfs_showargs(
        }
 
        if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
-               seq_printf(m, "," MNTOPT_ALLOCSIZE "=%dk",
+               seq_printf(m, ",allocsize=%dk",
                                (int)(1 << mp->m_writeio_log) >> 10);
 
        if (mp->m_logbufs > 0)
-               seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs);
+               seq_printf(m, ",logbufs=%d", mp->m_logbufs);
        if (mp->m_logbsize > 0)
-               seq_printf(m, "," MNTOPT_LOGBSIZE "=%dk", mp->m_logbsize >> 10);
+               seq_printf(m, ",logbsize=%dk", mp->m_logbsize >> 10);
 
        if (mp->m_logname)
-               seq_show_option(m, MNTOPT_LOGDEV, mp->m_logname);
+               seq_show_option(m, "logdev", mp->m_logname);
        if (mp->m_rtname)
-               seq_show_option(m, MNTOPT_RTDEV, mp->m_rtname);
+               seq_show_option(m, "rtdev", mp->m_rtname);
 
        if (mp->m_dalign > 0)
-               seq_printf(m, "," MNTOPT_SUNIT "=%d",
+               seq_printf(m, ",sunit=%d",
                                (int)XFS_FSB_TO_BB(mp, mp->m_dalign));
        if (mp->m_swidth > 0)
-               seq_printf(m, "," MNTOPT_SWIDTH "=%d",
+               seq_printf(m, ",swidth=%d",
                                (int)XFS_FSB_TO_BB(mp, mp->m_swidth));
 
        if (mp->m_qflags & (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD))
-               seq_puts(m, "," MNTOPT_USRQUOTA);
+               seq_puts(m, ",usrquota");
        else if (mp->m_qflags & XFS_UQUOTA_ACCT)
-               seq_puts(m, "," MNTOPT_UQUOTANOENF);
+               seq_puts(m, ",uqnoenforce");
 
        if (mp->m_qflags & XFS_PQUOTA_ACCT) {
                if (mp->m_qflags & XFS_PQUOTA_ENFD)
-                       seq_puts(m, "," MNTOPT_PRJQUOTA);
+                       seq_puts(m, ",prjquota");
                else
-                       seq_puts(m, "," MNTOPT_PQUOTANOENF);
+                       seq_puts(m, ",pqnoenforce");
        }
        if (mp->m_qflags & XFS_GQUOTA_ACCT) {
                if (mp->m_qflags & XFS_GQUOTA_ENFD)
-                       seq_puts(m, "," MNTOPT_GRPQUOTA);
+                       seq_puts(m, ",grpquota");
                else
-                       seq_puts(m, "," MNTOPT_GQUOTANOENF);
+                       seq_puts(m, ",gqnoenforce");
        }
 
        if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
-               seq_puts(m, "," MNTOPT_NOQUOTA);
+               seq_puts(m, ",noquota");
 
        return 0;
 }
@@ -573,23 +581,35 @@ xfs_max_file_offset(
 }
 
 /*
- * xfs_set_inode32() and xfs_set_inode64() are passed an agcount
- * because in the growfs case, mp->m_sb.sb_agcount is not updated
- * yet to the potentially higher ag count.
+ * Set parameters for inode allocation heuristics, taking into account
+ * filesystem size and inode32/inode64 mount options; i.e. specifically
+ * whether or not XFS_MOUNT_SMALL_INUMS is set.
+ *
+ * Inode allocation patterns are altered only if inode32 is requested
+ * (XFS_MOUNT_SMALL_INUMS), and the filesystem is sufficiently large.
+ * If altered, XFS_MOUNT_32BITINODES is set as well.
+ *
+ * An agcount independent of that in the mount structure is provided
+ * because in the growfs case, mp->m_sb.sb_agcount is not yet updated
+ * to the potentially higher ag count.
+ *
+ * Returns the maximum AG index which may contain inodes.
  */
 xfs_agnumber_t
-xfs_set_inode32(struct xfs_mount *mp, xfs_agnumber_t agcount)
+xfs_set_inode_alloc(
+       struct xfs_mount *mp,
+       xfs_agnumber_t  agcount)
 {
-       xfs_agnumber_t  index = 0;
+       xfs_agnumber_t  index;
        xfs_agnumber_t  maxagi = 0;
        xfs_sb_t        *sbp = &mp->m_sb;
        xfs_agnumber_t  max_metadata;
        xfs_agino_t     agino;
        xfs_ino_t       ino;
-       xfs_perag_t     *pag;
 
-       /* Calculate how much should be reserved for inodes to meet
-        * the max inode percentage.
+       /*
+        * Calculate how much should be reserved for inodes to meet
+        * the max inode percentage.  Used only for inode32.
         */
        if (mp->m_maxicount) {
                __uint64_t      icount;
@@ -603,54 +623,48 @@ xfs_set_inode32(struct xfs_mount *mp, xfs_agnumber_t agcount)
                max_metadata = agcount;
        }
 
+       /* Get the last possible inode in the filesystem */
        agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
+       ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
+
+       /*
+        * If user asked for no more than 32-bit inodes, and the fs is
+        * sufficiently large, set XFS_MOUNT_32BITINODES if we must alter
+        * the allocator to accommodate the request.
+        */
+       if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
+               mp->m_flags |= XFS_MOUNT_32BITINODES;
+       else
+               mp->m_flags &= ~XFS_MOUNT_32BITINODES;
 
        for (index = 0; index < agcount; index++) {
-               ino = XFS_AGINO_TO_INO(mp, index, agino);
+               struct xfs_perag        *pag;
 
-               if (ino > XFS_MAXINUMBER_32) {
-                       pag = xfs_perag_get(mp, index);
-                       pag->pagi_inodeok = 0;
-                       pag->pagf_metadata = 0;
-                       xfs_perag_put(pag);
-                       continue;
-               }
+               ino = XFS_AGINO_TO_INO(mp, index, agino);
 
                pag = xfs_perag_get(mp, index);
-               pag->pagi_inodeok = 1;
-               maxagi++;
-               if (index < max_metadata)
-                       pag->pagf_metadata = 1;
-               xfs_perag_put(pag);
-       }
-       mp->m_flags |= (XFS_MOUNT_32BITINODES |
-                       XFS_MOUNT_SMALL_INUMS);
-
-       return maxagi;
-}
 
-xfs_agnumber_t
-xfs_set_inode64(struct xfs_mount *mp, xfs_agnumber_t agcount)
-{
-       xfs_agnumber_t index = 0;
-
-       for (index = 0; index < agcount; index++) {
-               struct xfs_perag        *pag;
+               if (mp->m_flags & XFS_MOUNT_32BITINODES) {
+                       if (ino > XFS_MAXINUMBER_32) {
+                               pag->pagi_inodeok = 0;
+                               pag->pagf_metadata = 0;
+                       } else {
+                               pag->pagi_inodeok = 1;
+                               maxagi++;
+                               if (index < max_metadata)
+                                       pag->pagf_metadata = 1;
+                               else
+                                       pag->pagf_metadata = 0;
+                       }
+               } else {
+                       pag->pagi_inodeok = 1;
+                       pag->pagf_metadata = 0;
+               }
 
-               pag = xfs_perag_get(mp, index);
-               pag->pagi_inodeok = 1;
-               pag->pagf_metadata = 0;
                xfs_perag_put(pag);
        }
 
-       /* There is no need for lock protection on m_flags,
-        * the rw_semaphore of the VFS superblock is locked
-        * during mount/umount/remount operations, so this is
-        * enough to avoid concurency on the m_flags field
-        */
-       mp->m_flags &= ~(XFS_MOUNT_32BITINODES |
-                        XFS_MOUNT_SMALL_INUMS);
-       return index;
+       return (mp->m_flags & XFS_MOUNT_32BITINODES) ? maxagi : agcount;
 }
 
 STATIC int
@@ -1166,6 +1180,27 @@ xfs_quiesce_attr(
        xfs_log_quiesce(mp);
 }
 
+STATIC int
+xfs_test_remount_options(
+       struct super_block      *sb,
+       struct xfs_mount        *mp,
+       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_free_fsname(tmp_mp);
+       kfree(tmp_mp);
+
+       return error;
+}
+
 STATIC int
 xfs_fs_remount(
        struct super_block      *sb,
@@ -1178,6 +1213,11 @@ xfs_fs_remount(
        char                    *p;
        int                     error;
 
+       /* First, check for complete junk; i.e. invalid options */
+       error = xfs_test_remount_options(sb, mp, options);
+       if (error)
+               return error;
+
        sync_filesystem(sb);
        while ((p = strsep(&options, ",")) != NULL) {
                int token;
@@ -1194,10 +1234,12 @@ xfs_fs_remount(
                        mp->m_flags &= ~XFS_MOUNT_BARRIER;
                        break;
                case Opt_inode64:
-                       mp->m_maxagi = xfs_set_inode64(mp, sbp->sb_agcount);
+                       mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS;
+                       mp->m_maxagi = xfs_set_inode_alloc(mp, sbp->sb_agcount);
                        break;
                case Opt_inode32:
-                       mp->m_maxagi = xfs_set_inode32(mp, sbp->sb_agcount);
+                       mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
+                       mp->m_maxagi = xfs_set_inode_alloc(mp, sbp->sb_agcount);
                        break;
                default:
                        /*
@@ -1345,9 +1387,8 @@ xfs_finish_flags(
         */
        if (xfs_sb_version_hascrc(&mp->m_sb) &&
            (mp->m_flags & XFS_MOUNT_NOATTR2)) {
-               xfs_warn(mp,
-"Cannot mount a V5 filesystem as %s. %s is always enabled for V5 filesystems.",
-                       MNTOPT_NOATTR2, MNTOPT_ATTR2);
+               xfs_warn(mp, "Cannot mount a V5 filesystem as noattr2. "
+                            "attr2 is always enabled for V5 filesystems.");
                return -EINVAL;
        }