Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[firefly-linux-kernel-4.4.55.git] / fs / xfs / xfs_super.c
index 8f0333b3f7a011a25960c3ace80b57ebcaf58a19..b194652033cd11c8530ae762d01972fa455a23aa 100644 (file)
@@ -61,6 +61,7 @@
 static const struct super_operations xfs_super_operations;
 static kmem_zone_t *xfs_ioend_zone;
 mempool_t *xfs_ioend_pool;
+struct kset *xfs_kset;
 
 #define MNTOPT_LOGBUFS "logbufs"       /* number of XFS log buffers */
 #define MNTOPT_LOGBSIZE        "logbsize"      /* size of XFS log buffers */
@@ -185,7 +186,7 @@ xfs_parseargs(
         */
        mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL);
        if (!mp->m_fsname)
-               return ENOMEM;
+               return -ENOMEM;
        mp->m_fsname_len = strlen(mp->m_fsname) + 1;
 
        /*
@@ -204,9 +205,6 @@ xfs_parseargs(
         */
        mp->m_flags |= XFS_MOUNT_BARRIER;
        mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;
-#if !XFS_BIG_INUMS
-       mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
-#endif
 
        /*
         * These can be overridden by the mount option parsing.
@@ -227,57 +225,57 @@ xfs_parseargs(
                        if (!value || !*value) {
                                xfs_warn(mp, "%s option requires an argument",
                                        this_char);
-                               return EINVAL;
+                               return -EINVAL;
                        }
                        if (kstrtoint(value, 10, &mp->m_logbufs))
-                               return EINVAL;
+                               return -EINVAL;
                } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
                        if (!value || !*value) {
                                xfs_warn(mp, "%s option requires an argument",
                                        this_char);
-                               return EINVAL;
+                               return -EINVAL;
                        }
                        if (suffix_kstrtoint(value, 10, &mp->m_logbsize))
-                               return EINVAL;
+                               return -EINVAL;
                } else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
                        if (!value || !*value) {
                                xfs_warn(mp, "%s option requires an argument",
                                        this_char);
-                               return EINVAL;
+                               return -EINVAL;
                        }
                        mp->m_logname = kstrndup(value, MAXNAMELEN, GFP_KERNEL);
                        if (!mp->m_logname)
-                               return ENOMEM;
+                               return -ENOMEM;
                } else if (!strcmp(this_char, MNTOPT_MTPT)) {
                        xfs_warn(mp, "%s option not allowed on this system",
                                this_char);
-                       return EINVAL;
+                       return -EINVAL;
                } else if (!strcmp(this_char, MNTOPT_RTDEV)) {
                        if (!value || !*value) {
                                xfs_warn(mp, "%s option requires an argument",
                                        this_char);
-                               return EINVAL;
+                               return -EINVAL;
                        }
                        mp->m_rtname = kstrndup(value, MAXNAMELEN, GFP_KERNEL);
                        if (!mp->m_rtname)
-                               return ENOMEM;
+                               return -ENOMEM;
                } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
                        if (!value || !*value) {
                                xfs_warn(mp, "%s option requires an argument",
                                        this_char);
-                               return EINVAL;
+                               return -EINVAL;
                        }
                        if (kstrtoint(value, 10, &iosize))
-                               return EINVAL;
+                               return -EINVAL;
                        iosizelog = ffs(iosize) - 1;
                } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
                        if (!value || !*value) {
                                xfs_warn(mp, "%s option requires an argument",
                                        this_char);
-                               return EINVAL;
+                               return -EINVAL;
                        }
                        if (suffix_kstrtoint(value, 10, &iosize))
-                               return EINVAL;
+                               return -EINVAL;
                        iosizelog = ffs(iosize) - 1;
                } else if (!strcmp(this_char, MNTOPT_GRPID) ||
                           !strcmp(this_char, MNTOPT_BSDGROUPS)) {
@@ -297,27 +295,22 @@ xfs_parseargs(
                        if (!value || !*value) {
                                xfs_warn(mp, "%s option requires an argument",
                                        this_char);
-                               return EINVAL;
+                               return -EINVAL;
                        }
                        if (kstrtoint(value, 10, &dsunit))
-                               return EINVAL;
+                               return -EINVAL;
                } else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
                        if (!value || !*value) {
                                xfs_warn(mp, "%s option requires an argument",
                                        this_char);
-                               return EINVAL;
+                               return -EINVAL;
                        }
                        if (kstrtoint(value, 10, &dswidth))
-                               return EINVAL;
+                               return -EINVAL;
                } else if (!strcmp(this_char, MNTOPT_32BITINODE)) {
                        mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
                } else if (!strcmp(this_char, MNTOPT_64BITINODE)) {
                        mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS;
-#if !XFS_BIG_INUMS
-                       xfs_warn(mp, "%s option not allowed on this system",
-                               this_char);
-                       return EINVAL;
-#endif
                } else if (!strcmp(this_char, MNTOPT_NOUUID)) {
                        mp->m_flags |= XFS_MOUNT_NOUUID;
                } else if (!strcmp(this_char, MNTOPT_BARRIER)) {
@@ -390,7 +383,7 @@ xfs_parseargs(
        "irixsgid is now a sysctl(2) variable, option is deprecated.");
                } else {
                        xfs_warn(mp, "unknown mount option [%s].", this_char);
-                       return EINVAL;
+                       return -EINVAL;
                }
        }
 
@@ -400,32 +393,32 @@ xfs_parseargs(
        if ((mp->m_flags & XFS_MOUNT_NORECOVERY) &&
            !(mp->m_flags & XFS_MOUNT_RDONLY)) {
                xfs_warn(mp, "no-recovery mounts must be read-only.");
-               return EINVAL;
+               return -EINVAL;
        }
 
        if ((mp->m_flags & XFS_MOUNT_NOALIGN) && (dsunit || dswidth)) {
                xfs_warn(mp,
        "sunit and swidth options incompatible with the noalign option");
-               return EINVAL;
+               return -EINVAL;
        }
 
 #ifndef CONFIG_XFS_QUOTA
        if (XFS_IS_QUOTA_RUNNING(mp)) {
                xfs_warn(mp, "quota support not available in this kernel.");
-               return EINVAL;
+               return -EINVAL;
        }
 #endif
 
        if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
                xfs_warn(mp, "sunit and swidth must be specified together");
-               return EINVAL;
+               return -EINVAL;
        }
 
        if (dsunit && (dswidth % dsunit != 0)) {
                xfs_warn(mp,
        "stripe width (%d) must be a multiple of the stripe unit (%d)",
                        dswidth, dsunit);
-               return EINVAL;
+               return -EINVAL;
        }
 
 done:
@@ -446,7 +439,7 @@ done:
             mp->m_logbufs > XLOG_MAX_ICLOGS)) {
                xfs_warn(mp, "invalid logbufs value: %d [not %d-%d]",
                        mp->m_logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS);
-               return XFS_ERROR(EINVAL);
+               return -EINVAL;
        }
        if (mp->m_logbsize != -1 &&
            mp->m_logbsize !=  0 &&
@@ -456,7 +449,7 @@ done:
                xfs_warn(mp,
                        "invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
                        mp->m_logbsize);
-               return XFS_ERROR(EINVAL);
+               return -EINVAL;
        }
 
        if (iosizelog) {
@@ -465,7 +458,7 @@ done:
                        xfs_warn(mp, "invalid log iosize: %d [not %d-%d]",
                                iosizelog, XFS_MIN_IO_LOG,
                                XFS_MAX_IO_LOG);
-                       return XFS_ERROR(EINVAL);
+                       return -EINVAL;
                }
 
                mp->m_flags |= XFS_MOUNT_DFLT_IOSIZE;
@@ -597,15 +590,20 @@ xfs_max_file_offset(
        return (((__uint64_t)pagefactor) << bitshift) - 1;
 }
 
+/*
+ * 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.
+ */
 xfs_agnumber_t
