diff options
author | David Sterba <dsterba@suse.com> | 2017-07-14 14:37:38 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-07-14 14:37:38 -0400 |
commit | 1014f3d68fc4034966b15234dc12b81147ee83b2 (patch) | |
tree | 02c4fc56d21f6ec275d60bac8a8baad665f2e69e | |
parent | 848c23b78fafdcd3270b06a30737f8dbd70c347f (diff) | |
parent | 6592e58c6b68e61f003a01ba29a3716e7e2e9484 (diff) |
Merge branch 'next/filipe' into for-4.13-part2
- incremental send fixes
- raid56 corruption fix (cloned bio iteration)
-rw-r--r-- | fs/btrfs/raid56.c | 26 | ||||
-rw-r--r-- | fs/btrfs/send.c | 88 |
2 files changed, 73 insertions, 41 deletions
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index b9abb0b01021..b89d07003697 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c | |||
@@ -1136,20 +1136,27 @@ static void validate_rbio_for_rmw(struct btrfs_raid_bio *rbio) | |||
1136 | static void index_rbio_pages(struct btrfs_raid_bio *rbio) | 1136 | static void index_rbio_pages(struct btrfs_raid_bio *rbio) |
1137 | { | 1137 | { |
1138 | struct bio *bio; | 1138 | struct bio *bio; |
1139 | struct bio_vec *bvec; | ||
1140 | u64 start; | 1139 | u64 start; |
1141 | unsigned long stripe_offset; | 1140 | unsigned long stripe_offset; |
1142 | unsigned long page_index; | 1141 | unsigned long page_index; |
1143 | int i; | ||
1144 | 1142 | ||
1145 | spin_lock_irq(&rbio->bio_list_lock); | 1143 | spin_lock_irq(&rbio->bio_list_lock); |
1146 | bio_list_for_each(bio, &rbio->bio_list) { | 1144 | bio_list_for_each(bio, &rbio->bio_list) { |
1145 | struct bio_vec bvec; | ||
1146 | struct bvec_iter iter; | ||
1147 | int i = 0; | ||
1148 | |||
1147 | start = (u64)bio->bi_iter.bi_sector << 9; | 1149 | start = (u64)bio->bi_iter.bi_sector << 9; |
1148 | stripe_offset = start - rbio->bbio->raid_map[0]; | 1150 | stripe_offset = start - rbio->bbio->raid_map[0]; |
1149 | page_index = stripe_offset >> PAGE_SHIFT; | 1151 | page_index = stripe_offset >> PAGE_SHIFT; |
1150 | 1152 | ||
1151 | bio_for_each_segment_all(bvec, bio, i) | 1153 | if (bio_flagged(bio, BIO_CLONED)) |
1152 | rbio->bio_pages[page_index + i] = bvec->bv_page; | 1154 | bio->bi_iter = btrfs_io_bio(bio)->iter; |
1155 | |||
1156 | bio_for_each_segment(bvec, bio, iter) { | ||
1157 | rbio->bio_pages[page_index + i] = bvec.bv_page; | ||
1158 | i++; | ||
1159 | } | ||
1153 | } | 1160 | } |
1154 | spin_unlock_irq(&rbio->bio_list_lock); | 1161 | spin_unlock_irq(&rbio->bio_list_lock); |
1155 | } | 1162 | } |
@@ -1423,11 +1430,14 @@ static int fail_bio_stripe(struct btrfs_raid_bio *rbio, | |||
1423 | */ | 1430 | */ |
1424 | static void set_bio_pages_uptodate(struct bio *bio) | 1431 | static void set_bio_pages_uptodate(struct bio *bio) |
1425 | { | 1432 | { |
1426 | struct bio_vec *bvec; | 1433 | struct bio_vec bvec; |
1427 | int i; | 1434 | struct bvec_iter iter; |
1435 | |||
1436 | if (bio_flagged(bio, BIO_CLONED)) | ||
1437 | bio->bi_iter = btrfs_io_bio(bio)->iter; | ||
1428 | 1438 | ||
1429 | bio_for_each_segment_all(bvec, bio, i) | 1439 | bio_for_each_segment(bvec, bio, iter) |
1430 | SetPageUptodate(bvec->bv_page); | 1440 | SetPageUptodate(bvec.bv_page); |
1431 | } | 1441 | } |
1432 | 1442 | ||
1433 | /* | 1443 | /* |
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index e937c10b8287..b082210df9c8 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -1856,7 +1856,7 @@ out: | |||
1856 | */ | 1856 | */ |
1857 | static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen, | 1857 | static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen, |
1858 | const char *name, int name_len, | 1858 | const char *name, int name_len, |
1859 | u64 *who_ino, u64 *who_gen) | 1859 | u64 *who_ino, u64 *who_gen, u64 *who_mode) |
1860 | { | 1860 | { |
1861 | int ret = 0; | 1861 | int ret = 0; |
1862 | u64 gen; | 1862 | u64 gen; |
@@ -1905,7 +1905,7 @@ static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen, | |||
1905 | if (other_inode > sctx->send_progress || | 1905 | if (other_inode > sctx->send_progress || |
1906 | is_waiting_for_move(sctx, other_inode)) { | 1906 | is_waiting_for_move(sctx, other_inode)) { |
1907 | ret = get_inode_info(sctx->parent_root, other_inode, NULL, | 1907 | ret = get_inode_info(sctx->parent_root, other_inode, NULL, |
1908 | who_gen, NULL, NULL, NULL, NULL); | 1908 | who_gen, who_mode, NULL, NULL, NULL); |
1909 | if (ret < 0) | 1909 | if (ret < 0) |
1910 | goto out; | 1910 | goto out; |
1911 | 1911 | ||
@@ -3683,6 +3683,36 @@ out: | |||
3683 | return ret; | 3683 | return ret; |
3684 | } | 3684 | } |
3685 | 3685 | ||
3686 | static int update_ref_path(struct send_ctx *sctx, struct recorded_ref *ref) | ||
3687 | { | ||
3688 | int ret; | ||
3689 | struct fs_path *new_path; | ||
3690 | |||
3691 | /* | ||
3692 | * Our reference's name member points to its full_path member string, so | ||
3693 | * we use here a new path. | ||
3694 | */ | ||
3695 | new_path = fs_path_alloc(); | ||
3696 | if (!new_path) | ||
3697 | return -ENOMEM; | ||
3698 | |||
3699 | ret = get_cur_path(sctx, ref->dir, ref->dir_gen, new_path); | ||
3700 | if (ret < 0) { | ||
3701 | fs_path_free(new_path); | ||
3702 | return ret; | ||
3703 | } | ||
3704 | ret = fs_path_add(new_path, ref->name, ref->name_len); | ||
3705 | if (ret < 0) { | ||
3706 | fs_path_free(new_path); | ||
3707 | return ret; | ||
3708 | } | ||
3709 | |||
3710 | fs_path_free(ref->full_path); | ||
3711 | set_ref_path(ref, new_path); | ||
3712 | |||
3713 | return 0; | ||
3714 | } | ||
3715 | |||
3686 | /* | 3716 | /* |
3687 | * This does all the move/link/unlink/rmdir magic. | 3717 | * This does all the move/link/unlink/rmdir magic. |
3688 | */ | 3718 | */ |
@@ -3696,10 +3726,12 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) | |||
3696 | struct fs_path *valid_path = NULL; | 3726 | struct fs_path *valid_path = NULL; |
3697 | u64 ow_inode = 0; | 3727 | u64 ow_inode = 0; |
3698 | u64 ow_gen; | 3728 | u64 ow_gen; |
3729 | u64 ow_mode; | ||
3699 | int did_overwrite = 0; | 3730 | int did_overwrite = 0; |
3700 | int is_orphan = 0; | 3731 | int is_orphan = 0; |
3701 | u64 last_dir_ino_rm = 0; | 3732 | u64 last_dir_ino_rm = 0; |
3702 | bool can_rename = true; | 3733 | bool can_rename = true; |
3734 | bool orphanized_dir = false; | ||
3703 | bool orphanized_ancestor = false; | 3735 | bool orphanized_ancestor = false; |
3704 | 3736 | ||
3705 | btrfs_debug(fs_info, "process_recorded_refs %llu", sctx->cur_ino); | 3737 | btrfs_debug(fs_info, "process_recorded_refs %llu", sctx->cur_ino); |
@@ -3798,7 +3830,7 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) | |||
3798 | */ | 3830 | */ |
3799 | ret = will_overwrite_ref(sctx, cur->dir, cur->dir_gen, | 3831 | ret = will_overwrite_ref(sctx, cur->dir, cur->dir_gen, |
3800 | cur->name, cur->name_len, | 3832 | cur->name, cur->name_len, |
3801 | &ow_inode, &ow_gen); | 3833 | &ow_inode, &ow_gen, &ow_mode); |
3802 | if (ret < 0) | 3834 | if (ret < 0) |
3803 | goto out; | 3835 | goto out; |
3804 | if (ret) { | 3836 | if (ret) { |
@@ -3815,6 +3847,8 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) | |||
3815 | cur->full_path); | 3847 | cur->full_path); |
3816 | if (ret < 0) | 3848 | if (ret < 0) |
3817 | goto out; | 3849 | goto out; |
3850 | if (S_ISDIR(ow_mode)) | ||
3851 | orphanized_dir = true; | ||
3818 | 3852 | ||
3819 | /* | 3853 | /* |
3820 | * If ow_inode has its rename operation delayed | 3854 | * If ow_inode has its rename operation delayed |
@@ -3920,6 +3954,18 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) | |||
3920 | if (ret < 0) | 3954 | if (ret < 0) |
3921 | goto out; | 3955 | goto out; |
3922 | } else { | 3956 | } else { |
3957 | /* | ||
3958 | * We might have previously orphanized an inode | ||
3959 | * which is an ancestor of our current inode, | ||
3960 | * so our reference's full path, which was | ||
3961 | * computed before any such orphanizations, must | ||
3962 | * be updated. | ||
3963 | */ | ||
3964 | if (orphanized_dir) { | ||
3965 | ret = update_ref_path(sctx, cur); | ||
3966 | if (ret < 0) | ||
3967 | goto out; | ||
3968 | } | ||
3923 | ret = send_link(sctx, cur->full_path, | 3969 | ret = send_link(sctx, cur->full_path, |
3924 | valid_path); | 3970 | valid_path); |
3925 | if (ret < 0) | 3971 | if (ret < 0) |
@@ -3990,34 +4036,9 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) | |||
3990 | * ancestor inode. | 4036 | * ancestor inode. |
3991 | */ | 4037 | */ |
3992 | if (orphanized_ancestor) { | 4038 | if (orphanized_ancestor) { |
3993 | struct fs_path *new_path; | 4039 | ret = update_ref_path(sctx, cur); |
3994 | 4040 | if (ret < 0) | |
3995 | /* | ||
3996 | * Our reference's name member points to | ||
3997 | * its full_path member string, so we | ||
3998 | * use here a new path. | ||
3999 | */ | ||
4000 | new_path = fs_path_alloc(); | ||
4001 | if (!new_path) { | ||
4002 | ret = -ENOMEM; | ||
4003 | goto out; | ||
4004 | } | ||
4005 | ret = get_cur_path(sctx, cur->dir, | ||
4006 | cur->dir_gen, | ||
4007 | new_path); | ||
4008 | if (ret < 0) { | ||
4009 | fs_path_free(new_path); | ||
4010 | goto out; | ||
4011 | } | ||
4012 | ret = fs_path_add(new_path, | ||
4013 | cur->name, | ||
4014 | cur->name_len); | ||
4015 | if (ret < 0) { | ||
4016 | fs_path_free(new_path); | ||
4017 | goto out; | 4041 | goto out; |
4018 | } | ||
4019 | fs_path_free(cur->full_path); | ||
4020 | set_ref_path(cur, new_path); | ||
4021 | } | 4042 | } |
4022 | ret = send_unlink(sctx, cur->full_path); | 4043 | ret = send_unlink(sctx, cur->full_path); |
4023 | if (ret < 0) | 4044 | if (ret < 0) |
@@ -5249,15 +5270,12 @@ static int is_extent_unchanged(struct send_ctx *sctx, | |||
5249 | goto out; | 5270 | goto out; |
5250 | } | 5271 | } |
5251 | 5272 | ||
5252 | right_disknr = btrfs_file_extent_disk_bytenr(eb, ei); | ||
5253 | if (right_type == BTRFS_FILE_EXTENT_INLINE) { | 5273 | if (right_type == BTRFS_FILE_EXTENT_INLINE) { |
5254 | right_len = btrfs_file_extent_inline_len(eb, slot, ei); | 5274 | right_len = btrfs_file_extent_inline_len(eb, slot, ei); |
5255 | right_len = PAGE_ALIGN(right_len); | 5275 | right_len = PAGE_ALIGN(right_len); |
5256 | } else { | 5276 | } else { |
5257 | right_len = btrfs_file_extent_num_bytes(eb, ei); | 5277 | right_len = btrfs_file_extent_num_bytes(eb, ei); |
5258 | } | 5278 | } |
5259 | right_offset = btrfs_file_extent_offset(eb, ei); | ||
5260 | right_gen = btrfs_file_extent_generation(eb, ei); | ||
5261 | 5279 | ||
5262 | /* | 5280 | /* |
5263 | * Are we at extent 8? If yes, we know the extent is changed. | 5281 | * Are we at extent 8? If yes, we know the extent is changed. |
@@ -5282,6 +5300,10 @@ static int is_extent_unchanged(struct send_ctx *sctx, | |||
5282 | goto out; | 5300 | goto out; |
5283 | } | 5301 | } |
5284 | 5302 | ||
5303 | right_disknr = btrfs_file_extent_disk_bytenr(eb, ei); | ||
5304 | right_offset = btrfs_file_extent_offset(eb, ei); | ||
5305 | right_gen = btrfs_file_extent_generation(eb, ei); | ||
5306 | |||
5285 | left_offset_fixed = left_offset; | 5307 | left_offset_fixed = left_offset; |
5286 | if (key.offset < ekey->offset) { | 5308 | if (key.offset < ekey->offset) { |
5287 | /* Fix the right offset for 2a and 7. */ | 5309 | /* Fix the right offset for 2a and 7. */ |