aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/bitmap.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2010-06-01 05:37:33 -0400
committerNeilBrown <neilb@suse.de>2010-07-25 23:21:32 -0400
commitef4256733506f2459a0c436b62267d22a3f0cec6 (patch)
treec73e1849052f56a8f6033498f7fbd65c6259c776 /drivers/md/bitmap.c
parentb63d7c2e29bf9cc94989806f2df0cfca4976b830 (diff)
md/bitmap: optimise scanning of empty bitmaps.
A bitmap is stored as one page per 2048 bits. If none of the bits are set, the page is not allocated. When bitmap_get_counter finds that a page isn't allocate, it just reports that one bit work of space isn't flagged, rather than reporting that 2048 bits worth of space are unflagged. This can cause searches for flagged bits (e.g. bitmap_close_sync) to do more work than is really necessary. So change bitmap_get_counter (when creating) to report a number of blocks that more accurately reports the range of the device for which no counter currently exists. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r--drivers/md/bitmap.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 3f04699725db..29a3c864e6b0 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1235,29 +1235,32 @@ __acquires(bitmap->lock)
1235 unsigned long page = chunk >> PAGE_COUNTER_SHIFT; 1235 unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
1236 unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT; 1236 unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT;
1237 sector_t csize; 1237 sector_t csize;
1238 int err;
1239
1240 err = bitmap_checkpage(bitmap, page, create);
1238 1241
1239 if (bitmap_checkpage(bitmap, page, create) < 0) { 1242 if (bitmap->bp[page].hijacked ||
1243 bitmap->bp[page].map == NULL)
1244 csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap) +
1245 PAGE_COUNTER_SHIFT - 1);
1246 else
1240 csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap)); 1247 csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap));
1241 *blocks = csize - (offset & (csize - 1)); 1248 *blocks = csize - (offset & (csize - 1));
1249
1250 if (err < 0)
1242 return NULL; 1251 return NULL;
1243 } 1252
1244 /* now locked ... */ 1253 /* now locked ... */
1245 1254
1246 if (bitmap->bp[page].hijacked) { /* hijacked pointer */ 1255 if (bitmap->bp[page].hijacked) { /* hijacked pointer */
1247 /* should we use the first or second counter field 1256 /* should we use the first or second counter field
1248 * of the hijacked pointer? */ 1257 * of the hijacked pointer? */
1249 int hi = (pageoff > PAGE_COUNTER_MASK); 1258 int hi = (pageoff > PAGE_COUNTER_MASK);
1250 csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap) +
1251 PAGE_COUNTER_SHIFT - 1);
1252 *blocks = csize - (offset & (csize - 1));
1253 return &((bitmap_counter_t *) 1259 return &((bitmap_counter_t *)
1254 &bitmap->bp[page].map)[hi]; 1260 &bitmap->bp[page].map)[hi];
1255 } else { /* page is allocated */ 1261 } else /* page is allocated */
1256 csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap));
1257 *blocks = csize - (offset & (csize - 1));
1258 return (bitmap_counter_t *) 1262 return (bitmap_counter_t *)
1259 &(bitmap->bp[page].map[pageoff]); 1263 &(bitmap->bp[page].map[pageoff]);
1260 }
1261} 1264}
1262 1265
1263int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int behind) 1266int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int behind)