mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
bcachefs: Convert bch2_fpunch to bch2_extent_update()
As before - we're moving non Linux specific code out of fs-io.c. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
2925fc49b3
commit
2e87eae1fb
6 changed files with 163 additions and 129 deletions
|
@ -2145,78 +2145,6 @@ int bch2_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
|||
|
||||
/* truncate: */
|
||||
|
||||
int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
|
||||
struct bpos end, struct bch_inode_info *inode)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
unsigned max_sectors = KEY_SIZE_MAX & (~0 << c->block_bits);
|
||||
struct bkey_s_c k;
|
||||
int ret = 0, ret2 = 0;
|
||||
|
||||
while ((k = bch2_btree_iter_peek(iter)).k &&
|
||||
bkey_cmp(iter->pos, end) < 0) {
|
||||
struct disk_reservation disk_res =
|
||||
bch2_disk_reservation_init(c, 0);
|
||||
struct bkey_i delete;
|
||||
|
||||
ret = bkey_err(k);
|
||||
if (ret)
|
||||
goto btree_err;
|
||||
|
||||
bkey_init(&delete.k);
|
||||
delete.k.p = iter->pos;
|
||||
|
||||
/* create the biggest key we can */
|
||||
bch2_key_resize(&delete.k, max_sectors);
|
||||
bch2_cut_back(end, &delete.k);
|
||||
|
||||
bch2_trans_begin_updates(trans);
|
||||
|
||||
ret = bchfs_extent_update(trans, inode,
|
||||
&disk_res, NULL, iter, &delete,
|
||||
0, false, true, NULL);
|
||||
bch2_disk_reservation_put(c, &disk_res);
|
||||
btree_err:
|
||||
if (ret == -EINTR) {
|
||||
ret2 = ret;
|
||||
ret = 0;
|
||||
}
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
if (bkey_cmp(iter->pos, end) > 0) {
|
||||
bch2_btree_iter_set_pos(iter, end);
|
||||
ret = bch2_btree_iter_traverse(iter);
|
||||
}
|
||||
|
||||
return ret ?: ret2;
|
||||
}
|
||||
|
||||
static int __bch2_fpunch(struct bch_fs *c, struct bch_inode_info *inode,
|
||||
u64 start_offset, u64 end_offset)
|
||||
{
|
||||
struct btree_trans trans;
|
||||
struct btree_iter *iter;
|
||||
int ret = 0;
|
||||
|
||||
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 1024);
|
||||
|
||||
iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
|
||||
POS(inode->v.i_ino, start_offset),
|
||||
BTREE_ITER_INTENT);
|
||||
|
||||
ret = bch2_fpunch_at(&trans, iter,
|
||||
POS(inode->v.i_ino, end_offset), inode);
|
||||
|
||||
bch2_trans_exit(&trans);
|
||||
|
||||
if (ret == -EINTR)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int range_has_data(struct bch_fs *c,
|
||||
struct bpos start,
|
||||
struct bpos end)
|
||||
|
@ -2388,6 +2316,7 @@ int bch2_truncate(struct bch_inode_info *inode, struct iattr *iattr)
|
|||
struct btree_trans trans;
|
||||
struct btree_iter *iter;
|
||||
u64 new_i_size = iattr->ia_size;
|
||||
s64 i_sectors_delta = 0;
|
||||
int ret = 0;
|
||||
|
||||
inode_dio_wait(&inode->v);
|
||||
|
@ -2447,9 +2376,11 @@ int bch2_truncate(struct bch_inode_info *inode, struct iattr *iattr)
|
|||
|
||||
truncate_setsize(&inode->v, iattr->ia_size);
|
||||
|
||||
ret = __bch2_fpunch(c, inode,
|
||||
ret = bch2_fpunch(c, inode->v.i_ino,
|
||||
round_up(iattr->ia_size, block_bytes(c)) >> 9,
|
||||
U64_MAX);
|
||||
U64_MAX, &inode->ei_journal_seq, &i_sectors_delta);
|
||||
i_sectors_acct(c, inode, NULL, i_sectors_delta);
|
||||
|
||||
if (unlikely(ret))
|
||||
goto err;
|
||||
|
||||
|
@ -2467,7 +2398,7 @@ int bch2_truncate(struct bch_inode_info *inode, struct iattr *iattr)
|
|||
|
||||
/* fallocate: */
|
||||
|
||||
static long bch2_fpunch(struct bch_inode_info *inode, loff_t offset, loff_t len)
|
||||
static long bchfs_fpunch(struct bch_inode_info *inode, loff_t offset, loff_t len)
|
||||
{
|
||||
struct bch_fs *c = inode->v.i_sb->s_fs_info;
|
||||
u64 discard_start = round_up(offset, block_bytes(c)) >> 9;
|
||||
|
@ -2495,8 +2426,15 @@ static long bch2_fpunch(struct bch_inode_info *inode, loff_t offset, loff_t len)
|
|||
|
||||
truncate_pagecache_range(&inode->v, offset, offset + len - 1);
|
||||
|
||||
if (discard_start < discard_end)
|
||||
ret = __bch2_fpunch(c, inode, discard_start, discard_end);
|
||||
if (discard_start < discard_end) {
|
||||
s64 i_sectors_delta = 0;
|
||||
|
||||
ret = bch2_fpunch(c, inode->v.i_ino,
|
||||
discard_start, discard_end,
|
||||
&inode->ei_journal_seq,
|
||||
&i_sectors_delta);
|
||||
i_sectors_acct(c, inode, NULL, i_sectors_delta);
|
||||
}
|
||||
err:
|
||||
bch2_pagecache_block_put(&inode->ei_pagecache_lock);
|
||||
inode_unlock(&inode->v);
|
||||
|
@ -2504,7 +2442,7 @@ static long bch2_fpunch(struct bch_inode_info *inode, loff_t offset, loff_t len)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static long bch2_fcollapse_finsert(struct bch_inode_info *inode,
|
||||
static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
|
||||
loff_t offset, loff_t len,
|
||||
bool insert)
|
||||
{
|
||||
|
@ -2564,8 +2502,14 @@ static long bch2_fcollapse_finsert(struct bch_inode_info *inode,
|
|||
ATTR_MTIME|ATTR_CTIME);
|
||||
mutex_unlock(&inode->ei_update_lock);
|
||||
} else {
|
||||
ret = __bch2_fpunch(c, inode, offset >> 9,
|
||||
(offset + len) >> 9);
|
||||
s64 i_sectors_delta = 0;
|
||||
|
||||
ret = bch2_fpunch(c, inode->v.i_ino,
|
||||
offset >> 9, (offset + len) >> 9,
|
||||
&inode->ei_journal_seq,
|
||||
&i_sectors_delta);
|
||||
i_sectors_acct(c, inode, NULL, i_sectors_delta);
|
||||
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
@ -2715,8 +2659,8 @@ static long bch2_fcollapse_finsert(struct bch_inode_info *inode,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static long bch2_fallocate(struct bch_inode_info *inode, int mode,
|
||||
loff_t offset, loff_t len)
|
||||
static long bchfs_fallocate(struct bch_inode_info *inode, int mode,
|
||||
loff_t offset, loff_t len)
|
||||
{
|
||||
struct address_space *mapping = inode->v.i_mapping;
|
||||
struct bch_fs *c = inode->v.i_sb->s_fs_info;
|
||||
|
@ -2765,6 +2709,7 @@ static long bch2_fallocate(struct bch_inode_info *inode, int mode,
|
|||
end_pos = POS(inode->v.i_ino, block_end >> 9);
|
||||
|
||||
while (bkey_cmp(iter->pos, end_pos) < 0) {
|
||||
s64 i_sectors_delta = 0;
|
||||
struct disk_reservation disk_res = { 0 };
|
||||
struct quota_res quota_res = { 0 };
|
||||
struct bkey_i_reservation reservation;
|
||||
|
@ -2818,10 +2763,10 @@ static long bch2_fallocate(struct bch_inode_info *inode, int mode,
|
|||
|
||||
bch2_trans_begin_updates(&trans);
|
||||
|
||||
ret = bchfs_extent_update(&trans, inode,
|
||||
&disk_res, "a_res,
|
||||
iter, &reservation.k_i,
|
||||
0, true, true, NULL);
|
||||
ret = bch2_extent_update(&trans, iter, &reservation.k_i,
|
||||
&disk_res, &inode->ei_journal_seq,
|
||||
0, &i_sectors_delta);
|
||||
i_sectors_acct(c, inode, "a_res, i_sectors_delta);
|
||||
bkey_err:
|
||||
bch2_quota_reservation_put(c, inode, "a_res);
|
||||
bch2_disk_reservation_put(c, &disk_res);
|
||||
|
@ -2887,16 +2832,16 @@ long bch2_fallocate_dispatch(struct file *file, int mode,
|
|||
struct bch_inode_info *inode = file_bch_inode(file);
|
||||
|
||||
if (!(mode & ~(FALLOC_FL_KEEP_SIZE|FALLOC_FL_ZERO_RANGE)))
|
||||
return bch2_fallocate(inode, mode, offset, len);
|
||||
return bchfs_fallocate(inode, mode, offset, len);
|
||||
|
||||
if (mode == (FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE))
|
||||
return bch2_fpunch(inode, offset, len);
|
||||
return bchfs_fpunch(inode, offset, len);
|
||||
|
||||
if (mode == FALLOC_FL_INSERT_RANGE)
|
||||
return bch2_fcollapse_finsert(inode, offset, len, true);
|
||||
return bchfs_fcollapse_finsert(inode, offset, len, true);
|
||||
|
||||
if (mode == FALLOC_FL_COLLAPSE_RANGE)
|
||||
return bch2_fcollapse_finsert(inode, offset, len, false);
|
||||
return bchfs_fcollapse_finsert(inode, offset, len, false);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -2941,6 +2886,7 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src,
|
|||
struct bch_inode_info *src = file_bch_inode(file_src);
|
||||
struct bch_inode_info *dst = file_bch_inode(file_dst);
|
||||
struct bch_fs *c = src->v.i_sb->s_fs_info;
|
||||
s64 i_sectors_delta = 0;
|
||||
loff_t ret = 0;
|
||||
loff_t aligned_len;
|
||||
|
||||
|
@ -2960,6 +2906,8 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src,
|
|||
|
||||
bch2_lock_inodes(INODE_LOCK|INODE_PAGECACHE_BLOCK, src, dst);
|
||||
|
||||
file_update_time(file_dst);
|
||||
|
||||
inode_dio_wait(&src->v);
|
||||
inode_dio_wait(&dst->v);
|
||||
|
||||
|
@ -2967,26 +2915,40 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src,
|
|||
file_dst, pos_dst,
|
||||
&len, remap_flags);
|
||||
if (ret < 0 || len == 0)
|
||||
goto out_unlock;
|
||||
goto err;
|
||||
|
||||
aligned_len = round_up(len, block_bytes(c));
|
||||
|
||||
ret = write_invalidate_inode_pages_range(dst->v.i_mapping,
|
||||
pos_dst, pos_dst + aligned_len);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
goto err;
|
||||
|
||||
mark_range_unallocated(src, pos_src, pos_src + aligned_len);
|
||||
|
||||
ret = bch2_remap_range(c, dst,
|
||||
ret = bch2_remap_range(c,
|
||||
POS(dst->v.i_ino, pos_dst >> 9),
|
||||
POS(src->v.i_ino, pos_src >> 9),
|
||||
aligned_len >> 9,
|
||||
pos_dst + len);
|
||||
if (ret > 0)
|
||||
ret = min(ret << 9, len);
|
||||
&dst->ei_journal_seq,
|
||||
pos_dst + len, &i_sectors_delta);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
out_unlock:
|
||||
ret <<= 9;
|
||||
/*
|
||||
* due to alignment, we might have remapped slightly more than requsted
|
||||
*/
|
||||
ret = min(ret, len);
|
||||
|
||||
/* XXX get a quota reservation */
|
||||
i_sectors_acct(c, dst, NULL, i_sectors_delta);
|
||||
|
||||
spin_lock(&dst->v.i_lock);
|
||||
if (pos_dst + len > dst->v.i_size)
|
||||
i_size_write(&dst->v, pos_dst + len);
|
||||
spin_unlock(&dst->v.i_lock);
|
||||
err:
|
||||
bch2_unlock_inodes(INODE_LOCK|INODE_PAGECACHE_BLOCK, src, dst);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -18,8 +18,6 @@ int bchfs_extent_update(struct btree_trans *,
|
|||
struct btree_iter *,
|
||||
struct bkey_i *,
|
||||
u64, bool, bool, s64 *);
|
||||
int bch2_fpunch_at(struct btree_trans *, struct btree_iter *,
|
||||
struct bpos, struct bch_inode_info *);
|
||||
|
||||
int __must_check bch2_write_inode_size(struct bch_fs *,
|
||||
struct bch_inode_info *,
|
||||
|
|
|
@ -319,6 +319,77 @@ int bch2_extent_update(struct btree_trans *trans,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
|
||||
struct bpos 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 bkey_s_c k;
|
||||
int ret = 0, ret2 = 0;
|
||||
|
||||
while ((k = bch2_btree_iter_peek(iter)).k &&
|
||||
bkey_cmp(iter->pos, end) < 0) {
|
||||
struct disk_reservation disk_res =
|
||||
bch2_disk_reservation_init(c, 0);
|
||||
struct bkey_i delete;
|
||||
|
||||
ret = bkey_err(k);
|
||||
if (ret)
|
||||
goto btree_err;
|
||||
|
||||
bkey_init(&delete.k);
|
||||
delete.k.p = iter->pos;
|
||||
|
||||
/* create the biggest key we can */
|
||||
bch2_key_resize(&delete.k, max_sectors);
|
||||
bch2_cut_back(end, &delete.k);
|
||||
|
||||
bch2_trans_begin_updates(trans);
|
||||
|
||||
ret = bch2_extent_update(trans, iter, &delete,
|
||||
&disk_res, journal_seq,
|
||||
0, i_sectors_delta);
|
||||
bch2_disk_reservation_put(c, &disk_res);
|
||||
btree_err:
|
||||
if (ret == -EINTR) {
|
||||
ret2 = ret;
|
||||
ret = 0;
|
||||
}
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
if (bkey_cmp(iter->pos, end) > 0) {
|
||||
bch2_btree_iter_set_pos(iter, end);
|
||||
ret = bch2_btree_iter_traverse(iter);
|
||||
}
|
||||
|
||||
return ret ?: ret2;
|
||||
}
|
||||
|
||||
int bch2_fpunch(struct bch_fs *c, u64 inum, u64 start, u64 end,
|
||||
u64 *journal_seq, s64 *i_sectors_delta)
|
||||
{
|
||||
struct btree_trans trans;
|
||||
struct btree_iter *iter;
|
||||
int ret = 0;
|
||||
|
||||
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 1024);
|
||||
iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
|
||||
POS(inum, start),
|
||||
BTREE_ITER_INTENT);
|
||||
|
||||
ret = bch2_fpunch_at(&trans, iter, POS(inum, end),
|
||||
journal_seq, i_sectors_delta);
|
||||
bch2_trans_exit(&trans);
|
||||
|
||||
if (ret == -EINTR)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Writes */
|
||||
|
||||
void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c,
|
||||
|
|
|
@ -61,6 +61,10 @@ static inline struct workqueue_struct *index_update_wq(struct bch_write_op *op)
|
|||
int bch2_extent_update(struct btree_trans *, struct btree_iter *,
|
||||
struct bkey_i *, struct disk_reservation *,
|
||||
u64 *, u64, s64 *);
|
||||
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 *);
|
||||
|
||||
int bch2_write_index_default(struct bch_write_op *);
|
||||
|
||||
static inline void bch2_write_op_init(struct bch_write_op *op, struct bch_fs *c,
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
#include "bcachefs.h"
|
||||
#include "btree_update.h"
|
||||
#include "extents.h"
|
||||
#include "fs.h"
|
||||
#include "fs-io.h"
|
||||
#include "inode.h"
|
||||
#include "io.h"
|
||||
#include "reflink.h"
|
||||
|
||||
#include <linux/sched/signal.h>
|
||||
|
@ -70,12 +70,6 @@ void bch2_reflink_v_to_text(struct printbuf *out, struct bch_fs *c,
|
|||
bch2_bkey_ptrs_to_text(out, c, k);
|
||||
}
|
||||
|
||||
/*
|
||||
* bch2_remap_range() depends on bch2_extent_update(), which depends on various
|
||||
* things tied to the linux vfs for inode updates, for now:
|
||||
*/
|
||||
#ifndef NO_BCACHEFS_FS
|
||||
|
||||
static int bch2_make_extent_indirect(struct btree_trans *trans,
|
||||
struct btree_iter *extent_iter,
|
||||
struct bkey_i_extent *e)
|
||||
|
@ -159,9 +153,9 @@ static struct bkey_s_c get_next_src(struct btree_iter *iter, struct bpos end)
|
|||
}
|
||||
|
||||
s64 bch2_remap_range(struct bch_fs *c,
|
||||
struct bch_inode_info *dst_inode,
|
||||
struct bpos dst_start, struct bpos src_start,
|
||||
u64 remap_sectors, u64 new_i_size)
|
||||
u64 remap_sectors, u64 *journal_seq,
|
||||
u64 new_i_size, s64 *i_sectors_delta)
|
||||
{
|
||||
struct btree_trans trans;
|
||||
struct btree_iter *dst_iter, *src_iter;
|
||||
|
@ -170,7 +164,7 @@ s64 bch2_remap_range(struct bch_fs *c,
|
|||
struct bpos dst_end = dst_start, src_end = src_start;
|
||||
struct bpos dst_want, src_want;
|
||||
u64 src_done, dst_done;
|
||||
int ret = 0;
|
||||
int ret = 0, ret2 = 0;
|
||||
|
||||
if (!(c->sb.features & (1ULL << BCH_FEATURE_REFLINK))) {
|
||||
mutex_lock(&c->sb_lock);
|
||||
|
@ -213,7 +207,7 @@ s64 bch2_remap_range(struct bch_fs *c,
|
|||
|
||||
if (bkey_cmp(dst_iter->pos, dst_want) < 0) {
|
||||
ret = bch2_fpunch_at(&trans, dst_iter, dst_want,
|
||||
dst_inode);
|
||||
journal_seq, i_sectors_delta);
|
||||
if (ret)
|
||||
goto btree_err;
|
||||
continue;
|
||||
|
@ -259,9 +253,9 @@ s64 bch2_remap_range(struct bch_fs *c,
|
|||
min(src_k.k->p.offset - src_iter->pos.offset,
|
||||
dst_end.offset - dst_iter->pos.offset));
|
||||
|
||||
ret = bchfs_extent_update(&trans, dst_inode, NULL, NULL,
|
||||
dst_iter, &new_dst.k,
|
||||
new_i_size, false, true, NULL);
|
||||
ret = bch2_extent_update(&trans, dst_iter, &new_dst.k,
|
||||
NULL, journal_seq,
|
||||
new_i_size, i_sectors_delta);
|
||||
if (ret)
|
||||
goto btree_err;
|
||||
|
||||
|
@ -282,17 +276,24 @@ s64 bch2_remap_range(struct bch_fs *c,
|
|||
dst_done = dst_iter->pos.offset - dst_start.offset;
|
||||
new_i_size = min(dst_iter->pos.offset << 9, new_i_size);
|
||||
|
||||
bch2_trans_begin(&trans);
|
||||
|
||||
do {
|
||||
struct bch_inode_unpacked inode_u;
|
||||
struct btree_iter *inode_iter;
|
||||
|
||||
inode_iter = bch2_inode_peek(&trans, &inode_u,
|
||||
dst_start.inode, BTREE_ITER_INTENT);
|
||||
ret2 = PTR_ERR_OR_ZERO(inode_iter);
|
||||
|
||||
if (!ret2 &&
|
||||
inode_u.bi_size < new_i_size)
|
||||
ret2 = bch2_inode_write(&trans, inode_iter, &inode_u) ?:
|
||||
bch2_trans_commit(&trans, NULL, journal_seq,
|
||||
BTREE_INSERT_ATOMIC);
|
||||
} while (ret2 == -EINTR);
|
||||
|
||||
ret = bch2_trans_exit(&trans) ?: ret;
|
||||
|
||||
mutex_lock(&dst_inode->ei_update_lock);
|
||||
if (dst_inode->v.i_size < new_i_size) {
|
||||
i_size_write(&dst_inode->v, new_i_size);
|
||||
ret = bch2_write_inode_size(c, dst_inode, new_i_size,
|
||||
ATTR_MTIME|ATTR_CTIME);
|
||||
}
|
||||
mutex_unlock(&dst_inode->ei_update_lock);
|
||||
|
||||
return dst_done ?: ret;
|
||||
return dst_done ?: ret ?: ret2;
|
||||
}
|
||||
|
||||
#endif /* NO_BCACHEFS_FS */
|
||||
|
|
|
@ -24,9 +24,7 @@ void bch2_reflink_v_to_text(struct printbuf *, struct bch_fs *,
|
|||
.val_to_text = bch2_reflink_v_to_text, \
|
||||
}
|
||||
|
||||
#ifndef NO_BCACHEFS_FS
|
||||
s64 bch2_remap_range(struct bch_fs *, struct bch_inode_info *,
|
||||
struct bpos, struct bpos, u64, u64);
|
||||
#endif /* NO_BCACHEFS_FS */
|
||||
s64 bch2_remap_range(struct bch_fs *, struct bpos, struct bpos,
|
||||
u64, u64 *, u64, s64 *);
|
||||
|
||||
#endif /* _BCACHEFS_REFLINK_H */
|
||||
|
|
Loading…
Reference in a new issue