Commit 8c6d298a authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet
Browse files

bcachefs: Convert io paths for snapshots



This plumbs around the subvolume ID as was done previously for other
filesystem code, but now for the IO paths - the control flow in the IO
paths is trickier so the changes in this patch are more involved.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
parent ef1669ff
Loading
Loading
Loading
Loading
+36 −28
Original line number Diff line number Diff line
@@ -769,23 +769,35 @@ static void readpage_bio_extend(struct readpages_iter *iter,
	}
}

static void bchfs_read(struct btree_trans *trans, struct btree_iter *iter,
		       struct bch_read_bio *rbio, u64 inum,
static void bchfs_read(struct btree_trans *trans,
		       struct bch_read_bio *rbio,
		       subvol_inum inum,
		       struct readpages_iter *readpages_iter)
{
	struct bch_fs *c = trans->c;
	struct btree_iter iter;
	struct bkey_buf sk;
	int flags = BCH_READ_RETRY_IF_STALE|
		BCH_READ_MAY_PROMOTE;
	u32 snapshot;
	int ret = 0;

	rbio->c = c;
	rbio->start_time = local_clock();
	rbio->subvol = inum.subvol;

	bch2_bkey_buf_init(&sk);
retry:
	bch2_trans_begin(trans);
	iter = (struct btree_iter) { NULL };

	ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
	if (ret)
		goto err;

	bch2_trans_iter_init(trans, &iter, BTREE_ID_extents,
			     SPOS(inum.inum, rbio->bio.bi_iter.bi_sector, snapshot),
			     BTREE_ITER_SLOTS|BTREE_ITER_FILTER_SNAPSHOTS);
	while (1) {
		struct bkey_s_c k;
		unsigned bytes, sectors, offset_into_extent;
@@ -800,15 +812,15 @@ static void bchfs_read(struct btree_trans *trans, struct btree_iter *iter,
			break;
		}

		bch2_btree_iter_set_pos(iter,
				POS(inum, rbio->bio.bi_iter.bi_sector));
		bch2_btree_iter_set_pos(&iter,
				POS(inum.inum, rbio->bio.bi_iter.bi_sector));

		k = bch2_btree_iter_peek_slot(iter);
		k = bch2_btree_iter_peek_slot(&iter);
		ret = bkey_err(k);
		if (ret)
			break;

		offset_into_extent = iter->pos.offset -
		offset_into_extent = iter.pos.offset -
			bkey_start_offset(k.k);
		sectors = k.k->size - offset_into_extent;

@@ -838,7 +850,7 @@ static void bchfs_read(struct btree_trans *trans, struct btree_iter *iter,
		if (bkey_extent_is_allocation(k.k))
			bch2_add_page_sectors(&rbio->bio, k);

		bch2_read_extent(trans, rbio, iter->pos,
		bch2_read_extent(trans, rbio, iter.pos,
				 data_btree, k, offset_into_extent, flags);

		if (flags & BCH_READ_LAST_FRAGMENT)
@@ -847,12 +859,14 @@ static void bchfs_read(struct btree_trans *trans, struct btree_iter *iter,
		swap(rbio->bio.bi_iter.bi_size, bytes);
		bio_advance(&rbio->bio, bytes);
	}
err:
	bch2_trans_iter_exit(trans, &iter);

	if (ret == -EINTR)
		goto retry;

	if (ret) {
		bch_err_inum_ratelimited(c, inum,
		bch_err_inum_ratelimited(c, inum.inum,
				"read error %i from btree lookup", ret);
		rbio->bio.bi_status = BLK_STS_IOERR;
		bio_endio(&rbio->bio);
@@ -867,7 +881,6 @@ void bch2_readahead(struct readahead_control *ractl)
	struct bch_fs *c = inode->v.i_sb->s_fs_info;
	struct bch_io_opts opts = io_opts(c, &inode->ei_inode);
	struct btree_trans trans;
	struct btree_iter iter;
	struct page *page;
	struct readpages_iter readpages_iter;
	int ret;
@@ -876,8 +889,6 @@ void bch2_readahead(struct readahead_control *ractl)
	BUG_ON(ret);

	bch2_trans_init(&trans, c, 0, 0);
	bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents, POS_MIN,
			     BTREE_ITER_SLOTS);

	bch2_pagecache_add_get(&inode->ei_pagecache_lock);

@@ -898,22 +909,20 @@ void bch2_readahead(struct readahead_control *ractl)
		rbio->bio.bi_end_io = bch2_readpages_end_io;
		BUG_ON(!bio_add_page(&rbio->bio, page, PAGE_SIZE, 0));

		bchfs_read(&trans, &iter, rbio, inode->v.i_ino,
		bchfs_read(&trans, rbio, inode_inum(inode),
			   &readpages_iter);
	}

	bch2_pagecache_add_put(&inode->ei_pagecache_lock);

	bch2_trans_iter_exit(&trans, &iter);
	bch2_trans_exit(&trans);
	kfree(readpages_iter.pages);
}

static void __bchfs_readpage(struct bch_fs *c, struct bch_read_bio *rbio,
			     u64 inum, struct page *page)
			     subvol_inum inum, struct page *page)
{
	struct btree_trans trans;
	struct btree_iter iter;

	bch2_page_state_create(page, __GFP_NOFAIL);

@@ -923,12 +932,7 @@ static void __bchfs_readpage(struct bch_fs *c, struct bch_read_bio *rbio,
	BUG_ON(!bio_add_page(&rbio->bio, page, PAGE_SIZE, 0));

	bch2_trans_init(&trans, c, 0, 0);
	bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents, POS_MIN,
			     BTREE_ITER_SLOTS);

	bchfs_read(&trans, &iter, rbio, inum, NULL);

	bch2_trans_iter_exit(&trans, &iter);
	bchfs_read(&trans, rbio, inum, NULL);
	bch2_trans_exit(&trans);
}

@@ -951,7 +955,7 @@ static int bch2_read_single_page(struct page *page,
	rbio->bio.bi_private = &done;
	rbio->bio.bi_end_io = bch2_read_single_page_end_io;

	__bchfs_readpage(c, rbio, inode->v.i_ino, page);
	__bchfs_readpage(c, rbio, inode_inum(inode), page);
	wait_for_completion(&done);

	ret = blk_status_to_errno(rbio->bio.bi_status);
@@ -1096,6 +1100,7 @@ static void bch2_writepage_io_alloc(struct bch_fs *c,
	op->nr_replicas		= nr_replicas;
	op->res.nr_replicas	= nr_replicas;
	op->write_point		= writepoint_hashed(inode->ei_last_dirtied);
	op->subvol		= inode->ei_subvol;
	op->pos			= POS(inode->v.i_ino, sector);
	op->end_io		= bch2_writepage_io_done;
	op->wbio.bio.bi_iter.bi_sector = sector;
@@ -1733,7 +1738,7 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter)
		if (iter->count)
			closure_get(&dio->cl);

		bch2_read(c, rbio_init(bio, opts), inode->v.i_ino);
		bch2_read(c, rbio_init(bio, opts), inode_inum(inode));
	}

	iter->count += shorten;
@@ -1816,7 +1821,8 @@ static bool bch2_check_range_allocated(struct bch_fs *c, subvol_inum inum,
		if (bkey_cmp(bkey_start_pos(k.k), POS(inum.inum, end)) >= 0)
			break;

		if (nr_replicas > bch2_bkey_replicas(c, k) ||
		if (k.k->p.snapshot != snapshot ||
		    nr_replicas > bch2_bkey_replicas(c, k) ||
		    (!compressed && bch2_bkey_sectors_compressed(k))) {
			ret = false;
			break;
@@ -1944,6 +1950,7 @@ static long bch2_dio_write_loop(struct dio_write *dio)
		op_journal_seq_set(&dio->op, &inode->ei_journal_seq);
		dio->op.write_point	= writepoint_hashed((unsigned long) current);
		dio->op.nr_replicas	= dio->op.opts.data_replicas;
		dio->op.subvol		= inode->ei_subvol;
		dio->op.pos		= POS(inode->v.i_ino, (u64) req->ki_pos >> 9);

		if ((req->ki_flags & IOCB_DSYNC) &&
@@ -2438,7 +2445,7 @@ int bch2_truncate(struct mnt_idmap *idmap,

	truncate_setsize(&inode->v, iattr->ia_size);

	ret = bch2_fpunch(c, inode->v.i_ino,
	ret = bch2_fpunch(c, inode_inum(inode),
			round_up(iattr->ia_size, block_bytes(c)) >> 9,
			U64_MAX, &inode->ei_journal_seq, &i_sectors_delta);
	i_sectors_acct(c, inode, NULL, i_sectors_delta);
@@ -2498,7 +2505,7 @@ static long bchfs_fpunch(struct bch_inode_info *inode, loff_t offset, loff_t len
	if (discard_start < discard_end) {
		s64 i_sectors_delta = 0;

		ret = bch2_fpunch(c, inode->v.i_ino,
		ret = bch2_fpunch(c, inode_inum(inode),
				  discard_start, discard_end,
				  &inode->ei_journal_seq,
				  &i_sectors_delta);
@@ -2577,7 +2584,7 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
	} else {
		s64 i_sectors_delta = 0;

		ret = bch2_fpunch(c, inode->v.i_ino,
		ret = bch2_fpunch(c, inode_inum(inode),
				  offset >> 9, (offset + len) >> 9,
				  &inode->ei_journal_seq,
				  &i_sectors_delta);
@@ -2793,7 +2800,8 @@ static int __bchfs_fallocate(struct bch_inode_info *inode, int mode,
			reservation.v.nr_replicas = disk_res.nr_replicas;
		}

		ret = bch2_extent_update(&trans, &iter, &reservation.k_i,
		ret = bch2_extent_update(&trans, inode_inum(inode), &iter,
					 &reservation.k_i,
				&disk_res, &inode->ei_journal_seq,
				0, &i_sectors_delta, true);
		i_sectors_acct(c, inode, &quota_res, i_sectors_delta);
+80 −48
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "keylist.h"
#include "move.h"
#include "rebalance.h"
#include "subvolume.h"
#include "super.h"
#include "super-io.h"
#include "trace.h"
@@ -230,7 +231,8 @@ int bch2_sum_sector_overwrites(struct btree_trans *trans,
			: 0;

		if (!*usage_increasing &&
		    (new_replicas > bch2_bkey_replicas(c, old) ||
		    (new->k.p.snapshot != old.k->p.snapshot ||
		     new_replicas > bch2_bkey_replicas(c, old) ||
		     (!new_compressed && bch2_bkey_sectors_compressed(old))))
			*usage_increasing = true;

@@ -266,6 +268,7 @@ int bch2_sum_sector_overwrites(struct btree_trans *trans,
}

int bch2_extent_update(struct btree_trans *trans,
		       subvol_inum inum,
		       struct btree_iter *iter,
		       struct bkey_i *k,
		       struct disk_reservation *disk_res,
@@ -324,11 +327,8 @@ int bch2_extent_update(struct btree_trans *trans,
		struct btree_iter inode_iter;
		struct bch_inode_unpacked inode_u;

		ret = bch2_inode_peek(trans, &inode_iter, &inode_u,
				      (subvol_inum) {
				      .subvol = BCACHEFS_ROOT_SUBVOL,
				      .inum = k->k.p.inode,
				      }, BTREE_ITER_INTENT);
		ret = bch2_inode_peek(trans, &inode_iter, &inode_u, inum,
				      BTREE_ITER_INTENT);
		if (ret)
			return ret;

@@ -384,22 +384,37 @@ int bch2_extent_update(struct btree_trans *trans,
	return 0;
}

/*
 * Returns -EINTR if we had to drop locks:
 */
int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
		   struct bpos end, u64 *journal_seq,
		   s64 *i_sectors_delta)
		   subvol_inum inum, u64 end,
		   u64 *journal_seq, s64 *i_sectors_delta)
{
	struct bch_fs *c	= trans->c;
	unsigned max_sectors	= KEY_SIZE_MAX & (~0 << c->block_bits);
	struct bpos end_pos = POS(inum.inum, end);
	struct bkey_s_c k;
	int ret = 0, ret2 = 0;
	u32 snapshot;

	while ((bch2_trans_begin(trans),
		(k = bch2_btree_iter_peek(iter)).k) &&
	       bkey_cmp(iter->pos, end) < 0) {
	while (1) {
		struct disk_reservation disk_res =
			bch2_disk_reservation_init(c, 0);
		struct bkey_i delete;

		bch2_trans_begin(trans);

		ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
		if (ret)
			goto btree_err;

		bch2_btree_iter_set_snapshot(iter, snapshot);

		k = bch2_btree_iter_peek(iter);
		if (bkey_cmp(iter->pos, end_pos) >= 0)
			break;

		ret = bkey_err(k);
		if (ret)
			goto btree_err;
@@ -409,9 +424,9 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,

		/* create the biggest key we can */
		bch2_key_resize(&delete.k, max_sectors);
		bch2_cut_back(end, &delete);
		bch2_cut_back(end_pos, &delete);

		ret = bch2_extent_update(trans, iter, &delete,
		ret = bch2_extent_update(trans, inum, iter, &delete,
				&disk_res, journal_seq,
				0, i_sectors_delta, false);
		bch2_disk_reservation_put(c, &disk_res);
@@ -424,36 +439,31 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
			break;
	}

	if (bkey_cmp(iter->pos, end) > 0) {
		bch2_btree_iter_set_pos(iter, end);
		ret = bch2_btree_iter_traverse(iter);
	}
	if (bkey_cmp(iter->pos, end_pos) > 0)
		bch2_btree_iter_set_pos(iter, end_pos);

	return ret ?: ret2;
}

int bch2_fpunch(struct bch_fs *c, u64 inum, u64 start, u64 end,
int bch2_fpunch(struct bch_fs *c, subvol_inum inum, u64 start, u64 end,
		u64 *journal_seq, s64 *i_sectors_delta)
{
	struct btree_trans trans;
	struct btree_iter iter;
	int ret = 0;
	int ret;

	bch2_trans_init(&trans, c, BTREE_ITER_MAX, 1024);
	bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents,
				   POS(inum, start),
			     POS(inum.inum, start),
			     BTREE_ITER_INTENT);

	ret = bch2_fpunch_at(&trans, &iter, POS(inum, end),
	ret = bch2_fpunch_at(&trans, &iter, inum, end,
			     journal_seq, i_sectors_delta);

	bch2_trans_iter_exit(&trans, &iter);
	bch2_trans_exit(&trans);

	if (ret == -EINTR)
		ret = 0;

	return ret;
	return ret == -EINTR ? 0 : ret;
}

static int bch2_write_index_default(struct bch_write_op *op)
@@ -464,40 +474,51 @@ static int bch2_write_index_default(struct bch_write_op *op)
	struct bkey_i *k = bch2_keylist_front(keys);
	struct btree_trans trans;
	struct btree_iter iter;
	subvol_inum inum = {
		.subvol = op->subvol,
		.inum	= k->k.p.inode,
	};
	int ret;

	BUG_ON(!inum.subvol);

	bch2_bkey_buf_init(&sk);
	bch2_trans_init(&trans, c, BTREE_ITER_MAX, 1024);

	bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents,
			     bkey_start_pos(&k->k),
			     BTREE_ITER_SLOTS|BTREE_ITER_INTENT);

	do {
		bch2_trans_begin(&trans);

		k = bch2_keylist_front(keys);
		bch2_bkey_buf_copy(&sk, c, k);

		k->k.p.snapshot = iter.snapshot;
		ret = bch2_subvolume_get_snapshot(&trans, inum.subvol,
						  &sk.k->k.p.snapshot);
		if (ret == -EINTR)
			continue;
		if (ret)
			break;

		bch2_bkey_buf_realloc(&sk, c, k->k.u64s);
		bkey_copy(sk.k, k);
		bch2_cut_front(iter.pos, sk.k);
		bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents,
				     bkey_start_pos(&sk.k->k),
				     BTREE_ITER_SLOTS|BTREE_ITER_INTENT);

		ret = bch2_extent_update(&trans, &iter, sk.k,
		ret = bch2_extent_update(&trans, inum, &iter, sk.k,
					 &op->res, op_journal_seq(op),
					 op->new_i_size, &op->i_sectors_delta,
					 op->flags & BCH_WRITE_CHECK_ENOSPC);
		bch2_trans_iter_exit(&trans, &iter);

		if (ret == -EINTR)
			continue;
		if (ret)
			break;

		if (bkey_cmp(iter.pos, k->k.p) >= 0)
			bch2_keylist_pop_front(keys);
			bch2_keylist_pop_front(&op->insert_keys);
		else
			bch2_cut_front(iter.pos, k);
	} while (!bch2_keylist_empty(keys));

	bch2_trans_iter_exit(&trans, &iter);
	bch2_trans_exit(&trans);
	bch2_bkey_buf_exit(&sk, c);

@@ -1645,7 +1666,7 @@ static void bch2_rbio_done(struct bch_read_bio *rbio)
}

static void bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_bio *rbio,
				     struct bvec_iter bvec_iter, u64 inode,
				     struct bvec_iter bvec_iter,
				     struct bch_io_failures *failed,
				     unsigned flags)
{
@@ -1709,7 +1730,10 @@ static void bch2_rbio_retry(struct work_struct *work)
	struct bch_fs *c	= rbio->c;
	struct bvec_iter iter	= rbio->bvec_iter;
	unsigned flags		= rbio->flags;
	u64 inode		= rbio->read_pos.inode;
	subvol_inum inum = {
		.subvol = rbio->subvol,
		.inum	= rbio->read_pos.inode,
	};
	struct bch_io_failures failed = { .nr = 0 };

	trace_read_retry(&rbio->bio);
@@ -1725,12 +1749,12 @@ static void bch2_rbio_retry(struct work_struct *work)
	flags &= ~BCH_READ_MAY_PROMOTE;

	if (flags & BCH_READ_NODECODE) {
		bch2_read_retry_nodecode(c, rbio, iter, inode, &failed, flags);
		bch2_read_retry_nodecode(c, rbio, iter, &failed, flags);
	} else {
		flags &= ~BCH_READ_LAST_FRAGMENT;
		flags |= BCH_READ_MUST_CLONE;

		__bch2_read(c, rbio, iter, inode, &failed, flags);
		__bch2_read(c, rbio, iter, inum, &failed, flags);
	}
}

@@ -2174,6 +2198,7 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig,
	/* XXX: only initialize this if needed */
	rbio->devs_have		= bch2_bkey_devs(k);
	rbio->pick		= pick;
	rbio->subvol		= orig->subvol;
	rbio->read_pos		= read_pos;
	rbio->data_btree	= data_btree;
	rbio->data_pos		= data_pos;
@@ -2281,25 +2306,31 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig,
}

void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
		 struct bvec_iter bvec_iter, u64 inode,
		 struct bvec_iter bvec_iter, subvol_inum inum,
		 struct bch_io_failures *failed, unsigned flags)
{
	struct btree_trans trans;
	struct btree_iter iter;
	struct bkey_buf sk;
	struct bkey_s_c k;
	u32 snapshot;
	int ret;

	BUG_ON(flags & BCH_READ_NODECODE);

	bch2_bkey_buf_init(&sk);
	bch2_trans_init(&trans, c, 0, 0);
	bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents,
			     POS(inode, bvec_iter.bi_sector),
			     BTREE_ITER_SLOTS);
retry:
	bch2_trans_begin(&trans);
	iter = (struct btree_iter) { NULL };

	ret = bch2_subvolume_get_snapshot(&trans, inum.subvol, &snapshot);
	if (ret)
		goto err;

	bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents,
			     SPOS(inum.inum, bvec_iter.bi_sector, snapshot),
			     BTREE_ITER_SLOTS|BTREE_ITER_FILTER_SNAPSHOTS);
	while (1) {
		unsigned bytes, sectors, offset_into_extent;
		enum btree_id data_btree = BTREE_ID_extents;
@@ -2314,7 +2345,7 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
		}

		bch2_btree_iter_set_pos(&iter,
				POS(inode, bvec_iter.bi_sector));
				POS(inum.inum, bvec_iter.bi_sector));

		k = bch2_btree_iter_peek_slot(&iter);
		ret = bkey_err(k);
@@ -2364,16 +2395,17 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
		swap(bvec_iter.bi_size, bytes);
		bio_advance_iter(&rbio->bio, &bvec_iter, bytes);
	}
err:
	bch2_trans_iter_exit(&trans, &iter);

	if (ret == -EINTR || ret == READ_RETRY || ret == READ_RETRY_AVOID)
		goto retry;

	bch2_trans_iter_exit(&trans, &iter);
	bch2_trans_exit(&trans);
	bch2_bkey_buf_exit(&sk, c);

	if (ret) {
		bch_err_inum_ratelimited(c, inode,
		bch_err_inum_ratelimited(c, inum.inum,
					 "read error %i from btree lookup", ret);
		rbio->bio.bi_status = BLK_STS_IOERR;
		bch2_rbio_done(rbio);
+11 −8
Original line number Diff line number Diff line
@@ -83,12 +83,13 @@ static inline struct workqueue_struct *index_update_wq(struct bch_write_op *op)

int bch2_sum_sector_overwrites(struct btree_trans *, struct btree_iter *,
			       struct bkey_i *, bool *, bool *, s64 *, s64 *);
int bch2_extent_update(struct btree_trans *, struct btree_iter *,
		       struct bkey_i *, struct disk_reservation *,
		       u64 *, u64, s64 *, bool);
int bch2_extent_update(struct btree_trans *, subvol_inum,
		       struct btree_iter *, struct bkey_i *,
		       struct disk_reservation *, u64 *, u64, s64 *, bool);

int bch2_fpunch_at(struct btree_trans *, struct btree_iter *,
		   struct bpos, u64 *, s64 *);
int bch2_fpunch(struct bch_fs *c, u64, u64, u64, u64 *, s64 *);
		   subvol_inum, u64, u64 *, s64 *);
int bch2_fpunch(struct bch_fs *c, subvol_inum, u64, u64, u64 *, s64 *);

static inline void bch2_write_op_init(struct bch_write_op *op, struct bch_fs *c,
				      struct bch_io_opts opts)
@@ -108,6 +109,7 @@ static inline void bch2_write_op_init(struct bch_write_op *op, struct bch_fs *c,
	op->devs_have.nr	= 0;
	op->target		= 0;
	op->opts		= opts;
	op->subvol		= 0;
	op->pos			= POS_MAX;
	op->version		= ZERO_VERSION;
	op->write_point		= (struct write_point_specifier) { 0 };
@@ -174,10 +176,10 @@ static inline void bch2_read_extent(struct btree_trans *trans,
}

void __bch2_read(struct bch_fs *, struct bch_read_bio *, struct bvec_iter,
		 u64, struct bch_io_failures *, unsigned flags);
		 subvol_inum, struct bch_io_failures *, unsigned flags);

static inline void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
			     u64 inode)
			     subvol_inum inum)
{
	struct bch_io_failures failed = { .nr = 0 };

@@ -185,8 +187,9 @@ static inline void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,

	rbio->c = c;
	rbio->start_time = local_clock();
	rbio->subvol = inum.subvol;

	__bch2_read(c, rbio, rbio->bio.bi_iter, inode, &failed,
	__bch2_read(c, rbio, rbio->bio.bi_iter, inum, &failed,
		    BCH_READ_RETRY_IF_STALE|
		    BCH_READ_MAY_PROMOTE|
		    BCH_READ_USER_MAPPED);
+2 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ struct bch_read_bio {
	/*
	 * pos we read from - different from data_pos for indirect extents:
	 */
	u32			subvol;
	struct bpos		read_pos;

	/*
@@ -124,6 +125,7 @@ struct bch_write_op {
	u16			nonce;
	struct bch_io_opts	opts;

	u32			subvol;
	struct bpos		pos;
	struct bversion		version;

+15 −9
Original line number Diff line number Diff line
@@ -212,6 +212,7 @@ s64 bch2_remap_range(struct bch_fs *c,
	struct bpos dst_end = dst_start, src_end = src_start;
	struct bpos src_want;
	u64 dst_done;
	u32 dst_snapshot, src_snapshot;
	int ret = 0, ret2 = 0;

	if (!percpu_ref_tryget(&c->writes))
@@ -243,15 +244,19 @@ s64 bch2_remap_range(struct bch_fs *c,
		}

		ret = bch2_subvolume_get_snapshot(&trans, src_inum.subvol,
						  &src_iter.snapshot);
						  &src_snapshot);
		if (ret)
			continue;

		bch2_btree_iter_set_snapshot(&src_iter, src_snapshot);

		ret = bch2_subvolume_get_snapshot(&trans, dst_inum.subvol,
						  &dst_iter.snapshot);
						  &dst_snapshot);
		if (ret)
			continue;

		bch2_btree_iter_set_snapshot(&dst_iter, dst_snapshot);

		dst_done = dst_iter.pos.offset - dst_start.offset;
		src_want = POS(src_start.inode, src_start.offset + dst_done);
		bch2_btree_iter_set_pos(&src_iter, src_want);
@@ -262,10 +267,10 @@ s64 bch2_remap_range(struct bch_fs *c,
			continue;

		if (bkey_cmp(src_want, src_iter.pos) < 0) {
			ret = bch2_fpunch_at(&trans, &dst_iter,
					bpos_min(dst_end,
						 POS(dst_iter.pos.inode, dst_iter.pos.offset +
						     src_iter.pos.offset - src_want.offset)),
			ret = bch2_fpunch_at(&trans, &dst_iter, dst_inum,
					min(dst_end.offset,
					    dst_iter.pos.offset +
					    src_iter.pos.offset - src_want.offset),
					journal_seq, i_sectors_delta);
			continue;
		}
@@ -303,8 +308,9 @@ s64 bch2_remap_range(struct bch_fs *c,
		bch2_key_resize(&new_dst.k->k,
				min(src_k.k->p.offset - src_want.offset,
				    dst_end.offset - dst_iter.pos.offset));
		ret = bch2_extent_update(&trans, &dst_iter, new_dst.k,
					 &disk_res, journal_seq,

		ret = bch2_extent_update(&trans, dst_inum, &dst_iter,
					 new_dst.k, &disk_res, journal_seq,
					 new_i_size, i_sectors_delta,
					 true);
		bch2_disk_reservation_put(c, &disk_res);