X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libbcachefs%2Finode.c;h=992dcfed0518dd658737ccafaf4f396f3ad4ae6e;hb=46b2c553aa462cf2c25b1fe017c164c2da471a98;hp=ffce68a80490657461643e89f21fd72e96b78f85;hpb=837b76ce9507fa2a69ddeecc1e1b6d3fabb08227;p=bcachefs-tools-debian diff --git a/libbcachefs/inode.c b/libbcachefs/inode.c index ffce68a..992dcfe 100644 --- a/libbcachefs/inode.c +++ b/libbcachefs/inode.c @@ -4,6 +4,7 @@ #include "btree_key_cache.h" #include "bkey_methods.h" #include "btree_update.h" +#include "buckets.h" #include "error.h" #include "extents.h" #include "extent_update.h" @@ -24,16 +25,6 @@ const char * const bch2_inode_opts[] = { }; static const u8 byte_table[8] = { 1, 2, 3, 4, 6, 8, 10, 13 }; -static const u8 bits_table[8] = { - 1 * 8 - 1, - 2 * 8 - 2, - 3 * 8 - 3, - 4 * 8 - 4, - 6 * 8 - 5, - 8 * 8 - 6, - 10 * 8 - 7, - 13 * 8 - 8, -}; static int inode_decode_field(const u8 *in, const u8 *end, u64 out[2], unsigned *out_bits) @@ -150,9 +141,9 @@ static noinline int bch2_inode_unpack_v1(struct bkey_s_c_inode inode, #define x(_name, _bits) \ if (fieldnr++ == INODE_NR_FIELDS(inode.v)) { \ - memset(&unpacked->_name, 0, \ - sizeof(*unpacked) - \ - offsetof(struct bch_inode_unpacked, _name)); \ + unsigned offset = offsetof(struct bch_inode_unpacked, _name);\ + memset((void *) unpacked + offset, 0, \ + sizeof(*unpacked) - offset); \ return 0; \ } \ \ @@ -261,15 +252,13 @@ int bch2_inode_peek(struct btree_trans *trans, u32 snapshot; int ret; - if (0 && trans->c->opts.inodes_use_key_cache) - flags |= BTREE_ITER_CACHED; - ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot); if (ret) return ret; bch2_trans_iter_init(trans, iter, BTREE_ID_inodes, - SPOS(0, inum.inum, snapshot), flags); + SPOS(0, inum.inum, snapshot), + flags|BTREE_ITER_CACHED); k = bch2_btree_iter_peek_slot(iter); ret = bkey_err(k); if (ret) @@ -304,76 +293,89 @@ int bch2_inode_write(struct btree_trans *trans, return bch2_trans_update(trans, iter, &inode_p->inode.k_i, 0); } -const char *bch2_inode_invalid(const struct bch_fs *c, struct bkey_s_c k) +static int __bch2_inode_invalid(struct bkey_s_c k, struct printbuf *err) { - struct bkey_s_c_inode inode = bkey_s_c_to_inode(k); struct bch_inode_unpacked unpacked; - if (k.k->p.inode) - return "nonzero k.p.inode"; - - if (bkey_val_bytes(k.k) < sizeof(struct bch_inode)) - return "incorrect value size"; - - if (k.k->p.offset < BLOCKDEV_INODE_MAX) - return "fs inode in blockdev range"; + if (k.k->p.inode) { + pr_buf(err, "nonzero k.p.inode"); + return -EINVAL; + } - if (INODE_STR_HASH(inode.v) >= BCH_STR_HASH_NR) - return "invalid str hash type"; + if (k.k->p.offset < BLOCKDEV_INODE_MAX) { + pr_buf(err, "fs inode in blockdev range"); + return -EINVAL; + } - if (bch2_inode_unpack(k, &unpacked)) - return "invalid variable length fields"; + if (bch2_inode_unpack(k, &unpacked)){ + pr_buf(err, "invalid variable length fields"); + return -EINVAL; + } - if (unpacked.bi_data_checksum >= BCH_CSUM_OPT_NR + 1) - return "invalid data checksum type"; + if (unpacked.bi_data_checksum >= BCH_CSUM_OPT_NR + 1) { + pr_buf(err, "invalid data checksum type (%u >= %u", + unpacked.bi_data_checksum, BCH_CSUM_OPT_NR + 1); + return -EINVAL; + } - if (unpacked.bi_compression >= BCH_COMPRESSION_OPT_NR + 1) - return "invalid data checksum type"; + if (unpacked.bi_compression >= BCH_COMPRESSION_OPT_NR + 1) { + pr_buf(err, "invalid data checksum type (%u >= %u)", + unpacked.bi_compression, BCH_COMPRESSION_OPT_NR + 1); + return -EINVAL; + } if ((unpacked.bi_flags & BCH_INODE_UNLINKED) && - unpacked.bi_nlink != 0) - return "flagged as unlinked but bi_nlink != 0"; + unpacked.bi_nlink != 0) { + pr_buf(err, "flagged as unlinked but bi_nlink != 0"); + return -EINVAL; + } - if (unpacked.bi_subvol && !S_ISDIR(unpacked.bi_mode)) - return "subvolume root but not a directory"; + if (unpacked.bi_subvol && !S_ISDIR(unpacked.bi_mode)) { + pr_buf(err, "subvolume root but not a directory"); + return -EINVAL; + } - return NULL; + return 0; } -const char *bch2_inode_v2_invalid(const struct bch_fs *c, struct bkey_s_c k) +int bch2_inode_invalid(const struct bch_fs *c, struct bkey_s_c k, + int rw, struct printbuf *err) { - struct bkey_s_c_inode_v2 inode = bkey_s_c_to_inode_v2(k); - struct bch_inode_unpacked unpacked; - - if (k.k->p.inode) - return "nonzero k.p.inode"; - - if (bkey_val_bytes(k.k) < sizeof(struct bch_inode)) - return "incorrect value size"; - - if (k.k->p.offset < BLOCKDEV_INODE_MAX) - return "fs inode in blockdev range"; + struct bkey_s_c_inode inode = bkey_s_c_to_inode(k); - if (INODEv2_STR_HASH(inode.v) >= BCH_STR_HASH_NR) - return "invalid str hash type"; + if (bkey_val_bytes(k.k) < sizeof(*inode.v)) { + pr_buf(err, "incorrect value size (%zu < %zu)", + bkey_val_bytes(k.k), sizeof(*inode.v)); + return -EINVAL; + } - if (bch2_inode_unpack(k, &unpacked)) - return "invalid variable length fields"; + if (INODE_STR_HASH(inode.v) >= BCH_STR_HASH_NR) { + pr_buf(err, "invalid str hash type (%llu >= %u)", + INODE_STR_HASH(inode.v), BCH_STR_HASH_NR); + return -EINVAL; + } - if (unpacked.bi_data_checksum >= BCH_CSUM_OPT_NR + 1) - return "invalid data checksum type"; + return __bch2_inode_invalid(k, err); +} - if (unpacked.bi_compression >= BCH_COMPRESSION_OPT_NR + 1) - return "invalid data checksum type"; +int bch2_inode_v2_invalid(const struct bch_fs *c, struct bkey_s_c k, + int rw, struct printbuf *err) +{ + struct bkey_s_c_inode_v2 inode = bkey_s_c_to_inode_v2(k); - if ((unpacked.bi_flags & BCH_INODE_UNLINKED) && - unpacked.bi_nlink != 0) - return "flagged as unlinked but bi_nlink != 0"; + if (bkey_val_bytes(k.k) < sizeof(*inode.v)) { + pr_buf(err, "incorrect value size (%zu < %zu)", + bkey_val_bytes(k.k), sizeof(*inode.v)); + return -EINVAL; + } - if (unpacked.bi_subvol && !S_ISDIR(unpacked.bi_mode)) - return "subvolume root but not a directory"; + if (INODEv2_STR_HASH(inode.v) >= BCH_STR_HASH_NR) { + pr_buf(err, "invalid str hash type (%llu >= %u)", + INODEv2_STR_HASH(inode.v), BCH_STR_HASH_NR); + return -EINVAL; + } - return NULL; + return __bch2_inode_invalid(k, err); } static void __bch2_inode_unpacked_to_text(struct printbuf *out, struct bch_inode_unpacked *inode) @@ -407,16 +409,21 @@ void bch2_inode_to_text(struct printbuf *out, struct bch_fs *c, __bch2_inode_unpacked_to_text(out, &inode); } -const char *bch2_inode_generation_invalid(const struct bch_fs *c, - struct bkey_s_c k) +int bch2_inode_generation_invalid(const struct bch_fs *c, struct bkey_s_c k, + int rw, struct printbuf *err) { - if (k.k->p.inode) - return "nonzero k.p.inode"; + if (k.k->p.inode) { + pr_buf(err, "nonzero k.p.inode"); + return -EINVAL; + } - if (bkey_val_bytes(k.k) != sizeof(struct bch_inode_generation)) - return "incorrect value size"; + if (bkey_val_bytes(k.k) != sizeof(struct bch_inode_generation)) { + pr_buf(err, "incorrect value size (%zu != %zu)", + bkey_val_bytes(k.k), sizeof(struct bch_inode_generation)); + return -EINVAL; + } - return NULL; + return 0; } void bch2_inode_generation_to_text(struct printbuf *out, struct bch_fs *c, @@ -594,76 +601,62 @@ found_slot: static int bch2_inode_delete_keys(struct btree_trans *trans, subvol_inum inum, enum btree_id id) { - u64 offset = 0; + struct btree_iter iter; + struct bkey_s_c k; + struct bkey_i delete; + u32 snapshot; int ret = 0; - while (!ret || ret == -EINTR) { - struct btree_iter iter; - struct bkey_s_c k; - struct bkey_i delete; - u32 snapshot; + /* + * We're never going to be deleting extents, no need to use an extent + * iterator: + */ + bch2_trans_iter_init(trans, &iter, id, POS(inum.inum, 0), + BTREE_ITER_NOT_EXTENTS| + BTREE_ITER_INTENT); + while (1) { bch2_trans_begin(trans); ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot); if (ret) - continue; - - bch2_trans_iter_init(trans, &iter, id, - SPOS(inum.inum, offset, snapshot), - BTREE_ITER_INTENT); - k = bch2_btree_iter_peek(&iter); + goto err; - if (!k.k || iter.pos.inode != inum.inum) { - bch2_trans_iter_exit(trans, &iter); - break; - } + bch2_btree_iter_set_snapshot(&iter, snapshot); + k = bch2_btree_iter_peek_upto(&iter, POS(inum.inum, U64_MAX)); ret = bkey_err(k); if (ret) goto err; + if (!k.k) + break; + bkey_init(&delete.k); delete.k.p = iter.pos; - if (btree_node_type_is_extents(iter.btree_id)) { - unsigned max_sectors = - min_t(u64, U64_MAX - iter.pos.offset, - KEY_SIZE_MAX & (~0 << trans->c->block_bits)); - - /* create the biggest key we can */ - bch2_key_resize(&delete.k, max_sectors); - - ret = bch2_extent_trim_atomic(trans, &iter, &delete); - if (ret) - goto err; - } - ret = bch2_trans_update(trans, &iter, &delete, 0) ?: bch2_trans_commit(trans, NULL, NULL, BTREE_INSERT_NOFAIL); err: - offset = iter.pos.offset; - bch2_trans_iter_exit(trans, &iter); + if (ret && ret != -EINTR) + break; } + bch2_trans_iter_exit(trans, &iter); return ret; } -int bch2_inode_rm(struct bch_fs *c, subvol_inum inum, bool cached) +int bch2_inode_rm(struct bch_fs *c, subvol_inum inum) { struct btree_trans trans; struct btree_iter iter = { NULL }; struct bkey_i_inode_generation delete; struct bch_inode_unpacked inode_u; struct bkey_s_c k; - unsigned iter_flags = BTREE_ITER_INTENT; u32 snapshot; int ret; - if (0 && cached && c->opts.inodes_use_key_cache) - iter_flags |= BTREE_ITER_CACHED; - bch2_trans_init(&trans, c, 0, 1024); /* @@ -687,7 +680,8 @@ retry: goto err; bch2_trans_iter_init(&trans, &iter, BTREE_ID_inodes, - SPOS(0, inum.inum, snapshot), iter_flags); + SPOS(0, inum.inum, snapshot), + BTREE_ITER_INTENT|BTREE_ITER_CACHED); k = bch2_btree_iter_peek_slot(&iter); ret = bkey_err(k);