#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; \
} \
\
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;
}
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;
}
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;
}
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);
}
struct bch_inode_unpacked inode;
if (bch2_inode_unpack(k, &inode)) {
- pr_buf(out, "(unpack error)");
+ prt_printf(out, "(unpack error)");
return;
}
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;
}
{
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,
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;
+}