]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
mkfs: sparse inode chunk support
authorBrian Foster <bfoster@redhat.com>
Thu, 30 Jul 2015 23:16:07 +0000 (09:16 +1000)
committerDave Chinner <david@fromorbit.com>
Thu, 30 Jul 2015 23:16:07 +0000 (09:16 +1000)
Allow format of sparse inode chunk enabled filesystems via the '-i
sparse' flag. Note that sparse inode chunk support requires a v5
superblock (-m crc=1).

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
man/man8/mkfs.xfs.8
mkfs/xfs_mkfs.c

index e18f6d18f6a8d4d51f67974d2c863a08376a00a9..6260e0c6b9ba84745df6b611bc7177aba21938d8 100644 (file)
@@ -410,6 +410,23 @@ This is used to enable 32bit quota project identifiers. The
 is either 0 or 1, with 1 signifying that 32bit projid are to be enabled.
 If the value is omitted, 1 is assumed.  (This default changed
 in release version 3.2.0.)
+.TP
+.BI sparse[= value ]
+Enable sparse inode chunk allocation. The
+.I value
+is either 0 or 1, with 1 signifying that sparse allocation is enabled.
+If the value is omitted, 1 is assumed. Sparse inode allocation is
+disabled by default. This feature is only available for filesystems
+formatted with
+.B \-m crc=1.
+.IP
+When enabled, sparse inode allocation allows the filesystem to allocate
+smaller than the standard 64-inode chunk when free space is severely
+limited. This feature is useful for filesystems that might fragment free
+space over time such that no free extents are large enough to
+accommodate a chunk of 64 inodes. Without this feature enabled, inode
+allocations can fail with out of space errors under severe fragmented
+free space conditions.
 .RE
 .TP
 .BI \-l " log_section_options"
index 57a8683732ec829dd399ce02b0e8c54b6131383e..83f774982de91fc6123990956b653671276328e7 100644 (file)
@@ -109,6 +109,8 @@ char        *iopts[] = {
        "attr",
 #define        I_PROJID32BIT   6
        "projid32bit",
+#define I_SPINODES     7
+       "sparse",
        NULL
 };
 
@@ -1005,6 +1007,7 @@ main(
        int                     crcs_enabled;
        int                     finobt;
        bool                    finobtflag;
+       int                     spinodes;
 
        progname = basename(argv[0]);
        setlocale(LC_ALL, "");
@@ -1040,6 +1043,7 @@ main(
        crcs_enabled = 1;
        finobt = 1;
        finobtflag = false;
+       spinodes = 0;
        memset(&fsx, 0, sizeof(fsx));
 
        memset(&xi, 0, sizeof(xi));
@@ -1361,6 +1365,13 @@ main(
                                                illegal(value, "i projid32bit");
                                        projid16bit = c ? 0 : 1;
                                        break;
+                               case I_SPINODES:
+                                       if (!value || *value == '\0')
+                                               value = "1";
+                                       spinodes = atoi(value);
+                                       if (spinodes < 0 || spinodes > 1)
+                                               illegal(value, "i spinodes");
+                                       break;
                                default:
                                        unknown('i', value);
                                }
@@ -1903,6 +1914,12 @@ _("warning: finobt not supported without CRC support, disabled.\n"));
                finobt = 0;
        }
 
+       if (spinodes && !crcs_enabled) {
+               fprintf(stderr,
+_("warning: sparse inodes not supported without CRC support, disabled.\n"));
+               spinodes = 0;
+       }
+
        if (nsflag || nlflag) {
                if (dirblocksize < blocksize ||
                                        dirblocksize > XFS_MAX_BLOCKSIZE) {
@@ -2581,7 +2598,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
                printf(_(
                   "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n"
                   "         =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n"
-                  "         =%-22s crc=%-8u finobt=%u\n"
+                  "         =%-22s crc=%-8u finobt=%u, sparse=%u\n"
                   "data     =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
                   "         =%-22s sunit=%-6u swidth=%u blks\n"
                   "naming   =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n"
@@ -2590,7 +2607,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
                   "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"),
                        dfile, isize, (long long)agcount, (long long)agsize,
                        "", sectorsize, attrversion, !projid16bit,
-                       "", crcs_enabled, finobt,
+                       "", crcs_enabled, finobt, spinodes,
                        "", blocksize, (long long)dblocks, imaxpct,
                        "", dsunit, dswidth,
                        dirversion, dirblocksize, nci, dirftype,
@@ -2659,6 +2676,20 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
                sbp->sb_logsectsize = 0;
        }
 
+       /*
+        * Sparse inode chunk support has two main inode alignment requirements.
+        * First, sparse chunk alignment must match the cluster size. Second,
+        * full chunk alignment must match the inode chunk size.
+        *
+        * Copy the already calculated/scaled inoalignmt to spino_align and
+        * update the former to the full inode chunk size.
+        */
+       if (spinodes) {
+               sbp->sb_spino_align = sbp->sb_inoalignmt;
+               sbp->sb_inoalignmt = XFS_INODES_PER_CHUNK * isize >> blocklog;
+               sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_SPINODES;
+       }
+
        if (force_overwrite)
                zero_old_xfs_structures(&xi, sbp);
 
@@ -3206,7 +3237,7 @@ usage( void )
                            sectlog=n|sectsize=num\n\
 /* force overwrite */  [-f]\n\
 /* inode size */       [-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n\
-                           projid32bit=0|1]\n\
+                           projid32bit=0|1,sparse=0|1]\n\
 /* no discard */       [-K]\n\
 /* log subvol */       [-l agnum=n,internal,size=num,logdev=xxx,version=n\n\
                            sunit=value|su=num,sectlog=n|sectsize=num,\n\