diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/bcachefs_ioctl.h | 12 | ||||
-rw-r--r-- | fs/bcachefs/chardev.c | 16 | ||||
-rw-r--r-- | fs/bcachefs/chardev.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/extents.c | 51 | ||||
-rw-r--r-- | fs/bcachefs/fs-ioctl.c | 91 | ||||
-rw-r--r-- | fs/bcachefs/opts.c | 53 | ||||
-rw-r--r-- | fs/bcachefs/opts.h | 5 | ||||
-rw-r--r-- | fs/bcachefs/rebalance.c | 151 | ||||
-rw-r--r-- | fs/bcachefs/rebalance.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/sb-errors_format.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/sysfs.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/xattr.c | 10 |
12 files changed, 269 insertions, 133 deletions
diff --git a/fs/bcachefs/bcachefs_ioctl.h b/fs/bcachefs/bcachefs_ioctl.h index 5dc562f2a881..6043a8d93b1e 100644 --- a/fs/bcachefs/bcachefs_ioctl.h +++ b/fs/bcachefs/bcachefs_ioctl.h @@ -87,7 +87,9 @@ struct bch_ioctl_incremental { #define BCH_IOCTL_DISK_RESIZE_JOURNAL_v2 _IOW(0xbc, 28, struct bch_ioctl_disk_resize_journal_v2) #define BCH_IOCTL_SUBVOLUME_CREATE _IOW(0xbc, 16, struct bch_ioctl_subvolume) +#define BCH_IOCTL_SUBVOLUME_CREATE_v2 _IOW(0xbc, 29, struct bch_ioctl_subvolume_v2) #define BCH_IOCTL_SUBVOLUME_DESTROY _IOW(0xbc, 17, struct bch_ioctl_subvolume) +#define BCH_IOCTL_SUBVOLUME_DESTROY_v2 _IOW(0xbc, 30, struct bch_ioctl_subvolume_v2) #define BCH_IOCTL_DEV_USAGE_V2 _IOWR(0xbc, 18, struct bch_ioctl_dev_usage_v2) @@ -451,6 +453,16 @@ struct bch_ioctl_subvolume { __u64 src_ptr; }; +struct bch_ioctl_subvolume_v2 { + __u32 flags; + __u32 dirfd; + __u16 mode; + __u16 pad[3]; + __u64 dst_ptr; + __u64 src_ptr; + struct bch_ioctl_err_msg err; +}; + #define BCH_SUBVOL_SNAPSHOT_CREATE (1U << 0) #define BCH_SUBVOL_SNAPSHOT_RO (1U << 1) diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c index f6f90d421f27..108c362a0ff4 100644 --- a/fs/bcachefs/chardev.c +++ b/fs/bcachefs/chardev.c @@ -187,7 +187,7 @@ static long bch2_ioctl_stop(struct bch_fs *c) } #endif -static int copy_ioctl_err_msg(struct bch_ioctl_err_msg *dst, struct printbuf *src, int ret) +int bch2_copy_ioctl_err_msg(struct bch_ioctl_err_msg *dst, struct printbuf *src, int ret) { if (ret) { prt_printf(src, "error=%s", bch2_err_str(ret)); @@ -243,7 +243,7 @@ static long bch2_ioctl_disk_add_v2(struct bch_fs *c, struct bch_ioctl_disk_v2 ar CLASS(printbuf, err)(); ret = bch2_dev_add(c, path, &err); kfree(path); - return copy_ioctl_err_msg(&arg.err, &err, ret); + return bch2_copy_ioctl_err_msg(&arg.err, &err, ret); } static long bch2_ioctl_disk_remove(struct bch_fs *c, struct bch_ioctl_disk arg) @@ -287,7 +287,7 @@ static long bch2_ioctl_disk_remove_v2(struct bch_fs *c, struct bch_ioctl_disk_v2 CLASS(printbuf, err)(); int ret = bch2_dev_remove(c, ca, arg.flags, &err); - return copy_ioctl_err_msg(&arg.err, &err, ret); + return bch2_copy_ioctl_err_msg(&arg.err, &err, ret); } static long bch2_ioctl_disk_online(struct bch_fs *c, struct bch_ioctl_disk arg) @@ -333,7 +333,7 @@ static long bch2_ioctl_disk_online_v2(struct bch_fs *c, struct bch_ioctl_disk_v2 CLASS(printbuf, err)(); ret = bch2_dev_online(c, path, &err); kfree(path); - return copy_ioctl_err_msg(&arg.err, &err, ret); + return bch2_copy_ioctl_err_msg(&arg.err, &err, ret); } static long bch2_ioctl_disk_offline(struct bch_fs *c, struct bch_ioctl_disk arg) @@ -377,7 +377,7 @@ static long bch2_ioctl_disk_offline_v2(struct bch_fs *c, struct bch_ioctl_disk_v CLASS(printbuf, err)(); int ret = bch2_dev_offline(c, ca, arg.flags, &err); - return copy_ioctl_err_msg(&arg.err, &err, ret); + return bch2_copy_ioctl_err_msg(&arg.err, &err, ret); } static long bch2_ioctl_disk_set_state(struct bch_fs *c, @@ -429,7 +429,7 @@ static long bch2_ioctl_disk_set_state_v2(struct bch_fs *c, ret = bch2_dev_set_state(c, ca, arg.new_state, arg.flags, &err); err: - return copy_ioctl_err_msg(&arg.err, &err, ret); + return bch2_copy_ioctl_err_msg(&arg.err, &err, ret); } struct bch_data_ctx { @@ -783,7 +783,7 @@ static long bch2_ioctl_disk_resize_v2(struct bch_fs *c, CLASS(printbuf, err)(); int ret = bch2_dev_resize(c, ca, arg.nbuckets, &err); - return copy_ioctl_err_msg(&arg.err, &err, ret); + return bch2_copy_ioctl_err_msg(&arg.err, &err, ret); } static long bch2_ioctl_disk_resize_journal(struct bch_fs *c, @@ -825,7 +825,7 @@ static long bch2_ioctl_disk_resize_journal_v2(struct bch_fs *c, CLASS(printbuf, err)(); int ret = bch2_set_nr_journal_buckets(c, ca, arg.nbuckets); - return copy_ioctl_err_msg(&arg.err, &err, ret); + return bch2_copy_ioctl_err_msg(&arg.err, &err, ret); } #define BCH_IOCTL(_name, _argtype) \ diff --git a/fs/bcachefs/chardev.h b/fs/bcachefs/chardev.h index 0f563ca53c36..cdd63e7618e9 100644 --- a/fs/bcachefs/chardev.h +++ b/fs/bcachefs/chardev.h @@ -4,6 +4,9 @@ #ifndef NO_BCACHEFS_FS +struct printbuf; +int bch2_copy_ioctl_err_msg(struct bch_ioctl_err_msg *, struct printbuf *, int); + long bch2_fs_ioctl(struct bch_fs *, unsigned, void __user *); void bch2_fs_chardev_exit(struct bch_fs *); diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c index 016242ffc98d..2fac21812e19 100644 --- a/fs/bcachefs/extents.c +++ b/fs/bcachefs/extents.c @@ -1305,57 +1305,6 @@ void bch2_extent_crc_unpacked_to_text(struct printbuf *out, struct bch_extent_cr bch2_prt_compression_type(out, crc->compression_type); } -static void bch2_extent_rebalance_to_text(struct printbuf *out, struct bch_fs *c, - const struct bch_extent_rebalance *r) -{ - prt_str(out, "rebalance:"); - - prt_printf(out, " replicas=%u", r->data_replicas); - if (r->data_replicas_from_inode) - prt_str(out, " (inode)"); - - prt_str(out, " checksum="); - bch2_prt_csum_opt(out, r->data_checksum); - if (r->data_checksum_from_inode) - prt_str(out, " (inode)"); - - if (r->background_compression || r->background_compression_from_inode) { - prt_str(out, " background_compression="); - bch2_compression_opt_to_text(out, r->background_compression); - - if (r->background_compression_from_inode) - prt_str(out, " (inode)"); - } - - if (r->background_target || r->background_target_from_inode) { - prt_str(out, " background_target="); - if (c) - bch2_target_to_text(out, c, r->background_target); - else - prt_printf(out, "%u", r->background_target); - - if (r->background_target_from_inode) - prt_str(out, " (inode)"); - } - - if (r->promote_target || r->promote_target_from_inode) { - prt_str(out, " promote_target="); - if (c) - bch2_target_to_text(out, c, r->promote_target); - else - prt_printf(out, "%u", r->promote_target); - - if (r->promote_target_from_inode) - prt_str(out, " (inode)"); - } - - if (r->erasure_code || r->erasure_code_from_inode) { - prt_printf(out, " ec=%u", r->erasure_code); - if (r->erasure_code_from_inode) - prt_str(out, " (inode)"); - } -} - void bch2_bkey_ptrs_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k) { diff --git a/fs/bcachefs/fs-ioctl.c b/fs/bcachefs/fs-ioctl.c index 8b9d3c7d1f57..20b46126c066 100644 --- a/fs/bcachefs/fs-ioctl.c +++ b/fs/bcachefs/fs-ioctl.c @@ -199,8 +199,9 @@ static int bch2_ioc_goingdown(struct bch_fs *c, u32 __user *arg) return ret; } -static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, - struct bch_ioctl_subvolume arg) +static long __bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume_v2 arg, + struct printbuf *err) { struct inode *dir; struct bch_inode_info *inode; @@ -214,13 +215,17 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, unsigned create_flags = BCH_CREATE_SUBVOL; if (arg.flags & ~(BCH_SUBVOL_SNAPSHOT_CREATE| - BCH_SUBVOL_SNAPSHOT_RO)) + BCH_SUBVOL_SNAPSHOT_RO)) { + prt_str(err, "invalid flasg"); return -EINVAL; + } if (!(arg.flags & BCH_SUBVOL_SNAPSHOT_CREATE) && (arg.src_ptr || - (arg.flags & BCH_SUBVOL_SNAPSHOT_RO))) + (arg.flags & BCH_SUBVOL_SNAPSHOT_RO))) { + prt_str(err, "invalid flasg"); return -EINVAL; + } if (arg.flags & BCH_SUBVOL_SNAPSHOT_CREATE) create_flags |= BCH_CREATE_SNAPSHOT; @@ -243,6 +248,7 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, if (src_path.dentry->d_sb->s_fs_info != c) { path_put(&src_path); + prt_str(err, "src_path not on dst filesystem"); error = -EXDEV; goto err1; } @@ -258,6 +264,7 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, goto err2; if (dst_dentry->d_sb->s_fs_info != c) { + prt_str(err, "dst_path not on dst filesystem"); error = -EXDEV; goto err3; } @@ -276,6 +283,7 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, s_user_ns = dir->i_sb->s_user_ns; if (!kuid_has_mapping(s_user_ns, current_fsuid()) || !kgid_has_mapping(s_user_ns, current_fsgid())) { + prt_str(err, "current uid/gid not mapped into fs namespace"); error = -EOVERFLOW; goto err3; } @@ -315,8 +323,35 @@ err1: return error; } -static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp, - struct bch_ioctl_subvolume arg) +static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume arg) +{ + struct bch_ioctl_subvolume_v2 arg_v2 = { + .flags = arg.flags, + .dirfd = arg.dirfd, + .mode = arg.mode, + .dst_ptr = arg.dst_ptr, + .src_ptr = arg.src_ptr, + }; + + CLASS(printbuf, err)(); + long ret = __bch2_ioctl_subvolume_create(c, filp, arg_v2, &err); + if (ret) + bch_err_msg(c, ret, "%s", err.buf); + return ret; +} + +static long bch2_ioctl_subvolume_create_v2(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume_v2 arg) +{ + CLASS(printbuf, err)(); + long ret = __bch2_ioctl_subvolume_create(c, filp, arg, &err); + return bch2_copy_ioctl_err_msg(&arg.err, &err, ret); +} + +static long __bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume_v2 arg, + struct printbuf *err) { const char __user *name = (void __user *)(unsigned long)arg.dst_ptr; struct path path; @@ -350,6 +385,32 @@ err: return ret; } +static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume arg) +{ + struct bch_ioctl_subvolume_v2 arg_v2 = { + .flags = arg.flags, + .dirfd = arg.dirfd, + .mode = arg.mode, + .dst_ptr = arg.dst_ptr, + .src_ptr = arg.src_ptr, + }; + + CLASS(printbuf, err)(); + long ret = __bch2_ioctl_subvolume_destroy(c, filp, arg_v2, &err); + if (ret) + bch_err_msg(c, ret, "%s", err.buf); + return ret; +} + +static long bch2_ioctl_subvolume_destroy_v2(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume_v2 arg) +{ + CLASS(printbuf, err)(); + long ret = __bch2_ioctl_subvolume_destroy(c, filp, arg, &err); + return bch2_copy_ioctl_err_msg(&arg.err, &err, ret); +} + long bch2_fs_file_ioctl(struct file *file, unsigned cmd, unsigned long arg) { struct bch_inode_info *inode = file_bch_inode(file); @@ -391,6 +452,15 @@ long bch2_fs_file_ioctl(struct file *file, unsigned cmd, unsigned long arg) break; } + case BCH_IOCTL_SUBVOLUME_CREATE_v2: { + struct bch_ioctl_subvolume_v2 i; + + ret = copy_from_user(&i, (void __user *) arg, sizeof(i)) + ? -EFAULT + : bch2_ioctl_subvolume_create_v2(c, file, i); + break; + } + case BCH_IOCTL_SUBVOLUME_DESTROY: { struct bch_ioctl_subvolume i; @@ -400,6 +470,15 @@ long bch2_fs_file_ioctl(struct file *file, unsigned cmd, unsigned long arg) break; } + case BCH_IOCTL_SUBVOLUME_DESTROY_v2: { + struct bch_ioctl_subvolume_v2 i; + + ret = copy_from_user(&i, (void __user *) arg, sizeof(i)) + ? -EFAULT + : bch2_ioctl_subvolume_destroy_v2(c, file, i); + break; + } + default: ret = bch2_fs_ioctl(c, cmd, (void __user *) arg); break; diff --git a/fs/bcachefs/opts.c b/fs/bcachefs/opts.c index 9f5684ec056a..bd5faafc9aa7 100644 --- a/fs/bcachefs/opts.c +++ b/fs/bcachefs/opts.c @@ -518,7 +518,8 @@ void bch2_opts_to_text(struct printbuf *out, } } -int bch2_opt_hook_pre_set(struct bch_fs *c, struct bch_dev *ca, enum bch_opt_id id, u64 v) +int bch2_opt_hook_pre_set(struct bch_fs *c, struct bch_dev *ca, u64 inum, enum bch_opt_id id, u64 v, + bool change) { int ret = 0; @@ -531,6 +532,8 @@ int bch2_opt_hook_pre_set(struct bch_fs *c, struct bch_dev *ca, enum bch_opt_id case Opt_compression: case Opt_background_compression: ret = bch2_check_set_has_compressed_data(c, v); + if (ret) + return ret; break; case Opt_erasure_code: if (v) @@ -540,13 +543,26 @@ int bch2_opt_hook_pre_set(struct bch_fs *c, struct bch_dev *ca, enum bch_opt_id break; } + if (change && + (id == Opt_foreground_target || + id == Opt_background_target || + id == Opt_promote_target || + id == Opt_compression || + id == Opt_background_compression || + id == Opt_data_checksum || + id == Opt_data_replicas)) { + ret = bch2_set_rebalance_needs_scan(c, inum); + if (ret) + return ret; + } + return ret; } int bch2_opts_hooks_pre_set(struct bch_fs *c) { for (unsigned i = 0; i < bch2_opts_nr; i++) { - int ret = bch2_opt_hook_pre_set(c, NULL, i, bch2_opt_get_by_id(&c->opts, i)); + int ret = bch2_opt_hook_pre_set(c, NULL, 0, i, bch2_opt_get_by_id(&c->opts, i), false); if (ret) return ret; } @@ -555,27 +571,20 @@ int bch2_opts_hooks_pre_set(struct bch_fs *c) } void bch2_opt_hook_post_set(struct bch_fs *c, struct bch_dev *ca, u64 inum, - struct bch_opts *new_opts, enum bch_opt_id id) + enum bch_opt_id id, u64 v) { + if (id == Opt_foreground_target || + id == Opt_background_target || + id == Opt_promote_target || + id == Opt_compression || + id == Opt_background_compression || + id == Opt_data_checksum || + id == Opt_data_replicas) { + bch2_set_rebalance_needs_scan(c, inum); + bch2_rebalance_wakeup(c); + } + switch (id) { - case Opt_foreground_target: - if (new_opts->foreground_target && - !new_opts->background_target) - bch2_set_rebalance_needs_scan(c, inum); - break; - case Opt_compression: - if (new_opts->compression && - !new_opts->background_compression) - bch2_set_rebalance_needs_scan(c, inum); - break; - case Opt_background_target: - if (new_opts->background_target) - bch2_set_rebalance_needs_scan(c, inum); - break; - case Opt_background_compression: - if (new_opts->background_compression) - bch2_set_rebalance_needs_scan(c, inum); - break; case Opt_rebalance_enabled: bch2_rebalance_wakeup(c); break; @@ -600,7 +609,7 @@ void bch2_opt_hook_post_set(struct bch_fs *c, struct bch_dev *ca, u64 inum, * upgrades at runtime as well, but right now there's nothing * that does that: */ - if (new_opts->version_upgrade == BCH_VERSION_UPGRADE_incompatible) + if (v == BCH_VERSION_UPGRADE_incompatible) bch2_sb_upgrade_incompat(c); break; default: diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h index 263aeb55eef9..8b38f27afea4 100644 --- a/fs/bcachefs/opts.h +++ b/fs/bcachefs/opts.h @@ -658,10 +658,9 @@ void bch2_opts_to_text(struct printbuf *, struct bch_fs *, struct bch_sb *, unsigned, unsigned, unsigned); -int bch2_opt_hook_pre_set(struct bch_fs *, struct bch_dev *, enum bch_opt_id, u64); +int bch2_opt_hook_pre_set(struct bch_fs *, struct bch_dev *, u64, enum bch_opt_id, u64, bool); int bch2_opts_hooks_pre_set(struct bch_fs *); -void bch2_opt_hook_post_set(struct bch_fs *, struct bch_dev *, u64, - struct bch_opts *, enum bch_opt_id); +void bch2_opt_hook_post_set(struct bch_fs *, struct bch_dev *, u64, enum bch_opt_id, u64); int bch2_parse_one_mount_opt(struct bch_fs *, struct bch_opts *, struct printbuf *, const char *, const char *); diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c index f82aaf5faac0..f1497302332f 100644 --- a/fs/bcachefs/rebalance.c +++ b/fs/bcachefs/rebalance.c @@ -45,6 +45,57 @@ static const struct bch_extent_rebalance *bch2_bkey_rebalance_opts(struct bkey_s return bch2_bkey_ptrs_rebalance_opts(bch2_bkey_ptrs_c(k)); } +void bch2_extent_rebalance_to_text(struct printbuf *out, struct bch_fs *c, + const struct bch_extent_rebalance *r) +{ + prt_str(out, "rebalance:"); + + prt_printf(out, " replicas=%u", r->data_replicas); + if (r->data_replicas_from_inode) + prt_str(out, " (inode)"); + + prt_str(out, " checksum="); + bch2_prt_csum_opt(out, r->data_checksum); + if (r->data_checksum_from_inode) + prt_str(out, " (inode)"); + + if (r->background_compression || r->background_compression_from_inode) { + prt_str(out, " background_compression="); + bch2_compression_opt_to_text(out, r->background_compression); + + if (r->background_compression_from_inode) + prt_str(out, " (inode)"); + } + + if (r->background_target || r->background_target_from_inode) { + prt_str(out, " background_target="); + if (c) + bch2_target_to_text(out, c, r->background_target); + else + prt_printf(out, "%u", r->background_target); + + if (r->background_target_from_inode) + prt_str(out, " (inode)"); + } + + if (r->promote_target || r->promote_target_from_inode) { + prt_str(out, " promote_target="); + if (c) + bch2_target_to_text(out, c, r->promote_target); + else + prt_printf(out, "%u", r->promote_target); + + if (r->promote_target_from_inode) + prt_str(out, " (inode)"); + } + + if (r->erasure_code || r->erasure_code_from_inode) { + prt_printf(out, " ec=%u", r->erasure_code); + if (r->erasure_code_from_inode) + prt_str(out, " (inode)"); + } +} + static void bch2_bkey_needs_rebalance(struct bch_fs *c, struct bkey_s_c k, struct bch_inode_opts *io_opts, unsigned *move_ptrs, @@ -237,33 +288,56 @@ static int bch2_get_update_rebalance_opts(struct btree_trans *trans, struct bch_extent_rebalance new = io_opts_to_rebalance_opts(c, io_opts); - if (bkey_should_have_rb_opts(c, io_opts, k) + bool should_have_rb_opts = bkey_should_have_rb_opts(c, io_opts, k); + + if (should_have_rb_opts ? old && !memcmp(old, &new, sizeof(new)) : !old) return 0; if (k.k->type != KEY_TYPE_reflink_v) { - ret = have_rebalance_scan_cookie(trans, k.k->p.inode); - if (ret < 0) - return ret; - - if (!ret) { + if (old && !should_have_rb_opts) { CLASS(printbuf, buf)(); - prt_printf(&buf, "extent with incorrect/missing rebalance opts:\n"); + prt_printf(&buf, "extent with unneeded rebalance opts:\n"); bch2_bkey_val_to_text(&buf, c, k); - const struct bch_extent_rebalance _old = {}; - if (!old) - old = &_old; -#define x(_name) \ - if (old->_name != new._name) \ - prt_printf(&buf, "\n" #_name " %u != %u", \ - old->_name, new._name); \ - BCH_REBALANCE_OPTS() + fsck_err(trans, extent_io_opts_not_set, "%s", buf.buf); + } else { + ret = have_rebalance_scan_cookie(trans, k.k->p.inode); + if (ret < 0) + return ret; + + if (!ret) { + CLASS(printbuf, buf)(); + + prt_printf(&buf, "extent with incorrect/missing rebalance opts:\n"); + bch2_bkey_val_to_text(&buf, c, k); + const struct bch_extent_rebalance _old = {}; + if (!old) + old = &_old; + +#define x(_name) \ + if (old->_name != new._name) \ + prt_printf(&buf, "\n" #_name " %u != %u", \ + old->_name, new._name); \ + if (old->_name##_from_inode != new._name##_from_inode) \ + prt_printf(&buf, "\n" #_name "_from_inode %u != %u", \ + old->_name##_from_inode, new._name##_from_inode); + BCH_REBALANCE_OPTS() #undef x - fsck_err(trans, extent_io_opts_not_set, "%s", buf.buf); + if (old->unused != new.unused) + prt_printf(&buf, "\nunused %u != %u", old->unused, new.unused); + + if (old->type != new.type) + prt_printf(&buf, "\ntype %u != %u", old->type, new.type); + + prt_newline(&buf); + bch2_extent_rebalance_to_text(&buf, c, &new); + + fsck_err(trans, extent_io_opts_not_set, "%s", buf.buf); + } } } @@ -697,6 +771,8 @@ static int do_rebalance_scan(struct moving_context *ctxt, BTREE_ITER_prefetch, k, ({ ctxt->stats->pos = BBPOS(iter.btree_id, iter.pos); + atomic64_add(k.k->size, &r->scan_stats.sectors_seen); + struct bch_inode_opts *opts = bch2_extent_get_apply_io_opts(trans, snapshot_io_opts, iter.pos, &iter, k, SET_NEEDS_REBALANCE_opt_change); @@ -706,10 +782,31 @@ static int do_rebalance_scan(struct moving_context *ctxt, REFLINK_P_MAY_UPDATE_OPTIONS(bkey_s_c_to_reflink_p(k).v) ? do_rebalance_scan_indirect(trans, bkey_s_c_to_reflink_p(k), opts) : 0); - })) ?: - commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc, - bch2_clear_rebalance_needs_scan(trans, inum, cookie)); + })); + if (ret) + goto out; + if (!inum) { + ret = for_each_btree_key_max(trans, iter, BTREE_ID_reflink, + POS_MIN, POS_MAX, + BTREE_ITER_all_snapshots| + BTREE_ITER_prefetch, k, ({ + ctxt->stats->pos = BBPOS(iter.btree_id, iter.pos); + + atomic64_add(k.k->size, &r->scan_stats.sectors_seen); + + struct bch_inode_opts *opts = bch2_extent_get_apply_io_opts(trans, + snapshot_io_opts, iter.pos, &iter, k, + SET_NEEDS_REBALANCE_opt_change); + PTR_ERR_OR_ZERO(opts); + })); + if (ret) + goto out; + } + + ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc, + bch2_clear_rebalance_needs_scan(trans, inum, cookie)); +out: *sectors_scanned += atomic64_read(&r->scan_stats.sectors_seen); /* * Ensure that the rebalance_work entries we created are seen by the @@ -984,7 +1081,6 @@ int bch2_fs_rebalance_init(struct bch_fs *c) static int check_rebalance_work_one(struct btree_trans *trans, struct btree_iter *extent_iter, struct btree_iter *rebalance_iter, - struct per_snapshot_io_opts *snapshot_io_opts, struct bkey_buf *last_flushed) { struct bch_fs *c = trans->c; @@ -1055,13 +1151,6 @@ static int check_rebalance_work_one(struct btree_trans *trans, return ret; } - struct bch_inode_opts *opts = bch2_extent_get_apply_io_opts(trans, - snapshot_io_opts, extent_iter->pos, extent_iter, extent_k, - SET_NEEDS_REBALANCE_other); - ret = PTR_ERR_OR_ZERO(opts); - if (ret) - return ret; - if (cmp <= 0) bch2_btree_iter_advance(extent_iter); if (cmp >= 0) @@ -1074,14 +1163,10 @@ int bch2_check_rebalance_work(struct bch_fs *c) { CLASS(btree_trans, trans)(c); CLASS(btree_iter, extent_iter)(trans, BTREE_ID_reflink, POS_MIN, - BTREE_ITER_not_extents| BTREE_ITER_prefetch); CLASS(btree_iter, rebalance_iter)(trans, BTREE_ID_rebalance_work, POS_MIN, BTREE_ITER_prefetch); - struct per_snapshot_io_opts snapshot_io_opts; - per_snapshot_io_opts_init(&snapshot_io_opts, c); - struct bkey_buf last_flushed; bch2_bkey_buf_init(&last_flushed); bkey_init(&last_flushed.k->k); @@ -1095,14 +1180,12 @@ int bch2_check_rebalance_work(struct bch_fs *c) bch2_trans_begin(trans); - ret = check_rebalance_work_one(trans, &extent_iter, &rebalance_iter, - &snapshot_io_opts, &last_flushed); + ret = check_rebalance_work_one(trans, &extent_iter, &rebalance_iter, &last_flushed); if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) ret = 0; } - per_snapshot_io_opts_exit(&snapshot_io_opts); bch2_bkey_buf_exit(&last_flushed, c); return ret < 0 ? ret : 0; } diff --git a/fs/bcachefs/rebalance.h b/fs/bcachefs/rebalance.h index fd33e7aa2ecb..7a4e3a56d5a2 100644 --- a/fs/bcachefs/rebalance.h +++ b/fs/bcachefs/rebalance.h @@ -26,6 +26,9 @@ static inline struct bch_extent_rebalance io_opts_to_rebalance_opts(struct bch_f return r; }; +void bch2_extent_rebalance_to_text(struct printbuf *, struct bch_fs *, + const struct bch_extent_rebalance *); + u64 bch2_bkey_sectors_need_rebalance(struct bch_fs *, struct bkey_s_c); enum set_needs_rebalance_ctx { diff --git a/fs/bcachefs/sb-errors_format.h b/fs/bcachefs/sb-errors_format.h index 4816c4150261..cac8236317b2 100644 --- a/fs/bcachefs/sb-errors_format.h +++ b/fs/bcachefs/sb-errors_format.h @@ -338,7 +338,8 @@ enum bch_fsck_flags { x(rebalance_work_incorrectly_set, 309, FSCK_AUTOFIX) \ x(rebalance_work_incorrectly_unset, 310, FSCK_AUTOFIX) \ x(extent_io_opts_not_set, 326, FSCK_AUTOFIX) \ - x(MAX, 327, 0) + x(extent_io_opts_unneeded, 327, FSCK_AUTOFIX) \ + x(MAX, 328, 0) enum bch_sb_error_id { #define x(t, n, ...) BCH_FSCK_ERR_##t = n, diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c index 6b071dcc062b..ef6312c50f88 100644 --- a/fs/bcachefs/sysfs.c +++ b/fs/bcachefs/sysfs.c @@ -784,7 +784,7 @@ static ssize_t sysfs_opt_store(struct bch_fs *c, u64 v; ret = bch2_opt_parse(c, opt, strim(tmp), &v, NULL) ?: - bch2_opt_hook_pre_set(c, ca, id, v); + bch2_opt_hook_pre_set(c, ca, 0, id, v, true); kfree(tmp); if (ret < 0) @@ -807,7 +807,7 @@ static ssize_t sysfs_opt_store(struct bch_fs *c, bch2_opt_set_by_id(&c->opts, id, v); if (changed) - bch2_opt_hook_post_set(c, ca, 0, &c->opts, id); + bch2_opt_hook_post_set(c, ca, 0, id, v); ret = size; err: diff --git a/fs/bcachefs/xattr.c b/fs/bcachefs/xattr.c index de72a735a49d..2b8d0502db1e 100644 --- a/fs/bcachefs/xattr.c +++ b/fs/bcachefs/xattr.c @@ -535,10 +535,9 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler, return -EINVAL; s.id = inode_opt_id; + u64 v = 0; if (value) { - u64 v = 0; - buf = kmalloc(size + 1, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -551,7 +550,7 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler, if (ret < 0) goto err; - ret = bch2_opt_hook_pre_set(c, NULL, opt_id, v); + ret = bch2_opt_hook_pre_set(c, NULL, inode->ei_inode.bi_inum, opt_id, v, true); if (ret < 0) goto err; @@ -590,10 +589,9 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler, } ret = bch2_write_inode(c, inode, inode_opt_set_fn, &s, 0); - - if (!ret) - atomic_inc(&c->opt_change_cookie); } + + bch2_opt_hook_post_set(c, NULL, inode->ei_inode.bi_inum, opt_id, v); err: return bch2_err_class(ret); } |