diff options
-rw-r--r-- | fs/bcachefs/backpointers.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/bcachefs_format.h | 6 | ||||
-rw-r--r-- | fs/bcachefs/dirent.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/fs-io-buffered.c | 16 | ||||
-rw-r--r-- | fs/bcachefs/fsck.c | 5 | ||||
-rw-r--r-- | fs/bcachefs/inode.c | 11 | ||||
-rw-r--r-- | fs/bcachefs/inode.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/inode_format.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/migrate.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/move.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/namei.c | 3 | ||||
-rw-r--r-- | fs/bcachefs/opts.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/snapshot.c | 3 | ||||
-rw-r--r-- | fs/bcachefs/snapshot.h | 15 | ||||
-rw-r--r-- | fs/bcachefs/str_hash.h | 14 | ||||
-rw-r--r-- | fs/bcachefs/super-io.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/xattr.c | 19 |
17 files changed, 87 insertions, 26 deletions
diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c index 45d3db41225a..c43aaab4c108 100644 --- a/fs/bcachefs/backpointers.c +++ b/fs/bcachefs/backpointers.c @@ -809,6 +809,8 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans, for (enum btree_id btree_id = 0; btree_id < btree_id_nr_alive(c); btree_id++) { + /* btree_type_has_ptrs should probably include BTREE_ID_stripes, + * definitely her... */ int level, depth = btree_type_has_ptrs(btree_id) ? 0 : 1; ret = commit_do(trans, NULL, NULL, diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h index 7a0b602c1b27..b2de993d802b 100644 --- a/fs/bcachefs/bcachefs_format.h +++ b/fs/bcachefs/bcachefs_format.h @@ -706,7 +706,8 @@ struct bch_sb_field_ext { x(snapshot_deletion_v2, BCH_VERSION(1, 26)) \ x(fast_device_removal, BCH_VERSION(1, 27)) \ x(inode_has_case_insensitive, BCH_VERSION(1, 28)) \ - x(extent_snapshot_whiteouts, BCH_VERSION(1, 29)) + x(extent_snapshot_whiteouts, BCH_VERSION(1, 29)) \ + x(31bit_dirent_offset, BCH_VERSION(1, 30)) enum bcachefs_metadata_version { bcachefs_metadata_version_min = 9, @@ -1378,7 +1379,8 @@ enum btree_id_flags { BIT_ULL(KEY_TYPE_alloc_v4)) \ x(quotas, 5, 0, \ BIT_ULL(KEY_TYPE_quota)) \ - x(stripes, 6, 0, \ + x(stripes, 6, \ + BTREE_IS_data, \ BIT_ULL(KEY_TYPE_stripe)) \ x(reflink, 7, \ BTREE_IS_extents| \ diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c index cb44b35e0f1d..fe6f3d874a47 100644 --- a/fs/bcachefs/dirent.c +++ b/fs/bcachefs/dirent.c @@ -95,7 +95,7 @@ static u64 bch2_dirent_hash(const struct bch_hash_info *info, bch2_str_hash_update(&ctx, info, name->name, name->len); /* [0,2) reserved for dots */ - return max_t(u64, bch2_str_hash_end(&ctx, info), 2); + return max_t(u64, bch2_str_hash_end(&ctx, info, true), 2); } static u64 dirent_hash_key(const struct bch_hash_info *info, const void *key) diff --git a/fs/bcachefs/fs-io-buffered.c b/fs/bcachefs/fs-io-buffered.c index 9f6f9f0f21ff..fd8beb5167ee 100644 --- a/fs/bcachefs/fs-io-buffered.c +++ b/fs/bcachefs/fs-io-buffered.c @@ -42,6 +42,14 @@ struct readpages_iter { folios folios; }; +static inline void readpages_iter_folio_revert(struct readahead_control *ractl, + struct folio *folio) +{ + bch2_folio_release(folio); + ractl->_nr_pages += folio_nr_pages(folio); + ractl->_index -= folio_nr_pages(folio); +} + static int readpages_iter_init(struct readpages_iter *iter, struct readahead_control *ractl) { @@ -52,9 +60,7 @@ static int readpages_iter_init(struct readpages_iter *iter, while ((folio = __readahead_folio(ractl))) { if (!bch2_folio_create(folio, GFP_KERNEL) || darray_push(&iter->folios, folio)) { - bch2_folio_release(folio); - ractl->_nr_pages += folio_nr_pages(folio); - ractl->_index -= folio_nr_pages(folio); + readpages_iter_folio_revert(ractl, folio); return iter->folios.nr ? 0 : -ENOMEM; } @@ -68,9 +74,7 @@ static void readpages_iter_exit(struct readpages_iter *iter, struct readahead_control *ractl) { darray_for_each_reverse(iter->folios, folio) { - bch2_folio_release(*folio); - ractl->_nr_pages += folio_nr_pages(*folio); - ractl->_index -= folio_nr_pages(*folio); + readpages_iter_folio_revert(ractl, *folio); folio_get(*folio); } } diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c index 01c1c6372229..ccc44b1fc178 100644 --- a/fs/bcachefs/fsck.c +++ b/fs/bcachefs/fsck.c @@ -266,7 +266,8 @@ create_lostfound: root_inode.bi_nlink++; - ret = bch2_inode_create(trans, &lostfound_iter, lostfound, snapshot, cpu); + ret = bch2_inode_create(trans, &lostfound_iter, lostfound, snapshot, cpu, + inode_opt_get(c, &root_inode, inodes_32bit)); if (ret) goto err; @@ -573,7 +574,7 @@ static int reconstruct_subvol(struct btree_trans *trans, u32 snapshotid, u32 sub new_inode.bi_subvol = subvolid; - int ret = bch2_inode_create(trans, &inode_iter, &new_inode, snapshotid, cpu) ?: + int ret = bch2_inode_create(trans, &inode_iter, &new_inode, snapshotid, cpu, false) ?: bch2_btree_iter_traverse(&inode_iter) ?: bch2_inode_write(trans, &inode_iter, &new_inode); bch2_trans_iter_exit(&inode_iter); diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c index d5e5190f0663..4aa130ff7cf6 100644 --- a/fs/bcachefs/inode.c +++ b/fs/bcachefs/inode.c @@ -944,11 +944,12 @@ void bch2_inode_init(struct bch_fs *c, struct bch_inode_unpacked *inode_u, } static struct bkey_i_inode_alloc_cursor * -bch2_inode_alloc_cursor_get(struct btree_trans *trans, u64 cpu, u64 *min, u64 *max) +bch2_inode_alloc_cursor_get(struct btree_trans *trans, u64 cpu, u64 *min, u64 *max, + bool is_32bit) { struct bch_fs *c = trans->c; - u64 cursor_idx = c->opts.inodes_32bit ? 0 : cpu + 1; + u64 cursor_idx = is_32bit ? 0 : cpu + 1; cursor_idx &= ~(~0ULL << c->opts.shard_inode_numbers_bits); @@ -967,7 +968,7 @@ bch2_inode_alloc_cursor_get(struct btree_trans *trans, u64 cpu, u64 *min, u64 *m if (IS_ERR(cursor)) return cursor; - if (c->opts.inodes_32bit) { + if (is_32bit) { *min = BLOCKDEV_INODE_MAX; *max = INT_MAX; } else { @@ -996,11 +997,11 @@ bch2_inode_alloc_cursor_get(struct btree_trans *trans, u64 cpu, u64 *min, u64 *m int bch2_inode_create(struct btree_trans *trans, struct btree_iter *iter, struct bch_inode_unpacked *inode_u, - u32 snapshot, u64 cpu) + u32 snapshot, u64 cpu, bool is_32bit) { u64 min, max; struct bkey_i_inode_alloc_cursor *cursor = - bch2_inode_alloc_cursor_get(trans, cpu, &min, &max); + bch2_inode_alloc_cursor_get(trans, cpu, &min, &max, is_32bit); int ret = PTR_ERR_OR_ZERO(cursor); if (ret) return ret; diff --git a/fs/bcachefs/inode.h b/fs/bcachefs/inode.h index b8ec3e628d90..79092ea74844 100644 --- a/fs/bcachefs/inode.h +++ b/fs/bcachefs/inode.h @@ -172,7 +172,7 @@ void bch2_inode_init(struct bch_fs *, struct bch_inode_unpacked *, struct bch_inode_unpacked *); int bch2_inode_create(struct btree_trans *, struct btree_iter *, - struct bch_inode_unpacked *, u32, u64); + struct bch_inode_unpacked *, u32, u64, bool); int bch2_inode_rm(struct bch_fs *, subvol_inum); diff --git a/fs/bcachefs/inode_format.h b/fs/bcachefs/inode_format.h index 1f00938b1bdc..e07fa6cc99bd 100644 --- a/fs/bcachefs/inode_format.h +++ b/fs/bcachefs/inode_format.h @@ -144,7 +144,8 @@ enum inode_opt_id { x(unlinked, 7) \ x(backptr_untrusted, 8) \ x(has_child_snapshot, 9) \ - x(has_case_insensitive, 10) + x(has_case_insensitive, 10) \ + x(31bit_dirent_offset, 11) /* bits 20+ reserved for packed fields below: */ diff --git a/fs/bcachefs/migrate.c b/fs/bcachefs/migrate.c index a66d01d04e57..892990b4a6a6 100644 --- a/fs/bcachefs/migrate.c +++ b/fs/bcachefs/migrate.c @@ -125,6 +125,10 @@ static int bch2_dev_usrdata_drop(struct bch_fs *c, if (!btree_type_has_ptrs(id)) continue; + /* Stripe keys have pointers, but are handled separately */ + if (id == BTREE_ID_stripes) + continue; + int ret = for_each_btree_key_commit(trans, iter, id, POS_MIN, BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k, NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({ diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c index df6833416855..4f41f1f6ec6c 100644 --- a/fs/bcachefs/move.c +++ b/fs/bcachefs/move.c @@ -819,7 +819,9 @@ static int bch2_move_data(struct bch_fs *c, unsigned min_depth_this_btree = min_depth; - if (!btree_type_has_ptrs(id)) + /* Stripe keys have pointers, but are handled separately */ + if (!btree_type_has_ptrs(id) || + id == BTREE_ID_stripes) min_depth_this_btree = max(min_depth_this_btree, 1); for (unsigned level = min_depth_this_btree; diff --git a/fs/bcachefs/namei.c b/fs/bcachefs/namei.c index d1019052f182..5c321a0d1f89 100644 --- a/fs/bcachefs/namei.c +++ b/fs/bcachefs/namei.c @@ -62,7 +62,8 @@ int bch2_create_trans(struct btree_trans *trans, if (flags & BCH_CREATE_TMPFILE) new_inode->bi_flags |= BCH_INODE_unlinked; - ret = bch2_inode_create(trans, &inode_iter, new_inode, snapshot, cpu); + ret = bch2_inode_create(trans, &inode_iter, new_inode, snapshot, cpu, + inode_opt_get(c, dir_u, inodes_32bit)); if (ret) goto err; diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h index 84ce69a7f131..03e22fb83d17 100644 --- a/fs/bcachefs/opts.h +++ b/fs/bcachefs/opts.h @@ -242,7 +242,7 @@ enum fsck_err_opts { x(inodes_32bit, u8, \ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \ OPT_BOOL(), \ - BCH_SB_INODE_32BIT, true, \ + BCH_SB_INODE_32BIT, false, \ NULL, "Constrain inode numbers to 32 bits") \ x(shard_inode_numbers_bits, u8, \ OPT_FS|OPT_FORMAT, \ diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c index 84f987d3a02a..eab0c1e3ff56 100644 --- a/fs/bcachefs/snapshot.c +++ b/fs/bcachefs/snapshot.c @@ -1673,7 +1673,8 @@ static int bch2_fix_child_of_deleted_snapshot(struct btree_trans *trans, return ret; darray_for_each(*deleted, i) - nr_deleted_ancestors += bch2_snapshot_is_ancestor(c, s->k.p.offset, i->id); + nr_deleted_ancestors += bch2_snapshots_same_tree(c, s->k.p.offset, i->id) && + bch2_snapshot_is_ancestor(c, s->k.p.offset, i->id); if (!nr_deleted_ancestors) return 0; diff --git a/fs/bcachefs/snapshot.h b/fs/bcachefs/snapshot.h index fef32a0118c4..28d9a29a1fd0 100644 --- a/fs/bcachefs/snapshot.h +++ b/fs/bcachefs/snapshot.h @@ -51,6 +51,17 @@ static inline u32 bch2_snapshot_tree(struct bch_fs *c, u32 id) return s ? s->tree : 0; } +static inline bool bch2_snapshots_same_tree(struct bch_fs *c, u32 id1, u32 id2) +{ + if (id1 == id2) + return true; + + guard(rcu)(); + const struct snapshot_t *s1 = snapshot_t(c, id1); + const struct snapshot_t *s2 = snapshot_t(c, id2); + return s1 && s2 && s1->tree == s2->tree; +} + static inline u32 __bch2_snapshot_parent_early(struct bch_fs *c, u32 id) { const struct snapshot_t *s = snapshot_t(c, id); @@ -157,6 +168,10 @@ bool __bch2_snapshot_is_ancestor(struct bch_fs *, u32, u32); static inline bool bch2_snapshot_is_ancestor(struct bch_fs *c, u32 id, u32 ancestor) { + EBUG_ON(!id); + EBUG_ON(!ancestor); + EBUG_ON(!bch2_snapshots_same_tree(c, id, ancestor)); + return id == ancestor ? true : __bch2_snapshot_is_ancestor(c, id, ancestor); diff --git a/fs/bcachefs/str_hash.h b/fs/bcachefs/str_hash.h index 8c0fb44929cc..2a61cc36ddbf 100644 --- a/fs/bcachefs/str_hash.h +++ b/fs/bcachefs/str_hash.h @@ -34,6 +34,7 @@ bch2_str_hash_opt_to_type(struct bch_fs *c, enum bch_str_hash_opts opt) struct bch_hash_info { u32 inum_snapshot; u8 type; + bool is_31bit; struct unicode_map *cf_encoding; /* * For crc32 or crc64 string hashes the first key value of @@ -48,6 +49,7 @@ bch2_hash_info_init(struct bch_fs *c, const struct bch_inode_unpacked *bi) struct bch_hash_info info = { .inum_snapshot = bi->bi_snapshot, .type = INODE_STR_HASH(bi), + .is_31bit = bi->bi_flags & BCH_INODE_31bit_dirent_offset, .cf_encoding = bch2_inode_casefold(c, bi) ? c->cf_encoding : NULL, .siphash_key = { .k0 = bi->bi_hash_seed } }; @@ -112,8 +114,8 @@ static inline void bch2_str_hash_update(struct bch_str_hash_ctx *ctx, } } -static inline u64 bch2_str_hash_end(struct bch_str_hash_ctx *ctx, - const struct bch_hash_info *info) +static inline u64 __bch2_str_hash_end(struct bch_str_hash_ctx *ctx, + const struct bch_hash_info *info) { switch (info->type) { case BCH_STR_HASH_crc32c: @@ -128,6 +130,14 @@ static inline u64 bch2_str_hash_end(struct bch_str_hash_ctx *ctx, } } +static inline u64 bch2_str_hash_end(struct bch_str_hash_ctx *ctx, + const struct bch_hash_info *info, + bool maybe_31bit) +{ + return __bch2_str_hash_end(ctx, info) & + (maybe_31bit && info->is_31bit ? INT_MAX : U64_MAX); +} + struct bch_hash_desc { enum btree_id btree_id; u8 key_type; diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index be7ed612d28f..369465a4de77 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -89,7 +89,7 @@ int bch2_set_version_incompat(struct bch_fs *c, enum bcachefs_metadata_version v prt_str(&buf, "requested incompat feature "); bch2_version_to_text(&buf, version); prt_str(&buf, " currently not enabled, allowed up to "); - bch2_version_to_text(&buf, version); + bch2_version_to_text(&buf, c->sb.version_incompat_allowed); prt_printf(&buf, "\n set version_upgrade=incompat to enable"); bch_notice(c, "%s", buf.buf); diff --git a/fs/bcachefs/xattr.c b/fs/bcachefs/xattr.c index 6094b568dd33..6d7303008b19 100644 --- a/fs/bcachefs/xattr.c +++ b/fs/bcachefs/xattr.c @@ -4,6 +4,7 @@ #include "acl.h" #include "bkey_methods.h" #include "btree_update.h" +#include "dirent.h" #include "extents.h" #include "fs.h" #include "rebalance.h" @@ -25,7 +26,7 @@ static u64 bch2_xattr_hash(const struct bch_hash_info *info, bch2_str_hash_update(&ctx, info, &key->type, sizeof(key->type)); bch2_str_hash_update(&ctx, info, key->name.name, key->name.len); - return bch2_str_hash_end(&ctx, info); + return bch2_str_hash_end(&ctx, info, false); } static u64 xattr_hash_key(const struct bch_hash_info *info, const void *key) @@ -484,6 +485,22 @@ static int inode_opt_set_fn(struct btree_trans *trans, return ret; } + if (s->id == Inode_opt_inodes_32bit && + !bch2_request_incompat_feature(trans->c, bcachefs_metadata_version_31bit_dirent_offset)) { + /* + * Make sure the dir is empty, as otherwise we'd need to + * rehash everything and update the dirent keys. + */ + int ret = bch2_empty_dir_trans(trans, inode_inum(inode)); + if (ret < 0) + return ret; + + if (s->defined) + bi->bi_flags |= BCH_INODE_31bit_dirent_offset; + else + bi->bi_flags &= ~BCH_INODE_31bit_dirent_offset; + } + if (s->defined) bi->bi_fields_set |= 1U << s->id; else |