xfs
[Top] [All Lists]

[PATCH 04/18] xfs: introduce inode record hole mask for sparse inode chu

To: xfs@xxxxxxxxxxx
Subject: [PATCH 04/18] xfs: introduce inode record hole mask for sparse inode chunks
From: Brian Foster <bfoster@xxxxxxxxxx>
Date: Thu, 24 Jul 2014 10:22:54 -0400
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1406211788-63206-1-git-send-email-bfoster@xxxxxxxxxx>
References: <1406211788-63206-1-git-send-email-bfoster@xxxxxxxxxx>
The inode btrees track 64 inodes per record, regardless of inode size.
Thus, inode chunks on disk vary in size depending on the size of the
inodes. This creates a contiguous allocation requirement for new inode
chunks that can be difficult to satisfy on an aged and fragmented (free
space) filesystem.

The inode record freecount currently uses 4 bytes on disk to track the
free inode count. With a maximum freecount value of 64, only one byte is
required. Convert the freecount field to a single byte and reserve two
of the remaining 3 higher order bytes left to the hole mask field.

The hole mask field tracks potential holes in the chunks of physical
space that the inode record refers to. This facilitates the sparse
allocation of inode chunks when contiguous chunks are not available and
allows the inode btrees to identify what portions of the chunk contain
valid inodes.

Tracking holes means the field is initialized to zero and thus maintains
backwards compatibility with existing filesystems. E.g., the higher
order bytes of a counter with a max value of 64 are already initialized
to 0. Update the inode record management functions to handle the new
field and initialize it to zero for now.

Signed-off-by: Brian Foster <bfoster@xxxxxxxxxx>
---
 fs/xfs/libxfs/xfs_format.h       | 7 +++++--
 fs/xfs/libxfs/xfs_ialloc.c       | 9 +++++++--
 fs/xfs/libxfs/xfs_ialloc_btree.c | 4 +++-
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 34d85ac..39022d9 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -221,13 +221,16 @@ static inline xfs_inofree_t xfs_inobt_maskn(int i, int n)
  */
 typedef struct xfs_inobt_rec {
        __be32          ir_startino;    /* starting inode number */
-       __be32          ir_freecount;   /* count of free inodes (set bits) */
+       __be16          ir_holemask;    /* hole mask for sparse chunks */
+       __u8            ir_pad;
+       __u8            ir_freecount;   /* count of free inodes (set bits) */
        __be64          ir_free;        /* free inode mask */
 } xfs_inobt_rec_t;
 
 typedef struct xfs_inobt_rec_incore {
        xfs_agino_t     ir_startino;    /* starting inode number */
-       __int32_t       ir_freecount;   /* count of free inodes (set bits) */
+       __uint16_t      ir_holemask;    /* hole mask for sparse chunks */
+       __uint8_t       ir_freecount;   /* count of free inodes (set bits) */
        xfs_inofree_t   ir_free;        /* free inode mask */
 } xfs_inobt_rec_incore_t;
 
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 5448a74..8286fda 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -68,6 +68,7 @@ xfs_inobt_lookup(
        int                     *stat)  /* success/failure */
 {
        cur->bc_rec.i.ir_startino = ino;
+       cur->bc_rec.i.ir_holemask = 0;
        cur->bc_rec.i.ir_freecount = 0;
        cur->bc_rec.i.ir_free = 0;
        return xfs_btree_lookup(cur, dir, stat);
@@ -85,7 +86,9 @@ xfs_inobt_update(
        union xfs_btree_rec     rec;
 
        rec.inobt.ir_startino = cpu_to_be32(irec->ir_startino);
-       rec.inobt.ir_freecount = cpu_to_be32(irec->ir_freecount);
+       rec.inobt.ir_holemask = cpu_to_be16(irec->ir_holemask);
+       rec.inobt.ir_pad = 0;
+       rec.inobt.ir_freecount = irec->ir_freecount;
        rec.inobt.ir_free = cpu_to_be64(irec->ir_free);
        return xfs_btree_update(cur, &rec);
 }
@@ -105,7 +108,8 @@ xfs_inobt_get_rec(
        error = xfs_btree_get_rec(cur, &rec, stat);
        if (!error && *stat == 1) {
                irec->ir_startino = be32_to_cpu(rec->inobt.ir_startino);
-               irec->ir_freecount = be32_to_cpu(rec->inobt.ir_freecount);
+               irec->ir_holemask = be16_to_cpu(rec->inobt.ir_holemask);
+               irec->ir_freecount = rec->inobt.ir_freecount;
                irec->ir_free = be64_to_cpu(rec->inobt.ir_free);
        }
        return error;
@@ -121,6 +125,7 @@ xfs_inobt_insert_rec(
        xfs_inofree_t           free,
        int                     *stat)
 {
+       cur->bc_rec.i.ir_holemask = 0;
        cur->bc_rec.i.ir_freecount = freecount;
        cur->bc_rec.i.ir_free = free;
        return xfs_btree_insert(cur, stat);
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
index c9b06f3..0c94879 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
@@ -169,7 +169,9 @@ 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);
+       rec->inobt.ir_holemask = cpu_to_be16(cur->bc_rec.i.ir_holemask);
+       rec->inobt.ir_pad = 0;
+       rec->inobt.ir_freecount = cur->bc_rec.i.ir_freecount;
        rec->inobt.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free);
 }
 
-- 
1.8.3.1

<Prev in Thread] Current Thread [Next in Thread>