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

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
...@@ -769,23 +769,35 @@ static void readpage_bio_extend(struct readpages_iter *iter, ...@@ -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, static void bchfs_read(struct btree_trans *trans,
struct bch_read_bio *rbio, u64 inum, struct bch_read_bio *rbio,
subvol_inum inum,
struct readpages_iter *readpages_iter) struct readpages_iter *readpages_iter)
{ {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
struct btree_iter iter;
struct bkey_buf sk; struct bkey_buf sk;
int flags = BCH_READ_RETRY_IF_STALE| int flags = BCH_READ_RETRY_IF_STALE|
BCH_READ_MAY_PROMOTE; BCH_READ_MAY_PROMOTE;
u32 snapshot;
int ret = 0; int ret = 0;
rbio->c = c; rbio->c = c;
rbio->start_time = local_clock(); rbio->start_time = local_clock();
rbio->subvol = inum.subvol;
bch2_bkey_buf_init(&sk); bch2_bkey_buf_init(&sk);
retry: retry:
bch2_trans_begin(trans); 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) { while (1) {
struct bkey_s_c k; struct bkey_s_c k;
unsigned bytes, sectors, offset_into_extent; unsigned bytes, sectors, offset_into_extent;
...@@ -800,15 +812,15 @@ static void bchfs_read(struct btree_trans *trans, struct btree_iter *iter, ...@@ -800,15 +812,15 @@ static void bchfs_read(struct btree_trans *trans, struct btree_iter *iter,
break; break;
} }
bch2_btree_iter_set_pos(iter, bch2_btree_iter_set_pos(&iter,
POS(inum, rbio->bio.bi_iter.bi_sector)); 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); ret = bkey_err(k);
if (ret) if (ret)
break; break;
offset_into_extent = iter->pos.offset - offset_into_extent = iter.pos.offset -
bkey_start_offset(k.k); bkey_start_offset(k.k);
sectors = k.k->size - offset_into_extent; sectors = k.k->size - offset_into_extent;
...@@ -838,7 +850,7 @@ static void bchfs_read(struct btree_trans *trans, struct btree_iter *iter, ...@@ -838,7 +850,7 @@ static void bchfs_read(struct btree_trans *trans, struct btree_iter *iter,
if (bkey_extent_is_allocation(k.k)) if (bkey_extent_is_allocation(k.k))
bch2_add_page_sectors(&rbio->bio, 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); data_btree, k, offset_into_extent, flags);
if (flags & BCH_READ_LAST_FRAGMENT) if (flags & BCH_READ_LAST_FRAGMENT)
...@@ -847,12 +859,14 @@ static void bchfs_read(struct btree_trans *trans, struct btree_iter *iter, ...@@ -847,12 +859,14 @@ static void bchfs_read(struct btree_trans *trans, struct btree_iter *iter,
swap(rbio->bio.bi_iter.bi_size, bytes); swap(rbio->bio.bi_iter.bi_size, bytes);
bio_advance(&rbio->bio, bytes); bio_advance(&rbio->bio, bytes);
} }
err:
bch2_trans_iter_exit(trans, &iter);
if (ret == -EINTR) if (ret == -EINTR)
goto retry; goto retry;
if (ret) { if (ret) {
bch_err_inum_ratelimited(c, inum, bch_err_inum_ratelimited(c, inum.inum,
"read error %i from btree lookup", ret); "read error %i from btree lookup", ret);
rbio->bio.bi_status = BLK_STS_IOERR; rbio->bio.bi_status = BLK_STS_IOERR;
bio_endio(&rbio->bio); bio_endio(&rbio->bio);
...@@ -867,7 +881,6 @@ void bch2_readahead(struct readahead_control *ractl) ...@@ -867,7 +881,6 @@ void bch2_readahead(struct readahead_control *ractl)
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct bch_io_opts opts = io_opts(c, &inode->ei_inode); struct bch_io_opts opts = io_opts(c, &inode->ei_inode);
struct btree_trans trans; struct btree_trans trans;
struct btree_iter iter;
struct page *page; struct page *page;
struct readpages_iter readpages_iter; struct readpages_iter readpages_iter;
int ret; int ret;
...@@ -876,8 +889,6 @@ void bch2_readahead(struct readahead_control *ractl) ...@@ -876,8 +889,6 @@ void bch2_readahead(struct readahead_control *ractl)
BUG_ON(ret); BUG_ON(ret);
bch2_trans_init(&trans, c, 0, 0); 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); bch2_pagecache_add_get(&inode->ei_pagecache_lock);
...@@ -898,22 +909,20 @@ void bch2_readahead(struct readahead_control *ractl) ...@@ -898,22 +909,20 @@ void bch2_readahead(struct readahead_control *ractl)
rbio->bio.bi_end_io = bch2_readpages_end_io; rbio->bio.bi_end_io = bch2_readpages_end_io;
BUG_ON(!bio_add_page(&rbio->bio, page, PAGE_SIZE, 0)); 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); &readpages_iter);
} }
bch2_pagecache_add_put(&inode->ei_pagecache_lock); bch2_pagecache_add_put(&inode->ei_pagecache_lock);
bch2_trans_iter_exit(&trans, &iter);
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
kfree(readpages_iter.pages); kfree(readpages_iter.pages);
} }
static void __bchfs_readpage(struct bch_fs *c, struct bch_read_bio *rbio, 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_trans trans;
struct btree_iter iter;
bch2_page_state_create(page, __GFP_NOFAIL); bch2_page_state_create(page, __GFP_NOFAIL);
...@@ -923,12 +932,7 @@ static void __bchfs_readpage(struct bch_fs *c, struct bch_read_bio *rbio, ...@@ -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)); BUG_ON(!bio_add_page(&rbio->bio, page, PAGE_SIZE, 0));
bch2_trans_init(&trans, c, 0, 0); bch2_trans_init(&trans, c, 0, 0);
bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents, POS_MIN, bchfs_read(&trans, rbio, inum, NULL);
BTREE_ITER_SLOTS);
bchfs_read(&trans, &iter, rbio, inum, NULL);
bch2_trans_iter_exit(&trans, &iter);
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
} }
...@@ -951,7 +955,7 @@ static int bch2_read_single_page(struct page *page, ...@@ -951,7 +955,7 @@ static int bch2_read_single_page(struct page *page,
rbio->bio.bi_private = &done; rbio->bio.bi_private = &done;
rbio->bio.bi_end_io = bch2_read_single_page_end_io; 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); wait_for_completion(&done);
ret = blk_status_to_errno(rbio->bio.bi_status); ret = blk_status_to_errno(rbio->bio.bi_status);
...@@ -1096,6 +1100,7 @@ static void bch2_writepage_io_alloc(struct bch_fs *c, ...@@ -1096,6 +1100,7 @@ static void bch2_writepage_io_alloc(struct bch_fs *c,
op->nr_replicas = nr_replicas; op->nr_replicas = nr_replicas;
op->res.nr_replicas = nr_replicas; op->res.nr_replicas = nr_replicas;
op->write_point = writepoint_hashed(inode->ei_last_dirtied); op->write_point = writepoint_hashed(inode->ei_last_dirtied);
op->subvol = inode->ei_subvol;
op->pos = POS(inode->v.i_ino, sector); op->pos = POS(inode->v.i_ino, sector);
op->end_io = bch2_writepage_io_done; op->end_io = bch2_writepage_io_done;
op->wbio.bio.bi_iter.bi_sector = sector; 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) ...@@ -1733,7 +1738,7 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter)
if (iter->count) if (iter->count)
closure_get(&dio->cl); 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; iter->count += shorten;
...@@ -1816,7 +1821,8 @@ static bool bch2_check_range_allocated(struct bch_fs *c, subvol_inum inum, ...@@ -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) if (bkey_cmp(bkey_start_pos(k.k), POS(inum.inum, end)) >= 0)
break; 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))) { (!compressed && bch2_bkey_sectors_compressed(k))) {
ret = false; ret = false;
break; break;
...@@ -1944,6 +1950,7 @@ static long bch2_dio_write_loop(struct dio_write *dio) ...@@ -1944,6 +1950,7 @@ static long bch2_dio_write_loop(struct dio_write *dio)
op_journal_seq_set(&dio->op, &inode->ei_journal_seq); op_journal_seq_set(&dio->op, &inode->ei_journal_seq);
dio->op.write_point = writepoint_hashed((unsigned long) current); dio->op.write_point = writepoint_hashed((unsigned long) current);
dio->op.nr_replicas = dio->op.opts.data_replicas; 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); dio->op.pos = POS(inode->v.i_ino, (u64) req->ki_pos >> 9);
if ((req->ki_flags & IOCB_DSYNC) && if ((req->ki_flags & IOCB_DSYNC) &&
...@@ -2438,7 +2445,7 @@ int bch2_truncate(struct mnt_idmap *idmap, ...@@ -2438,7 +2445,7 @@ int bch2_truncate(struct mnt_idmap *idmap,
truncate_setsize(&inode->v, iattr->ia_size); 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, round_up(iattr->ia_size, block_bytes(c)) >> 9,
U64_MAX, &inode->ei_journal_seq, &i_sectors_delta); U64_MAX, &inode->ei_journal_seq, &i_sectors_delta);
i_sectors_acct(c, inode, NULL, 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 ...@@ -2498,7 +2505,7 @@ static long bchfs_fpunch(struct bch_inode_info *inode, loff_t offset, loff_t len
if (discard_start < discard_end) { if (discard_start < discard_end) {
s64 i_sectors_delta = 0; s64 i_sectors_delta = 0;
ret = bch2_fpunch(c, inode->v.i_ino, ret = bch2_fpunch(c, inode_inum(inode),
discard_start, discard_end, discard_start, discard_end,
&inode->ei_journal_seq, &inode->ei_journal_seq,
&i_sectors_delta); &i_sectors_delta);
...@@ -2577,7 +2584,7 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode, ...@@ -2577,7 +2584,7 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
} else { } else {
s64 i_sectors_delta = 0; 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, offset >> 9, (offset + len) >> 9,
&inode->ei_journal_seq, &inode->ei_journal_seq,
&i_sectors_delta); &i_sectors_delta);
...@@ -2793,7 +2800,8 @@ static int __bchfs_fallocate(struct bch_inode_info *inode, int mode, ...@@ -2793,7 +2800,8 @@ static int __bchfs_fallocate(struct bch_inode_info *inode, int mode,
reservation.v.nr_replicas = disk_res.nr_replicas; 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, &disk_res, &inode->ei_journal_seq,
0, &i_sectors_delta, true); 0, &i_sectors_delta, true);
i_sectors_acct(c, inode, &quota_res, i_sectors_delta); i_sectors_acct(c, inode, &quota_res, i_sectors_delta);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "keylist.h" #include "keylist.h"
#include "move.h" #include "move.h"
#include "rebalance.h" #include "rebalance.h"
#include "subvolume.h"
#include "super.h" #include "super.h"
#include "super-io.h" #include "super-io.h"
#include "trace.h" #include "trace.h"
...@@ -230,7 +231,8 @@ int bch2_sum_sector_overwrites(struct btree_trans *trans, ...@@ -230,7 +231,8 @@ int bch2_sum_sector_overwrites(struct btree_trans *trans,
: 0; : 0;
if (!*usage_increasing && 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)))) (!new_compressed && bch2_bkey_sectors_compressed(old))))
*usage_increasing = true; *usage_increasing = true;
...@@ -266,6 +268,7 @@ int bch2_sum_sector_overwrites(struct btree_trans *trans, ...@@ -266,6 +268,7 @@ int bch2_sum_sector_overwrites(struct btree_trans *trans,
} }
int bch2_extent_update(struct btree_trans *trans, int bch2_extent_update(struct btree_trans *trans,
subvol_inum inum,
struct btree_iter *iter, struct btree_iter *iter,
struct bkey_i *k, struct bkey_i *k,
struct disk_reservation *disk_res, struct disk_reservation *disk_res,
...@@ -324,11 +327,8 @@ int bch2_extent_update(struct btree_trans *trans, ...@@ -324,11 +327,8 @@ int bch2_extent_update(struct btree_trans *trans,
struct btree_iter inode_iter; struct btree_iter inode_iter;
struct bch_inode_unpacked inode_u; struct bch_inode_unpacked inode_u;
ret = bch2_inode_peek(trans, &inode_iter, &inode_u, ret = bch2_inode_peek(trans, &inode_iter, &inode_u, inum,
(subvol_inum) { BTREE_ITER_INTENT);
.subvol = BCACHEFS_ROOT_SUBVOL,
.inum = k->k.p.inode,
}, BTREE_ITER_INTENT);
if (ret) if (ret)
return ret; return ret;
...@@ -384,22 +384,37 @@ int bch2_extent_update(struct btree_trans *trans, ...@@ -384,22 +384,37 @@ int bch2_extent_update(struct btree_trans *trans,
return 0; return 0;
} }
/*
* Returns -EINTR if we had to drop locks:
*/
int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter, int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
struct bpos end, u64 *journal_seq, subvol_inum inum, u64 end,
s64 *i_sectors_delta) u64 *journal_seq, s64 *i_sectors_delta)
{ {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
unsigned max_sectors = KEY_SIZE_MAX & (~0 << c->block_bits); unsigned max_sectors = KEY_SIZE_MAX & (~0 << c->block_bits);
struct bpos end_pos = POS(inum.inum, end);
struct bkey_s_c k; struct bkey_s_c k;
int ret = 0, ret2 = 0; int ret = 0, ret2 = 0;
u32 snapshot;
while ((bch2_trans_begin(trans), while (1) {
(k = bch2_btree_iter_peek(iter)).k) &&
bkey_cmp(iter->pos, end) < 0) {
struct disk_reservation disk_res = struct disk_reservation disk_res =
bch2_disk_reservation_init(c, 0); bch2_disk_reservation_init(c, 0);
struct bkey_i delete; 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); ret = bkey_err(k);
if (ret) if (ret)
goto btree_err; goto btree_err;
...@@ -409,9 +424,9 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter, ...@@ -409,9 +424,9 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
/* create the biggest key we can */ /* create the biggest key we can */
bch2_key_resize(&delete.k, max_sectors); 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, &disk_res, journal_seq,
0, i_sectors_delta, false); 0, i_sectors_delta, false);
bch2_disk_reservation_put(c, &disk_res); bch2_disk_reservation_put(c, &disk_res);
...@@ -424,36 +439,31 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter, ...@@ -424,36 +439,31 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
break; break;
} }
if (bkey_cmp(iter->pos, end) > 0) { if (bkey_cmp(iter->pos, end_pos) > 0)
bch2_btree_iter_set_pos(iter, end); bch2_btree_iter_set_pos(iter, end_pos);
ret = bch2_btree_iter_traverse(iter);
}
return ret ?: ret2; 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) u64 *journal_seq, s64 *i_sectors_delta)
{ {
struct btree_trans trans; struct btree_trans trans;
struct btree_iter iter; struct btree_iter iter;
int ret = 0; int ret;
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 1024); bch2_trans_init(&trans, c, BTREE_ITER_MAX, 1024);
bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents, bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents,
POS(inum, start), POS(inum.inum, start),
BTREE_ITER_INTENT); 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); journal_seq, i_sectors_delta);
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
if (ret == -EINTR) return ret == -EINTR ? 0 : ret;
ret = 0;
return ret;
} }
static int bch2_write_index_default(struct bch_write_op *op) 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) ...@@ -464,40 +474,51 @@ static int bch2_write_index_default(struct bch_write_op *op)
struct bkey_i *k = bch2_keylist_front(keys); struct bkey_i *k = bch2_keylist_front(keys);
struct btree_trans trans; struct btree_trans trans;
struct btree_iter iter; struct btree_iter iter;
subvol_inum inum = {
.subvol = op->subvol,
.inum = k->k.p.inode,
};
int ret; int ret;
BUG_ON(!inum.subvol);
bch2_bkey_buf_init(&sk); bch2_bkey_buf_init(&sk);
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 1024); 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 { do {
bch2_trans_begin(&trans); bch2_trans_begin(&trans);
k = bch2_keylist_front(keys); 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); bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents,
bkey_copy(sk.k, k); bkey_start_pos(&sk.k->k),
bch2_cut_front(iter.pos, sk.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->res, op_journal_seq(op),
op->new_i_size, &op->i_sectors_delta, op->new_i_size, &op->i_sectors_delta,
op->flags & BCH_WRITE_CHECK_ENOSPC); op->flags & BCH_WRITE_CHECK_ENOSPC);
bch2_trans_iter_exit(&trans, &iter);
if (ret == -EINTR) if (ret == -EINTR)
continue; continue;
if (ret) if (ret)
break; break;
if (bkey_cmp(iter.pos, k->k.p) >= 0) 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)); } while (!bch2_keylist_empty(keys));
bch2_trans_iter_exit(&trans, &iter);
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&sk, c); bch2_bkey_buf_exit(&sk, c);
...@@ -1645,7 +1666,7 @@ static void bch2_rbio_done(struct bch_read_bio *rbio) ...@@ -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, 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, struct bch_io_failures *failed,
unsigned flags) unsigned flags)
{ {
...@@ -1709,7 +1730,10 @@ static void bch2_rbio_retry(struct work_struct *work) ...@@ -1709,7 +1730,10 @@ static void bch2_rbio_retry(struct work_struct *work)
struct bch_fs *c = rbio->c; struct bch_fs *c = rbio->c;
struct bvec_iter iter = rbio->bvec_iter; struct bvec_iter iter = rbio->bvec_iter;
unsigned flags = rbio->flags; 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 }; struct bch_io_failures failed = { .nr = 0 };
trace_read_retry(&rbio->bio); trace_read_retry(&rbio->bio);
...@@ -1725,12 +1749,12 @@ static void bch2_rbio_retry(struct work_struct *work) ...@@ -1725,12 +1749,12 @@ static void bch2_rbio_retry(struct work_struct *work)
flags &= ~BCH_READ_MAY_PROMOTE; flags &= ~BCH_READ_MAY_PROMOTE;
if (flags & BCH_READ_NODECODE) { 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 { } else {
flags &= ~BCH_READ_LAST_FRAGMENT; flags &= ~BCH_READ_LAST_FRAGMENT;
flags |= BCH_READ_MUST_CLONE; 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, ...@@ -2174,6 +2198,7 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig,
/* XXX: only initialize this if needed */ /* XXX: only initialize this if needed */
rbio->devs_have = bch2_bkey_devs(k); rbio->devs_have = bch2_bkey_devs(k);
rbio->pick = pick; rbio->pick = pick;
rbio->subvol = orig->subvol;
rbio->read_pos = read_pos; rbio->read_pos = read_pos;
rbio->data_btree = data_btree; rbio->data_btree = data_btree;
rbio->data_pos = data_pos; rbio->data_pos = data_pos;
...@@ -2281,25 +2306,31 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, ...@@ -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, 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 bch_io_failures *failed, unsigned flags)
{ {
struct btree_trans trans; struct btree_trans trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_buf sk; struct bkey_buf sk;
struct bkey_s_c k; struct bkey_s_c k;
u32 snapshot;
int ret; int ret;
BUG_ON(flags & BCH_READ_NODECODE); BUG_ON(flags & BCH_READ_NODECODE);
bch2_bkey_buf_init(&sk); bch2_bkey_buf_init(&sk);
bch2_trans_init(&trans, c, 0, 0); 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: retry:
bch2_trans_begin(&trans); 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) { while (1) {
unsigned bytes, sectors, offset_into_extent; unsigned bytes, sectors, offset_into_extent;
enum btree_id data_btree = BTREE_ID_extents; enum btree_id data_btree = BTREE_ID_extents;
...@@ -2314,7 +2345,7 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, ...@@ -2314,7 +2345,7 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
} }
bch2_btree_iter_set_pos(&iter, 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); k = bch2_btree_iter_peek_slot(&iter);
ret = bkey_err(k); ret = bkey_err(k);
...@@ -2364,16 +2395,17 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, ...@@ -2364,16 +2395,17 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
swap(bvec_iter.bi_size, bytes); swap(bvec_iter.bi_size, bytes);
bio_advance_iter(&rbio->bio, &bvec_iter, 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) if (ret == -EINTR || ret == READ_RETRY || ret == READ_RETRY_AVOID)
goto retry; goto retry;
bch2_trans_iter_exit(&trans, &iter);
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&sk, c); bch2_bkey_buf_exit(&sk, c);
if (ret) { if (ret) {
bch_err_inum_ratelimited(c, inode, bch_err_inum_ratelimited(c, inum.inum,
"read error %i from btree lookup", ret); "read error %i from btree lookup", ret);
rbio->bio.bi_status = BLK_STS_IOERR; rbio->bio.bi_status = BLK_STS_IOERR;
bch2_rbio_done(rbio); bch2_rbio_done(rbio);
......
...@@ -83,12 +83,13 @@ static inline struct workqueue_struct *index_update_wq(struct bch_write_op *op) ...@@ -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 *, int bch2_sum_sector_overwrites(struct btree_trans *, struct btree_iter *,
struct bkey_i *, bool *, bool *, s64 *, s64 *); struct bkey_i *, bool *, bool *, s64 *, s64 *);
int bch2_extent_update(struct btree_trans *, struct btree_iter *, int bch2_extent_update(struct btree_trans *, subvol_inum,
struct bkey_i *, struct disk_reservation *, struct btree_iter *, struct bkey_i *,
u64 *, u64, s64 *, bool); struct disk_reservation *, u64 *, u64, s64 *, bool);
int bch2_fpunch_at(struct btree_trans *, struct btree_iter *, int bch2_fpunch_at(struct btree_trans *, struct btree_iter *,
struct bpos, u64 *, s64 *); subvol_inum, u64, u64 *, s64 *);
int bch2_fpunch(struct bch_fs *c, u64, u64, 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, static inline void bch2_write_op_init(struct bch_write_op *op, struct bch_fs *c,
struct bch_io_opts opts) 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, ...@@ -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->devs_have.nr = 0;
op->target = 0; op->target = 0;
op->opts = opts; op->opts = opts;
op->subvol = 0;
op->pos = POS_MAX; op->pos = POS_MAX;
op->version = ZERO_VERSION; op->version = ZERO_VERSION;
op->write_point = (struct write_point_specifier) { 0 }; op->write_point = (struct write_point_specifier) { 0 };
...@@ -174,10 +176,10 @@ static inline void bch2_read_extent(struct btree_trans *trans, ...@@ -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, 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, 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 }; 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, ...@@ -185,8 +187,9 @@ static inline void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
rbio->c = c; rbio->c = c;
rbio->start_time = local_clock(); 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_RETRY_IF_STALE|
BCH_READ_MAY_PROMOTE| BCH_READ_MAY_PROMOTE|
BCH_READ_USER_MAPPED); BCH_READ_USER_MAPPED);
......
...@@ -62,6 +62,7 @@ struct bch_read_bio { ...@@ -62,6 +62,7 @@ struct bch_read_bio {
/* /*
* pos we read from - different from data_pos for indirect extents: * pos we read from - different from data_pos for indirect extents:
*/ */
u32 subvol;
struct bpos read_pos; struct bpos read_pos;
/* /*
...@@ -124,6 +125,7 @@ struct bch_write_op { ...@@ -124,6 +125,7 @@ struct bch_write_op {
u16 nonce; u16 nonce;
struct bch_io_opts opts; struct bch_io_opts opts;
u32 subvol;
struct bpos pos; struct bpos pos;
struct bversion version; struct bversion version;
......
...@@ -212,6 +212,7 @@ s64 bch2_remap_range(struct bch_fs *c, ...@@ -212,6 +212,7 @@ s64 bch2_remap_range(struct bch_fs *c,
struct bpos dst_end = dst_start, src_end = src_start; struct bpos dst_end = dst_start, src_end = src_start;
struct bpos src_want; struct bpos src_want;
u64 dst_done; u64 dst_done;
u32 dst_snapshot, src_snapshot;
int ret = 0, ret2 = 0; int ret = 0, ret2 = 0;
if (!percpu_ref_tryget(&c->writes)) if (!percpu_ref_tryget(&c->writes))
...@@ -243,15 +244,19 @@ s64 bch2_remap_range(struct bch_fs *c, ...@@ -243,15 +244,19 @@ s64 bch2_remap_range(struct bch_fs *c,
} }
ret = bch2_subvolume_get_snapshot(&trans, src_inum.subvol, ret = bch2_subvolume_get_snapshot(&trans, src_inum.subvol,
&src_iter.snapshot); &src_snapshot);
if (ret) if (ret)
continue; continue;
bch2_btree_iter_set_snapshot(&src_iter, src_snapshot);
ret = bch2_subvolume_get_snapshot(&trans, dst_inum.subvol, ret = bch2_subvolume_get_snapshot(&trans, dst_inum.subvol,
&dst_iter.snapshot); &dst_snapshot);
if (ret) if (ret)
continue; continue;
bch2_btree_iter_set_snapshot(&dst_iter, dst_snapshot);
dst_done = dst_iter.pos.offset - dst_start.offset; dst_done = dst_iter.pos.offset - dst_start.offset;
src_want = POS(src_start.inode, src_start.offset + dst_done); src_want = POS(src_start.inode, src_start.offset + dst_done);
bch2_btree_iter_set_pos(&src_iter, src_want); bch2_btree_iter_set_pos(&src_iter, src_want);
...@@ -262,11 +267,11 @@ s64 bch2_remap_range(struct bch_fs *c, ...@@ -262,11 +267,11 @@ s64 bch2_remap_range(struct bch_fs *c,
continue; continue;
if (bkey_cmp(src_want, src_iter.pos) < 0) { if (bkey_cmp(src_want, src_iter.pos) < 0) {
ret = bch2_fpunch_at(&trans, &dst_iter, ret = bch2_fpunch_at(&trans, &dst_iter, dst_inum,
bpos_min(dst_end, min(dst_end.offset,
POS(dst_iter.pos.inode, dst_iter.pos.offset + dst_iter.pos.offset +
src_iter.pos.offset - src_want.offset)), src_iter.pos.offset - src_want.offset),
journal_seq, i_sectors_delta); journal_seq, i_sectors_delta);
continue; continue;
} }
...@@ -303,8 +308,9 @@ s64 bch2_remap_range(struct bch_fs *c, ...@@ -303,8 +308,9 @@ s64 bch2_remap_range(struct bch_fs *c,
bch2_key_resize(&new_dst.k->k, bch2_key_resize(&new_dst.k->k,
min(src_k.k->p.offset - src_want.offset, min(src_k.k->p.offset - src_want.offset,
dst_end.offset - dst_iter.pos.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, new_i_size, i_sectors_delta,
true); true);
bch2_disk_reservation_put(c, &disk_res); bch2_disk_reservation_put(c, &disk_res);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment