提交 bc243704 编写于 作者: L Linus Torvalds

Merge branch 'for-4.13-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fixes from David Sterba:
 "We've identified and fixed a silent corruption (introduced by code in
  the first pull), a fixup after the blk_status_t merge and two fixes to
  incremental send that Filipe has been hunting for some time"

* 'for-4.13-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  Btrfs: fix unexpected return value of bio_readpage_error
  btrfs: btrfs_create_repair_bio never fails, skip error handling
  btrfs: cloned bios must not be iterated by bio_for_each_segment_all
  Btrfs: fix write corruption due to bio cloning on raid5/6
  Btrfs: incremental send, fix invalid memory access
  Btrfs: incremental send, fix invalid path for link commands
...@@ -152,6 +152,7 @@ static void end_compressed_bio_read(struct bio *bio) ...@@ -152,6 +152,7 @@ static void end_compressed_bio_read(struct bio *bio)
* we have verified the checksum already, set page * we have verified the checksum already, set page
* checked so the end_io handlers know about it * checked so the end_io handlers know about it
*/ */
ASSERT(!bio_flagged(bio, BIO_CLONED));
bio_for_each_segment_all(bvec, cb->orig_bio, i) bio_for_each_segment_all(bvec, cb->orig_bio, i)
SetPageChecked(bvec->bv_page); SetPageChecked(bvec->bv_page);
......
...@@ -964,6 +964,7 @@ static blk_status_t btree_csum_one_bio(struct bio *bio) ...@@ -964,6 +964,7 @@ static blk_status_t btree_csum_one_bio(struct bio *bio)
struct btrfs_root *root; struct btrfs_root *root;
int i, ret = 0; int i, ret = 0;
ASSERT(!bio_flagged(bio, BIO_CLONED));
bio_for_each_segment_all(bvec, bio, i) { bio_for_each_segment_all(bvec, bio, i) {
root = BTRFS_I(bvec->bv_page->mapping->host)->root; root = BTRFS_I(bvec->bv_page->mapping->host)->root;
ret = csum_dirty_buffer(root->fs_info, bvec->bv_page); ret = csum_dirty_buffer(root->fs_info, bvec->bv_page);
......
...@@ -2258,7 +2258,7 @@ int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end, ...@@ -2258,7 +2258,7 @@ int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
return 0; return 0;
} }
int btrfs_check_repairable(struct inode *inode, struct bio *failed_bio, bool btrfs_check_repairable(struct inode *inode, struct bio *failed_bio,
struct io_failure_record *failrec, int failed_mirror) struct io_failure_record *failrec, int failed_mirror)
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
...@@ -2274,7 +2274,7 @@ int btrfs_check_repairable(struct inode *inode, struct bio *failed_bio, ...@@ -2274,7 +2274,7 @@ int btrfs_check_repairable(struct inode *inode, struct bio *failed_bio,
btrfs_debug(fs_info, btrfs_debug(fs_info,
"Check Repairable: cannot repair, num_copies=%d, next_mirror %d, failed_mirror %d", "Check Repairable: cannot repair, num_copies=%d, next_mirror %d, failed_mirror %d",
num_copies, failrec->this_mirror, failed_mirror); num_copies, failrec->this_mirror, failed_mirror);
return 0; return false;
} }
/* /*
...@@ -2315,10 +2315,10 @@ int btrfs_check_repairable(struct inode *inode, struct bio *failed_bio, ...@@ -2315,10 +2315,10 @@ int btrfs_check_repairable(struct inode *inode, struct bio *failed_bio,
btrfs_debug(fs_info, btrfs_debug(fs_info,
"Check Repairable: (fail) num_copies=%d, next_mirror %d, failed_mirror %d", "Check Repairable: (fail) num_copies=%d, next_mirror %d, failed_mirror %d",
num_copies, failrec->this_mirror, failed_mirror); num_copies, failrec->this_mirror, failed_mirror);
return 0; return false;
} }
return 1; return true;
} }
...@@ -2382,8 +2382,8 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset, ...@@ -2382,8 +2382,8 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset,
if (ret) if (ret)
return ret; return ret;
ret = btrfs_check_repairable(inode, failed_bio, failrec, failed_mirror); if (!btrfs_check_repairable(inode, failed_bio, failrec,
if (!ret) { failed_mirror)) {
free_io_failure(failure_tree, tree, failrec); free_io_failure(failure_tree, tree, failrec);
return -EIO; return -EIO;
} }
...@@ -2396,10 +2396,6 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset, ...@@ -2396,10 +2396,6 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset,
start - page_offset(page), start - page_offset(page),
(int)phy_offset, failed_bio->bi_end_io, (int)phy_offset, failed_bio->bi_end_io,
NULL); NULL);
if (!bio) {
free_io_failure(failure_tree, tree, failrec);
return -EIO;
}
bio_set_op_attrs(bio, REQ_OP_READ, read_mode); bio_set_op_attrs(bio, REQ_OP_READ, read_mode);
btrfs_debug(btrfs_sb(inode->i_sb), btrfs_debug(btrfs_sb(inode->i_sb),
...@@ -2456,6 +2452,7 @@ static void end_bio_extent_writepage(struct bio *bio) ...@@ -2456,6 +2452,7 @@ static void end_bio_extent_writepage(struct bio *bio)
u64 end; u64 end;
int i; int i;
ASSERT(!bio_flagged(bio, BIO_CLONED));
bio_for_each_segment_all(bvec, bio, i) { bio_for_each_segment_all(bvec, bio, i) {
struct page *page = bvec->bv_page; struct page *page = bvec->bv_page;
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
...@@ -2526,6 +2523,7 @@ static void end_bio_extent_readpage(struct bio *bio) ...@@ -2526,6 +2523,7 @@ static void end_bio_extent_readpage(struct bio *bio)
int ret; int ret;
int i; int i;
ASSERT(!bio_flagged(bio, BIO_CLONED));
bio_for_each_segment_all(bvec, bio, i) { bio_for_each_segment_all(bvec, bio, i) {
struct page *page = bvec->bv_page; struct page *page = bvec->bv_page;
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
...@@ -3680,6 +3678,7 @@ static void end_bio_extent_buffer_writepage(struct bio *bio) ...@@ -3680,6 +3678,7 @@ static void end_bio_extent_buffer_writepage(struct bio *bio)
struct extent_buffer *eb; struct extent_buffer *eb;
int i, done; int i, done;
ASSERT(!bio_flagged(bio, BIO_CLONED));
bio_for_each_segment_all(bvec, bio, i) { bio_for_each_segment_all(bvec, bio, i) {
struct page *page = bvec->bv_page; struct page *page = bvec->bv_page;
......
...@@ -539,8 +539,8 @@ void btrfs_free_io_failure_record(struct btrfs_inode *inode, u64 start, ...@@ -539,8 +539,8 @@ void btrfs_free_io_failure_record(struct btrfs_inode *inode, u64 start,
u64 end); u64 end);
int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end, int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
struct io_failure_record **failrec_ret); struct io_failure_record **failrec_ret);
int btrfs_check_repairable(struct inode *inode, struct bio *failed_bio, bool btrfs_check_repairable(struct inode *inode, struct bio *failed_bio,
struct io_failure_record *failrec, int fail_mirror); struct io_failure_record *failrec, int fail_mirror);
struct bio *btrfs_create_repair_bio(struct inode *inode, struct bio *failed_bio, struct bio *btrfs_create_repair_bio(struct inode *inode, struct bio *failed_bio,
struct io_failure_record *failrec, struct io_failure_record *failrec,
struct page *page, int pg_offset, int icsum, struct page *page, int pg_offset, int icsum,
......
...@@ -8016,10 +8016,6 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio, ...@@ -8016,10 +8016,6 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio,
isector >>= inode->i_sb->s_blocksize_bits; isector >>= inode->i_sb->s_blocksize_bits;
bio = btrfs_create_repair_bio(inode, failed_bio, failrec, page, bio = btrfs_create_repair_bio(inode, failed_bio, failrec, page,
pgoff, isector, repair_endio, repair_arg); pgoff, isector, repair_endio, repair_arg);
if (!bio) {
free_io_failure(failure_tree, io_tree, failrec);
return -EIO;
}
bio_set_op_attrs(bio, REQ_OP_READ, read_mode); bio_set_op_attrs(bio, REQ_OP_READ, read_mode);
btrfs_debug(BTRFS_I(inode)->root->fs_info, btrfs_debug(BTRFS_I(inode)->root->fs_info,
...@@ -8059,6 +8055,7 @@ static void btrfs_retry_endio_nocsum(struct bio *bio) ...@@ -8059,6 +8055,7 @@ static void btrfs_retry_endio_nocsum(struct bio *bio)
ASSERT(bio->bi_io_vec->bv_len == btrfs_inode_sectorsize(inode)); ASSERT(bio->bi_io_vec->bv_len == btrfs_inode_sectorsize(inode));
done->uptodate = 1; done->uptodate = 1;
ASSERT(!bio_flagged(bio, BIO_CLONED));
bio_for_each_segment_all(bvec, bio, i) bio_for_each_segment_all(bvec, bio, i)
clean_io_failure(BTRFS_I(inode)->root->fs_info, failure_tree, clean_io_failure(BTRFS_I(inode)->root->fs_info, failure_tree,
io_tree, done->start, bvec->bv_page, io_tree, done->start, bvec->bv_page,
...@@ -8150,6 +8147,7 @@ static void btrfs_retry_endio(struct bio *bio) ...@@ -8150,6 +8147,7 @@ static void btrfs_retry_endio(struct bio *bio)
io_tree = &BTRFS_I(inode)->io_tree; io_tree = &BTRFS_I(inode)->io_tree;
failure_tree = &BTRFS_I(inode)->io_failure_tree; failure_tree = &BTRFS_I(inode)->io_failure_tree;
ASSERT(!bio_flagged(bio, BIO_CLONED));
bio_for_each_segment_all(bvec, bio, i) { bio_for_each_segment_all(bvec, bio, i) {
ret = __readpage_endio_check(inode, io_bio, i, bvec->bv_page, ret = __readpage_endio_check(inode, io_bio, i, bvec->bv_page,
bvec->bv_offset, done->start, bvec->bv_offset, done->start,
......
...@@ -1136,20 +1136,27 @@ static void validate_rbio_for_rmw(struct btrfs_raid_bio *rbio) ...@@ -1136,20 +1136,27 @@ static void validate_rbio_for_rmw(struct btrfs_raid_bio *rbio)
static void index_rbio_pages(struct btrfs_raid_bio *rbio) static void index_rbio_pages(struct btrfs_raid_bio *rbio)
{ {
struct bio *bio; struct bio *bio;
struct bio_vec *bvec;
u64 start; u64 start;
unsigned long stripe_offset; unsigned long stripe_offset;
unsigned long page_index; unsigned long page_index;
int i;
spin_lock_irq(&rbio->bio_list_lock); spin_lock_irq(&rbio->bio_list_lock);
bio_list_for_each(bio, &rbio->bio_list) { bio_list_for_each(bio, &rbio->bio_list) {
struct bio_vec bvec;
struct bvec_iter iter;
int i = 0;
start = (u64)bio->bi_iter.bi_sector << 9; start = (u64)bio->bi_iter.bi_sector << 9;
stripe_offset = start - rbio->bbio->raid_map[0]; stripe_offset = start - rbio->bbio->raid_map[0];
page_index = stripe_offset >> PAGE_SHIFT; page_index = stripe_offset >> PAGE_SHIFT;
bio_for_each_segment_all(bvec, bio, i) if (bio_flagged(bio, BIO_CLONED))
rbio->bio_pages[page_index + i] = bvec->bv_page; bio->bi_iter = btrfs_io_bio(bio)->iter;
bio_for_each_segment(bvec, bio, iter) {
rbio->bio_pages[page_index + i] = bvec.bv_page;
i++;
}
} }
spin_unlock_irq(&rbio->bio_list_lock); spin_unlock_irq(&rbio->bio_list_lock);
} }
...@@ -1423,11 +1430,14 @@ static int fail_bio_stripe(struct btrfs_raid_bio *rbio, ...@@ -1423,11 +1430,14 @@ static int fail_bio_stripe(struct btrfs_raid_bio *rbio,
*/ */
static void set_bio_pages_uptodate(struct bio *bio) static void set_bio_pages_uptodate(struct bio *bio)
{ {
struct bio_vec *bvec; struct bio_vec bvec;
int i; struct bvec_iter iter;
if (bio_flagged(bio, BIO_CLONED))
bio->bi_iter = btrfs_io_bio(bio)->iter;
bio_for_each_segment_all(bvec, bio, i) bio_for_each_segment(bvec, bio, iter)
SetPageUptodate(bvec->bv_page); SetPageUptodate(bvec.bv_page);
} }
/* /*
......
...@@ -1856,7 +1856,7 @@ static int is_first_ref(struct btrfs_root *root, ...@@ -1856,7 +1856,7 @@ static int is_first_ref(struct btrfs_root *root,
*/ */
static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen, static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen,
const char *name, int name_len, const char *name, int name_len,
u64 *who_ino, u64 *who_gen) u64 *who_ino, u64 *who_gen, u64 *who_mode)
{ {
int ret = 0; int ret = 0;
u64 gen; u64 gen;
...@@ -1905,7 +1905,7 @@ static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen, ...@@ -1905,7 +1905,7 @@ static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen,
if (other_inode > sctx->send_progress || if (other_inode > sctx->send_progress ||
is_waiting_for_move(sctx, other_inode)) { is_waiting_for_move(sctx, other_inode)) {
ret = get_inode_info(sctx->parent_root, other_inode, NULL, ret = get_inode_info(sctx->parent_root, other_inode, NULL,
who_gen, NULL, NULL, NULL, NULL); who_gen, who_mode, NULL, NULL, NULL);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -3683,6 +3683,36 @@ static int wait_for_parent_move(struct send_ctx *sctx, ...@@ -3683,6 +3683,36 @@ static int wait_for_parent_move(struct send_ctx *sctx,
return ret; return ret;
} }
static int update_ref_path(struct send_ctx *sctx, struct recorded_ref *ref)
{
int ret;
struct fs_path *new_path;
/*
* Our reference's name member points to its full_path member string, so
* we use here a new path.
*/
new_path = fs_path_alloc();
if (!new_path)
return -ENOMEM;
ret = get_cur_path(sctx, ref->dir, ref->dir_gen, new_path);
if (ret < 0) {
fs_path_free(new_path);
return ret;
}
ret = fs_path_add(new_path, ref->name, ref->name_len);
if (ret < 0) {
fs_path_free(new_path);
return ret;
}
fs_path_free(ref->full_path);
set_ref_path(ref, new_path);
return 0;
}
/* /*
* This does all the move/link/unlink/rmdir magic. * This does all the move/link/unlink/rmdir magic.
*/ */
...@@ -3696,10 +3726,12 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) ...@@ -3696,10 +3726,12 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
struct fs_path *valid_path = NULL; struct fs_path *valid_path = NULL;
u64 ow_inode = 0; u64 ow_inode = 0;
u64 ow_gen; u64 ow_gen;
u64 ow_mode;
int did_overwrite = 0; int did_overwrite = 0;
int is_orphan = 0; int is_orphan = 0;
u64 last_dir_ino_rm = 0; u64 last_dir_ino_rm = 0;
bool can_rename = true; bool can_rename = true;
bool orphanized_dir = false;
bool orphanized_ancestor = false; bool orphanized_ancestor = false;
btrfs_debug(fs_info, "process_recorded_refs %llu", sctx->cur_ino); 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,7 +3830,7 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
*/ */
ret = will_overwrite_ref(sctx, cur->dir, cur->dir_gen, ret = will_overwrite_ref(sctx, cur->dir, cur->dir_gen,
cur->name, cur->name_len, cur->name, cur->name_len,
&ow_inode, &ow_gen); &ow_inode, &ow_gen, &ow_mode);
if (ret < 0) if (ret < 0)
goto out; goto out;
if (ret) { if (ret) {
...@@ -3815,6 +3847,8 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) ...@@ -3815,6 +3847,8 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
cur->full_path); cur->full_path);
if (ret < 0) if (ret < 0)
goto out; goto out;
if (S_ISDIR(ow_mode))
orphanized_dir = true;
/* /*
* If ow_inode has its rename operation delayed * 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,6 +3954,18 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
if (ret < 0) if (ret < 0)
goto out; goto out;
} else { } else {
/*
* We might have previously orphanized an inode
* which is an ancestor of our current inode,
* so our reference's full path, which was
* computed before any such orphanizations, must
* be updated.
*/
if (orphanized_dir) {
ret = update_ref_path(sctx, cur);
if (ret < 0)
goto out;
}
ret = send_link(sctx, cur->full_path, ret = send_link(sctx, cur->full_path,
valid_path); valid_path);
if (ret < 0) if (ret < 0)
...@@ -3990,34 +4036,9 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) ...@@ -3990,34 +4036,9 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
* ancestor inode. * ancestor inode.
*/ */
if (orphanized_ancestor) { if (orphanized_ancestor) {
struct fs_path *new_path; ret = update_ref_path(sctx, cur);
if (ret < 0)
/*
* Our reference's name member points to
* its full_path member string, so we
* use here a new path.
*/
new_path = fs_path_alloc();
if (!new_path) {
ret = -ENOMEM;
goto out;
}
ret = get_cur_path(sctx, cur->dir,
cur->dir_gen,
new_path);
if (ret < 0) {
fs_path_free(new_path);
goto out;
}
ret = fs_path_add(new_path,
cur->name,
cur->name_len);
if (ret < 0) {
fs_path_free(new_path);
goto out; goto out;
}
fs_path_free(cur->full_path);
set_ref_path(cur, new_path);
} }
ret = send_unlink(sctx, cur->full_path); ret = send_unlink(sctx, cur->full_path);
if (ret < 0) if (ret < 0)
...@@ -5249,15 +5270,12 @@ static int is_extent_unchanged(struct send_ctx *sctx, ...@@ -5249,15 +5270,12 @@ static int is_extent_unchanged(struct send_ctx *sctx,
goto out; goto out;
} }
right_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
if (right_type == BTRFS_FILE_EXTENT_INLINE) { if (right_type == BTRFS_FILE_EXTENT_INLINE) {
right_len = btrfs_file_extent_inline_len(eb, slot, ei); right_len = btrfs_file_extent_inline_len(eb, slot, ei);
right_len = PAGE_ALIGN(right_len); right_len = PAGE_ALIGN(right_len);
} else { } else {
right_len = btrfs_file_extent_num_bytes(eb, ei); right_len = btrfs_file_extent_num_bytes(eb, ei);
} }
right_offset = btrfs_file_extent_offset(eb, ei);
right_gen = btrfs_file_extent_generation(eb, ei);
/* /*
* Are we at extent 8? If yes, we know the extent is changed. * 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,6 +5300,10 @@ static int is_extent_unchanged(struct send_ctx *sctx,
goto out; goto out;
} }
right_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
right_offset = btrfs_file_extent_offset(eb, ei);
right_gen = btrfs_file_extent_generation(eb, ei);
left_offset_fixed = left_offset; left_offset_fixed = left_offset;
if (key.offset < ekey->offset) { if (key.offset < ekey->offset) {
/* Fix the right offset for 2a and 7. */ /* Fix the right offset for 2a and 7. */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册