]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfsprogs: use common code for multi-disk detection
authorDave Chinner <dchinner@redhat.com>
Tue, 10 May 2016 07:16:06 +0000 (17:16 +1000)
committerDave Chinner <david@fromorbit.com>
Tue, 10 May 2016 07:16:06 +0000 (17:16 +1000)
Both xfs_repair and mkfs.xfs need to agree on what is a "multidisk:
configuration - mkfs for determining the AG count of the filesystem,
repair for determining how to automatically parallelise it's
execution. This requires a bunch of common defines that both mkfs
and reapir need to share.

In fact, most of the defines in xfs_mkfs.h could be shared with
other programs (i.e. all the defaults mkfs uses) and so it is
simplest to move xfs_mkfs.h to the shared include directory and add
the new defines to it directly.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
include/Makefile
include/xfs_multidisk.h [moved from mkfs/xfs_mkfs.h with 88% similarity]
mkfs/Makefile
mkfs/maxtrres.c
mkfs/proto.c
mkfs/xfs_mkfs.c
repair/xfs_repair.c

index 6148756e4d36b97b982869747f9fc6ae0618accb..5fb443aa4e33a6318c3dea543acb5245d9f9dd5b 100644 (file)
@@ -33,13 +33,16 @@ LIBHFILES = libxfs.h \
        xfs_log_recover.h \
        xfs_metadump.h \
        xfs_mount.h \
+       xfs_quota_defs.h \
+       xfs_sb.h \
+       xfs_shared.h \
        xfs_trace.h \
        xfs_trans.h \
        command.h \
        input.h \
        path.h \
        project.h \
-       platform_defs.h \
+       platform_defs.h
 
 HFILES = handle.h \
        jdm.h \
