bcachefs: bcachefs_metadata_version_reflink_p_may_update_opts

Previously, io path option changes on a file would be picked up
automatically and applied to existing data - but not for reflinked data,
as we had no way of doing this safely. A user may have had permission to
copy (and reflink) a given file, but not write to it, and if so they
shouldn't be allowed to change e.g. nr_replicas or other options.

This uses the incompat feature mechanism in the previous patch to add a
new incompatible flag to bch_reflink_p, indicating whether a given
reflink pointer may propagate io path option changes back to the
indirect extent.

In this initial patch we're only setting it for the source extents.

We'd like to set it for the destination in a reflink copy, when the user
has write access to the source, but that requires mnt_idmap which is not
curretly plumbed up to remap_file_range.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2024-11-06 23:16:24 -05:00
parent a06f09e44c
commit 710fb4e0ab
5 changed files with 29 additions and 6 deletions

View File

@ -680,7 +680,8 @@ struct bch_sb_field_ext {
x(rebalance_work_acct_fix, BCH_VERSION(1, 12)) \
x(inode_has_child_snapshots, BCH_VERSION(1, 13)) \
x(backpointer_bucket_gen, BCH_VERSION(1, 14)) \
x(disk_accounting_big_endian, BCH_VERSION(1, 15))
x(disk_accounting_big_endian, BCH_VERSION(1, 15)) \
x(reflink_p_may_update_opts, BCH_VERSION(1, 16))
enum bcachefs_metadata_version {
bcachefs_metadata_version_min = 9,

View File

@ -906,11 +906,18 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src,
bch2_mark_pagecache_unallocated(src, pos_src >> 9,
(pos_src + aligned_len) >> 9);
/*
* XXX: we'd like to be telling bch2_remap_range() if we have
* permission to write to the source file, and thus if io path option
* changes should be propagated through the copy, but we need mnt_idmap
* from the pathwalk, awkward
*/
ret = bch2_remap_range(c,
inode_inum(dst), pos_dst >> 9,
inode_inum(src), pos_src >> 9,
aligned_len >> 9,
pos_dst + len, &i_sectors_delta);
pos_dst + len, &i_sectors_delta,
false);
if (ret < 0)
goto err;

View File

@ -482,7 +482,8 @@ int bch2_trigger_indirect_inline_data(struct btree_trans *trans,
static int bch2_make_extent_indirect(struct btree_trans *trans,
struct btree_iter *extent_iter,
struct bkey_i *orig)
struct bkey_i *orig,
bool reflink_p_may_update_opts_field)
{
struct bch_fs *c = trans->c;
struct btree_iter reflink_iter = { NULL };
@ -548,6 +549,9 @@ static int bch2_make_extent_indirect(struct btree_trans *trans,
SET_REFLINK_P_IDX(&r_p->v, bkey_start_offset(&r_v->k));
if (reflink_p_may_update_opts_field)
SET_REFLINK_P_MAY_UPDATE_OPTIONS(&r_p->v, true);
ret = bch2_trans_update(trans, extent_iter, &r_p->k_i,
BTREE_UPDATE_internal_snapshot_node);
err:
@ -578,7 +582,8 @@ s64 bch2_remap_range(struct bch_fs *c,
subvol_inum dst_inum, u64 dst_offset,
subvol_inum src_inum, u64 src_offset,
u64 remap_sectors,
u64 new_i_size, s64 *i_sectors_delta)
u64 new_i_size, s64 *i_sectors_delta,
bool may_change_src_io_path_opts)
{
struct btree_trans *trans;
struct btree_iter dst_iter, src_iter;
@ -591,6 +596,8 @@ s64 bch2_remap_range(struct bch_fs *c,
struct bpos src_want;
u64 dst_done = 0;
u32 dst_snapshot, src_snapshot;
bool reflink_p_may_update_opts_field =
bch2_request_incompat_feature(c, bcachefs_metadata_version_reflink_p_may_update_opts);
int ret = 0, ret2 = 0;
if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_reflink))
@ -672,7 +679,8 @@ s64 bch2_remap_range(struct bch_fs *c,
src_k = bkey_i_to_s_c(new_src.k);
ret = bch2_make_extent_indirect(trans, &src_iter,
new_src.k);
new_src.k,
reflink_p_may_update_opts_field);
if (ret)
continue;
@ -690,6 +698,10 @@ s64 bch2_remap_range(struct bch_fs *c,
bkey_start_offset(src_k.k));
SET_REFLINK_P_IDX(&dst_p->v, offset);
if (reflink_p_may_update_opts_field &&
may_change_src_io_path_opts)
SET_REFLINK_P_MAY_UPDATE_OPTIONS(&dst_p->v, true);
} else {
BUG();
}

View File

@ -78,7 +78,8 @@ struct bkey_s_c bch2_lookup_indirect_extent(struct btree_trans *, struct btree_i
bool, unsigned);
s64 bch2_remap_range(struct bch_fs *, subvol_inum, u64,
subvol_inum, u64, u64, u64, s64 *);
subvol_inum, u64, u64, u64, s64 *,
bool);
int bch2_gc_reflink_done(struct bch_fs *);
int bch2_gc_reflink_start(struct bch_fs *);

View File

@ -19,6 +19,8 @@ struct bch_reflink_p {
LE64_BITMASK(REFLINK_P_IDX, struct bch_reflink_p, idx_flags, 0, 56);
LE64_BITMASK(REFLINK_P_ERROR, struct bch_reflink_p, idx_flags, 56, 57);
LE64_BITMASK(REFLINK_P_MAY_UPDATE_OPTIONS,
struct bch_reflink_p, idx_flags, 57, 58);
struct bch_reflink_v {
struct bch_val v;