summaryrefslogtreecommitdiff
path: root/fs/bcachefs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2025-08-17 19:49:31 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2025-08-17 19:52:21 -0400
commit913e63252a3b3e076837bc2791abdfbacf106aad (patch)
tree594c455c19422e8d2a735a9d1fd3287cf63c98c9 /fs/bcachefs
parent6a8d62bbb0feda0cd215228edde0d0e166a96325 (diff)
bcachefs: Plumb printbuf through device_set_statebcachefs-testing
To be used for improving ioctl error messages. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs')
-rw-r--r--fs/bcachefs/chardev.c3
-rw-r--r--fs/bcachefs/error.c12
-rw-r--r--fs/bcachefs/opts.c2
-rw-r--r--fs/bcachefs/replicas.c14
-rw-r--r--fs/bcachefs/replicas.h2
-rw-r--r--fs/bcachefs/super-io.c4
-rw-r--r--fs/bcachefs/super.c40
-rw-r--r--fs/bcachefs/super.h9
8 files changed, 48 insertions, 38 deletions
diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c
index 467fc45e84fe..e6ed64dc11b7 100644
--- a/fs/bcachefs/chardev.c
+++ b/fs/bcachefs/chardev.c
@@ -287,7 +287,8 @@ static long bch2_ioctl_disk_set_state(struct bch_fs *c,
if (IS_ERR(ca))
return PTR_ERR(ca);
- int ret = bch2_dev_set_state(c, ca, arg.new_state, arg.flags);
+ CLASS(printbuf, err)();
+ int ret = bch2_dev_set_state(c, ca, arg.new_state, arg.flags, &err);
bch_err_msg(ca, ret, "setting device state");
return ret;
}
diff --git a/fs/bcachefs/error.c b/fs/bcachefs/error.c
index 32a286b3a74e..e33f3166c48a 100644
--- a/fs/bcachefs/error.c
+++ b/fs/bcachefs/error.c
@@ -141,14 +141,16 @@ void bch2_io_error_work(struct work_struct *work)
if (ca->mi.state >= BCH_MEMBER_STATE_ro)
return;
- bool dev = !__bch2_dev_set_state(c, ca, BCH_MEMBER_STATE_ro,
- BCH_FORCE_IF_DEGRADED);
CLASS(printbuf, buf)();
__bch2_log_msg_start(ca->name, &buf);
- prt_printf(&buf, "writes erroring for %u seconds, setting %s ro",
- c->opts.write_error_timeout,
- dev ? "device" : "filesystem");
+ prt_printf(&buf, "writes erroring for %u seconds\n",
+ c->opts.write_error_timeout);
+
+ bool dev = !__bch2_dev_set_state(c, ca, BCH_MEMBER_STATE_ro,
+ BCH_FORCE_IF_DEGRADED, &buf);
+
+ prt_printf(&buf, "setting %s ro", dev ? "device" : "filesystem");
if (!dev)
bch2_fs_emergency_read_only2(c, &buf);
diff --git a/fs/bcachefs/opts.c b/fs/bcachefs/opts.c
index 921f9049912d..c3ef35dc01e2 100644
--- a/fs/bcachefs/opts.c
+++ b/fs/bcachefs/opts.c
@@ -525,7 +525,7 @@ int bch2_opt_hook_pre_set(struct bch_fs *c, struct bch_dev *ca, enum bch_opt_id
switch (id) {
case Opt_state:
if (ca)
- return bch2_dev_set_state(c, ca, v, BCH_FORCE_IF_DEGRADED);
+ return bch2_dev_set_state(c, ca, v, BCH_FORCE_IF_DEGRADED, NULL);
break;
case Opt_compression:
diff --git a/fs/bcachefs/replicas.c b/fs/bcachefs/replicas.c
index 0784283ce78c..3ffd68d2608d 100644
--- a/fs/bcachefs/replicas.c
+++ b/fs/bcachefs/replicas.c
@@ -784,7 +784,7 @@ const struct bch_sb_field_ops bch_sb_field_ops_replicas_v0 = {
/* Query replicas: */
bool bch2_have_enough_devs(struct bch_fs *c, struct bch_devs_mask devs,
- unsigned flags, bool print)
+ unsigned flags, struct printbuf *err)
{
struct bch_replicas_entry_v1 *e;
@@ -823,16 +823,14 @@ bool bch2_have_enough_devs(struct bch_fs *c, struct bch_devs_mask devs,
: BCH_FORCE_IF_DATA_DEGRADED;
if (dflags & ~flags) {
- if (print) {
- CLASS(printbuf, buf)();
-
- bch2_replicas_entry_to_text(&buf, e);
- bch_err(c, "insufficient devices online (%u) for replicas entry %s",
- nr_online, buf.buf);
+ if (err) {
+ prt_printf(err, "insufficient devices online (%u) for replicas entry ",
+ nr_online);
+ bch2_replicas_entry_to_text(err, e);
+ prt_newline(err);
}
return false;
}
-
}
return true;
diff --git a/fs/bcachefs/replicas.h b/fs/bcachefs/replicas.h
index 5aba2c1ce133..15023a9b0b1e 100644
--- a/fs/bcachefs/replicas.h
+++ b/fs/bcachefs/replicas.h
@@ -44,7 +44,7 @@ static inline void bch2_replicas_entry_cached(struct bch_replicas_entry_v1 *e,
}
bool bch2_have_enough_devs(struct bch_fs *, struct bch_devs_mask,
- unsigned, bool);
+ unsigned, struct printbuf *);
unsigned bch2_sb_dev_has_data(struct bch_sb *, unsigned);
unsigned bch2_dev_has_data(struct bch_fs *, struct bch_dev *);
diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c
index 5897380c4c08..61eeac671283 100644
--- a/fs/bcachefs/super-io.c
+++ b/fs/bcachefs/super-io.c
@@ -1189,13 +1189,13 @@ int bch2_write_super(struct bch_fs *c)
nr_wrote = dev_mask_nr(&sb_written);
can_mount_with_written =
- bch2_have_enough_devs(c, sb_written, degraded_flags, false);
+ bch2_have_enough_devs(c, sb_written, degraded_flags, NULL);
for (unsigned i = 0; i < ARRAY_SIZE(sb_written.d); i++)
sb_written.d[i] = ~sb_written.d[i];
can_mount_without_written =
- bch2_have_enough_devs(c, sb_written, degraded_flags, false);
+ bch2_have_enough_devs(c, sb_written, degraded_flags, NULL);
/*
* If we would be able to mount _without_ the devices we successfully
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index ee3b30b1c2b5..4281a20f7856 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -1368,10 +1368,14 @@ static bool bch2_fs_may_start(struct bch_fs *c)
return false;
}
break;
- }
+ }
}
- return bch2_have_enough_devs(c, c->online_devs, flags, true);
+ CLASS(printbuf, err)();
+ bool ret = bch2_have_enough_devs(c, c->online_devs, flags, &err);
+ if (!ret)
+ bch2_print_str(c, KERN_ERR, err.buf);
+ return ret;
}
int bch2_fs_start(struct bch_fs *c)
@@ -1833,7 +1837,8 @@ static int bch2_dev_attach_bdev(struct bch_fs *c, struct bch_sb_handle *sb)
* because we got an error or what have you?
*/
bool bch2_dev_state_allowed(struct bch_fs *c, struct bch_dev *ca,
- enum bch_member_state new_state, int flags)
+ enum bch_member_state new_state, int flags,
+ struct printbuf *err)
{
struct bch_devs_mask new_online_devs;
int nr_rw = 0, required;
@@ -1870,7 +1875,7 @@ bool bch2_dev_state_allowed(struct bch_fs *c, struct bch_dev *ca,
new_online_devs = c->online_devs;
__clear_bit(ca->dev_idx, new_online_devs.d);
- return bch2_have_enough_devs(c, new_online_devs, flags, false);
+ return bch2_have_enough_devs(c, new_online_devs, flags, err);
default:
BUG();
}
@@ -1904,14 +1909,15 @@ static void __bch2_dev_read_write(struct bch_fs *c, struct bch_dev *ca)
}
int __bch2_dev_set_state(struct bch_fs *c, struct bch_dev *ca,
- enum bch_member_state new_state, int flags)
+ enum bch_member_state new_state, int flags,
+ struct printbuf *err)
{
int ret = 0;
if (ca->mi.state == new_state)
return 0;
- if (!bch2_dev_state_allowed(c, ca, new_state, flags))
+ if (!bch2_dev_state_allowed(c, ca, new_state, flags, err))
return bch_err_throw(c, device_state_not_allowed);
if (new_state != BCH_MEMBER_STATE_rw)
@@ -1934,10 +1940,11 @@ int __bch2_dev_set_state(struct bch_fs *c, struct bch_dev *ca,
}
int bch2_dev_set_state(struct bch_fs *c, struct bch_dev *ca,
- enum bch_member_state new_state, int flags)
+ enum bch_member_state new_state, int flags,
+ struct printbuf *err)
{
guard(rwsem_write)(&c->state_lock);
- return __bch2_dev_set_state(c, ca, new_state, flags);
+ return __bch2_dev_set_state(c, ca, new_state, flags, err);
}
/* Device add/removal: */
@@ -1957,7 +1964,7 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
*/
bch2_dev_put(ca);
- if (!bch2_dev_state_allowed(c, ca, BCH_MEMBER_STATE_failed, flags)) {
+ if (!bch2_dev_state_allowed(c, ca, BCH_MEMBER_STATE_failed, flags, NULL)) {
bch_err(ca, "Cannot remove without losing data");
ret = bch_err_throw(c, device_state_not_allowed);
goto err;
@@ -2278,7 +2285,7 @@ int bch2_dev_offline(struct bch_fs *c, struct bch_dev *ca, int flags)
return 0;
}
- if (!bch2_dev_state_allowed(c, ca, BCH_MEMBER_STATE_failed, flags)) {
+ if (!bch2_dev_state_allowed(c, ca, BCH_MEMBER_STATE_failed, flags, NULL)) {
bch_err(ca, "Cannot offline required disk");
return bch_err_throw(c, device_state_not_allowed);
}
@@ -2455,10 +2462,14 @@ static void bch2_fs_bdev_mark_dead(struct block_device *bdev, bool surprise)
struct bch_dev *ca = bdev_to_bch_dev(c, bdev);
if (ca) {
+ CLASS(printbuf, buf)();
+ __bch2_log_msg_start(ca->name, &buf);
+ prt_printf(&buf, "offline from block layer\n");
+
bool dev = bch2_dev_state_allowed(c, ca,
BCH_MEMBER_STATE_failed,
- BCH_FORCE_IF_DEGRADED);
-
+ BCH_FORCE_IF_DEGRADED,
+ &buf);
if (!dev && sb) {
if (!surprise)
sync_filesystem(sb);
@@ -2466,11 +2477,6 @@ static void bch2_fs_bdev_mark_dead(struct block_device *bdev, bool surprise)
evict_inodes(sb);
}
- CLASS(printbuf, buf)();
- __bch2_log_msg_start(ca->name, &buf);
-
- prt_printf(&buf, "offline from block layer");
-
if (dev) {
__bch2_dev_offline(c, ca);
} else {
diff --git a/fs/bcachefs/super.h b/fs/bcachefs/super.h
index e90bab9afe78..de2c4430b8f7 100644
--- a/fs/bcachefs/super.h
+++ b/fs/bcachefs/super.h
@@ -17,11 +17,14 @@ struct bch_fs *bch2_dev_to_fs(dev_t);
struct bch_fs *bch2_uuid_to_fs(__uuid_t);
bool bch2_dev_state_allowed(struct bch_fs *, struct bch_dev *,
- enum bch_member_state, int);
+ enum bch_member_state, int,
+ struct printbuf *);
int __bch2_dev_set_state(struct bch_fs *, struct bch_dev *,
- enum bch_member_state, int);
+ enum bch_member_state, int,
+ struct printbuf *);
int bch2_dev_set_state(struct bch_fs *, struct bch_dev *,
- enum bch_member_state, int);
+ enum bch_member_state, int,
+ struct printbuf *);
int bch2_dev_fail(struct bch_dev *, int);
int bch2_dev_remove(struct bch_fs *, struct bch_dev *, int);