diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/bcachefs.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/btree_gc.c | 6 | ||||
-rw-r--r-- | fs/bcachefs/btree_io.c | 1 | ||||
-rw-r--r-- | fs/bcachefs/disk_accounting.c | 7 | ||||
-rw-r--r-- | fs/bcachefs/errcode.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/inode.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/io_read.c | 13 | ||||
-rw-r--r-- | fs/bcachefs/journal_reclaim.c | 7 | ||||
-rw-r--r-- | fs/bcachefs/opts.c | 9 | ||||
-rw-r--r-- | fs/bcachefs/opts.h | 23 | ||||
-rw-r--r-- | fs/bcachefs/replicas_format.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/sb-errors_format.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 13 |
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; |