aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJan Schmidt <list.btrfs@jan-o-sch.net>2011-08-04 12:11:04 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2011-09-29 07:38:43 -0400
commit5da6fcbc4eb50c0f55d520750332f5a6ab13508c (patch)
treef9f681b494b8120ab7298a04d45f6081a41869e2 /fs/btrfs
parent4a54c8c165b66300830a67349fc7595e3fc442f7 (diff)
btrfs: integrating raid-repair and scrub-fixup-nodatasum
This ties nodatasum fixup in scrub together with raid repair patches. While both series are working fine alone, scrub will report uncorrectable errors if they occur in a nodatasum extent *and* the page is in the page cache. Previously, we would have triggered readpage to find good data and do the repair. However, readpage wouldn't read anything in the case where the page is up to date in the cache. So, we simply take that good data we have and call repair_io_failure directly (unless the page in the cache is dirty). Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/scrub.c92
1 files changed, 67 insertions, 25 deletions
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 97142a218f0a..eba42e5fd5fd 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -24,6 +24,7 @@
24#include "ordered-data.h" 24#include "ordered-data.h"
25#include "transaction.h" 25#include "transaction.h"
26#include "backref.h" 26#include "backref.h"
27#include "extent_io.h"
27 28
28/* 29/*
29 * This is only the first step towards a full-features scrub. It reads all 30 * This is only the first step towards a full-features scrub. It reads all
@@ -360,13 +361,13 @@ out:
360 361
361static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *ctx) 362static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *ctx)
362{ 363{
363 struct page *page; 364 struct page *page = NULL;
364 unsigned long index; 365 unsigned long index;
365 struct scrub_fixup_nodatasum *fixup = ctx; 366 struct scrub_fixup_nodatasum *fixup = ctx;
366 int ret; 367 int ret;
367 int corrected; 368 int corrected = 0;
368 struct btrfs_key key; 369 struct btrfs_key key;
369 struct inode *inode; 370 struct inode *inode = NULL;
370 u64 end = offset + PAGE_SIZE - 1; 371 u64 end = offset + PAGE_SIZE - 1;
371 struct btrfs_root *local_root; 372 struct btrfs_root *local_root;
372 373
@@ -384,34 +385,75 @@ static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *ctx)
384 if (IS_ERR(inode)) 385 if (IS_ERR(inode))
385 return PTR_ERR(inode); 386 return PTR_ERR(inode);
386 387
387 ret = set_extent_bit(&BTRFS_I(inode)->io_tree, offset, end,
388 EXTENT_DAMAGED, 0, NULL, NULL, GFP_NOFS);
389
390 /* set_extent_bit should either succeed or give proper error */
391 WARN_ON(ret > 0);
392 if (ret)
393 return ret < 0 ? ret : -EFAULT;
394
395 index = offset >> PAGE_CACHE_SHIFT; 388 index = offset >> PAGE_CACHE_SHIFT;
396 389
397 page = find_or_create_page(inode->i_mapping, index, GFP_NOFS); 390 page = find_or_create_page(inode->i_mapping, index, GFP_NOFS);
398 if (!page) 391 if (!page) {
399 return -ENOMEM; 392 ret = -ENOMEM;
393 goto out;
394 }
395
396 if (PageUptodate(page)) {
397 struct btrfs_mapping_tree *map_tree;
398 if (PageDirty(page)) {
399 /*
400 * we need to write the data to the defect sector. the
401 * data that was in that sector is not in memory,
402 * because the page was modified. we must not write the
403 * modified page to that sector.
404 *
405 * TODO: what could be done here: wait for the delalloc
406 * runner to write out that page (might involve
407 * COW) and see whether the sector is still
408 * referenced afterwards.
409 *
410 * For the meantime, we'll treat this error
411 * incorrectable, although there is a chance that a
412 * later scrub will find the bad sector again and that
413 * there's no dirty page in memory, then.
414 */
415 ret = -EIO;
416 goto out;
417 }
418 map_tree = &BTRFS_I(inode)->root->fs_info->mapping_tree;
419 ret = repair_io_failure(map_tree, offset, PAGE_SIZE,
420 fixup->logical, page,
421 fixup->mirror_num);
422 unlock_page(page);
423 corrected = !ret;
424 } else {
425 /*
426 * we need to get good data first. the general readpage path
427 * will call repair_io_failure for us, we just have to make
428 * sure we read the bad mirror.
429 */
430 ret = set_extent_bits(&BTRFS_I(inode)->io_tree, offset, end,
431 EXTENT_DAMAGED, GFP_NOFS);
432 if (ret) {
433 /* set_extent_bits should give proper error */
434 WARN_ON(ret > 0);
435 if (ret > 0)
436 ret = -EFAULT;
437 goto out;
438 }
400 439
401 ret = extent_read_full_page(&BTRFS_I(inode)->io_tree, page, 440 ret = extent_read_full_page(&BTRFS_I(inode)->io_tree, page,
402 btrfs_get_extent, fixup->mirror_num); 441 btrfs_get_extent,
403 wait_on_page_locked(page); 442 fixup->mirror_num);
404 corrected = !test_range_bit(&BTRFS_I(inode)->io_tree, offset, end, 443 wait_on_page_locked(page);
405 EXTENT_DAMAGED, 0, NULL);
406 444
407 if (corrected) 445 corrected = !test_range_bit(&BTRFS_I(inode)->io_tree, offset,
408 WARN_ON(!PageUptodate(page)); 446 end, EXTENT_DAMAGED, 0, NULL);
409 else 447 if (!corrected)
410 clear_extent_bit(&BTRFS_I(inode)->io_tree, offset, end, 448 clear_extent_bits(&BTRFS_I(inode)->io_tree, offset, end,
411 EXTENT_DAMAGED, 0, 0, NULL, GFP_NOFS); 449 EXTENT_DAMAGED, GFP_NOFS);
450 }
412 451
413 put_page(page); 452out:
414 iput(inode); 453 if (page)
454 put_page(page);
455 if (inode)
456 iput(inode);
415 457
416 if (ret < 0) 458 if (ret < 0)
417 return ret; 459 return ret;