Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1014f3d6 authored by David Sterba's avatar David Sterba
Browse files

Merge branch 'next/filipe' into for-4.13-part2

- incremental send fixes
- raid56 corruption fix (cloned bio iteration)
parents 848c23b7 6592e58c
Loading
Loading
Loading
Loading
+18 −8
Original line number Diff line number Diff line
@@ -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)
{
	struct bio *bio;
	struct bio_vec *bvec;
	u64 start;
	unsigned long stripe_offset;
	unsigned long page_index;
	int i;

	spin_lock_irq(&rbio->bio_list_lock);
	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;
		stripe_offset = start - rbio->bbio->raid_map[0];
		page_index = stripe_offset >> PAGE_SHIFT;

		bio_for_each_segment_all(bvec, bio, i)
			rbio->bio_pages[page_index + i] = bvec->bv_page;
		if (bio_flagged(bio, BIO_CLONED))
			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);
}
@@ -1423,11 +1430,14 @@ static int fail_bio_stripe(struct btrfs_raid_bio *rbio,
 */
static void set_bio_pages_uptodate(struct bio *bio)
{
	struct bio_vec *bvec;
	int i;
	struct bio_vec bvec;
	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)
		SetPageUptodate(bvec->bv_page);
	bio_for_each_segment(bvec, bio, iter)
		SetPageUptodate(bvec.bv_page);
}

/*
+55 −33
Original line number Diff line number Diff line
@@ -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,
			      const char *name, int name_len,
			      u64 *who_ino, u64 *who_gen)
			      u64 *who_ino, u64 *who_gen, u64 *who_mode)
{
	int ret = 0;
	u64 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 ||
	    is_waiting_for_move(sctx, other_inode)) {
		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)
			goto out;

@@ -3683,6 +3683,36 @@ static int wait_for_parent_move(struct send_ctx *sctx,
	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.
 */
@@ -3696,10 +3726,12 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
	struct fs_path *valid_path = NULL;
	u64 ow_inode = 0;
	u64 ow_gen;
	u64 ow_mode;
	int did_overwrite = 0;
	int is_orphan = 0;
	u64 last_dir_ino_rm = 0;
	bool can_rename = true;
	bool orphanized_dir = false;
	bool orphanized_ancestor = false;

	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)
		 */
		ret = will_overwrite_ref(sctx, cur->dir, cur->dir_gen,
				cur->name, cur->name_len,
				&ow_inode, &ow_gen);
				&ow_inode, &ow_gen, &ow_mode);
		if (ret < 0)
			goto out;
		if (ret) {
@@ -3815,6 +3847,8 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
						cur->full_path);
				if (ret < 0)
					goto out;
				if (S_ISDIR(ow_mode))
					orphanized_dir = true;

				/*
				 * If ow_inode has its rename operation delayed
@@ -3920,6 +3954,18 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
				if (ret < 0)
					goto out;
			} 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,
						valid_path);
				if (ret < 0)
@@ -3990,35 +4036,10 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
				 * ancestor inode.
				 */
				if (orphanized_ancestor) {
					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) {
						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);
					ret = update_ref_path(sctx, cur);
					if (ret < 0)
						goto out;
				}
					fs_path_free(cur->full_path);
					set_ref_path(cur, new_path);
				}
				ret = send_unlink(sctx, cur->full_path);
				if (ret < 0)
					goto out;
@@ -5249,15 +5270,12 @@ static int is_extent_unchanged(struct send_ctx *sctx,
			goto out;
		}

		right_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
		if (right_type == BTRFS_FILE_EXTENT_INLINE) {
			right_len = btrfs_file_extent_inline_len(eb, slot, ei);
			right_len = PAGE_ALIGN(right_len);
		} else {
			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.
@@ -5282,6 +5300,10 @@ static int is_extent_unchanged(struct send_ctx *sctx,
			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;
		if (key.offset < ekey->offset) {
			/* Fix the right offset for 2a and 7. */