diff options
Diffstat (limited to 'fs/btrfs/scrub.c')
-rw-r--r-- | fs/btrfs/scrub.c | 71 |
1 files changed, 35 insertions, 36 deletions
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index ed11d3866afd..c27bcb67f330 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -256,6 +256,11 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx) | |||
256 | btrfs_release_path(swarn->path); | 256 | btrfs_release_path(swarn->path); |
257 | 257 | ||
258 | ipath = init_ipath(4096, local_root, swarn->path); | 258 | ipath = init_ipath(4096, local_root, swarn->path); |
259 | if (IS_ERR(ipath)) { | ||
260 | ret = PTR_ERR(ipath); | ||
261 | ipath = NULL; | ||
262 | goto err; | ||
263 | } | ||
259 | ret = paths_from_inode(inum, ipath); | 264 | ret = paths_from_inode(inum, ipath); |
260 | 265 | ||
261 | if (ret < 0) | 266 | if (ret < 0) |
@@ -272,7 +277,7 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx) | |||
272 | swarn->logical, swarn->dev->name, | 277 | swarn->logical, swarn->dev->name, |
273 | (unsigned long long)swarn->sector, root, inum, offset, | 278 | (unsigned long long)swarn->sector, root, inum, offset, |
274 | min(isize - offset, (u64)PAGE_SIZE), nlink, | 279 | min(isize - offset, (u64)PAGE_SIZE), nlink, |
275 | (char *)ipath->fspath->val[i]); | 280 | (char *)(unsigned long)ipath->fspath->val[i]); |
276 | 281 | ||
277 | free_ipath(ipath); | 282 | free_ipath(ipath); |
278 | return 0; | 283 | return 0; |
@@ -944,50 +949,18 @@ static int scrub_checksum_super(struct scrub_bio *sbio, void *buffer) | |||
944 | static int scrub_submit(struct scrub_dev *sdev) | 949 | static int scrub_submit(struct scrub_dev *sdev) |
945 | { | 950 | { |
946 | struct scrub_bio *sbio; | 951 | struct scrub_bio *sbio; |
947 | struct bio *bio; | ||
948 | int i; | ||
949 | 952 | ||
950 | if (sdev->curr == -1) | 953 | if (sdev->curr == -1) |
951 | return 0; | 954 | return 0; |
952 | 955 | ||
953 | sbio = sdev->bios[sdev->curr]; | 956 | sbio = sdev->bios[sdev->curr]; |
954 | |||
955 | bio = bio_alloc(GFP_NOFS, sbio->count); | ||
956 | if (!bio) | ||
957 | goto nomem; | ||
958 | |||
959 | bio->bi_private = sbio; | ||
960 | bio->bi_end_io = scrub_bio_end_io; | ||
961 | bio->bi_bdev = sdev->dev->bdev; | ||
962 | bio->bi_sector = sbio->physical >> 9; | ||
963 | |||
964 | for (i = 0; i < sbio->count; ++i) { | ||
965 | struct page *page; | ||
966 | int ret; | ||
967 | |||
968 | page = alloc_page(GFP_NOFS); | ||
969 | if (!page) | ||
970 | goto nomem; | ||
971 | |||
972 | ret = bio_add_page(bio, page, PAGE_SIZE, 0); | ||
973 | if (!ret) { | ||
974 | __free_page(page); | ||
975 | goto nomem; | ||
976 | } | ||
977 | } | ||
978 | |||
979 | sbio->err = 0; | 957 | sbio->err = 0; |
980 | sdev->curr = -1; | 958 | sdev->curr = -1; |
981 | atomic_inc(&sdev->in_flight); | 959 | atomic_inc(&sdev->in_flight); |
982 | 960 | ||
983 | submit_bio(READ, bio); | 961 | submit_bio(READ, sbio->bio); |
984 | 962 | ||
985 | return 0; | 963 | return 0; |
986 | |||
987 | nomem: | ||
988 | scrub_free_bio(bio); | ||
989 | |||
990 | return -ENOMEM; | ||
991 | } | 964 | } |
992 | 965 | ||
993 | static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len, | 966 | static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len, |
@@ -995,6 +968,8 @@ static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len, | |||
995 | u8 *csum, int force) | 968 | u8 *csum, int force) |
996 | { | 969 | { |
997 | struct scrub_bio *sbio; | 970 | struct scrub_bio *sbio; |
971 | struct page *page; | ||
972 | int ret; | ||
998 | 973 | ||
999 | again: | 974 | again: |
1000 | /* | 975 | /* |
@@ -1015,12 +990,22 @@ again: | |||
1015 | } | 990 | } |
1016 | sbio = sdev->bios[sdev->curr]; | 991 | sbio = sdev->bios[sdev->curr]; |
1017 | if (sbio->count == 0) { | 992 | if (sbio->count == 0) { |
993 | struct bio *bio; | ||
994 | |||
1018 | sbio->physical = physical; | 995 | sbio->physical = physical; |
1019 | sbio->logical = logical; | 996 | sbio->logical = logical; |
997 | bio = bio_alloc(GFP_NOFS, SCRUB_PAGES_PER_BIO); | ||
998 | if (!bio) | ||
999 | return -ENOMEM; | ||
1000 | |||
1001 | bio->bi_private = sbio; | ||
1002 | bio->bi_end_io = scrub_bio_end_io; | ||
1003 | bio->bi_bdev = sdev->dev->bdev; | ||
1004 | bio->bi_sector = sbio->physical >> 9; | ||
1005 | sbio->err = 0; | ||
1006 | sbio->bio = bio; | ||
1020 | } else if (sbio->physical + sbio->count * PAGE_SIZE != physical || | 1007 | } else if (sbio->physical + sbio->count * PAGE_SIZE != physical || |
1021 | sbio->logical + sbio->count * PAGE_SIZE != logical) { | 1008 | sbio->logical + sbio->count * PAGE_SIZE != logical) { |
1022 | int ret; | ||
1023 | |||
1024 | ret = scrub_submit(sdev); | 1009 | ret = scrub_submit(sdev); |
1025 | if (ret) | 1010 | if (ret) |
1026 | return ret; | 1011 | return ret; |
@@ -1030,6 +1015,20 @@ again: | |||
1030 | sbio->spag[sbio->count].generation = gen; | 1015 | sbio->spag[sbio->count].generation = gen; |
1031 | sbio->spag[sbio->count].have_csum = 0; | 1016 | sbio->spag[sbio->count].have_csum = 0; |
1032 | sbio->spag[sbio->count].mirror_num = mirror_num; | 1017 | sbio->spag[sbio->count].mirror_num = mirror_num; |
1018 | |||
1019 | page = alloc_page(GFP_NOFS); | ||
1020 | if (!page) | ||
1021 | return -ENOMEM; | ||
1022 | |||
1023 | ret = bio_add_page(sbio->bio, page, PAGE_SIZE, 0); | ||
1024 | if (!ret) { | ||
1025 | __free_page(page); | ||
1026 | ret = scrub_submit(sdev); | ||
1027 | if (ret) | ||
1028 | return ret; | ||
1029 | goto again; | ||
1030 | } | ||
1031 | |||
1033 | if (csum) { | 1032 | if (csum) { |
1034 | sbio->spag[sbio->count].have_csum = 1; | 1033 | sbio->spag[sbio->count].have_csum = 1; |
1035 | memcpy(sbio->spag[sbio->count].csum, csum, sdev->csum_size); | 1034 | memcpy(sbio->spag[sbio->count].csum, csum, sdev->csum_size); |