-xfs_set_inode32(struct xfs_mount *mp)
+xfs_set_inode32(struct xfs_mount *mp, xfs_agnumber_t agcount)
 {
        xfs_agnumber_t  index = 0;
        xfs_agnumber_t  maxagi = 0;
        xfs_sb_t        *sbp = &mp->m_sb;
        xfs_agnumber_t  max_metadata;
-       xfs_agino_t     agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks -1, 0);
-       xfs_ino_t       ino = XFS_AGINO_TO_INO(mp, sbp->sb_agcount -1, agino);
+       xfs_agino_t     agino;
+       xfs_ino_t       ino;
        xfs_perag_t     *pag;
 
        /* Calculate how much should be reserved for inodes to meet
@@ -620,10 +618,12 @@ xfs_set_inode32(struct xfs_mount *mp)
                do_div(icount, sbp->sb_agblocks);
                max_metadata = icount;
        } else {
-               max_metadata = sbp->sb_agcount;
+               max_metadata = agcount;
        }
 
-       for (index = 0; index < sbp->sb_agcount; index++) {
+       agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
+
+       for (index = 0; index < agcount; index++) {
                ino = XFS_AGINO_TO_INO(mp, index, agino);
 
                if (ino > XFS_MAXINUMBER_32) {
@@ -648,11 +648,11 @@ xfs_set_inode32(struct xfs_mount *mp)
 }
 
 xfs_agnumber_t
-xfs_set_inode64(struct xfs_mount *mp)
+xfs_set_inode64(struct xfs_mount *mp, xfs_agnumber_t agcount)
 {
        xfs_agnumber_t index = 0;
 
-       for (index = 0; index < mp->m_sb.sb_agcount; index++) {
+       for (index = 0; index < agcount; index++) {
                struct xfs_perag        *pag;
 
                pag = xfs_perag_get(mp, index);
@@ -686,7 +686,7 @@ xfs_blkdev_get(
                xfs_warn(mp, "Invalid device [%s], error=%d\n", name, error);
        }
 
-       return -error;
+       return error;
 }
 
 STATIC void
@@ -756,7 +756,7 @@ xfs_open_devices(
                if (rtdev == ddev || rtdev == logdev) {
                        xfs_warn(mp,
        "Cannot mount filesystem with identical rtdev and ddev/logdev.");
-                       error = EINVAL;
+                       error = -EINVAL;
                        goto out_close_rtdev;
                }
        }
@@ -764,7 +764,7 @@ xfs_open_devices(
        /*
         * Setup xfs_mount buffer target pointers
         */
