diff options
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r-- | drivers/md/bitmap.c | 54 |
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 | |||
241 | static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) | 241 | static 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 | ||
291 | static void bitmap_file_kick(struct bitmap *bitmap); | 296 | static 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 | ||