From: Brian Foster Date: Thu, 30 Jul 2015 23:16:07 +0000 (+1000) Subject: mkfs: sparse inode chunk support X-Git-Tag: v4.2.0-rc1~28 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6003fd816c2e0c4ec2b6352571e14765cca62d07;p=thirdparty%2Fxfsprogs-dev.git mkfs: sparse inode chunk support 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 Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8 index e18f6d18f..6260e0c6b 100644 --- a/man/man8/mkfs.xfs.8 +++ b/man/man8/mkfs.xfs.8 @@ -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" diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 57a868373..83f774982 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -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\