GFS2: Add structure to contain rgrp, bitmap, offset tuple
This patch introduces a new structure, gfs2_rbm, which is a
tuple of a resource group, a bitmap within the resource group
and an offset within that bitmap. This is designed to make
manipulating these sets of variables easier. There is also a
new helper function which converts this representation back
to a disk block address.
In addition, the rbtree nodes which are used for the reservations
were not being correctly initialised, which is now fixed. Also,
the tracing was not passing through the inode where it should
have been. That is mostly fixed aside from one corner case. This
needs to be revisited since there can also be a NULL rgrp in
some cases which results in the device being incorrect in the
trace.
This is intended to be the first step towards cleaning up some
of the allocation code, and some further bug fixes.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
+struct gfs2_rbm {
+ struct gfs2_rgrpd *rgd;
+ struct gfs2_bitmap *bi; /* Bitmap must belong to the rgd */
+ u32 offset; /* The offset is bitmap relative */
+};
+
+static inline u64 gfs2_rbm_to_block(const struct gfs2_rbm *rbm)
+{
+ return rbm->rgd->rd_data0 + (rbm->bi->bi_start * GFS2_NBBY) + rbm->offset;
+}
+
enum gfs2_state_bits {
BH_Pinned = BH_PrivateStart,
BH_Escaped = BH_PrivateStart + 1,
@@ -251,13 +262,11 @@ struct gfs2_blkreserv {
atomic_t rs_sizehint; /* hint of the write size */
/* components used during get_local_rgrp (step 3): */
- struct gfs2_rgrpd *rs_rgd; /* pointer to the gfs2_rgrpd */
+ struct gfs2_rbm rs_rbm;
struct gfs2_holder rs_rgd_gh; /* Filled in by get_local_rgrp */
struct rb_node rs_node; /* link to other block reservations */
/* components used during block searches and assignments (step 4): */
- struct gfs2_bitmap *rs_bi; /* bitmap for the current allocation */
- u32 rs_biblk; /* start block relative to the bi */
u32 rs_free; /* how many blocks are still free */
- rgd = rs->rs_rgd;
- /* We can't do this: The reason is that when the rgrp is invalidated,
- it's in the "middle" of acquiring the glock, but the HOLDER bit
- isn't set yet:
- BUG_ON(!gfs2_glock_is_locked_by_me(rs->rs_rgd->rd_gl));*/
- trace_gfs2_rs(NULL, rs, TRACE_RS_TREEDEL);
-
- if (!RB_EMPTY_ROOT(&rgd->rd_rstree))
- rb_erase(&rs->rs_node, &rgd->rd_rstree);
+ rgd = rs->rs_rbm.rgd;
+ trace_gfs2_rs(ip, rs, TRACE_RS_TREEDEL);
+ rb_erase(&rs->rs_node, &rgd->rd_rstree);
+ rb_init_node(&rs->rs_node);
BUG_ON(!rgd->rd_rs_cnt);
rgd->rd_rs_cnt--;
if (rs->rs_free) {
/* return reserved blocks to the rgrp and the ip */
- BUG_ON(rs->rs_rgd->rd_reserved < rs->rs_free);
- rs->rs_rgd->rd_reserved -= rs->rs_free;
+ BUG_ON(rs->rs_rbm.rgd->rd_reserved < rs->rs_free);
+ rs->rs_rbm.rgd->rd_reserved -= rs->rs_free;
rs->rs_free = 0;
- clear_bit(GBF_FULL, &rs->rs_bi->bi_flags);
+ clear_bit(GBF_FULL, &rs->rs_rbm.bi->bi_flags);
smp_mb__after_clear_bit();
}
- /* We can't change any of the step 1 or step 2 components of the rs.
- E.g. We can't set rs_rgd to NULL because the rgd glock is held and
- dequeued through this pointer.
- Can't: atomic_set(&rs->rs_sizehint, 0);
- Can't: rs->rs_rgd = NULL;*/
- rs->rs_bi = NULL;
- rs->rs_biblk = 0;
}
return start_block;
}
@@ -2001,40 +1991,37 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head *dibh;
- struct gfs2_rgrpd *rgd;
+ struct gfs2_rbm rbm = { .rgd = ip->i_rgd, };
unsigned int ndata;
- u32 goal, blk; /* block, within the rgrp scope */
+ u32 goal; /* block, within the rgrp scope */
u64 block; /* block, within the file system scope */
int error;
- struct gfs2_bitmap *bi;
/* If we have a reservation, claim blocks from it. */
if (gfs2_rs_active(ip->i_res)) {
BUG_ON(!ip->i_res->rs_free);
- rgd = ip->i_res->rs_rgd;
+ rbm.rgd = ip->i_res->rs_rbm.rgd;
block = claim_reserved_blks(ip, dinode, nblocks);
if (*nblocks)
goto found_blocks;
}
-/* This is how to tell if a multi-block reservation is in the rgrp tree: */
-static inline int gfs2_rs_active(struct gfs2_blkreserv *rs)
+/* This is how to tell if a reservation is in the rgrp tree: */
+static inline bool gfs2_rs_active(struct gfs2_blkreserv *rs)
{
- if (rs && rs->rs_bi)
- return 1;
- return 0;
+ return rs && !RB_EMPTY_NODE(&rs->rs_node);
}
GFS2: Add structure to contain rgrp, bitmap, offset tuple
----- Original Message -----
|
| This patch introduces a new structure, gfs2_rbm, which is a
| tuple of a resource group, a bitmap within the resource group
| and an offset within that bitmap. This is designed to make
| manipulating these sets of variables easier. There is also a
| new helper function which converts this representation back
| to a disk block address.
|
| In addition, the rbtree nodes which are used for the reservations
| were not being correctly initialised, which is now fixed. Also,
| the tracing was not passing through the inode where it should
| have been. That is mostly fixed aside from one corner case. This
| needs to be revisited since there can also be a NULL rgrp in
| some cases which results in the device being incorrect in the
| trace.
|
| This is intended to be the first step towards cleaning up some
| of the allocation code, and some further bug fixes.
|
| Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
(snip)
| diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
| index a2b43bb..eaa4188 100644
| --- a/fs/gfs2/rgrp.c
| +++ b/fs/gfs2/rgrp.c
(snip)
| @@ -499,8 +501,8 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
| static void dump_rs(struct seq_file *seq, struct gfs2_blkreserv *rs)
| {
| gfs2_print_dbg(seq, " r: %llu s:%llu b:%u f:%u
",
| - rs->rs_rgd->rd_addr, gfs2_rs_startblk(rs), rs->rs_biblk,
| - rs->rs_free);
| + rs->rs_rbm.rgd->rd_addr, gfs2_rbm_to_block(&rs->rs_rbm),
Hm, just fyi: When I copied the patch, I see an extra space (resulting in a
whitespace warning from git) at the end of this last line. On my reply, I don't
see it, so I'm not sure what's going on there.