aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r--drivers/md/bitmap.c54
1 files changed, 39 insertions, 15 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index b26927ce889c..621a272a2c74 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -225,7 +225,7 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
225 || test_bit(Faulty, &rdev->flags)) 225 || test_bit(Faulty, &rdev->flags))
226 continue; 226 continue;
227 227
228 target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512); 228 target = rdev->sb_start + offset + index * (PAGE_SIZE/512);
229 229
230 if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) { 230 if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) {
231 page->index = index; 231 page->index = index;
@@ -241,10 +241,10 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
241static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) 241static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
242{ 242{
243 mdk_rdev_t *rdev; 243 mdk_rdev_t *rdev;
244 struct list_head *tmp;
245 mddev_t *mddev = bitmap->mddev; 244 mddev_t *mddev = bitmap->mddev;
246 245
247 rdev_for_each(rdev, tmp, mddev) 246 rcu_read_lock();
247 rdev_for_each_rcu(rdev, mddev)
248 if (test_bit(In_sync, &rdev->flags) 248 if (test_bit(In_sync, &rdev->flags)
249 && !test_bit(Faulty, &rdev->flags)) { 249 && !test_bit(Faulty, &rdev->flags)) {
250 int size = PAGE_SIZE; 250 int size = PAGE_SIZE;
@@ -260,32 +260,37 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
260 + (long)(page->index * (PAGE_SIZE/512)) 260 + (long)(page->index * (PAGE_SIZE/512))
261 + size/512 > 0) 261 + size/512 > 0)
262 /* bitmap runs in to metadata */ 262 /* bitmap runs in to metadata */
263 return -EINVAL; 263 goto bad_alignment;
264 if (rdev->data_offset + mddev->size*2 264 if (rdev->data_offset + mddev->size*2
265 > rdev->sb_offset*2 + bitmap->offset) 265 > rdev->sb_start + bitmap->offset)
266 /* data runs in to bitmap */ 266 /* data runs in to bitmap */
267 return -EINVAL; 267 goto bad_alignment;
268 } else if (rdev->sb_offset*2 < rdev->data_offset) { 268 } else if (rdev->sb_start < rdev->data_offset) {
269 /* METADATA BITMAP DATA */ 269 /* METADATA BITMAP DATA */
270 if (rdev->sb_offset*2 270 if (rdev->sb_start
271 + bitmap->offset 271 + bitmap->offset
272 + page->index*(PAGE_SIZE/512) + size/512 272 + page->index*(PAGE_SIZE/512) + size/512
273 > rdev->data_offset) 273 > rdev->data_offset)
274 /* bitmap runs in to data */ 274 /* bitmap runs in to data */
275 return -EINVAL; 275 goto bad_alignment;
276 } else { 276 } else {
277 /* DATA METADATA BITMAP - no problems */ 277 /* DATA METADATA BITMAP - no problems */
278 } 278 }
279 md_super_write(mddev, rdev, 279 md_super_write(mddev, rdev,
280 (rdev->sb_offset<<1) + bitmap->offset 280 rdev->sb_start + bitmap->offset
281 + page->index * (PAGE_SIZE/512), 281 + page->index * (PAGE_SIZE/512),
282 size, 282 size,
283 page); 283 page);
284 } 284 }
285 rcu_read_unlock();
285 286
286 if (wait) 287 if (wait)
287 md_super_wait(mddev); 288 md_super_wait(mddev);
288 return 0; 289 return 0;
290
291 bad_alignment:
292 rcu_read_unlock();
293 return -EINVAL;
289} 294}
290 295
291static void bitmap_file_kick(struct bitmap *bitmap); 296static void bitmap_file_kick(struct bitmap *bitmap);
@@ -454,8 +459,11 @@ void bitmap_update_sb(struct bitmap *bitmap)
454 spin_unlock_irqrestore(&bitmap->lock, flags); 459 spin_unlock_irqrestore(&bitmap->lock, flags);
455 sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); 460 sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
456 sb->events = cpu_to_le64(bitmap->mddev->events); 461 sb->events = cpu_to_le64(bitmap->mddev->events);
457 if (!bitmap->mddev->degraded) 462 if (bitmap->mddev->events < bitmap->events_cleared) {
458 sb->events_cleared = cpu_to_le64(bitmap->mddev->events); 463 /* rocking back to read-only */
464 bitmap->events_cleared = bitmap->mddev->events;
465 sb->events_cleared = cpu_to_le64(bitmap->events_cleared);
466 }
459 kunmap_atomic(sb, KM_USER0); 467 kunmap_atomic(sb, KM_USER0);
460 write_page(bitmap, bitmap->sb_page, 1); 468 write_page(bitmap, bitmap->sb_page, 1);
461} 469}
@@ -1085,9 +1093,19 @@ void bitmap_daemon_work(struct bitmap *bitmap)
1085 } else 1093 } else
1086 spin_unlock_irqrestore(&bitmap->lock, flags); 1094 spin_unlock_irqrestore(&bitmap->lock, flags);
1087 lastpage = page; 1095 lastpage = page;
1088/* 1096
1089 printk("bitmap clean at page %lu\n", j); 1097 /* We are possibly going to clear some bits, so make
1090*/ 1098 * sure that events_cleared is up-to-date.
1099 */
1100 if (bitmap->need_sync) {
1101 bitmap_super_t *sb;
1102 bitmap->need_sync = 0;
1103 sb = kmap_atomic(bitmap->sb_page, KM_USER0);
1104 sb->events_cleared =
1105 cpu_to_le64(bitmap->events_cleared);
1106 kunmap_atomic(sb, KM_USER0);
1107 write_page(bitmap, bitmap->sb_page, 1);
1108 }
1091 spin_lock_irqsave(&bitmap->lock, flags); 1109 spin_lock_irqsave(&bitmap->lock, flags);
1092 clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); 1110 clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
1093 } 1111 }
@@ -1257,6 +1275,12 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
1257 return; 1275 return;
1258 } 1276 }
1259 1277
1278 if (success &&
1279 bitmap->events_cleared < bitmap->mddev->events) {
1280 bitmap->events_cleared = bitmap->mddev->events;
1281 bitmap->need_sync = 1;
1282 }
1283
1260 if (!success && ! (*bmc & NEEDED_MASK)) 1284 if (!success && ! (*bmc & NEEDED_MASK))
1261 *bmc |= NEEDED_MASK; 1285 *bmc |= NEEDED_MASK;
1262 1286