]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/inode.c
Update bcachefs sources to 95ff72a6c1 fixup! mm: Centralize & improve oom reporting...
[bcachefs-tools-debian] / libbcachefs / inode.c
index 8a82489753e5098c26ad8badbdf1d160bc757b39..6a2b94908371e230c69f3cc4a6d65760248e00c6 100644 (file)
@@ -141,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;                                               \
        }                                                               \
                                                                        \
@@ -298,40 +298,40 @@ static int __bch2_inode_invalid(struct bkey_s_c k, struct printbuf *err)
        struct bch_inode_unpacked unpacked;
 
        if (k.k->p.inode) {
-               pr_buf(err, "nonzero k.p.inode");
+               prt_printf(err, "nonzero k.p.inode");
                return -EINVAL;
        }
 
        if (k.k->p.offset < BLOCKDEV_INODE_MAX) {
-               pr_buf(err, "fs inode in blockdev range");
+               prt_printf(err, "fs inode in blockdev range");
                return -EINVAL;
        }
 
        if (bch2_inode_unpack(k, &unpacked)){
-               pr_buf(err, "invalid variable length fields");
+               prt_printf(err, "invalid variable length fields");
                return -EINVAL;
        }
 
        if (unpacked.bi_data_checksum >= BCH_CSUM_OPT_NR + 1) {
-               pr_buf(err, "invalid data checksum type (%u >= %u",
+               prt_printf(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) {
-               pr_buf(err, "invalid data checksum type (%u >= %u)",
+               prt_printf(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) {
-               pr_buf(err, "flagged as unlinked but bi_nlink != 0");
+               prt_printf(err, "flagged as unlinked but bi_nlink != 0");
                return -EINVAL;
        }
 
        if (unpacked.bi_subvol && !S_ISDIR(unpacked.bi_mode)) {
-               pr_buf(err, "subvolume root but not a directory");
+               prt_printf(err, "subvolume root but not a directory");
                return -EINVAL;
        }
 
@@ -344,13 +344,13 @@ int bch2_inode_invalid(const struct bch_fs *c, struct bkey_s_c k,
        struct bkey_s_c_inode inode = bkey_s_c_to_inode(k);
 
        if (bkey_val_bytes(k.k) < sizeof(*inode.v)) {
-               pr_buf(err, "incorrect value size (%zu < %zu)",
+               prt_printf(err, "incorrect value size (%zu < %zu)",
                       bkey_val_bytes(k.k), sizeof(*inode.v));
                return -EINVAL;
        }
 
        if (INODE_STR_HASH(inode.v) >= BCH_STR_HASH_NR) {
-               pr_buf(err, "invalid str hash type (%llu >= %u)",
+               prt_printf(err, "invalid str hash type (%llu >= %u)",
                       INODE_STR_HASH(inode.v), BCH_STR_HASH_NR);
                return -EINVAL;
        }
@@ -364,13 +364,13 @@ int bch2_inode_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
        struct bkey_s_c_inode_v2 inode = bkey_s_c_to_inode_v2(k);
 
        if (bkey_val_bytes(k.k) < sizeof(*inode.v)) {
-               pr_buf(err, "incorrect value size (%zu < %zu)",
+               prt_printf(err, "incorrect value size (%zu < %zu)",
                       bkey_val_bytes(k.k), sizeof(*inode.v));
                return -EINVAL;
        }
 
        if (INODEv2_STR_HASH(inode.v) >= BCH_STR_HASH_NR) {
-               pr_buf(err, "invalid str hash type (%llu >= %u)",
+               prt_printf(err, "invalid str hash type (%llu >= %u)",
                       INODEv2_STR_HASH(inode.v), BCH_STR_HASH_NR);
                return -EINVAL;
        }
@@ -380,19 +380,19 @@ int bch2_inode_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
 
 static void __bch2_inode_unpacked_to_text(struct printbuf *out, struct bch_inode_unpacked *inode)
 {
-       pr_buf(out, "mode %o flags %x journal_seq %llu",
+       prt_printf(out, "mode %o flags %x journal_seq %llu",
               inode->bi_mode, inode->bi_flags,
               inode->bi_journal_seq);
 
 #define x(_name, _bits)                                                \
-       pr_buf(out, " "#_name " %llu", (u64) inode->_name);
+       prt_printf(out, " "#_name " %llu", (u64) inode->_name);
        BCH_INODE_FIELDS()
 #undef  x
 }
 
 void bch2_inode_unpacked_to_text(struct printbuf *out, struct bch_inode_unpacked *inode)
 {
-       pr_buf(out, "inum: %llu ", inode->bi_inum);
+       prt_printf(out, "inum: %llu ", inode->bi_inum);
        __bch2_inode_unpacked_to_text(out, inode);
 }
 
@@ -402,7 +402,7 @@ void bch2_inode_to_text(struct printbuf *out, struct bch_fs *c,
        struct bch_inode_unpacked inode;
 
        if (bch2_inode_unpack(k, &inode)) {
-               pr_buf(out, "(unpack error)");
+               prt_printf(out, "(unpack error)");
                return;
        }
 
@@ -413,12 +413,12 @@ 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) {
-               pr_buf(err, "nonzero k.p.inode");
+               prt_printf(err, "nonzero k.p.inode");
                return -EINVAL;
        }
 
        if (bkey_val_bytes(k.k) != sizeof(struct bch_inode_generation)) {
-               pr_buf(err, "incorrect value size (%zu != %zu)",
+               prt_printf(err, "incorrect value size (%zu != %zu)",
                       bkey_val_bytes(k.k), sizeof(struct bch_inode_generation));
                return -EINVAL;
        }
@@ -431,7 +431,7 @@ void bch2_inode_generation_to_text(struct printbuf *out, struct bch_fs *c,
 {
        struct bkey_s_c_inode_generation gen = bkey_s_c_to_inode_generation(k);
 
-       pr_buf(out, "generation: %u", le32_to_cpu(gen.v->bi_generation));
+       prt_printf(out, "generation: %u", le32_to_cpu(gen.v->bi_generation));
 }
 
 void bch2_inode_init_early(struct bch_fs *c,
@@ -736,3 +736,36 @@ int bch2_inode_find_by_inum(struct bch_fs *c, subvol_inum inum,
        return bch2_trans_do(c, NULL, NULL, 0,
                bch2_inode_find_by_inum_trans(&trans, inum, inode));
 }
+
+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;
+
+               bi->bi_nlink++;
+       }
+
+       return 0;
+}
+
+void bch2_inode_nlink_dec(struct btree_trans *trans, struct bch_inode_unpacked *bi)
+{
+       if (bi->bi_nlink && (bi->bi_flags & BCH_INODE_UNLINKED)) {
+               bch2_trans_inconsistent(trans, "inode %llu unlinked but link count nonzero",
+                                       bi->bi_inum);
+               return;
+       }
+
+       if (bi->bi_flags & BCH_INODE_UNLINKED) {
+               bch2_trans_inconsistent(trans, "inode %llu link count underflow", bi->bi_inum);
+               return;
+       }
+
+       if (bi->bi_nlink)
+               bi->bi_nlink--;
+       else
+               bi->bi_flags |= BCH_INODE_UNLINKED;
+}