Commit 2e87eae1 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

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: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 2925fc49
......@@ -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, &quota_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, &quota_res, i_sectors_delta);
bkey_err:
bch2_quota_reservation_put(c, inode, &quota_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);
ret = bch2_trans_exit(&trans) ?: ret;
bch2_trans_begin(&trans);
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);
do {
struct bch_inode_unpacked inode_u;
struct btree_iter *inode_iter;
return dst_done ?: ret;
}
inode_iter = bch2_inode_peek(&trans, &inode_u,
dst_start.inode, BTREE_ITER_INTENT);
ret2 = PTR_ERR_OR_ZERO(inode_iter);
#endif /* NO_BCACHEFS_FS */
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;
return dst_done ?: ret ?: ret2;
}
......@@ -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 */
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