* [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