aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2018-08-07 11:07:00 -0400
committerBob Peterson <rpeterso@redhat.com>2018-08-07 11:07:00 -0400
commitdffe12a82826082d2129ef91b17b257254cb60fc (patch)
tree8fea704759c5760f46a27468f6d8ec4dbbcc5c15
parent21e2156f3c4b2ad8b780a6d02342ca0e028a8acd (diff)
gfs2: Fix gfs2_testbit to use clone bitmaps
Function gfs2_testbit is called in three places. Two of those places, gfs2_alloc_extent and gfs2_unaligned_extlen, should be using the clone bitmaps, not the "real" bitmaps. Function gfs2_unaligned_extlen is used by the block reservations scheme to determine the length of an extent of free blocks. Before this patch, it wasn't using the clone bitmap, which means recently-freed blocks were treated as free blocks for the purposes of an allocation. This patch adds a new parameter to gfs2_testbit to indicate whether or not the clone bitmaps should be used (if available). Signed-off-by: Bob Peterson <rpeterso@redhat.com> Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
-rw-r--r--fs/gfs2/incore.h21
-rw-r--r--fs/gfs2/rgrp.c44
2 files changed, 40 insertions, 25 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index b50908211b69..b96d39c28e17 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -65,6 +65,27 @@ struct gfs2_log_operations {
65 65
66#define GBF_FULL 1 66#define GBF_FULL 1
67 67
68/**
69 * Clone bitmaps (bi_clone):
70 *
71 * - When a block is freed, we remember the previous state of the block in the
72 * clone bitmap, and only mark the block as free in the real bitmap.
73 *
74 * - When looking for a block to allocate, we check for a free block in the
75 * clone bitmap, and if no clone bitmap exists, in the real bitmap.
76 *
77 * - For allocating a block, we mark it as allocated in the real bitmap, and if
78 * a clone bitmap exists, also in the clone bitmap.
79 *
80 * - At the end of a log_flush, we copy the real bitmap into the clone bitmap
81 * to make the clone bitmap reflect the current allocation state.
82 * (Alternatively, we could remove the clone bitmap.)
83 *
84 * The clone bitmaps are in-core only, and is never written to disk.
85 *
86 * These steps ensure that blocks which have been freed in a transaction cannot
87 * be reallocated in that same transaction.
88 */
68struct gfs2_bitmap { 89struct gfs2_bitmap {
69 struct buffer_head *bi_bh; 90 struct buffer_head *bi_bh;
70 char *bi_clone; 91 char *bi_clone;
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 7c5afeba8888..ef50fe9b880a 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -123,17 +123,26 @@ static inline void gfs2_setbit(const struct gfs2_rbm *rbm, bool do_clone,
123/** 123/**
124 * gfs2_testbit - test a bit in the bitmaps 124 * gfs2_testbit - test a bit in the bitmaps
125 * @rbm: The bit to test 125 * @rbm: The bit to test
126 * @use_clone: If true, test the clone bitmap, not the official bitmap.
127 *
128 * Some callers like gfs2_unaligned_extlen need to test the clone bitmaps,
129 * not the "real" bitmaps, to avoid allocating recently freed blocks.
126 * 130 *
127 * Returns: The two bit block state of the requested bit 131 * Returns: The two bit block state of the requested bit
128 */ 132 */
129 133
130static inline u8 gfs2_testbit(const struct gfs2_rbm *rbm) 134static inline u8 gfs2_testbit(const struct gfs2_rbm *rbm, bool use_clone)
131{ 135{
132 struct gfs2_bitmap *bi = rbm_bi(rbm); 136 struct gfs2_bitmap *bi = rbm_bi(rbm);
133 const u8 *buffer = bi->bi_bh->b_data + bi->bi_offset; 137 const u8 *buffer;
134 const u8 *byte; 138 const u8 *byte;
135 unsigned int bit; 139 unsigned int bit;
136 140
141 if (use_clone && bi->bi_clone)
142 buffer = bi->bi_clone;
143 else
144 buffer = bi->bi_bh->b_data;
145 buffer += bi->bi_offset;
137 byte = buffer + (rbm->offset / GFS2_NBBY); 146 byte = buffer + (rbm->offset / GFS2_NBBY);
138 bit = (rbm->offset % GFS2_NBBY) * GFS2_BIT_SIZE; 147 bit = (rbm->offset % GFS2_NBBY) * GFS2_BIT_SIZE;
139 148
@@ -322,7 +331,7 @@ static bool gfs2_unaligned_extlen(struct gfs2_rbm *rbm, u32 n_unaligned, u32 *le
322 u8 res; 331 u8 res;
323 332
324 for (n = 0; n < n_unaligned; n++) { 333 for (n = 0; n < n_unaligned; n++) {
325 res = gfs2_testbit(rbm); 334 res = gfs2_testbit(rbm, true);
326 if (res != GFS2_BLKST_FREE) 335 if (res != GFS2_BLKST_FREE)
327 return true; 336 return true;
328 (*len)--; 337 (*len)--;
@@ -2147,26 +2156,6 @@ void gfs2_inplace_release(struct gfs2_inode *ip)
2147} 2156}
2148 2157
2149/** 2158/**
2150 * gfs2_get_block_type - Check a block in a RG is of given type
2151 * @rgd: the resource group holding the block
2152 * @block: the block number
2153 *
2154 * Returns: The block type (GFS2_BLKST_*)
2155 */
2156
2157static unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
2158{
2159 struct gfs2_rbm rbm = { .rgd = rgd, };
2160 int ret;
2161
2162 ret = gfs2_rbm_from_block(&rbm, block);
2163 WARN_ON_ONCE(ret != 0);
2164
2165 return gfs2_testbit(&rbm);
2166}
2167
2168
2169/**
2170 * gfs2_alloc_extent - allocate an extent from a given bitmap 2159 * gfs2_alloc_extent - allocate an extent from a given bitmap
2171 * @rbm: the resource group information 2160 * @rbm: the resource group information
2172 * @dinode: TRUE if the first block we allocate is for a dinode 2161 * @dinode: TRUE if the first block we allocate is for a dinode
@@ -2190,7 +2179,7 @@ static void gfs2_alloc_extent(const struct gfs2_rbm *rbm, bool dinode,
2190 block++; 2179 block++;
2191 while (*n < elen) { 2180 while (*n < elen) {
2192 ret = gfs2_rbm_from_block(&pos, block); 2181 ret = gfs2_rbm_from_block(&pos, block);
2193 if (ret || gfs2_testbit(&pos) != GFS2_BLKST_FREE) 2182 if (ret || gfs2_testbit(&pos, true) != GFS2_BLKST_FREE)
2194 break; 2183 break;
2195 gfs2_trans_add_meta(pos.rgd->rd_gl, rbm_bi(&pos)->bi_bh); 2184 gfs2_trans_add_meta(pos.rgd->rd_gl, rbm_bi(&pos)->bi_bh);
2196 gfs2_setbit(&pos, true, GFS2_BLKST_USED); 2185 gfs2_setbit(&pos, true, GFS2_BLKST_USED);
@@ -2543,6 +2532,7 @@ int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type)
2543{ 2532{
2544 struct gfs2_rgrpd *rgd; 2533 struct gfs2_rgrpd *rgd;
2545 struct gfs2_holder rgd_gh; 2534 struct gfs2_holder rgd_gh;
2535 struct gfs2_rbm rbm;
2546 int error = -EINVAL; 2536 int error = -EINVAL;
2547 2537
2548 rgd = gfs2_blk2rgrpd(sdp, no_addr, 1); 2538 rgd = gfs2_blk2rgrpd(sdp, no_addr, 1);
@@ -2553,7 +2543,11 @@ int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type)
2553 if (error) 2543 if (error)
2554 goto fail; 2544 goto fail;
2555 2545
2556 if (gfs2_get_block_type(rgd, no_addr) != type) 2546 rbm.rgd = rgd;
2547 error = gfs2_rbm_from_block(&rbm, no_addr);
2548 WARN_ON_ONCE(error != 0);
2549
2550 if (gfs2_testbit(&rbm, false) != type)
2557 error = -ESTALE; 2551 error = -ESTALE;
2558 2552
2559 gfs2_glock_dq_uninit(&rgd_gh); 2553 gfs2_glock_dq_uninit(&rgd_gh);