summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/bcachefs/bcachefs.h1
-rw-r--r--fs/bcachefs/btree_gc.c6
-rw-r--r--fs/bcachefs/btree_io.c1
-rw-r--r--fs/bcachefs/disk_accounting.c7
-rw-r--r--fs/bcachefs/errcode.h1
-rw-r--r--fs/bcachefs/inode.c4
-rw-r--r--fs/bcachefs/io_read.c13
-rw-r--r--fs/bcachefs/journal_reclaim.c7
-rw-r--r--fs/bcachefs/opts.c9
-rw-r--r--fs/bcachefs/opts.h23
-rw-r--r--fs/bcachefs/replicas_format.h3
-rw-r--r--fs/bcachefs/sb-errors_format.h3
-rw-r--r--fs/bcachefs/super.c13
13 files changed, 53 insertions, 38 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h
index 3ccca855f05e..3673290586e2 100644
--- a/fs/bcachefs/bcachefs.h
+++ b/fs/bcachefs/bcachefs.h
@@ -686,6 +686,7 @@ struct btree_debug {
unsigned id;
};
+#define BCH_LINK_MAX U32_MAX
#define BCH_TRANSACTIONS_NR 128
struct btree_transaction_stats {
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index 63dc0836bf08..638c2a9268a9 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -204,7 +204,7 @@ static int btree_check_node_boundaries(struct btree_trans *trans, struct btree *
if (bpos_eq(expected_start, cur->data->min_key))
return 0;
- prt_printf(&buf, " at ");
+ prt_printf(&buf, " at ");
bch2_btree_id_level_to_text(&buf, b->c.btree_id, b->c.level);
prt_printf(&buf, ":\nparent: ");
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
@@ -229,8 +229,8 @@ static int btree_check_node_boundaries(struct btree_trans *trans, struct btree *
*pulled_from_scan = cur->data->min_key;
ret = bch_err_throw(c, topology_repair_did_fill_from_scan);
} else {
- if (mustfix_fsck_err(trans, btree_node_topology_bad_min_key,
- "btree node with incorrect min_key%s", buf.buf))
+ if (mustfix_fsck_err(trans, btree_node_topology_gap_between_nodes,
+ "gap between btree nodes%s", buf.buf))
ret = set_node_min(c, cur, expected_start);
}
} else { /* overlap */
diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c
index 52d21259ed6f..3808c41dda84 100644
--- a/fs/bcachefs/btree_io.c
+++ b/fs/bcachefs/btree_io.c
@@ -1318,6 +1318,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
set_btree_bset_end(b, b->set);
set_btree_node_need_rewrite(b);
set_btree_node_need_rewrite_error(b);
+ ret = 0;
continue;
}
if (ret)
diff --git a/fs/bcachefs/disk_accounting.c b/fs/bcachefs/disk_accounting.c
index a99f821c6a1c..22b2dbe865f3 100644
--- a/fs/bcachefs/disk_accounting.c
+++ b/fs/bcachefs/disk_accounting.c
@@ -814,6 +814,8 @@ int bch2_accounting_read(struct bch_fs *c)
struct journal_keys *keys = &c->journal_keys;
struct journal_key *jk = keys->data;
+ move_gap(keys, keys->nr);
+
while (jk < &darray_top(*keys) &&
__journal_key_cmp(c, BTREE_ID_accounting, 0, POS_MIN, jk) > 0)
jk++;
@@ -829,9 +831,6 @@ int bch2_accounting_read(struct bch_fs *c)
iter.flags &= ~BTREE_ITER_with_journal;
int ret = for_each_btree_key_continue(trans, iter,
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k, ({
- struct bkey u;
- struct bkey_s_c k = bch2_btree_path_peek_slot_exact(btree_iter_path(trans, &iter), &u);
-
if (k.k->type != KEY_TYPE_accounting)
continue;
@@ -860,7 +859,7 @@ int bch2_accounting_read(struct bch_fs *c)
struct disk_accounting_pos next_acc;
memset(&next_acc, 0, sizeof(next_acc));
next_acc.type = acc_k.type + 1;
- struct bpos next = disk_accounting_pos_to_bpos(&next_acc);
+ struct bpos next = bpos_predecessor(disk_accounting_pos_to_bpos(&next_acc));
if (jk < end)
next = bpos_min(next, journal_key_k(c, jk)->k.p);
diff --git a/fs/bcachefs/errcode.h b/fs/bcachefs/errcode.h
index db2dc5b0e0f2..2712a9754100 100644
--- a/fs/bcachefs/errcode.h
+++ b/fs/bcachefs/errcode.h
@@ -228,6 +228,7 @@
x(BCH_ERR_topology_repair, topology_repair_drop_this_node) \
x(BCH_ERR_topology_repair, topology_repair_drop_prev_node) \
x(BCH_ERR_topology_repair, topology_repair_did_fill_from_scan) \
+ x(EMLINK, too_many_links) \
x(EOPNOTSUPP, may_not_use_incompat_feature) \
x(EOPNOTSUPP, no_casefolding_without_utf8) \
x(EOPNOTSUPP, casefolding_disabled) \
diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c
index 543627fb58be..fda4ca783848 100644
--- a/fs/bcachefs/inode.c
+++ b/fs/bcachefs/inode.c
@@ -1184,8 +1184,8 @@ int bch2_inode_nlink_inc(struct bch_inode_unpacked *bi)
if (bi->bi_flags & BCH_INODE_unlinked)
bi->bi_flags &= ~BCH_INODE_unlinked;
else {
- if (bi->bi_nlink == U32_MAX)
- return -EINVAL;
+ if (bi->bi_nlink == BCH_LINK_MAX - nlink_bias(bi->bi_mode))
+ return -BCH_ERR_too_many_links;
bi->bi_nlink++;
}
diff --git a/fs/bcachefs/io_read.c b/fs/bcachefs/io_read.c
index ca480b8f8dae..ac545f962ce9 100644
--- a/fs/bcachefs/io_read.c
+++ b/fs/bcachefs/io_read.c
@@ -42,12 +42,6 @@ module_param_named(read_corrupt_device, bch2_read_corrupt_device, int, 0644);
MODULE_PARM_DESC(read_corrupt_device, "");
#endif
-static bool bch2_poison_extents_on_checksum_error;
-module_param_named(poison_extents_on_checksum_error,
- bch2_poison_extents_on_checksum_error, bool, 0644);
-MODULE_PARM_DESC(poison_extents_on_checksum_error,
- "Extents with checksum errors are marked as poisoned - unsafe without read fua support");
-
#ifndef CONFIG_BCACHEFS_NO_LATENCY_ACCT
static inline u32 bch2_dev_congested_read(struct bch_dev *ca, u64 now)
@@ -551,9 +545,6 @@ static void get_rbio_extent(struct btree_trans *trans,
static noinline int maybe_poison_extent(struct btree_trans *trans, struct bch_read_bio *rbio,
enum btree_id btree, struct bkey_s_c read_k)
{
- if (!bch2_poison_extents_on_checksum_error)
- return 0;
-
struct bch_fs *c = trans->c;
struct data_update *u = rbio_data_update(rbio);
@@ -1291,6 +1282,10 @@ retry_pick:
async_object_list_add(c, rbio, rbio, &rbio->list_idx);
+ /* XXX: also nvme read recovery level */
+ if (unlikely(failed && bch2_dev_io_failures(failed, pick.ptr.dev)))
+ rbio->bio.bi_opf |= REQ_FUA;
+
if (rbio->bounce)
trace_and_count(c, io_read_bounce, &rbio->bio);
diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c
index ae747c87fcf9..f7b0fdd99c75 100644
--- a/fs/bcachefs/journal_reclaim.c
+++ b/fs/bcachefs/journal_reclaim.c
@@ -766,6 +766,9 @@ static int bch2_journal_reclaim_thread(void *arg)
set_freezable();
+ kthread_wait_freezable(test_bit(BCH_FS_rw, &c->flags) ||
+ kthread_should_stop());
+
j->last_flushed = jiffies;
while (!ret && !kthread_should_stop()) {
@@ -826,8 +829,10 @@ int bch2_journal_reclaim_start(struct journal *j)
struct task_struct *p;
int ret;
- if (j->reclaim_thread)
+ if (j->reclaim_thread) {
+ wake_up_process(j->reclaim_thread);
return 0;
+ }
p = kthread_create(bch2_journal_reclaim_thread, j,
"bch-reclaim/%s", c->name);
diff --git a/fs/bcachefs/opts.c b/fs/bcachefs/opts.c
index b9bac9fbbafb..2dec7cb76dd9 100644
--- a/fs/bcachefs/opts.c
+++ b/fs/bcachefs/opts.c
@@ -646,7 +646,8 @@ int bch2_parse_one_mount_opt(struct bch_fs *c, struct bch_opts *opts,
val = bch2_opt_val_synonym_lookup(name, val);
- if (!(bch2_opt_table[id].flags & OPT_MOUNT))
+ if (!(bch2_opt_table[id].flags & OPT_MOUNT) &&
+ !(bch2_opt_table[id].flags & OPT_MOUNT_OLD))
return -BCH_ERR_option_name;
if ((id == Opt_usrquota ||
@@ -669,6 +670,12 @@ int bch2_parse_one_mount_opt(struct bch_fs *c, struct bch_opts *opts,
if (ret < 0)
return -BCH_ERR_option_value;
+ if (bch2_opt_table[id].flags & OPT_MOUNT_OLD) {
+ pr_err("option %s may no longer be specified at mount time; set via sysfs opts dir",
+ bch2_opt_table[id].attr.name);
+ return 0;
+ }
+
if (opts)
bch2_opt_set_by_id(opts, id, v);
diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h
index 6b9f18839345..1b527602f048 100644
--- a/fs/bcachefs/opts.h
+++ b/fs/bcachefs/opts.h
@@ -66,6 +66,7 @@ enum opt_flags {
OPT_SB_FIELD_ILOG2 = BIT(9), /* Superblock field is ilog2 of actual value */
OPT_SB_FIELD_ONE_BIAS = BIT(10), /* 0 means default value */
OPT_HIDDEN = BIT(11),
+ OPT_MOUNT_OLD = BIT(12), /* May not be specified at mount time, but don't fail the mount */
};
enum opt_type {
@@ -149,12 +150,12 @@ enum fsck_err_opts {
BCH_SB_WRITE_ERROR_TIMEOUT, 30, \
NULL, "Number of consecutive write errors allowed before kicking out a device")\
x(metadata_replicas, u8, \
- OPT_FS|OPT_FORMAT|OPT_RUNTIME, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT_OLD|OPT_RUNTIME, \
OPT_UINT(1, BCH_REPLICAS_MAX + 1), \
BCH_SB_META_REPLICAS_WANT, 1, \
"#", "Number of metadata replicas") \
x(data_replicas, u8, \
- OPT_FS|OPT_INODE|OPT_FORMAT|OPT_RUNTIME, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT_OLD|OPT_RUNTIME, \
OPT_UINT(1, BCH_REPLICAS_MAX + 1), \
BCH_SB_DATA_REPLICAS_WANT, 1, \
"#", "Number of data replicas") \
@@ -175,12 +176,12 @@ enum fsck_err_opts {
BCH_SB_ENCODED_EXTENT_MAX_BITS, 64 << 10, \
"size", "Maximum size of checksummed/compressed extents")\
x(metadata_checksum, u8, \
- OPT_FS|OPT_FORMAT|OPT_RUNTIME, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT_OLD|OPT_RUNTIME, \
OPT_STR(__bch2_csum_opts), \
BCH_SB_META_CSUM_TYPE, BCH_CSUM_OPT_crc32c, \
NULL, NULL) \
x(data_checksum, u8, \
- OPT_FS|OPT_INODE|OPT_FORMAT|OPT_RUNTIME, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT_OLD|OPT_RUNTIME, \
OPT_STR(__bch2_csum_opts), \
BCH_SB_DATA_CSUM_TYPE, BCH_CSUM_OPT_crc32c, \
NULL, NULL) \
@@ -190,12 +191,12 @@ enum fsck_err_opts {
BCH_SB_CSUM_ERR_RETRY_NR, 3, \
NULL, NULL) \
x(compression, u8, \
- OPT_FS|OPT_INODE|OPT_FORMAT|OPT_RUNTIME, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT_OLD|OPT_RUNTIME, \
OPT_FN(bch2_opt_compression), \
BCH_SB_COMPRESSION_TYPE, BCH_COMPRESSION_OPT_none, \
NULL, NULL) \
x(background_compression, u8, \
- OPT_FS|OPT_INODE|OPT_FORMAT|OPT_RUNTIME, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT_OLD|OPT_RUNTIME, \
OPT_FN(bch2_opt_compression), \
BCH_SB_BACKGROUND_COMPRESSION_TYPE,BCH_COMPRESSION_OPT_none, \
NULL, NULL) \
@@ -205,27 +206,27 @@ enum fsck_err_opts {
BCH_SB_STR_HASH_TYPE, BCH_STR_HASH_OPT_siphash, \
NULL, "Hash function for directory entries and xattrs")\
x(metadata_target, u16, \
- OPT_FS|OPT_FORMAT|OPT_RUNTIME, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT_OLD|OPT_RUNTIME, \
OPT_FN(bch2_opt_target), \
BCH_SB_METADATA_TARGET, 0, \
"(target)", "Device or label for metadata writes") \
x(foreground_target, u16, \
- OPT_FS|OPT_INODE|OPT_FORMAT|OPT_RUNTIME, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT_OLD|OPT_RUNTIME, \
OPT_FN(bch2_opt_target), \
BCH_SB_FOREGROUND_TARGET, 0, \
"(target)", "Device or label for foreground writes") \
x(background_target, u16, \
- OPT_FS|OPT_INODE|OPT_FORMAT|OPT_RUNTIME, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT_OLD|OPT_RUNTIME, \
OPT_FN(bch2_opt_target), \
BCH_SB_BACKGROUND_TARGET, 0, \
"(target)", "Device or label to move data to in the background")\
x(promote_target, u16, \
- OPT_FS|OPT_INODE|OPT_FORMAT|OPT_RUNTIME, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT_OLD|OPT_RUNTIME, \
OPT_FN(bch2_opt_target), \
BCH_SB_PROMOTE_TARGET, 0, \
"(target)", "Device or label to promote data to on read") \
x(erasure_code, u16, \
- OPT_FS|OPT_INODE|OPT_FORMAT|OPT_RUNTIME, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT_OLD|OPT_RUNTIME, \
OPT_BOOL(), \
BCH_SB_ERASURE_CODE, false, \
NULL, "Enable erasure coding (DO NOT USE YET)") \
diff --git a/fs/bcachefs/replicas_format.h b/fs/bcachefs/replicas_format.h
index b7eff904acdb..898caf943b34 100644
--- a/fs/bcachefs/replicas_format.h
+++ b/fs/bcachefs/replicas_format.h
@@ -17,7 +17,8 @@ struct bch_replicas_entry_v1 {
__u8 data_type;
__u8 nr_devs;
__u8 nr_required;
- __u8 devs[] __counted_by(nr_devs);
+ /* No counted_by: bch_replicas_cpu entries are all the size of the biggest entry */
+ __u8 devs[];
} __packed;
struct bch_sb_field_replicas {
diff --git a/fs/bcachefs/sb-errors_format.h b/fs/bcachefs/sb-errors_format.h
index 77e3fc92e39b..fbdb7b7df23e 100644
--- a/fs/bcachefs/sb-errors_format.h
+++ b/fs/bcachefs/sb-errors_format.h
@@ -74,6 +74,7 @@ enum bch_fsck_flags {
x(btree_root_bad_min_key, 60, 0) \
x(btree_root_bad_max_key, 61, 0) \
x(btree_node_read_error, 62, FSCK_AUTOFIX) \
+ x(btree_node_topology_gap_between_nodes, 328, FSCK_AUTOFIX) \
x(btree_node_topology_bad_min_key, 63, FSCK_AUTOFIX) \
x(btree_node_topology_bad_max_key, 64, FSCK_AUTOFIX) \
x(btree_node_topology_bad_root_min_key, 323, FSCK_AUTOFIX) \
@@ -339,7 +340,7 @@ enum bch_fsck_flags {
x(dirent_stray_data_after_cf_name, 305, 0) \
x(rebalance_work_incorrectly_set, 309, FSCK_AUTOFIX) \
x(rebalance_work_incorrectly_unset, 310, FSCK_AUTOFIX) \
- x(MAX, 328, 0)
+ x(MAX, 329, 0)
enum bch_sb_error_id {
#define x(t, n, ...) BCH_FSCK_ERR_##t = n,
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index 5cd308a68035..3038b5e6c1f0 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -564,15 +564,17 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early)
* successfully marked the filesystem dirty
*/
- ret = bch2_journal_reclaim_start(&c->journal);
- if (ret)
- goto err;
-
set_bit(BCH_FS_rw, &c->flags);
set_bit(BCH_FS_was_rw, &c->flags);
enumerated_ref_start(&c->writes);
+ ret = bch2_journal_reclaim_start(&c->journal);
+ if (ret) {
+ bch_err_msg(c, ret, "error starting journal reclaim thread");
+ goto err;
+ }
+
ret = bch2_copygc_start(c);
if (ret) {
bch_err_msg(c, ret, "error starting copygc thread");
@@ -852,7 +854,8 @@ int bch2_fs_init_rw(struct bch_fs *c)
bch2_fs_btree_write_buffer_init(c) ?:
bch2_fs_fs_io_buffered_init(c) ?:
bch2_fs_io_write_init(c) ?:
- bch2_fs_journal_init(&c->journal);
+ bch2_fs_journal_init(&c->journal) ?:
+ bch2_journal_reclaim_start(&c->journal);
if (ret)
return ret;