diff options
author | NeilBrown <neilb@suse.de> | 2012-05-21 23:55:08 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-05-21 23:55:08 -0400 |
commit | 27581e5ae01f77b5472dc5c2368b41063fed7f37 (patch) | |
tree | 202d2ee37bcfb82ce09bc72c0d3d81045a941637 /drivers/md/bitmap.c | |
parent | ef99bf480de9bde9d3b2afdf05324670fab4e571 (diff) |
md/bitmap: centralise allocation of bitmap file pages.
Instead of allocating pages in read_sb_page, read_page and
bitmap_read_sb, allocate them all in bitmap_init_from disk.
Also replace the hack of calling "attach_page_buffers(page, NULL)" to
ensure that free_buffer() won't complain, by putting a test for
PagePrivate in free_buffer().
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r-- | drivers/md/bitmap.c | 149 |
1 files changed, 68 insertions, 81 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index c042efd019c3..324a198e8be7 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -130,22 +130,14 @@ static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) | |||
130 | */ | 130 | */ |
131 | 131 | ||
132 | /* IO operations when bitmap is stored near all superblocks */ | 132 | /* IO operations when bitmap is stored near all superblocks */ |
133 | static struct page *read_sb_page(struct mddev *mddev, loff_t offset, | 133 | static int read_sb_page(struct mddev *mddev, loff_t offset, |
134 | struct page *page, | 134 | struct page *page, |
135 | unsigned long index, int size) | 135 | unsigned long index, int size) |
136 | { | 136 | { |
137 | /* choose a good rdev and read the page from there */ | 137 | /* choose a good rdev and read the page from there */ |
138 | 138 | ||
139 | struct md_rdev *rdev; | 139 | struct md_rdev *rdev; |
140 | sector_t target; | 140 | sector_t target; |
141 | int did_alloc = 0; | ||
142 | |||
143 | if (!page) { | ||
144 | page = alloc_page(GFP_KERNEL); | ||
145 | if (!page) | ||
146 | return ERR_PTR(-ENOMEM); | ||
147 | did_alloc = 1; | ||
148 | } | ||
149 | 141 | ||
150 | rdev_for_each(rdev, mddev) { | 142 | rdev_for_each(rdev, mddev) { |
151 | if (! test_bit(In_sync, &rdev->flags) | 143 | if (! test_bit(In_sync, &rdev->flags) |
@@ -158,15 +150,10 @@ static struct page *read_sb_page(struct mddev *mddev, loff_t offset, | |||
158 | roundup(size, bdev_logical_block_size(rdev->bdev)), | 150 | roundup(size, bdev_logical_block_size(rdev->bdev)), |
159 | page, READ, true)) { | 151 | page, READ, true)) { |
160 | page->index = index; | 152 | page->index = index; |
161 | attach_page_buffers(page, NULL); /* so that free_buffer will | 153 | return 0; |
162 | * quietly no-op */ | ||
163 | return page; | ||
164 | } | 154 | } |
165 | } | 155 | } |
166 | if (did_alloc) | 156 | return -EIO; |
167 | put_page(page); | ||
168 | return ERR_PTR(-EIO); | ||
169 | |||
170 | } | 157 | } |
171 | 158 | ||
172 | static struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mddev) | 159 | static struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mddev) |
@@ -325,8 +312,12 @@ __clear_page_buffers(struct page *page) | |||
325 | } | 312 | } |
326 | static void free_buffers(struct page *page) | 313 | static void free_buffers(struct page *page) |
327 | { | 314 | { |
328 | struct buffer_head *bh = page_buffers(page); | 315 | struct buffer_head *bh; |
329 | 316 | ||
317 | if (!PagePrivate(page)) | ||
318 | return; | ||
319 | |||
320 | bh = page_buffers(page); | ||
330 | while (bh) { | 321 | while (bh) { |
331 | struct buffer_head *next = bh->b_this_page; | 322 | struct buffer_head *next = bh->b_this_page; |
332 | free_buffer_head(bh); | 323 | free_buffer_head(bh); |
@@ -343,11 +334,12 @@ static void free_buffers(struct page *page) | |||
343 | * This usage is similar to how swap files are handled, and allows us | 334 | * This usage is similar to how swap files are handled, and allows us |
344 | * to write to a file with no concerns of memory allocation failing. | 335 | * to write to a file with no concerns of memory allocation failing. |
345 | */ | 336 | */ |
346 | static struct page *read_page(struct file *file, unsigned long index, | 337 | static int read_page(struct file *file, unsigned long index, |
347 | struct bitmap *bitmap, | 338 | struct bitmap *bitmap, |
348 | unsigned long count) | 339 | unsigned long count, |
340 | struct page *page) | ||
349 | { | 341 | { |
350 | struct page *page = NULL; | 342 | int ret = 0; |
351 | struct inode *inode = file->f_path.dentry->d_inode; | 343 | struct inode *inode = file->f_path.dentry->d_inode; |
352 | struct buffer_head *bh; | 344 | struct buffer_head *bh; |
353 | sector_t block; | 345 | sector_t block; |
@@ -355,16 +347,9 @@ static struct page *read_page(struct file *file, unsigned long index, | |||
355 | pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE, | 347 | pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE, |
356 | (unsigned long long)index << PAGE_SHIFT); | 348 | (unsigned long long)index << PAGE_SHIFT); |
357 | 349 | ||
358 | page = alloc_page(GFP_KERNEL); | ||
359 | if (!page) | ||
360 | page = ERR_PTR(-ENOMEM); | ||
361 | if (IS_ERR(page)) | ||
362 | goto out; | ||
363 | |||
364 | bh = alloc_page_buffers(page, 1<<inode->i_blkbits, 0); | 350 | bh = alloc_page_buffers(page, 1<<inode->i_blkbits, 0); |
365 | if (!bh) { | 351 | if (!bh) { |
366 | put_page(page); | 352 | ret = -ENOMEM; |
367 | page = ERR_PTR(-ENOMEM); | ||
368 | goto out; | 353 | goto out; |
369 | } | 354 | } |
370 | attach_page_buffers(page, bh); | 355 | attach_page_buffers(page, bh); |
@@ -376,8 +361,7 @@ static struct page *read_page(struct file *file, unsigned long index, | |||
376 | bh->b_blocknr = bmap(inode, block); | 361 | bh->b_blocknr = bmap(inode, block); |
377 | if (bh->b_blocknr == 0) { | 362 | if (bh->b_blocknr == 0) { |
378 | /* Cannot use this file! */ | 363 | /* Cannot use this file! */ |
379 | free_buffers(page); | 364 | ret = -EINVAL; |
380 | page = ERR_PTR(-EINVAL); | ||
381 | goto out; | 365 | goto out; |
382 | } | 366 | } |
383 | bh->b_bdev = inode->i_sb->s_bdev; | 367 | bh->b_bdev = inode->i_sb->s_bdev; |
@@ -400,17 +384,15 @@ static struct page *read_page(struct file *file, unsigned long index, | |||
400 | 384 | ||
401 | wait_event(bitmap->write_wait, | 385 | wait_event(bitmap->write_wait, |
402 | atomic_read(&bitmap->pending_writes)==0); | 386 | atomic_read(&bitmap->pending_writes)==0); |
403 | if (bitmap->flags & BITMAP_WRITE_ERROR) { | 387 | if (bitmap->flags & BITMAP_WRITE_ERROR) |
404 | free_buffers(page); | 388 | ret = -EIO; |
405 | page = ERR_PTR(-EIO); | ||
406 | } | ||
407 | out: | 389 | out: |
408 | if (IS_ERR(page)) | 390 | if (ret) |
409 | printk(KERN_ALERT "md: bitmap read error: (%dB @ %llu): %ld\n", | 391 | printk(KERN_ALERT "md: bitmap read error: (%dB @ %llu): %d\n", |
410 | (int)PAGE_SIZE, | 392 | (int)PAGE_SIZE, |
411 | (unsigned long long)index << PAGE_SHIFT, | 393 | (unsigned long long)index << PAGE_SHIFT, |
412 | PTR_ERR(page)); | 394 | ret); |
413 | return page; | 395 | return ret; |
414 | } | 396 | } |
415 | 397 | ||
416 | /* | 398 | /* |
@@ -552,6 +534,7 @@ static int bitmap_read_sb(struct bitmap *bitmap) | |||
552 | unsigned long chunksize, daemon_sleep, write_behind; | 534 | unsigned long chunksize, daemon_sleep, write_behind; |
553 | unsigned long long events; | 535 | unsigned long long events; |
554 | int err = -EINVAL; | 536 | int err = -EINVAL; |
537 | struct page *sb_page; | ||
555 | 538 | ||
556 | if (!bitmap->file && !bitmap->mddev->bitmap_info.offset) { | 539 | if (!bitmap->file && !bitmap->mddev->bitmap_info.offset) { |
557 | chunksize = 128 * 1024 * 1024; | 540 | chunksize = 128 * 1024 * 1024; |
@@ -562,24 +545,27 @@ static int bitmap_read_sb(struct bitmap *bitmap) | |||
562 | goto out_no_sb; | 545 | goto out_no_sb; |
563 | } | 546 | } |
564 | /* page 0 is the superblock, read it... */ | 547 | /* page 0 is the superblock, read it... */ |
548 | sb_page = alloc_page(GFP_KERNEL); | ||
549 | if (!sb_page) | ||
550 | return -ENOMEM; | ||
551 | bitmap->sb_page = sb_page; | ||
552 | |||
565 | if (bitmap->file) { | 553 | if (bitmap->file) { |
566 | loff_t isize = i_size_read(bitmap->file->f_mapping->host); | 554 | loff_t isize = i_size_read(bitmap->file->f_mapping->host); |
567 | int bytes = isize > PAGE_SIZE ? PAGE_SIZE : isize; | 555 | int bytes = isize > PAGE_SIZE ? PAGE_SIZE : isize; |
568 | 556 | ||
569 | bitmap->sb_page = read_page(bitmap->file, 0, bitmap, bytes); | 557 | err = read_page(bitmap->file, 0, |
558 | bitmap, bytes, sb_page); | ||
570 | } else { | 559 | } else { |
571 | bitmap->sb_page = read_sb_page(bitmap->mddev, | 560 | err = read_sb_page(bitmap->mddev, |
572 | bitmap->mddev->bitmap_info.offset, | 561 | bitmap->mddev->bitmap_info.offset, |
573 | NULL, | 562 | sb_page, |
574 | 0, sizeof(bitmap_super_t)); | 563 | 0, sizeof(bitmap_super_t)); |
575 | } | 564 | } |
576 | if (IS_ERR(bitmap->sb_page)) { | 565 | if (err) |
577 | err = PTR_ERR(bitmap->sb_page); | ||
578 | bitmap->sb_page = NULL; | ||
579 | return err; | 566 | return err; |
580 | } | ||
581 | 567 | ||
582 | sb = kmap_atomic(bitmap->sb_page); | 568 | sb = kmap_atomic(sb_page); |
583 | 569 | ||
584 | chunksize = le32_to_cpu(sb->chunksize); | 570 | chunksize = le32_to_cpu(sb->chunksize); |
585 | daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ; | 571 | daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ; |
@@ -948,7 +934,8 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n | |||
948 | static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) | 934 | static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) |
949 | { | 935 | { |
950 | unsigned long i, chunks, index, oldindex, bit; | 936 | unsigned long i, chunks, index, oldindex, bit; |
951 | struct page *page = NULL, *oldpage = NULL; | 937 | int pnum; |
938 | struct page *page = NULL; | ||
952 | unsigned long num_pages, bit_cnt = 0; | 939 | unsigned long num_pages, bit_cnt = 0; |
953 | struct file *file; | 940 | struct file *file; |
954 | unsigned long bytes, offset; | 941 | unsigned long bytes, offset; |
@@ -999,6 +986,22 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) | |||
999 | if (!bitmap->filemap) | 986 | if (!bitmap->filemap) |
1000 | goto err; | 987 | goto err; |
1001 | 988 | ||
989 | pnum = 0; | ||
990 | offset = 0; | ||
991 | if (bitmap->sb_page) { | ||
992 | bitmap->filemap[0] = bitmap->sb_page; | ||
993 | pnum = 1; | ||
994 | offset = sizeof(bitmap_super_t); | ||
995 | } | ||
996 | for ( ; pnum < num_pages; pnum++) { | ||
997 | bitmap->filemap[pnum] = alloc_page(GFP_KERNEL); | ||
998 | if (!bitmap->filemap[pnum]) { | ||
999 | bitmap->file_pages = pnum; | ||
1000 | goto err; | ||
1001 | } | ||
1002 | } | ||
1003 | bitmap->file_pages = pnum; | ||
1004 | |||
1002 | /* We need 4 bits per page, rounded up to a multiple of sizeof(unsigned long) */ | 1005 | /* We need 4 bits per page, rounded up to a multiple of sizeof(unsigned long) */ |
1003 | bitmap->filemap_attr = kzalloc( | 1006 | bitmap->filemap_attr = kzalloc( |
1004 | roundup(DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)), | 1007 | roundup(DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)), |
@@ -1019,39 +1022,22 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) | |||
1019 | count = bytes - index * PAGE_SIZE; | 1022 | count = bytes - index * PAGE_SIZE; |
1020 | else | 1023 | else |
1021 | count = PAGE_SIZE; | 1024 | count = PAGE_SIZE; |
1022 | if (index == 0 && bitmap->sb_page) { | 1025 | page = bitmap->filemap[index]; |
1023 | /* | 1026 | if (file) |
1024 | * if we're here then the superblock page | 1027 | ret = read_page(file, index, bitmap, |
1025 | * contains some bits (PAGE_SIZE != sizeof sb) | 1028 | count, page); |
1026 | * we've already read it in, so just use it | 1029 | else |
1027 | */ | 1030 | ret = read_sb_page( |
1028 | page = bitmap->sb_page; | 1031 | bitmap->mddev, |
1029 | offset = sizeof(bitmap_super_t); | 1032 | bitmap->mddev->bitmap_info.offset, |
1030 | if (!file) | 1033 | page, |
1031 | page = read_sb_page( | 1034 | index, count); |
1032 | bitmap->mddev, | 1035 | |
1033 | bitmap->mddev->bitmap_info.offset, | 1036 | if (ret) |
1034 | page, | ||
1035 | index, count); | ||
1036 | } else if (file) { | ||
1037 | page = read_page(file, index, bitmap, count); | ||
1038 | offset = 0; | ||
1039 | } else { | ||
1040 | page = read_sb_page(bitmap->mddev, | ||
1041 | bitmap->mddev->bitmap_info.offset, | ||
1042 | NULL, | ||
1043 | index, count); | ||
1044 | offset = 0; | ||
1045 | } | ||
1046 | if (IS_ERR(page)) { /* read error */ | ||
1047 | ret = PTR_ERR(page); | ||
1048 | goto err; | 1037 | goto err; |
1049 | } | ||
1050 | 1038 | ||
1051 | oldindex = index; | 1039 | oldindex = index; |
1052 | oldpage = page; | ||
1053 | 1040 | ||
1054 | bitmap->filemap[bitmap->file_pages++] = page; | ||
1055 | bitmap->last_page_size = count; | 1041 | bitmap->last_page_size = count; |
1056 | 1042 | ||
1057 | if (outofdate) { | 1043 | if (outofdate) { |
@@ -1085,6 +1071,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) | |||
1085 | needed); | 1071 | needed); |
1086 | bit_cnt++; | 1072 | bit_cnt++; |
1087 | } | 1073 | } |
1074 | offset = 0; | ||
1088 | } | 1075 | } |
1089 | 1076 | ||
1090 | printk(KERN_INFO "%s: bitmap initialized from disk: " | 1077 | printk(KERN_INFO "%s: bitmap initialized from disk: " |