similarity index 88%
rename from mkfs/xfs_mkfs.h
rename to include/xfs_multidisk.h
index 128068e8bb65bebf167fdfcc914f10d41eb75844..4b99992f8b777b5bf4d9c9d6f4abf86e6283d754 100644 (file)
@@ -15,8 +15,8 @@
  * along with this program; if not, write the Free Software Foundation,
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-#ifndef __XFS_MKFS_H__
-#define        __XFS_MKFS_H__
+#ifndef __XFS_MULTIDISK_H__
+#define        __XFS_MULTIDISK_H__
 
 #define XFS_DFL_SB_VERSION_BITS \
                 (XFS_SB_VERSION_NLINKBIT | \
 
 #define XFS_MAX_AGNUMBER       ((xfs_agnumber_t)(NULLAGNUMBER - 1))
 
+/*
+ * These values define what we consider a "multi-disk" filesystem. That is, a
+ * filesystem that is likely to be made up of multiple devices, and hence have
+ * some level of parallelism available to it at the IO level.
+ */
+#define XFS_MULTIDISK_AGLOG            5       /* 32 AGs */
+#define XFS_NOMULTIDISK_AGLOG          2       /* 4 AGs */
+#define XFS_MULTIDISK_AGCOUNT          (1 << XFS_MULTIDISK_AGLOG)
+
 
 /* xfs_mkfs.c */
 extern int isdigits (char *str);
@@ -86,4 +95,4 @@ extern int max_trans_res (int crcs_enabled, int dirversion,
                int sectorlog, int blocklog, int inodelog, int dirblocklog,
                int logversion, int log_sunit, int finobt);
 
-#endif /* __XFS_MKFS_H__ */
+#endif /* __XFS_MULTIDISK_H__ */
index 570ab0749bbb87cde52e50c19bad0ff23032aa79..63ba4eca1e0b554ae7f4c7b18e14d4bb7d7dfed0 100644 (file)
@@ -7,7 +7,7 @@ include $(TOPDIR)/include/builddefs
 
 LTCOMMAND = mkfs.xfs
 
-HFILES = xfs_mkfs.h
+HFILES =
 CFILES = maxtrres.c proto.c xfs_mkfs.c
 
 LLDLIBS += $(LIBBLKID) $(LIBXFS) $(LIBUUID) $(LIBRT) $(LIBPTHREAD)
index b97d020a68a9575f2adc41f114e715da0c5d47ed..f48a0f748d3802bbbc4b799baa36c007245a8abd 100644 (file)
@@ -25,7 +25,7 @@
  */
 
 #include "libxfs.h"
-#include "xfs_mkfs.h"
+#include "xfs_multidisk.h"
 
 int
 max_trans_res(
index d99e965896407bddd8a495be4c1222c06ed31c44..f3327d1b5c598e48ce45e240ca2775447df4280c 100644 (file)
@@ -18,7 +18,7 @@
 
 #include "libxfs.h"
 #include <sys/stat.h>
-#include "xfs_mkfs.h"
+#include "xfs_multidisk.h"
 
 /*
  * Prototypes for internal functions.
index 4c3a802627046ce5860b1bccd3e6320f3108925a..5527b872cb52bc5a31e80e665fc242b1e84574a4 100644 (file)
@@ -21,7 +21,7 @@
 #ifdef ENABLE_BLKID
 #  include <blkid/blkid.h>
 #endif /* ENABLE_BLKID */
-#include "xfs_mkfs.h"
+#include "xfs_multidisk.h"
 
 /*
  * Device topology information.
@@ -664,43 +664,46 @@ calc_default_ag_geometry(
        }
 
        /*
-        * For the remainder we choose an AG size based on the
-        * number of data blocks available, trying to keep the
-        * number of AGs relatively small (especially compared
-        * to the original algorithm).  AG count is calculated
-        * based on the preferred AG size, not vice-versa - the
-        * count can be increased by growfs, so prefer to use
-        * smaller counts at mkfs time.
-        *
-        * For a single underlying storage device between 128MB
-        * and 4TB in size, just use 4 AGs, otherwise scale up
-        * smoothly between min/max AG sizes.
+        * For a single underlying storage device over 4TB in size
+        * use the maximum AG size.  Between 128MB and 4TB, just use
+        * 4 AGs and scale up smoothly between min/max AG sizes.
         */
-
-       if (!multidisk && dblocks >= MEGABYTES(128, blocklog)) {
+       if (!multidisk) {
                if (dblocks >= TERABYTES(4, blocklog)) {
                        blocks = XFS_AG_MAX_BLOCKS(blocklog);
                        goto done;
+               } else if (dblocks >= MEGABYTES(128, blocklog)) {
+                       shift = XFS_NOMULTIDISK_AGLOG;
+                       goto calc_blocks;
                }
-               shift = 2;
-       } else if (dblocks > GIGABYTES(512, blocklog))
-               shift = 5;
-       else if (dblocks > GIGABYTES(8, blocklog))
-               shift = 4;
-       else if (dblocks >= MEGABYTES(128, blocklog))
-               shift = 3;
-       else if (dblocks >= MEGABYTES(64, blocklog))
-               shift = 2;
-       else if (dblocks >= MEGABYTES(32, blocklog))
-               shift = 1;
-       else
-               shift = 0;
+       }
+
+       /*
+        * For the multidisk configs we choose an AG count based on the number
+        * of data blocks available, trying to keep the number of AGs higher
+        * than the single disk configurations. This makes the assumption that
+        * larger filesystems have more parallelism available to them.
+        */
+       shift = XFS_MULTIDISK_AGLOG;
+       if (dblocks <= GIGABYTES(512, blocklog))
+               shift--;
+       if (dblocks <= GIGABYTES(8, blocklog))
+               shift--;
+       if (dblocks < MEGABYTES(128, blocklog))
+               shift--;
+       if (dblocks < MEGABYTES(64, blocklog))
+               shift--;
+       if (dblocks < MEGABYTES(32, blocklog))
+               shift--;
+
        /*
         * If dblocks is not evenly divisible by the number of
         * desired AGs, round "blocks" up so we don't lose the
         * last bit of the filesystem. The same principle applies
         * to the AG count, so we don't lose the last AG!
         */
+calc_blocks:
+       ASSERT(shift >= 0 && shift <= XFS_MULTIDISK_AGLOG);
        blocks = dblocks >> shift;
        if (dblocks & xfs_mask32lo(shift)) {
                if (blocks < XFS_AG_MAX_BLOCKS(blocklog))
index 5d5f3aa855045370edb1d9706db1553bc441baf9..9d91f2df57382618efb573c4993c3481c7eb2aa9 100644 (file)
@@ -19,6 +19,7 @@
 #include "libxfs.h"
 #include "libxlog.h"
 #include <sys/resource.h>
+#include "xfs_multidisk.h"
 #include "avl.h"
 #include "avl64.h"
 #include "globals.h"
@@ -589,6 +590,33 @@ format_log_max_lsn(
                         XLOG_FMT, new_cycle, true);
 }
 
+/*
+ * mkfs increases the AG count for "multidisk" configurations, we want
+ * to target these for an increase in thread count. Hence check the superlock
+ * geometry information to determine if mkfs considered this a multidisk
+ * configuration.
+ */
+static bool
+is_multidisk_filesystem(
+       struct xfs_mount        *mp)
+{
+       struct xfs_sb           *sbp = &mp->m_sb;
+
+       /* High agcount filesystems are always considered "multidisk" */
+       if (sbp->sb_agcount >= XFS_MULTIDISK_AGCOUNT)
+               return true;
+
+       /*
+        * If it doesn't have a sunit/swidth, mkfs didn't consider it a
+        * multi-disk array, so we don't either.
+        */
+       if (!sbp->sb_unit)
+               return false;
+
+       ASSERT(sbp->sb_width);
+       return true;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -729,9 +757,21 @@ main(int argc, char **argv)
         * threads/CPU as this is enough threads to saturate a CPU on fast
         * devices, yet few enough that it will saturate but won't overload slow
         * devices.
+        *
+        * Multidisk filesystems can handle more IO parallelism so we should try
+        * to process multiple AGs at a time in such a configuration to try to
+        * saturate the underlying storage and speed the repair process. Only do
+        * this if prefetching is enabled.
         */
-       if (!ag_stride && glob_agcount >= 16 && do_prefetch)
-               ag_stride = 15;
+       if (!ag_stride && do_prefetch && is_multidisk_filesystem(mp)) {
+               /*
+                * For small agcount multidisk systems, just double the
+                * parallelism. For larger AG count filesystems (32 and above)
+                * use more parallelism, and linearly increase the parallelism
+                * with the number of AGs.
+                */
+               ag_stride = min(glob_agcount, XFS_MULTIDISK_AGCOUNT / 2) - 1;
+       }
 
        if (ag_stride) {
                int max_threads = platform_nproc() * 8;