* [PATCH 0/3] better error messages for ioctls
@ 2025-08-29 6:54 Kent Overstreet
2025-08-29 6:54 ` [PATCH 1/3] bcachefs: Add v2 ioctls that return error strings Kent Overstreet
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Kent Overstreet @ 2025-08-29 6:54 UTC (permalink / raw)
To: linux-bcachefs; +Cc: Kent Overstreet
This fixes a common user complaint - uninformative error messages from
various bcachefs-tools commands.
Add v2 versions of various ioctls that include a 'struct
bch_ioctl_err_mesg', a pointer to a userspace buffer for an error
message - and plumb a printbuf through various code for returning
errors.
Kent Overstreet (3):
bcachefs: Add v2 ioctls that return error strings
bcachefs: v2 versions of subvolume ioctls
bcachefs: Plumb error messages through data drop paths
fs/bcachefs/bcachefs_ioctl.h | 87 ++++++++++++++-----
fs/bcachefs/chardev.c | 159 +++++++++++++++++++++++++++++++++--
fs/bcachefs/chardev.h | 3 +
fs/bcachefs/ec.c | 23 +++--
fs/bcachefs/ec.h | 5 +-
fs/bcachefs/fs-ioctl.c | 91 ++++++++++++++++++--
fs/bcachefs/migrate.c | 55 ++++++------
fs/bcachefs/migrate.h | 4 +-
fs/bcachefs/super.c | 6 +-
9 files changed, 359 insertions(+), 74 deletions(-)
--
2.50.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/3] bcachefs: Add v2 ioctls that return error strings
2025-08-29 6:54 [PATCH 0/3] better error messages for ioctls Kent Overstreet
@ 2025-08-29 6:54 ` Kent Overstreet
2025-08-29 6:54 ` [PATCH 2/3] bcachefs: v2 versions of subvolume ioctls Kent Overstreet
2025-08-29 6:54 ` [PATCH 3/3] bcachefs: Plumb error messages through data drop paths Kent Overstreet
2 siblings, 0 replies; 4+ messages in thread
From: Kent Overstreet @ 2025-08-29 6:54 UTC (permalink / raw)
To: linux-bcachefs; +Cc: Kent Overstreet
Like BCH_IOCTL_DISK_SET_STATE_v2, implement v2 of other device ioctls
that return error messages via 'struct bch_ioctl_err_msg'.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
---
fs/bcachefs/bcachefs_ioctl.h | 75 ++++++++++++-----
fs/bcachefs/chardev.c | 159 +++++++++++++++++++++++++++++++++--
2 files changed, 204 insertions(+), 30 deletions(-)
diff --git a/fs/bcachefs/bcachefs_ioctl.h b/fs/bcachefs/bcachefs_ioctl.h
index 08fa1636dde2..5dc562f2a881 100644
--- a/fs/bcachefs/bcachefs_ioctl.h
+++ b/fs/bcachefs/bcachefs_ioctl.h
@@ -66,29 +66,35 @@ struct bch_ioctl_incremental {
#define BCH_IOCTL_STOP _IO(0xbc, 3)
#endif
-#define BCH_IOCTL_DISK_ADD _IOW(0xbc, 4, struct bch_ioctl_disk)
-#define BCH_IOCTL_DISK_REMOVE _IOW(0xbc, 5, struct bch_ioctl_disk)
-#define BCH_IOCTL_DISK_ONLINE _IOW(0xbc, 6, struct bch_ioctl_disk)
-#define BCH_IOCTL_DISK_OFFLINE _IOW(0xbc, 7, struct bch_ioctl_disk)
-#define BCH_IOCTL_DISK_SET_STATE _IOW(0xbc, 8, struct bch_ioctl_disk_set_state)
-#define BCH_IOCTL_DISK_SET_STATE_v2 _IOW(0xbc, 22, struct bch_ioctl_disk_set_state_v2)
-#define BCH_IOCTL_DATA _IOW(0xbc, 10, struct bch_ioctl_data)
-#define BCH_IOCTL_FS_USAGE _IOWR(0xbc, 11, struct bch_ioctl_fs_usage)
-#define BCH_IOCTL_DEV_USAGE _IOWR(0xbc, 11, struct bch_ioctl_dev_usage)
-#define BCH_IOCTL_READ_SUPER _IOW(0xbc, 12, struct bch_ioctl_read_super)
-#define BCH_IOCTL_DISK_GET_IDX _IOW(0xbc, 13, struct bch_ioctl_disk_get_idx)
-#define BCH_IOCTL_DISK_RESIZE _IOW(0xbc, 14, struct bch_ioctl_disk_resize)
-#define BCH_IOCTL_DISK_RESIZE_JOURNAL _IOW(0xbc,15, struct bch_ioctl_disk_resize_journal)
-
-#define BCH_IOCTL_SUBVOLUME_CREATE _IOW(0xbc, 16, struct bch_ioctl_subvolume)
-#define BCH_IOCTL_SUBVOLUME_DESTROY _IOW(0xbc, 17, struct bch_ioctl_subvolume)
-
-#define BCH_IOCTL_DEV_USAGE_V2 _IOWR(0xbc, 18, struct bch_ioctl_dev_usage_v2)
-
-#define BCH_IOCTL_FSCK_OFFLINE _IOW(0xbc, 19, struct bch_ioctl_fsck_offline)
-#define BCH_IOCTL_FSCK_ONLINE _IOW(0xbc, 20, struct bch_ioctl_fsck_online)
-#define BCH_IOCTL_QUERY_ACCOUNTING _IOW(0xbc, 21, struct bch_ioctl_query_accounting)
-#define BCH_IOCTL_QUERY_COUNTERS _IOW(0xbc, 21, struct bch_ioctl_query_counters)
+#define BCH_IOCTL_DISK_ADD _IOW(0xbc, 4, struct bch_ioctl_disk)
+#define BCH_IOCTL_DISK_ADD_v2 _IOW(0xbc, 23, struct bch_ioctl_disk_v2)
+#define BCH_IOCTL_DISK_REMOVE _IOW(0xbc, 5, struct bch_ioctl_disk)
+#define BCH_IOCTL_DISK_REMOVE_v2 _IOW(0xbc, 24, struct bch_ioctl_disk_v2)
+#define BCH_IOCTL_DISK_ONLINE _IOW(0xbc, 6, struct bch_ioctl_disk)
+#define BCH_IOCTL_DISK_ONLINE_v2 _IOW(0xbc, 25, struct bch_ioctl_disk_v2)
+#define BCH_IOCTL_DISK_OFFLINE _IOW(0xbc, 7, struct bch_ioctl_disk)
+#define BCH_IOCTL_DISK_OFFLINE_v2 _IOW(0xbc, 26, struct bch_ioctl_disk_v2)
+#define BCH_IOCTL_DISK_SET_STATE _IOW(0xbc, 8, struct bch_ioctl_disk_set_state)
+#define BCH_IOCTL_DISK_SET_STATE_v2 _IOW(0xbc, 22, struct bch_ioctl_disk_set_state_v2)
+#define BCH_IOCTL_DATA _IOW(0xbc, 10, struct bch_ioctl_data)
+#define BCH_IOCTL_FS_USAGE _IOWR(0xbc, 11, struct bch_ioctl_fs_usage)
+#define BCH_IOCTL_DEV_USAGE _IOWR(0xbc, 11, struct bch_ioctl_dev_usage)
+#define BCH_IOCTL_READ_SUPER _IOW(0xbc, 12, struct bch_ioctl_read_super)
+#define BCH_IOCTL_DISK_GET_IDX _IOW(0xbc, 13, struct bch_ioctl_disk_get_idx)
+#define BCH_IOCTL_DISK_RESIZE _IOW(0xbc, 14, struct bch_ioctl_disk_resize)
+#define BCH_IOCTL_DISK_RESIZE_v2 _IOW(0xbc, 27, struct bch_ioctl_disk_resize_v2)
+#define BCH_IOCTL_DISK_RESIZE_JOURNAL _IOW(0xbc, 15, struct bch_ioctl_disk_resize_journal)
+#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_DESTROY _IOW(0xbc, 17, struct bch_ioctl_subvolume)
+
+#define BCH_IOCTL_DEV_USAGE_V2 _IOWR(0xbc, 18, struct bch_ioctl_dev_usage_v2)
+
+#define BCH_IOCTL_FSCK_OFFLINE _IOW(0xbc, 19, struct bch_ioctl_fsck_offline)
+#define BCH_IOCTL_FSCK_ONLINE _IOW(0xbc, 20, struct bch_ioctl_fsck_online)
+#define BCH_IOCTL_QUERY_ACCOUNTING _IOW(0xbc, 21, struct bch_ioctl_query_accounting)
+#define BCH_IOCTL_QUERY_COUNTERS _IOW(0xbc, 21, struct bch_ioctl_query_counters)
/* ioctl below act on a particular file, not the filesystem as a whole: */
@@ -164,6 +170,13 @@ struct bch_ioctl_disk {
__u64 dev;
};
+struct bch_ioctl_disk_v2 {
+ __u32 flags;
+ __u32 pad;
+ __u64 dev;
+ struct bch_ioctl_err_msg err;
+};
+
/*
* BCH_IOCTL_DISK_SET_STATE: modify state of a member device of a filesystem
*
@@ -400,6 +413,14 @@ struct bch_ioctl_disk_resize {
__u64 nbuckets;
};
+struct bch_ioctl_disk_resize_v2 {
+ __u32 flags;
+ __u32 pad;
+ __u64 dev;
+ __u64 nbuckets;
+ struct bch_ioctl_err_msg err;
+};
+
/*
* BCH_IOCTL_DISK_RESIZE_JOURNAL: resize journal on a device
*
@@ -413,6 +434,14 @@ struct bch_ioctl_disk_resize_journal {
__u64 nbuckets;
};
+struct bch_ioctl_disk_resize_journal_v2 {
+ __u32 flags;
+ __u32 pad;
+ __u64 dev;
+ __u64 nbuckets;
+ struct bch_ioctl_err_msg err;
+};
+
struct bch_ioctl_subvolume {
__u32 flags;
__u32 dirfd;
diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c
index 2370c15e28b6..f6f90d421f27 100644
--- a/fs/bcachefs/chardev.c
+++ b/fs/bcachefs/chardev.c
@@ -187,6 +187,18 @@ 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)
+{
+ if (ret) {
+ prt_printf(src, "error=%s", bch2_err_str(ret));
+ ret = copy_to_user_errcode((void __user *)(ulong)dst->msg_ptr,
+ src->buf,
+ min(src->pos, dst->msg_len)) ?: ret;
+ }
+
+ return ret;
+}
+
static long bch2_ioctl_disk_add(struct bch_fs *c, struct bch_ioctl_disk arg)
{
char *path;
@@ -212,6 +224,28 @@ static long bch2_ioctl_disk_add(struct bch_fs *c, struct bch_ioctl_disk arg)
return ret;
}
+static long bch2_ioctl_disk_add_v2(struct bch_fs *c, struct bch_ioctl_disk_v2 arg)
+{
+ char *path = NULL;
+ int ret;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (arg.flags || arg.pad)
+ return -EINVAL;
+
+ path = strndup_user((const char __user *)(unsigned long) arg.dev, PATH_MAX);
+ ret = PTR_ERR_OR_ZERO(path);
+ if (ret)
+ return ret;
+
+ CLASS(printbuf, err)();
+ ret = bch2_dev_add(c, path, &err);
+ kfree(path);
+ return copy_ioctl_err_msg(&arg.err, &err, ret);
+}
+
static long bch2_ioctl_disk_remove(struct bch_fs *c, struct bch_ioctl_disk arg)
{
if (!capable(CAP_SYS_ADMIN))
@@ -235,6 +269,27 @@ static long bch2_ioctl_disk_remove(struct bch_fs *c, struct bch_ioctl_disk arg)
return ret;
}
+static long bch2_ioctl_disk_remove_v2(struct bch_fs *c, struct bch_ioctl_disk_v2 arg)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if ((arg.flags & ~(BCH_FORCE_IF_DATA_LOST|
+ BCH_FORCE_IF_METADATA_LOST|
+ BCH_FORCE_IF_DEGRADED|
+ BCH_BY_INDEX)) ||
+ arg.pad)
+ return -EINVAL;
+
+ struct bch_dev *ca = bch2_device_lookup(c, arg.dev, arg.flags);
+ if (IS_ERR(ca))
+ return PTR_ERR(ca);
+
+ CLASS(printbuf, err)();
+ int ret = bch2_dev_remove(c, ca, arg.flags, &err);
+ return copy_ioctl_err_msg(&arg.err, &err, ret);
+}
+
static long bch2_ioctl_disk_online(struct bch_fs *c, struct bch_ioctl_disk arg)
{
char *path;
@@ -259,6 +314,28 @@ static long bch2_ioctl_disk_online(struct bch_fs *c, struct bch_ioctl_disk arg)
return ret;
}
+static long bch2_ioctl_disk_online_v2(struct bch_fs *c, struct bch_ioctl_disk_v2 arg)
+{
+ char *path;
+ int ret;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (arg.flags || arg.pad)
+ return -EINVAL;
+
+ path = strndup_user((const char __user *)(unsigned long) arg.dev, PATH_MAX);
+ ret = PTR_ERR_OR_ZERO(path);
+ if (ret)
+ return ret;
+
+ CLASS(printbuf, err)();
+ ret = bch2_dev_online(c, path, &err);
+ kfree(path);
+ return copy_ioctl_err_msg(&arg.err, &err, ret);
+}
+
static long bch2_ioctl_disk_offline(struct bch_fs *c, struct bch_ioctl_disk arg)
{
if (!capable(CAP_SYS_ADMIN))
@@ -282,6 +359,27 @@ static long bch2_ioctl_disk_offline(struct bch_fs *c, struct bch_ioctl_disk arg)
return ret;
}
+static long bch2_ioctl_disk_offline_v2(struct bch_fs *c, struct bch_ioctl_disk_v2 arg)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if ((arg.flags & ~(BCH_FORCE_IF_DATA_LOST|
+ BCH_FORCE_IF_METADATA_LOST|
+ BCH_FORCE_IF_DEGRADED|
+ BCH_BY_INDEX)) ||
+ arg.pad)
+ return -EINVAL;
+
+ CLASS(bch2_device_lookup, ca)(c, arg.dev, arg.flags);
+ if (IS_ERR(ca))
+ return PTR_ERR(ca);
+
+ CLASS(printbuf, err)();
+ int ret = bch2_dev_offline(c, ca, arg.flags, &err);
+ return copy_ioctl_err_msg(&arg.err, &err, ret);
+}
+
static long bch2_ioctl_disk_set_state(struct bch_fs *c,
struct bch_ioctl_disk_set_state arg)
{
@@ -331,13 +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:
- if (ret) {
- prt_printf(&err, "error=%s", bch2_err_str(ret));
- ret = copy_to_user_errcode((void __user *)(ulong)arg.err.msg_ptr,
- err.buf,
- min(err.pos, arg.err.msg_len)) ?: ret;
- }
- return ret;
+ return copy_ioctl_err_msg(&arg.err, &err, ret);
}
struct bch_data_ctx {
@@ -675,6 +767,25 @@ static long bch2_ioctl_disk_resize(struct bch_fs *c,
return ret;
}
+static long bch2_ioctl_disk_resize_v2(struct bch_fs *c,
+ struct bch_ioctl_disk_resize_v2 arg)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if ((arg.flags & ~BCH_BY_INDEX) ||
+ arg.pad)
+ return -EINVAL;
+
+ CLASS(bch2_device_lookup, ca)(c, arg.dev, arg.flags);
+ if (IS_ERR(ca))
+ return PTR_ERR(ca);
+
+ CLASS(printbuf, err)();
+ int ret = bch2_dev_resize(c, ca, arg.nbuckets, &err);
+ return copy_ioctl_err_msg(&arg.err, &err, ret);
+}
+
static long bch2_ioctl_disk_resize_journal(struct bch_fs *c,
struct bch_ioctl_disk_resize_journal arg)
{
@@ -695,6 +806,28 @@ static long bch2_ioctl_disk_resize_journal(struct bch_fs *c,
return bch2_set_nr_journal_buckets(c, ca, arg.nbuckets);
}
+static long bch2_ioctl_disk_resize_journal_v2(struct bch_fs *c,
+ struct bch_ioctl_disk_resize_journal_v2 arg)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if ((arg.flags & ~BCH_BY_INDEX) ||
+ arg.pad)
+ return -EINVAL;
+
+ if (arg.nbuckets > U32_MAX)
+ return -EINVAL;
+
+ CLASS(bch2_device_lookup, ca)(c, arg.dev, arg.flags);
+ if (IS_ERR(ca))
+ return PTR_ERR(ca);
+
+ CLASS(printbuf, err)();
+ int ret = bch2_set_nr_journal_buckets(c, ca, arg.nbuckets);
+ return copy_ioctl_err_msg(&arg.err, &err, ret);
+}
+
#define BCH_IOCTL(_name, _argtype) \
do { \
_argtype i; \
@@ -736,12 +869,20 @@ long bch2_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg)
switch (cmd) {
case BCH_IOCTL_DISK_ADD:
BCH_IOCTL(disk_add, struct bch_ioctl_disk);
+ case BCH_IOCTL_DISK_ADD_v2:
+ BCH_IOCTL(disk_add_v2, struct bch_ioctl_disk_v2);
case BCH_IOCTL_DISK_REMOVE:
BCH_IOCTL(disk_remove, struct bch_ioctl_disk);
+ case BCH_IOCTL_DISK_REMOVE_v2:
+ BCH_IOCTL(disk_remove_v2, struct bch_ioctl_disk_v2);
case BCH_IOCTL_DISK_ONLINE:
BCH_IOCTL(disk_online, struct bch_ioctl_disk);
+ case BCH_IOCTL_DISK_ONLINE_v2:
+ BCH_IOCTL(disk_online_v2, struct bch_ioctl_disk_v2);
case BCH_IOCTL_DISK_OFFLINE:
BCH_IOCTL(disk_offline, struct bch_ioctl_disk);
+ case BCH_IOCTL_DISK_OFFLINE_v2:
+ BCH_IOCTL(disk_offline_v2, struct bch_ioctl_disk_v2);
case BCH_IOCTL_DISK_SET_STATE:
BCH_IOCTL(disk_set_state, struct bch_ioctl_disk_set_state);
case BCH_IOCTL_DISK_SET_STATE_v2:
@@ -750,8 +891,12 @@ long bch2_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg)
BCH_IOCTL(data, struct bch_ioctl_data);
case BCH_IOCTL_DISK_RESIZE:
BCH_IOCTL(disk_resize, struct bch_ioctl_disk_resize);
+ case BCH_IOCTL_DISK_RESIZE_v2:
+ BCH_IOCTL(disk_resize_v2, struct bch_ioctl_disk_resize_v2);
case BCH_IOCTL_DISK_RESIZE_JOURNAL:
BCH_IOCTL(disk_resize_journal, struct bch_ioctl_disk_resize_journal);
+ case BCH_IOCTL_DISK_RESIZE_JOURNAL_v2:
+ BCH_IOCTL(disk_resize_journal_v2, struct bch_ioctl_disk_resize_journal_v2);
case BCH_IOCTL_FSCK_ONLINE:
BCH_IOCTL(fsck_online, struct bch_ioctl_fsck_online);
case BCH_IOCTL_QUERY_ACCOUNTING:
--
2.50.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] bcachefs: v2 versions of subvolume ioctls
2025-08-29 6:54 [PATCH 0/3] better error messages for ioctls Kent Overstreet
2025-08-29 6:54 ` [PATCH 1/3] bcachefs: Add v2 ioctls that return error strings Kent Overstreet
@ 2025-08-29 6:54 ` Kent Overstreet
2025-08-29 6:54 ` [PATCH 3/3] bcachefs: Plumb error messages through data drop paths Kent Overstreet
2 siblings, 0 replies; 4+ messages in thread
From: Kent Overstreet @ 2025-08-29 6:54 UTC (permalink / raw)
To: linux-bcachefs; +Cc: Kent Overstreet
Like we recently did for the device ioctl, add v2 versions that can
return error strings.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
---
fs/bcachefs/bcachefs_ioctl.h | 12 +++++
fs/bcachefs/chardev.c | 16 +++----
fs/bcachefs/chardev.h | 3 ++
fs/bcachefs/fs-ioctl.c | 91 +++++++++++++++++++++++++++++++++---
4 files changed, 108 insertions(+), 14 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/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 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp,
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 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
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;
--
2.50.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] bcachefs: Plumb error messages through data drop paths
2025-08-29 6:54 [PATCH 0/3] better error messages for ioctls Kent Overstreet
2025-08-29 6:54 ` [PATCH 1/3] bcachefs: Add v2 ioctls that return error strings Kent Overstreet
2025-08-29 6:54 ` [PATCH 2/3] bcachefs: v2 versions of subvolume ioctls Kent Overstreet
@ 2025-08-29 6:54 ` Kent Overstreet
2 siblings, 0 replies; 4+ messages in thread
From: Kent Overstreet @ 2025-08-29 6:54 UTC (permalink / raw)
To: linux-bcachefs; +Cc: Kent Overstreet
The ioctl v2 rework added the ability to return error messages to
userspace directly - instead of via the dmesg log.
This lets us return more informative error messages: we can now return a
message with the key we failed on.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
---
fs/bcachefs/ec.c | 23 ++++++++++++------
fs/bcachefs/ec.h | 5 ++--
fs/bcachefs/migrate.c | 55 ++++++++++++++++++++++++-------------------
fs/bcachefs/migrate.h | 4 ++--
fs/bcachefs/super.c | 6 ++---
5 files changed, 55 insertions(+), 38 deletions(-)
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c
index c2840cb674b2..271e252152da 100644
--- a/fs/bcachefs/ec.c
+++ b/fs/bcachefs/ec.c
@@ -2040,7 +2040,7 @@ int bch2_invalidate_stripe_to_dev(struct btree_trans *trans,
struct btree_iter *iter,
struct bkey_s_c k,
unsigned dev_idx,
- unsigned flags)
+ unsigned flags, struct printbuf *err)
{
if (k.k->type != KEY_TYPE_stripe)
return 0;
@@ -2081,13 +2081,21 @@ int bch2_invalidate_stripe_to_dev(struct btree_trans *trans,
nr_good += ca && ca->mi.state != BCH_MEMBER_STATE_failed;
}
- if (nr_good < s->v.nr_blocks && !(flags & BCH_FORCE_IF_DATA_DEGRADED))
+ if (nr_good < s->v.nr_blocks && !(flags & BCH_FORCE_IF_DATA_DEGRADED)) {
+ prt_str(err, "cannot drop device without degrading\n ");
+ bch2_bkey_val_to_text(err, c, k);
+ prt_newline(err);
return bch_err_throw(c, remove_would_lose_data);
+ }
unsigned nr_data = s->v.nr_blocks - s->v.nr_redundant;
- if (nr_good < nr_data && !(flags & BCH_FORCE_IF_DATA_LOST))
+ if (nr_good < nr_data && !(flags & BCH_FORCE_IF_DATA_LOST)) {
+ prt_str(err, "cannot drop device without losing data\n ");
+ bch2_bkey_val_to_text(err, c, k);
+ prt_newline(err);
return bch_err_throw(c, remove_would_lose_data);
+ }
sectors = -sectors;
@@ -2099,7 +2107,7 @@ int bch2_invalidate_stripe_to_dev(struct btree_trans *trans,
}
static int bch2_invalidate_stripe_to_dev_from_alloc(struct btree_trans *trans, struct bkey_s_c k_a,
- unsigned flags)
+ unsigned flags, struct printbuf *err)
{
struct bch_alloc_v4 a_convert;
const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k_a, &a_convert);
@@ -2119,17 +2127,18 @@ static int bch2_invalidate_stripe_to_dev_from_alloc(struct btree_trans *trans, s
if (ret)
return ret;
- return bch2_invalidate_stripe_to_dev(trans, &iter, s.s_c, k_a.k->p.inode, flags);
+ return bch2_invalidate_stripe_to_dev(trans, &iter, s.s_c, k_a.k->p.inode, flags, err);
}
-int bch2_dev_remove_stripes(struct bch_fs *c, unsigned dev_idx, unsigned flags)
+int bch2_dev_remove_stripes(struct bch_fs *c, unsigned dev_idx,
+ unsigned flags, struct printbuf *err)
{
CLASS(btree_trans, trans)(c);
int ret = for_each_btree_key_max_commit(trans, iter,
BTREE_ID_alloc, POS(dev_idx, 0), POS(dev_idx, U64_MAX),
BTREE_ITER_intent, k,
NULL, NULL, 0, ({
- bch2_invalidate_stripe_to_dev_from_alloc(trans, k, flags);
+ bch2_invalidate_stripe_to_dev_from_alloc(trans, k, flags, err);
}));
bch_err_fn(c, ret);
return ret;
diff --git a/fs/bcachefs/ec.h b/fs/bcachefs/ec.h
index e807e7027d7a..cc778da99030 100644
--- a/fs/bcachefs/ec.h
+++ b/fs/bcachefs/ec.h
@@ -289,8 +289,9 @@ static inline void ec_stripe_new_put(struct bch_fs *c, struct ec_stripe_new *s,
}
int bch2_invalidate_stripe_to_dev(struct btree_trans *, struct btree_iter *,
- struct bkey_s_c, unsigned, unsigned);
-int bch2_dev_remove_stripes(struct bch_fs *, unsigned, unsigned);
+ struct bkey_s_c, unsigned,
+ unsigned, struct printbuf *);
+int bch2_dev_remove_stripes(struct bch_fs *, unsigned, unsigned, struct printbuf *);
void bch2_ec_stop_dev(struct bch_fs *, struct bch_dev *);
void bch2_fs_ec_stop(struct bch_fs *);
diff --git a/fs/bcachefs/migrate.c b/fs/bcachefs/migrate.c
index 892990b4a6a6..5b4c3f4b1c25 100644
--- a/fs/bcachefs/migrate.c
+++ b/fs/bcachefs/migrate.c
@@ -22,8 +22,8 @@
#include "replicas.h"
#include "super-io.h"
-static int drop_dev_ptrs(struct bch_fs *c, struct bkey_s k,
- unsigned dev_idx, unsigned flags, bool metadata)
+static int drop_dev_ptrs(struct bch_fs *c, struct bkey_s k, unsigned dev_idx,
+ unsigned flags, struct printbuf *err, bool metadata)
{
unsigned replicas = metadata ? c->opts.metadata_replicas : c->opts.data_replicas;
unsigned lost = metadata ? BCH_FORCE_IF_METADATA_LOST : BCH_FORCE_IF_DATA_LOST;
@@ -34,14 +34,19 @@ static int drop_dev_ptrs(struct bch_fs *c, struct bkey_s k,
nr_good = bch2_bkey_durability(c, k.s_c);
if ((!nr_good && !(flags & lost)) ||
- (nr_good < replicas && !(flags & degraded)))
+ (nr_good < replicas && !(flags & degraded))) {
+ prt_str(err, "cannot drop device without degrading/losing data\n ");
+ bch2_bkey_val_to_text(err, c, k.s_c);
+ prt_newline(err);
return bch_err_throw(c, remove_would_lose_data);
+ }
return 0;
}
static int drop_btree_ptrs(struct btree_trans *trans, struct btree_iter *iter,
- struct btree *b, unsigned dev_idx, unsigned flags)
+ struct btree *b, unsigned dev_idx,
+ unsigned flags, struct printbuf *err)
{
struct bch_fs *c = trans->c;
struct bkey_buf k;
@@ -49,10 +54,9 @@ static int drop_btree_ptrs(struct btree_trans *trans, struct btree_iter *iter,
bch2_bkey_buf_init(&k);
bch2_bkey_buf_copy(&k, c, &b->key);
- int ret = drop_dev_ptrs(c, bkey_i_to_s(k.k), dev_idx, flags, true) ?:
+ int ret = drop_dev_ptrs(c, bkey_i_to_s(k.k), dev_idx, flags, err, true) ?:
bch2_btree_node_update_key(trans, iter, b, k.k, 0, false);
- bch_err_fn(c, ret);
bch2_bkey_buf_exit(&k, c);
return ret;
}
@@ -61,7 +65,7 @@ static int bch2_dev_usrdata_drop_key(struct btree_trans *trans,
struct btree_iter *iter,
struct bkey_s_c k,
unsigned dev_idx,
- unsigned flags)
+ unsigned flags, struct printbuf *err)
{
struct bch_fs *c = trans->c;
struct bkey_i *n;
@@ -75,7 +79,7 @@ static int bch2_dev_usrdata_drop_key(struct btree_trans *trans,
if (ret)
return ret;
- ret = drop_dev_ptrs(c, bkey_i_to_s(n), dev_idx, flags, false);
+ ret = drop_dev_ptrs(c, bkey_i_to_s(n), dev_idx, flags, err, false);
if (ret)
return ret;
@@ -101,7 +105,7 @@ static int bch2_dev_btree_drop_key(struct btree_trans *trans,
struct bkey_s_c_backpointer bp,
unsigned dev_idx,
struct bkey_buf *last_flushed,
- unsigned flags)
+ unsigned flags, struct printbuf *err)
{
struct btree_iter iter;
struct btree *b = bch2_backpointer_get_node(trans, bp, &iter, last_flushed);
@@ -109,7 +113,7 @@ static int bch2_dev_btree_drop_key(struct btree_trans *trans,
if (ret)
return ret == -BCH_ERR_backpointer_to_overwritten_btree_node ? 0 : ret;
- ret = drop_btree_ptrs(trans, &iter, b, dev_idx, flags);
+ ret = drop_btree_ptrs(trans, &iter, b, dev_idx, flags, err);
bch2_trans_iter_exit(&iter);
return ret;
@@ -117,7 +121,8 @@ static int bch2_dev_btree_drop_key(struct btree_trans *trans,
static int bch2_dev_usrdata_drop(struct bch_fs *c,
struct progress_indicator_state *progress,
- unsigned dev_idx, unsigned flags)
+ unsigned dev_idx,
+ unsigned flags, struct printbuf *err)
{
CLASS(btree_trans, trans)(c);
@@ -133,7 +138,7 @@ static int bch2_dev_usrdata_drop(struct bch_fs *c,
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
bch2_progress_update_iter(trans, progress, &iter, "dropping user data");
- bch2_dev_usrdata_drop_key(trans, &iter, k, dev_idx, flags);
+ bch2_dev_usrdata_drop_key(trans, &iter, k, dev_idx, flags, err);
}));
if (ret)
return ret;
@@ -144,7 +149,8 @@ static int bch2_dev_usrdata_drop(struct bch_fs *c,
static int bch2_dev_metadata_drop(struct bch_fs *c,
struct progress_indicator_state *progress,
- unsigned dev_idx, unsigned flags)
+ unsigned dev_idx,
+ unsigned flags, struct printbuf *err)
{
struct btree_iter iter;
struct closure cl;
@@ -174,7 +180,7 @@ static int bch2_dev_metadata_drop(struct bch_fs *c,
if (!bch2_bkey_has_device_c(bkey_i_to_s_c(&b->key), dev_idx))
goto next;
- ret = drop_btree_ptrs(trans, &iter, b, dev_idx, flags);
+ ret = drop_btree_ptrs(trans, &iter, b, dev_idx, flags, err);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
ret = 0;
continue;
@@ -206,7 +212,7 @@ static int bch2_dev_metadata_drop(struct bch_fs *c,
static int data_drop_bp(struct btree_trans *trans, unsigned dev_idx,
struct bkey_s_c_backpointer bp, struct bkey_buf *last_flushed,
- unsigned flags)
+ unsigned flags, struct printbuf *err)
{
struct btree_iter iter;
struct bkey_s_c k = bch2_backpointer_get_key(trans, bp, &iter, BTREE_ITER_intent,
@@ -226,17 +232,18 @@ static int data_drop_bp(struct btree_trans *trans, unsigned dev_idx,
*/
if (bkey_is_btree_ptr(k.k))
- ret = bch2_dev_btree_drop_key(trans, bp, dev_idx, last_flushed, flags);
+ ret = bch2_dev_btree_drop_key(trans, bp, dev_idx, last_flushed, flags, err);
else if (k.k->type == KEY_TYPE_stripe)
- ret = bch2_invalidate_stripe_to_dev(trans, &iter, k, dev_idx, flags);
+ ret = bch2_invalidate_stripe_to_dev(trans, &iter, k, dev_idx, flags, err);
else
- ret = bch2_dev_usrdata_drop_key(trans, &iter, k, dev_idx, flags);
+ ret = bch2_dev_usrdata_drop_key(trans, &iter, k, dev_idx, flags, err);
out:
bch2_trans_iter_exit(&iter);
return ret;
}
-int bch2_dev_data_drop_by_backpointers(struct bch_fs *c, unsigned dev_idx, unsigned flags)
+int bch2_dev_data_drop_by_backpointers(struct bch_fs *c, unsigned dev_idx, unsigned flags,
+ struct printbuf *err)
{
CLASS(btree_trans, trans)(c);
@@ -253,22 +260,22 @@ int bch2_dev_data_drop_by_backpointers(struct bch_fs *c, unsigned dev_idx, unsig
continue;
data_drop_bp(trans, dev_idx, bkey_s_c_to_backpointer(k),
- &last_flushed, flags);
+ &last_flushed, flags, err);
}));
bch2_bkey_buf_exit(&last_flushed, trans->c);
- bch_err_fn(c, ret);
return ret;
}
-int bch2_dev_data_drop(struct bch_fs *c, unsigned dev_idx, unsigned flags)
+int bch2_dev_data_drop(struct bch_fs *c, unsigned dev_idx,
+ unsigned flags, struct printbuf *err)
{
struct progress_indicator_state progress;
bch2_progress_init(&progress, c,
BIT_ULL(BTREE_ID_extents)|
BIT_ULL(BTREE_ID_reflink));
- return bch2_dev_usrdata_drop(c, &progress, dev_idx, flags) ?:
- bch2_dev_metadata_drop(c, &progress, dev_idx, flags);
+ return bch2_dev_usrdata_drop(c, &progress, dev_idx, flags, err) ?:
+ bch2_dev_metadata_drop(c, &progress, dev_idx, flags, err);
}
diff --git a/fs/bcachefs/migrate.h b/fs/bcachefs/migrate.h
index 30018140711b..ff4567fb5a83 100644
--- a/fs/bcachefs/migrate.h
+++ b/fs/bcachefs/migrate.h
@@ -2,7 +2,7 @@
#ifndef _BCACHEFS_MIGRATE_H
#define _BCACHEFS_MIGRATE_H
-int bch2_dev_data_drop_by_backpointers(struct bch_fs *, unsigned, unsigned);
-int bch2_dev_data_drop(struct bch_fs *, unsigned, unsigned);
+int bch2_dev_data_drop_by_backpointers(struct bch_fs *, unsigned, unsigned, struct printbuf *);
+int bch2_dev_data_drop(struct bch_fs *, unsigned, unsigned, struct printbuf *);
#endif /* _BCACHEFS_MIGRATE_H */
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index 793c16fa8b09..d640ae188722 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -1992,9 +1992,9 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags,
__bch2_dev_read_only(c, ca);
ret = fast_device_removal
- ? bch2_dev_data_drop_by_backpointers(c, ca->dev_idx, flags)
- : (bch2_dev_data_drop(c, ca->dev_idx, flags) ?:
- bch2_dev_remove_stripes(c, ca->dev_idx, flags));
+ ? bch2_dev_data_drop_by_backpointers(c, ca->dev_idx, flags, err)
+ : (bch2_dev_data_drop(c, ca->dev_idx, flags, err) ?:
+ bch2_dev_remove_stripes(c, ca->dev_idx, flags, err));
if (ret)
goto err;
--
2.50.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-08-29 6:54 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-29 6:54 [PATCH 0/3] better error messages for ioctls Kent Overstreet
2025-08-29 6:54 ` [PATCH 1/3] bcachefs: Add v2 ioctls that return error strings Kent Overstreet
2025-08-29 6:54 ` [PATCH 2/3] bcachefs: v2 versions of subvolume ioctls Kent Overstreet
2025-08-29 6:54 ` [PATCH 3/3] bcachefs: Plumb error messages through data drop paths Kent Overstreet
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.