]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: support larger inode clusters on v5 filesystems
authorDave Chinner <dchinner@redhat.com>
Wed, 13 Nov 2013 06:40:56 +0000 (06:40 +0000)
committerRich Johnston <rjohnston@sgi.com>
Thu, 14 Nov 2013 14:59:26 +0000 (08:59 -0600)
To allow the kernel to use larger inode clusters than the standard
8192 bytes, we need to set the inode alignment fields appropriately
so that the kernel is consistent in it's inode to buffer mappings.
We set the alignment to allow a constant 32 inodes per cluster,
instead of a fixed 8k cluster size.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Rich Johnston <rjohnston@sgi.com>
include/libxfs.h
mkfs/xfs_mkfs.c
repair/sb.c

index 40a950ee2f2ef7c72e8ee66bd5d9f71d353c984c..4bf331c4c1d75cd94425735957cb80d3e79ec6ff 100644 (file)
@@ -181,7 +181,7 @@ typedef struct xfs_mount {
        __uint8_t               m_sectbb_log;   /* sectorlog - BBSHIFT */
        __uint8_t               m_agno_log;     /* log #ag's */
        __uint8_t               m_agino_log;    /* #bits for agino in inum */
-       __uint16_t              m_inode_cluster_size;/* min inode buf size */
+       uint                    m_inode_cluster_size;/* min inode buf size */
        uint                    m_blockmask;    /* sb_blocksize-1 */
        uint                    m_blockwsize;   /* sb_blocksize in words */
        uint                    m_blockwmask;   /* blockwsize-1 */
index 3a032c05b94df1bf3aabd592c2f7bbd4ded862b6..d82128c038903298694d020560650bf93d92a2e3 100644 (file)
@@ -2532,7 +2532,10 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
        } else
                sbp->sb_logsunit = 0;
        if (iaflag) {
-               sbp->sb_inoalignmt = XFS_INODE_BIG_CLUSTER_SIZE >> blocklog;
+               int     cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
+               if (crcs_enabled)
+                       cluster_size *= isize / XFS_DINODE_MIN_SIZE;
+               sbp->sb_inoalignmt = cluster_size >> blocklog;
                iaflag = sbp->sb_inoalignmt != 0;
        } else
                sbp->sb_inoalignmt = 0;
index 2e35a4cb0d0bd6bb297bf9b9078f705c1957703d..c54d89b740a6f163d9d67f8293b58cf8578af9c4 100644 (file)
@@ -169,17 +169,37 @@ find_secondary_sb(xfs_sb_t *rsb)
 }
 
 /*
- * calculate what inode alignment field ought to be
- * based on internal superblock info
+ * Calculate what inode alignment field ought to be
+ * based on internal superblock info and determine if it is valid.
+ *
+ * For v5 superblocks, the inode alignment will either match that of the
+ * standard XFS_INODE_BIG_CLUSTER_SIZE, or it will be scaled based on the inode
+ * size. Either value is valid in this case.
+ *
+ * Return true if the alignment is valid, false otherwise.
  */
-static int
-calc_ino_align(xfs_sb_t *sb)
+static bool
+sb_validate_ino_align(struct xfs_sb *sb)
 {
-       xfs_extlen_t align;
+       xfs_extlen_t    align;
 
+       if (!xfs_sb_version_hasalign(sb))
+               return true;
+
+       /* standard cluster size alignment is always valid */
        align = XFS_INODE_BIG_CLUSTER_SIZE >> sb->sb_blocklog;
+       if (align == sb->sb_inoalignmt)
+               return true;
+
+       /* alignment scaled by inode size is v5 only for now */
+       if (!xfs_sb_version_hascrc(sb))
+               return false;
 
-       return(align);
+       align *= sb->sb_inodesize / XFS_DINODE_MIN_SIZE;
+       if (align == sb->sb_inoalignmt)
+               return true;
+
+       return false;
 }
 
 /*
@@ -228,7 +248,6 @@ int
 verify_sb(xfs_sb_t *sb, int is_primary_sb)
 {
        __uint32_t      bsize;
-       xfs_extlen_t    align;
        int             i;
 
        /* check magic number and version number */
@@ -364,12 +383,8 @@ verify_sb(xfs_sb_t *sb, int is_primary_sb)
        /*
         * verify correctness of inode alignment if it's there
         */
-       if (xfs_sb_version_hasalign(sb))  {
-               align = calc_ino_align(sb);
-
-               if (align != sb->sb_inoalignmt)
-                       return(XR_BAD_INO_ALIGN);
-       }
+       if (!sb_validate_ino_align(sb))
+               return(XR_BAD_INO_ALIGN);
 
        /*
         * verify max. % of inodes (sb_imax_pct)