From: Kent Overstreet Date: Fri, 16 Feb 2024 04:45:29 +0000 (-0500) Subject: Update bcachefs sources to 9a555a741e80 bcachefs: omit alignment attribute on big... X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=e773e86495534ede8efc0f3059cf0939c374a925;p=bcachefs-tools-debian Update bcachefs sources to 9a555a741e80 bcachefs: omit alignment attribute on big endian struct bkey --- diff --git a/.bcachefs_revision b/.bcachefs_revision index e94031f..a0ce33c 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -39a84c99af2dbbd797eb2f0d1bed04111f04f245 +9a555a741e807275c320807babd3f42efb8fee90 diff --git a/include/linux/eytzinger.h b/include/linux/eytzinger.h index 9565a5c..1031501 100644 --- a/include/linux/eytzinger.h +++ b/include/linux/eytzinger.h @@ -277,7 +277,7 @@ static inline ssize_t eytzinger0_find_le(void *base, size_t nr, size_t size, int _res; \ \ while (_i < _nr && \ - (_res = _cmp(_search, _base + _i * _size, _size))) \ + (_res = _cmp(_search, _base + _i * _size))) \ _i = eytzinger0_child(_i, _res > 0); \ _i; \ }) diff --git a/libbcachefs/alloc_background.c b/libbcachefs/alloc_background.c index fd3e175..c7be6af 100644 --- a/libbcachefs/alloc_background.c +++ b/libbcachefs/alloc_background.c @@ -860,23 +860,28 @@ int bch2_trigger_alloc(struct btree_trans *trans, *bucket_gen(ca, new.k->p.offset) = new_a->gen; bch2_dev_usage_update(c, ca, old_a, new_a, journal_seq, false); + percpu_up_read(&c->mark_lock); + +#define eval_state(_a, expr) ({ const struct bch_alloc_v4 *a = _a; expr; }) +#define statechange(expr) !eval_state(old_a, expr) && eval_state(new_a, expr) +#define bucket_flushed(a) (!a->journal_seq || a->journal_seq <= c->journal.flushed_seq_ondisk) - if (new_a->data_type == BCH_DATA_free && - (!new_a->journal_seq || new_a->journal_seq < c->journal.flushed_seq_ondisk)) + if (statechange(a->data_type == BCH_DATA_free && + bucket_flushed(a))) closure_wake_up(&c->freelist_wait); - if (new_a->data_type == BCH_DATA_need_discard && - (!bucket_journal_seq || bucket_journal_seq < c->journal.flushed_seq_ondisk)) + if (statechange(a->data_type == BCH_DATA_need_discard && + bucket_flushed(a)) && + !bch2_bucket_is_open(c, new.k->p.inode, new.k->p.offset)) bch2_do_discards(c); - if (old_a->data_type != BCH_DATA_cached && - new_a->data_type == BCH_DATA_cached && + if (statechange(a->data_type == BCH_DATA_cached) && + !bch2_bucket_is_open(c, new.k->p.inode, new.k->p.offset) && should_invalidate_buckets(ca, bch2_dev_usage_read(ca))) bch2_do_invalidates(c); - if (new_a->data_type == BCH_DATA_need_gc_gens) + if (statechange(a->data_type == BCH_DATA_need_gc_gens)) bch2_do_gc_gens(c); - percpu_up_read(&c->mark_lock); } if ((flags & BTREE_TRIGGER_GC) && diff --git a/libbcachefs/bcachefs.h b/libbcachefs/bcachefs.h index 3b48c5e..4d04e9c 100644 --- a/libbcachefs/bcachefs.h +++ b/libbcachefs/bcachefs.h @@ -267,6 +267,9 @@ do { \ #define bch2_fmt(_c, fmt) bch2_log_msg(_c, fmt "\n") +__printf(2, 3) +void bch2_print_opts(struct bch_opts *, const char *, ...); + __printf(2, 3) void __bch2_print(struct bch_fs *c, const char *fmt, ...); diff --git a/libbcachefs/bcachefs_format.h b/libbcachefs/bcachefs_format.h index 20604e2..8aa5241 100644 --- a/libbcachefs/bcachefs_format.h +++ b/libbcachefs/bcachefs_format.h @@ -222,7 +222,36 @@ struct bkey { __u8 pad[1]; #endif -} __packed __aligned(8); +} __packed +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +/* + * The big-endian version of bkey can't be compiled by rustc with the "aligned" + * attr since it doesn't allow types to have both "packed" and "aligned" attrs. + * So for Rust compatibility, don't include this. It can be included in the LE + * version because the "packed" attr is redundant in that case. + * + * History: (quoting Kent) + * + * Specifically, when i was designing bkey, I wanted the header to be no + * bigger than necessary so that bkey_packed could use the rest. That means that + * decently offten extent keys will fit into only 8 bytes, instead of spilling over + * to 16. + * + * But packed_bkey treats the part after the header - the packed section - + * as a single multi word, variable length integer. And bkey, the unpacked + * version, is just a special case version of a bkey_packed; all the packed + * bkey code will work on keys in any packed format, the in-memory + * representation of an unpacked key also is just one type of packed key... + * + * So that constrains the key part of a bkig endian bkey to start right + * after the header. + * + * If we ever do a bkey_v2 and need to expand the hedaer by another byte for + * some reason - that will clean up this wart. + */ +__aligned(8) +#endif +; struct bkey_packed { __u64 _data[0]; @@ -1426,17 +1455,14 @@ LE32_BITMASK(JSET_NO_FLUSH, struct jset, flags, 5, 6); /* Btree: */ enum btree_id_flags { - /* key size field is nonzero, btree iterators handle as ranges */ - BTREE_ID_EXTENTS = BIT(0), - BTREE_ID_SNAPSHOTS = BIT(1), - BTREE_ID_SNAPSHOT_FIELD = BIT(2), - BTREE_ID_SNAPSHOTS_UNREFFED = BIT(3), - BTREE_ID_DATA = BIT(3), + BTREE_ID_EXTENTS = BIT(0), + BTREE_ID_SNAPSHOTS = BIT(1), + BTREE_ID_SNAPSHOT_FIELD = BIT(2), + BTREE_ID_DATA = BIT(3), }; #define BCH_BTREE_IDS() \ - x(extents, 0, BTREE_ID_EXTENTS|BTREE_ID_SNAPSHOTS| \ - BTREE_ID_SNAPSHOTS_UNREFFED|BTREE_ID_DATA,\ + x(extents, 0, BTREE_ID_EXTENTS|BTREE_ID_SNAPSHOTS|BTREE_ID_DATA,\ BIT_ULL(KEY_TYPE_whiteout)| \ BIT_ULL(KEY_TYPE_error)| \ BIT_ULL(KEY_TYPE_cookie)| \ @@ -1454,7 +1480,7 @@ enum btree_id_flags { BIT_ULL(KEY_TYPE_whiteout)| \ BIT_ULL(KEY_TYPE_hash_whiteout)| \ BIT_ULL(KEY_TYPE_dirent)) \ - x(xattrs, 3, BTREE_ID_SNAPSHOTS|BTREE_ID_SNAPSHOTS_UNREFFED,\ + x(xattrs, 3, BTREE_ID_SNAPSHOTS, \ BIT_ULL(KEY_TYPE_whiteout)| \ BIT_ULL(KEY_TYPE_cookie)| \ BIT_ULL(KEY_TYPE_hash_whiteout)| \ diff --git a/libbcachefs/bkey_methods.h b/libbcachefs/bkey_methods.h index f8217b2..03efe8e 100644 --- a/libbcachefs/bkey_methods.h +++ b/libbcachefs/bkey_methods.h @@ -78,7 +78,6 @@ bool bch2_bkey_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c); enum btree_update_flags { __BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE = __BTREE_ITER_FLAGS_END, - __BTREE_UPDATE_SNAPSHOT_WHITEOUT_CHECKS_DONE, __BTREE_UPDATE_NOJOURNAL, __BTREE_UPDATE_KEY_CACHE_RECLAIM, @@ -92,8 +91,6 @@ enum btree_update_flags { }; #define BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE (1U << __BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE) -#define BTREE_UPDATE_SNAPSHOT_WHITEOUT_CHECKS_DONE \ - (1U << __BTREE_UPDATE_SNAPSHOT_WHITEOUT_CHECKS_DONE) #define BTREE_UPDATE_NOJOURNAL (1U << __BTREE_UPDATE_NOJOURNAL) #define BTREE_UPDATE_KEY_CACHE_RECLAIM (1U << __BTREE_UPDATE_KEY_CACHE_RECLAIM) diff --git a/libbcachefs/btree_iter.c b/libbcachefs/btree_iter.c index 07b1de5..20b32c7 100644 --- a/libbcachefs/btree_iter.c +++ b/libbcachefs/btree_iter.c @@ -1520,7 +1520,7 @@ static noinline void btree_paths_realloc(struct btree_trans *trans) { unsigned nr = trans->nr_paths * 2; - void *p = kzalloc(BITS_TO_LONGS(nr) * sizeof(unsigned long) + + void *p = kvzalloc(BITS_TO_LONGS(nr) * sizeof(unsigned long) + sizeof(struct btree_trans_paths) + nr * sizeof(struct btree_path) + nr * sizeof(btree_path_idx_t) + 8 + @@ -3087,7 +3087,7 @@ void bch2_trans_put(struct btree_trans *trans) trans->paths = NULL; if (paths_allocated != trans->_paths_allocated) - kfree_rcu_mightsleep(paths_allocated); + kvfree_rcu_mightsleep(paths_allocated); if (trans->mem_bytes == BTREE_TRANS_MEM_MAX) mempool_free(trans->mem, &c->btree_trans_mem_pool); diff --git a/libbcachefs/btree_types.h b/libbcachefs/btree_types.h index 0791531..b2ebf14 100644 --- a/libbcachefs/btree_types.h +++ b/libbcachefs/btree_types.h @@ -705,17 +705,6 @@ static inline bool btree_type_has_snapshots(enum btree_id id) return (1U << id) & mask; } -static inline bool btree_type_snapshots_unreffed(enum btree_id id) -{ - const unsigned mask = 0 -#define x(name, nr, flags, ...) |((!!((flags) & BTREE_ID_SNAPSHOTS_UNREFFED)) << nr) - BCH_BTREE_IDS() -#undef x - ; - - return (1U << id) & mask; -} - static inline bool btree_type_has_snapshot_field(enum btree_id id) { const unsigned mask = 0 diff --git a/libbcachefs/btree_update.c b/libbcachefs/btree_update.c index ac85231..cbb7cf2 100644 --- a/libbcachefs/btree_update.c +++ b/libbcachefs/btree_update.c @@ -82,168 +82,38 @@ static noinline int extent_back_merge(struct btree_trans *trans, return 0; } -static struct bkey_s_c peek_slot_including_whiteouts(struct btree_trans *trans, struct btree_iter *iter, - enum btree_id btree, struct bpos pos) -{ - struct bkey_s_c k; - int ret; - - for_each_btree_key_norestart(trans, *iter, btree, pos, - BTREE_ITER_ALL_SNAPSHOTS| - BTREE_ITER_NOPRESERVE, k, ret) { - if (!bkey_eq(k.k->p, pos)) - break; - if (bch2_snapshot_is_ancestor(trans->c, pos.snapshot, k.k->p.snapshot)) - return k; - } - bch2_trans_iter_exit(trans, iter); - - return ret ? bkey_s_c_err(ret) : bkey_s_c_null; -} - /* * When deleting, check if we need to emit a whiteout (because we're overwriting * something in an ancestor snapshot) */ -static int need_whiteout_for_snapshot(struct btree_trans *trans, enum btree_id btree, struct bpos pos) -{ - pos.snapshot = bch2_snapshot_parent(trans->c, pos.snapshot); - if (!pos.snapshot) - return 0; - - struct btree_iter iter; - struct bkey_s_c k = peek_slot_including_whiteouts(trans, &iter, btree, pos); - int ret = bkey_err(k) ?: k.k && !bkey_whiteout(k.k); - bch2_trans_iter_exit(trans, &iter); - - return ret; -} - -/* - * We're overwriting a key at @pos in snapshot @snapshot, so we need to insert a - * whiteout: that might be in @snapshot, or if there are overwites in sibling - * snapshots, find the common ancestor where @pos is overwritten in every - * descendent and insert the whiteout there - which might be at @pos. - */ -static int delete_interior_snapshot_key(struct btree_trans *trans, - enum btree_id btree, - struct bpos whiteout, bool deleting, - struct bpos overwrite, bool old_is_whiteout) +static int need_whiteout_for_snapshot(struct btree_trans *trans, + enum btree_id btree_id, struct bpos pos) { - struct bch_fs *c = trans->c; - struct bpos orig_whiteout = whiteout, sib = whiteout; struct btree_iter iter; struct bkey_s_c k; + u32 snapshot = pos.snapshot; int ret; - sib.snapshot = bch2_snapshot_sibling(c, sib.snapshot); + if (!bch2_snapshot_parent(trans->c, pos.snapshot)) + return 0; - for_each_btree_key_norestart(trans, iter, btree, sib, - BTREE_ITER_ALL_SNAPSHOTS|BTREE_ITER_INTENT, k, ret) { - BUG_ON(bpos_gt(k.k->p, overwrite)); + pos.snapshot++; - if (bpos_lt(k.k->p, sib)) /* unrelated branch - skip */ - continue; - if (bpos_gt(k.k->p, sib)) /* did not find @sib */ + for_each_btree_key_norestart(trans, iter, btree_id, pos, + BTREE_ITER_ALL_SNAPSHOTS| + BTREE_ITER_NOPRESERVE, k, ret) { + if (!bkey_eq(k.k->p, pos)) break; - /* @overwrite is also written in @sib, now check parent */ - whiteout.snapshot = bch2_snapshot_parent(c, whiteout.snapshot); - if (bpos_eq(whiteout, overwrite)) + if (bch2_snapshot_is_ancestor(trans->c, snapshot, + k.k->p.snapshot)) { + ret = !bkey_whiteout(k.k); break; - - sib = whiteout; - sib.snapshot = bch2_snapshot_sibling(c, sib.snapshot); - } - - if (ret) - goto err; - - if (!deleting && bpos_eq(whiteout, orig_whiteout)) - goto out; - - if (!bpos_eq(iter.pos, whiteout)) { - bch2_trans_iter_exit(trans, &iter); - bch2_trans_iter_init(trans, &iter, btree, whiteout, BTREE_ITER_INTENT); - k = bch2_btree_iter_peek_slot(&iter); - ret = bkey_err(k); - if (ret) - goto err; - } - - iter.flags &= ~BTREE_ITER_ALL_SNAPSHOTS; - iter.flags |= BTREE_ITER_FILTER_SNAPSHOTS; - - struct bkey_i *delete = bch2_trans_kmalloc(trans, sizeof(*delete)); - ret = PTR_ERR_OR_ZERO(delete); - if (ret) - goto err; - - bkey_init(&delete->k); - delete->k.p = whiteout; - - ret = !bpos_eq(whiteout, overwrite) - ? !old_is_whiteout - : need_whiteout_for_snapshot(trans, btree, whiteout); - if (ret < 0) - goto err; - if (ret) - delete->k.type = KEY_TYPE_whiteout; - - ret = bch2_trans_update(trans, &iter, delete, - BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE| - BTREE_UPDATE_SNAPSHOT_WHITEOUT_CHECKS_DONE); -out: -err: - bch2_trans_iter_exit(trans, &iter); - return ret; -} - -/* - * We're overwriting a key in a snapshot that has ancestors: if we're - * overwriting a key in a different snapshot, we need to check if it is now - * fully overritten and can be deleted, and if we're deleting a key in the - * current snapshot we need to check if we need to leave a whiteout. - */ -static noinline int -overwrite_interior_snapshot_key(struct btree_trans *trans, - struct btree_iter *iter, - struct bkey_i *k) -{ - struct bkey_s_c old = bch2_btree_iter_peek_slot(iter); - - int ret = bkey_err(old); - if (ret) - return ret; - - if (!bkey_deleted(old.k)) { - if (btree_type_snapshots_unreffed(iter->btree_id) && - old.k->p.snapshot != k->k.p.snapshot) { - /* - * We're overwriting a key in a different snapshot: - * check if it's also been overwritten in siblings - */ - ret = delete_interior_snapshot_key(trans, iter->btree_id, - k->k.p, bkey_deleted(&k->k), - old.k->p, bkey_whiteout(old.k)); - if (ret) - return ret; - if (bkey_deleted(&k->k)) - return 1; - } else if (bkey_deleted(&k->k)) { - /* - * We're deleting a key in the current snapshot: - * check if we need to leave a whiteout - */ - ret = need_whiteout_for_snapshot(trans, iter->btree_id, k->k.p); - if (unlikely(ret < 0)) - return ret; - if (ret) - k->k.type = KEY_TYPE_whiteout; } } + bch2_trans_iter_exit(trans, &iter); - return 0; + return ret; } int __bch2_insert_snapshot_whiteouts(struct btree_trans *trans, @@ -633,29 +503,32 @@ static noinline int bch2_trans_update_get_key_cache(struct btree_trans *trans, int __must_check bch2_trans_update(struct btree_trans *trans, struct btree_iter *iter, struct bkey_i *k, enum btree_update_flags flags) { + btree_path_idx_t path_idx = iter->update_path ?: iter->path; + int ret; + if (iter->flags & BTREE_ITER_IS_EXTENTS) return bch2_trans_update_extent(trans, iter, k, flags); - if (!(flags & (BTREE_UPDATE_SNAPSHOT_WHITEOUT_CHECKS_DONE| - BTREE_UPDATE_KEY_CACHE_RECLAIM)) && - (iter->flags & BTREE_ITER_FILTER_SNAPSHOTS) && - bch2_snapshot_parent(trans->c, k->k.p.snapshot)) { - int ret = overwrite_interior_snapshot_key(trans, iter, k); + if (bkey_deleted(&k->k) && + !(flags & BTREE_UPDATE_KEY_CACHE_RECLAIM) && + (iter->flags & BTREE_ITER_FILTER_SNAPSHOTS)) { + ret = need_whiteout_for_snapshot(trans, iter->btree_id, k->k.p); + if (unlikely(ret < 0)) + return ret; + if (ret) - return ret < 0 ? ret : 0; + k->k.type = KEY_TYPE_whiteout; } /* * Ensure that updates to cached btrees go to the key cache: */ - btree_path_idx_t path_idx = iter->update_path ?: iter->path; struct btree_path *path = trans->paths + path_idx; - if (!(flags & BTREE_UPDATE_KEY_CACHE_RECLAIM) && !path->cached && !path->level && btree_id_cached(trans->c, path->btree_id)) { - int ret = bch2_trans_update_get_key_cache(trans, iter, path); + ret = bch2_trans_update_get_key_cache(trans, iter, path); if (ret) return ret; diff --git a/libbcachefs/chardev.c b/libbcachefs/chardev.c index 4cbda66..a2f30f4 100644 --- a/libbcachefs/chardev.c +++ b/libbcachefs/chardev.c @@ -165,6 +165,11 @@ static void bch2_fsck_offline_thread_fn(struct thread_with_stdio *stdio) bch2_fs_stop(c); } +static const struct thread_with_stdio_ops bch2_offline_fsck_ops = { + .exit = bch2_fsck_thread_exit, + .fn = bch2_fsck_offline_thread_fn, +}; + static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_arg) { struct bch_ioctl_fsck_offline arg; @@ -217,9 +222,7 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a opt_set(thr->opts, stdio, (u64)(unsigned long)&thr->thr.stdio); - ret = run_thread_with_stdio(&thr->thr, - bch2_fsck_thread_exit, - bch2_fsck_offline_thread_fn); + ret = run_thread_with_stdio(&thr->thr, &bch2_offline_fsck_ops); err: if (ret < 0) { if (thr) @@ -794,6 +797,11 @@ static void bch2_fsck_online_thread_fn(struct thread_with_stdio *stdio) bch2_ro_ref_put(c); } +static const struct thread_with_stdio_ops bch2_online_fsck_ops = { + .exit = bch2_fsck_thread_exit, + .fn = bch2_fsck_online_thread_fn, +}; + static long bch2_ioctl_fsck_online(struct bch_fs *c, struct bch_ioctl_fsck_online arg) { @@ -834,9 +842,7 @@ static long bch2_ioctl_fsck_online(struct bch_fs *c, goto err; } - ret = run_thread_with_stdio(&thr->thr, - bch2_fsck_thread_exit, - bch2_fsck_online_thread_fn); + ret = run_thread_with_stdio(&thr->thr, &bch2_online_fsck_ops); err: if (ret < 0) { bch_err_fn(c, ret); diff --git a/libbcachefs/dirent.c b/libbcachefs/dirent.c index b5ee11b..d37bd07 100644 --- a/libbcachefs/dirent.c +++ b/libbcachefs/dirent.c @@ -512,7 +512,7 @@ u64 bch2_dirent_lookup(struct bch_fs *c, subvol_inum dir, return ret; } -int bch2_empty_dir_snapshot(struct btree_trans *trans, u64 dir, u32 snapshot) +int bch2_empty_dir_snapshot(struct btree_trans *trans, u64 dir, u32 subvol, u32 snapshot) { struct btree_iter iter; struct bkey_s_c k; @@ -522,6 +522,9 @@ int bch2_empty_dir_snapshot(struct btree_trans *trans, u64 dir, u32 snapshot) SPOS(dir, 0, snapshot), POS(dir, U64_MAX), 0, k, ret) if (k.k->type == KEY_TYPE_dirent) { + struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k); + if (d.v->d_type == DT_SUBVOL && le32_to_cpu(d.v->d_parent_subvol) != subvol) + continue; ret = -BCH_ERR_ENOTEMPTY_dir_not_empty; break; } @@ -535,7 +538,7 @@ int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir) u32 snapshot; return bch2_subvolume_get_snapshot(trans, dir.subvol, &snapshot) ?: - bch2_empty_dir_snapshot(trans, dir.inum, snapshot); + bch2_empty_dir_snapshot(trans, dir.inum, dir.subvol, snapshot); } int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx) diff --git a/libbcachefs/dirent.h b/libbcachefs/dirent.h index 34cb8e1..bee55cc 100644 --- a/libbcachefs/dirent.h +++ b/libbcachefs/dirent.h @@ -69,7 +69,7 @@ u64 bch2_dirent_lookup(struct bch_fs *, subvol_inum, const struct bch_hash_info *, const struct qstr *, subvol_inum *); -int bch2_empty_dir_snapshot(struct btree_trans *, u64, u32); +int bch2_empty_dir_snapshot(struct btree_trans *, u64, u32, u32); int bch2_empty_dir_trans(struct btree_trans *, subvol_inum); int bch2_readdir(struct bch_fs *, subvol_inum, struct dir_context *); diff --git a/libbcachefs/fs-common.c b/libbcachefs/fs-common.c index 255857c..624e6f9 100644 --- a/libbcachefs/fs-common.c +++ b/libbcachefs/fs-common.c @@ -486,10 +486,10 @@ int bch2_rename_trans(struct btree_trans *trans, goto err; } - if (S_ISDIR(dst_inode_u->bi_mode) && - bch2_empty_dir_trans(trans, dst_inum)) { - ret = -ENOTEMPTY; - goto err; + if (S_ISDIR(dst_inode_u->bi_mode)) { + ret = bch2_empty_dir_trans(trans, dst_inum); + if (ret) + goto err; } } diff --git a/libbcachefs/fs-io-direct.c b/libbcachefs/fs-io-direct.c index e3b219e..33cb6da 100644 --- a/libbcachefs/fs-io-direct.c +++ b/libbcachefs/fs-io-direct.c @@ -88,6 +88,8 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter) return ret; shorten = iov_iter_count(iter) - round_up(ret, block_bytes(c)); + if (shorten >= iter->count) + shorten = 0; iter->count -= shorten; bio = bio_alloc_bioset(NULL, diff --git a/libbcachefs/inode.c b/libbcachefs/inode.c index 414aebe..a3139bb 100644 --- a/libbcachefs/inode.c +++ b/libbcachefs/inode.c @@ -1117,8 +1117,9 @@ static int may_delete_deleted_inode(struct btree_trans *trans, goto out; if (S_ISDIR(inode.bi_mode)) { - ret = bch2_empty_dir_snapshot(trans, pos.offset, pos.snapshot); - if (fsck_err_on(ret == -ENOTEMPTY, c, deleted_inode_is_dir, + ret = bch2_empty_dir_snapshot(trans, pos.offset, 0, pos.snapshot); + if (fsck_err_on(bch2_err_matches(ret, ENOTEMPTY), + c, deleted_inode_is_dir, "non empty directory %llu:%u in deleted_inodes btree", pos.offset, pos.snapshot)) goto delete; diff --git a/libbcachefs/journal_io.c b/libbcachefs/journal_io.c index 057e7c6..16c1249 100644 --- a/libbcachefs/journal_io.c +++ b/libbcachefs/journal_io.c @@ -1506,8 +1506,8 @@ static int journal_write_alloc(struct journal *j, struct journal_buf *w) c->opts.foreground_target; unsigned i, replicas = 0, replicas_want = READ_ONCE(c->opts.metadata_replicas); - unsigned replicas_need = min(replicas_want, - READ_ONCE(c->opts.metadata_replicas_required)); + unsigned replicas_need = min_t(unsigned, replicas_want, + READ_ONCE(c->opts.metadata_replicas_required)); rcu_read_lock(); retry: diff --git a/libbcachefs/printbuf.c b/libbcachefs/printbuf.c index accf246..b27d229 100644 --- a/libbcachefs/printbuf.c +++ b/libbcachefs/printbuf.c @@ -56,6 +56,7 @@ void bch2_prt_vprintf(struct printbuf *out, const char *fmt, va_list args) va_copy(args2, args); len = vsnprintf(out->buf + out->pos, printbuf_remaining(out), fmt, args2); + va_end(args2); } while (len + 1 >= printbuf_remaining(out) && !bch2_printbuf_make_room(out, len + 1)); diff --git a/libbcachefs/recovery.c b/libbcachefs/recovery.c index 4f8782d..c584945 100644 --- a/libbcachefs/recovery.c +++ b/libbcachefs/recovery.c @@ -577,8 +577,9 @@ u64 bch2_recovery_passes_from_stable(u64 v) static bool check_version_upgrade(struct bch_fs *c) { - unsigned latest_compatible = bch2_latest_compatible_version(c->sb.version); unsigned latest_version = bcachefs_metadata_version_current; + unsigned latest_compatible = min(latest_version, + bch2_latest_compatible_version(c->sb.version)); unsigned old_version = c->sb.version_upgrade_complete ?: c->sb.version; unsigned new_version = 0; @@ -597,7 +598,7 @@ static bool check_version_upgrade(struct bch_fs *c) new_version = latest_version; break; case BCH_VERSION_UPGRADE_none: - new_version = old_version; + new_version = min(old_version, latest_version); break; } } @@ -774,7 +775,7 @@ int bch2_fs_recovery(struct bch_fs *c) goto err; } - if (!(c->opts.nochanges && c->opts.norecovery)) { + if (!c->opts.nochanges) { mutex_lock(&c->sb_lock); bool write_sb = false; @@ -804,7 +805,7 @@ int bch2_fs_recovery(struct bch_fs *c) if (bch2_check_version_downgrade(c)) { struct printbuf buf = PRINTBUF; - prt_str(&buf, "Version downgrade required:\n"); + prt_str(&buf, "Version downgrade required:"); __le64 passes = ext->recovery_passes_required[0]; bch2_sb_set_downgrade(c, @@ -812,7 +813,7 @@ int bch2_fs_recovery(struct bch_fs *c) BCH_VERSION_MINOR(c->sb.version)); passes = ext->recovery_passes_required[0] & ~passes; if (passes) { - prt_str(&buf, " running recovery passes: "); + prt_str(&buf, "\n running recovery passes: "); prt_bitflags(&buf, bch2_recovery_passes, bch2_recovery_passes_from_stable(le64_to_cpu(passes))); } diff --git a/libbcachefs/replicas.c b/libbcachefs/replicas.c index 75fdce3..678b9c2 100644 --- a/libbcachefs/replicas.c +++ b/libbcachefs/replicas.c @@ -232,7 +232,7 @@ static inline int __replicas_entry_idx(struct bch_replicas_cpu *r, verify_replicas_entry(search); -#define entry_cmp(_l, _r, size) memcmp(_l, _r, entry_size) +#define entry_cmp(_l, _r) memcmp(_l, _r, entry_size) idx = eytzinger0_find(r->entries, r->nr, r->entry_size, entry_cmp, search); #undef entry_cmp diff --git a/libbcachefs/super-io.c b/libbcachefs/super-io.c index 36988ad..a3a9e85 100644 --- a/libbcachefs/super-io.c +++ b/libbcachefs/super-io.c @@ -717,6 +717,7 @@ retry: if (IS_ERR(sb->bdev_handle)) { ret = PTR_ERR(sb->bdev_handle); + prt_printf(&err, "error opening %s: %s", path, bch2_err_str(ret)); goto err; } sb->bdev = sb->bdev_handle->bdev; @@ -743,9 +744,9 @@ retry: prt_printf(&err2, "bcachefs (%s): error reading default superblock: %s\n", path, err.buf); if (ret == -BCH_ERR_invalid_sb_magic && ignore_notbchfs_msg) - printk(KERN_INFO "%s", err2.buf); + bch2_print_opts(opts, KERN_INFO "%s", err2.buf); else - printk(KERN_ERR "%s", err2.buf); + bch2_print_opts(opts, KERN_ERR "%s", err2.buf); printbuf_exit(&err2); printbuf_reset(&err); @@ -808,16 +809,16 @@ got_super: ret = bch2_sb_validate(sb, &err, READ); if (ret) { - printk(KERN_ERR "bcachefs (%s): error validating superblock: %s\n", - path, err.buf); + bch2_print_opts(opts, KERN_ERR "bcachefs (%s): error validating superblock: %s\n", + path, err.buf); goto err_no_print; } out: printbuf_exit(&err); return ret; err: - printk(KERN_ERR "bcachefs (%s): error reading superblock: %s\n", - path, err.buf); + bch2_print_opts(opts, KERN_ERR "bcachefs (%s): error reading superblock: %s\n", + path, err.buf); err_no_print: bch2_free_super(sb); goto out; diff --git a/libbcachefs/super.c b/libbcachefs/super.c index 8c6caeb..a7f9de2 100644 --- a/libbcachefs/super.c +++ b/libbcachefs/super.c @@ -87,6 +87,23 @@ const char * const bch2_fs_flag_strs[] = { NULL }; +void bch2_print_opts(struct bch_opts *opts, const char *fmt, ...) +{ + struct stdio_redirect *stdio = (void *)(unsigned long)opts->stdio; + + va_list args; + va_start(args, fmt); + if (likely(!stdio)) { + vprintk(fmt, args); + } else { + if (fmt[0] == KERN_SOH[0]) + fmt += 2; + + stdio_redirect_vprintf(stdio, true, fmt, args); + } + va_end(args); +} + void __bch2_print(struct bch_fs *c, const char *fmt, ...) { struct stdio_redirect *stdio = bch2_fs_stdio_redirect(c); @@ -1592,27 +1609,27 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags) __bch2_dev_read_only(c, ca); ret = bch2_dev_data_drop(c, ca->dev_idx, flags); - bch_err_msg(ca, ret, "dropping data"); + bch_err_msg(ca, ret, "bch2_dev_data_drop()"); if (ret) goto err; ret = bch2_dev_remove_alloc(c, ca); - bch_err_msg(ca, ret, "deleting alloc info"); + bch_err_msg(ca, ret, "bch2_dev_remove_alloc()"); if (ret) goto err; ret = bch2_journal_flush_device_pins(&c->journal, ca->dev_idx); - bch_err_msg(ca, ret, "flushing journal"); + bch_err_msg(ca, ret, "bch2_journal_flush_device_pins()"); if (ret) goto err; ret = bch2_journal_flush(&c->journal); - bch_err(ca, "journal error"); + bch_err_msg(ca, ret, "bch2_journal_flush()"); if (ret) goto err; ret = bch2_replicas_gc2(c); - bch_err_msg(ca, ret, "in replicas_gc2()"); + bch_err_msg(ca, ret, "bch2_replicas_gc2()"); if (ret) goto err;