summaryrefslogtreecommitdiffstats
path: root/fs/xfs/libxfs/xfs_ialloc.c
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2015-05-29 09:20:10 +1000
committerDave Chinner <david@fromorbit.com>2015-05-29 09:20:10 +1000
commit26dd5217dee0ecfb95f8015ed8e9deebf8257608 (patch)
tree4fb075d2c0f6486bacfc253476bdec8eceb6430b /fs/xfs/libxfs/xfs_ialloc.c
parent1cdadee11f8d44b16f8110cf01498bd7c38474d8 (diff)
downloadop-kernel-dev-26dd5217dee0ecfb95f8015ed8e9deebf8257608.zip
op-kernel-dev-26dd5217dee0ecfb95f8015ed8e9deebf8257608.tar.gz
xfs: filter out sparse regions from individual inode allocation
Inode allocation from an existing record with free inodes traditionally selects the first inode available according to the ir_free mask. With sparse inode chunks, the ir_free mask could refer to an unallocated region. We must mask the unallocated regions out of ir_free before using it to select a free inode in the chunk. Update the xfs_inobt_first_free_inode() helper to find the first free inode available of the allocated regions of the inode chunk. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/libxfs/xfs_ialloc.c')
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 9a18c0b..6451a80 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -1076,13 +1076,24 @@ xfs_ialloc_get_rec(
}
/*
- * Return the offset of the first free inode in the record.
+ * Return the offset of the first free inode in the record. If the inode chunk
+ * is sparsely allocated, we convert the record holemask to inode granularity
+ * and mask off the unallocated regions from the inode free mask.
*/
STATIC int
xfs_inobt_first_free_inode(
struct xfs_inobt_rec_incore *rec)
{
- return xfs_lowbit64(rec->ir_free);
+ xfs_inofree_t realfree;
+
+ /* if there are no holes, return the first available offset */
+ if (!xfs_inobt_issparse(rec->ir_holemask))
+ return xfs_lowbit64(rec->ir_free);
+
+ realfree = xfs_inobt_irec_to_allocmask(rec);
+ realfree &= rec->ir_free;
+
+ return xfs_lowbit64(realfree);
}
/*
OpenPOWER on IntegriCloud