These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / fs / xfs / libxfs / xfs_ialloc_btree.c
index 964c465..f39b285 100644 (file)
@@ -167,7 +167,16 @@ xfs_inobt_init_rec_from_cur(
        union xfs_btree_rec     *rec)
 {
        rec->inobt.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino);
-       rec->inobt.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount);
+       if (xfs_sb_version_hassparseinodes(&cur->bc_mp->m_sb)) {
+               rec->inobt.ir_u.sp.ir_holemask =
+                                       cpu_to_be16(cur->bc_rec.i.ir_holemask);
+               rec->inobt.ir_u.sp.ir_count = cur->bc_rec.i.ir_count;
+               rec->inobt.ir_u.sp.ir_freecount = cur->bc_rec.i.ir_freecount;
+       } else {
+               /* ir_holemask/ir_count not supported on-disk */
+               rec->inobt.ir_u.f.ir_freecount =
+                                       cpu_to_be32(cur->bc_rec.i.ir_freecount);
+       }
        rec->inobt.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free);
 }
 
@@ -230,7 +239,7 @@ xfs_inobt_verify(
        case cpu_to_be32(XFS_FIBT_CRC_MAGIC):
                if (!xfs_sb_version_hascrc(&mp->m_sb))
                        return false;
-               if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid))
+               if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid))
                        return false;
                if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn))
                        return false;
@@ -418,3 +427,85 @@ xfs_inobt_maxrecs(
                return blocklen / sizeof(xfs_inobt_rec_t);
        return blocklen / (sizeof(xfs_inobt_key_t) + sizeof(xfs_inobt_ptr_t));
 }
+
+/*
+ * Convert the inode record holemask to an inode allocation bitmap. The inode
+ * allocation bitmap is inode granularity and specifies whether an inode is
+ * physically allocated on disk (not whether the inode is considered allocated
+ * or free by the fs).
+ *
+ * A bit value of 1 means the inode is allocated, a value of 0 means it is free.
+ */
+uint64_t
+xfs_inobt_irec_to_allocmask(
+       struct xfs_inobt_rec_incore     *rec)
+{
+       uint64_t                        bitmap = 0;
+       uint64_t                        inodespbit;
+       int                             nextbit;
+       uint                            allocbitmap;
+
+       /*
+        * The holemask has 16-bits for a 64 inode record. Therefore each
+        * holemask bit represents multiple inodes. Create a mask of bits to set
+        * in the allocmask for each holemask bit.
+        */
+       inodespbit = (1 << XFS_INODES_PER_HOLEMASK_BIT) - 1;
+
+       /*
+        * Allocated inodes are represented by 0 bits in holemask. Invert the 0
+        * bits to 1 and convert to a uint so we can use xfs_next_bit(). Mask
+        * anything beyond the 16 holemask bits since this casts to a larger
+        * type.
+        */
+       allocbitmap = ~rec->ir_holemask & ((1 << XFS_INOBT_HOLEMASK_BITS) - 1);
+
+       /*
+        * allocbitmap is the inverted holemask so every set bit represents
+        * allocated inodes. To expand from 16-bit holemask granularity to
+        * 64-bit (e.g., bit-per-inode), set inodespbit bits in the target
+        * bitmap for every holemask bit.
+        */
+       nextbit = xfs_next_bit(&allocbitmap, 1, 0);
+       while (nextbit != -1) {
+               ASSERT(nextbit < (sizeof(rec->ir_holemask) * NBBY));
+
+               bitmap |= (inodespbit <<
+                          (nextbit * XFS_INODES_PER_HOLEMASK_BIT));
+
+               nextbit = xfs_next_bit(&allocbitmap, 1, nextbit + 1);
+       }
+
+       return bitmap;
+}
+
+#if defined(DEBUG) || defined(XFS_WARN)
+/*
+ * Verify that an in-core inode record has a valid inode count.
+ */
+int
+xfs_inobt_rec_check_count(
+       struct xfs_mount                *mp,
+       struct xfs_inobt_rec_incore     *rec)
+{
+       int                             inocount = 0;
+       int                             nextbit = 0;
+       uint64_t                        allocbmap;
+       int                             wordsz;
+
+       wordsz = sizeof(allocbmap) / sizeof(unsigned int);
+       allocbmap = xfs_inobt_irec_to_allocmask(rec);
+
+       nextbit = xfs_next_bit((uint *) &allocbmap, wordsz, nextbit);
+       while (nextbit != -1) {
+               inocount++;
+               nextbit = xfs_next_bit((uint *) &allocbmap, wordsz,
+                                      nextbit + 1);
+       }
+
+       if (inocount != rec->ir_count)
+               return -EFSCORRUPTED;
+
+       return 0;
+}
+#endif /* DEBUG */