-       error = ENOMEM;
+       error = -ENOMEM;
        mp->m_ddev_targp = xfs_alloc_buftarg(mp, ddev);
        if (!mp->m_ddev_targp)
                goto out_close_rtdev;
@@ -1188,6 +1188,7 @@ xfs_fs_remount(
        char                    *options)
 {
        struct xfs_mount        *mp = XFS_M(sb);
+       xfs_sb_t                *sbp = &mp->m_sb;
        substring_t             args[MAX_OPT_ARGS];
        char                    *p;
        int                     error;
@@ -1208,10 +1209,10 @@ xfs_fs_remount(
                        mp->m_flags &= ~XFS_MOUNT_BARRIER;
                        break;
                case Opt_inode64:
-                       mp->m_maxagi = xfs_set_inode64(mp);
+                       mp->m_maxagi = xfs_set_inode64(mp, sbp->sb_agcount);
                        break;
                case Opt_inode32:
-                       mp->m_maxagi = xfs_set_inode32(mp);
+                       mp->m_maxagi = xfs_set_inode32(mp, sbp->sb_agcount);
                        break;
                default:
                        /*
@@ -1295,7 +1296,7 @@ xfs_fs_freeze(
 
        xfs_save_resvblks(mp);
        xfs_quiesce_attr(mp);
-       return -xfs_fs_log_dummy(mp);
+       return xfs_fs_log_dummy(mp);
 }
 
 STATIC int
@@ -1314,7 +1315,7 @@ xfs_fs_show_options(
        struct seq_file         *m,
        struct dentry           *root)
 {
-       return -xfs_showargs(XFS_M(root->d_sb), m);
+       return xfs_showargs(XFS_M(root->d_sb), m);
 }
 
 /*
@@ -1336,14 +1337,14 @@ xfs_finish_flags(
                           mp->m_logbsize < mp->m_sb.sb_logsunit) {
                        xfs_warn(mp,
                "logbuf size must be greater than or equal to log stripe size");
-                       return XFS_ERROR(EINVAL);
+                       return -EINVAL;
                }
        } else {
                /* Fail a mount if the logbuf is larger than 32K */
                if (mp->m_logbsize > XLOG_BIG_RECORD_BSIZE) {
                        xfs_warn(mp,
                "logbuf size for version 1 logs must be 16K or 32K");
-                       return XFS_ERROR(EINVAL);
+                       return -EINVAL;
                }
        }
 
@@ -1355,7 +1356,7 @@ xfs_finish_flags(
                xfs_warn(mp,
 "Cannot mount a V5 filesystem as %s. %s is always enabled for V5 filesystems.",
                        MNTOPT_NOATTR2, MNTOPT_ATTR2);
-               return XFS_ERROR(EINVAL);
+               return -EINVAL;
        }
 
        /*
@@ -1372,7 +1373,7 @@ xfs_finish_flags(
        if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) {
                xfs_warn(mp,
                        "cannot mount a read-only filesystem as read-write");
-               return XFS_ERROR(EROFS);
+               return -EROFS;
        }
 
        if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
@@ -1380,7 +1381,7 @@ xfs_finish_flags(
            !xfs_sb_version_has_pquotino(&mp->m_sb)) {
                xfs_warn(mp,
                  "Super block does not support project and group quota together");
-               return XFS_ERROR(EINVAL);
+               return -EINVAL;
        }
 
        return 0;
@@ -1394,7 +1395,7 @@ xfs_fs_fill_super(
 {
        struct inode            *root;
        struct xfs_mount        *mp = NULL;
-       int                     flags = 0, error = ENOMEM;
+       int                     flags = 0, error = -ENOMEM;
 
        mp = kzalloc(sizeof(struct xfs_mount), GFP_KERNEL);
        if (!mp)
@@ -1428,11 +1429,11 @@ xfs_fs_fill_super(
        if (error)
                goto out_free_fsname;
 
-       error = -xfs_init_mount_workqueues(mp);
+       error = xfs_init_mount_workqueues(mp);
        if (error)
                goto out_close_devices;
 
-       error = -xfs_icsb_init_counters(mp);
+       error = xfs_icsb_init_counters(mp);
        if (error)
                goto out_destroy_workqueues;
 
@@ -1474,12 +1475,12 @@ xfs_fs_fill_super(
 
        root = igrab(VFS_I(mp->m_rootip));
        if (!root) {
-               error = ENOENT;
+               error = -ENOENT;
                goto out_unmount;
        }
        sb->s_root = d_make_root(root);
        if (!sb->s_root) {
-               error = ENOMEM;
+               error = -ENOMEM;
                goto out_unmount;
        }
 
@@ -1499,7 +1500,7 @@ out_destroy_workqueues:
        xfs_free_fsname(mp);
        kfree(mp);
  out:
-       return -error;
+       return error;
 
  out_unmount:
        xfs_filestream_unmount(mp);
@@ -1761,9 +1762,15 @@ init_xfs_fs(void)
        if (error)
                goto out_cleanup_procfs;
 
+       xfs_kset = kset_create_and_add("xfs", NULL, fs_kobj);
+       if (!xfs_kset) {
+               error = -ENOMEM;
+               goto out_sysctl_unregister;;
+       }
+
        error = xfs_qm_init();
        if (error)
-               goto out_sysctl_unregister;
+               goto out_kset_unregister;
 
        error = register_filesystem(&xfs_fs_type);
        if (error)
@@ -1772,6 +1779,8 @@ init_xfs_fs(void)
 
  out_qm_exit:
        xfs_qm_exit();
+ out_kset_unregister:
+       kset_unregister(xfs_kset);
  out_sysctl_unregister:
        xfs_sysctl_unregister();
  out_cleanup_procfs:
@@ -1793,6 +1802,7 @@ exit_xfs_fs(void)
 {
        xfs_qm_exit();
        unregister_filesystem(&xfs_fs_type);
+       kset_unregister(xfs_kset);
        xfs_sysctl_unregister();
        xfs_cleanup_procfs();
        xfs_buf_terminate();