summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2025-02-25 20:42:40 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2025-02-25 20:56:41 -0500
commit559ae9ec988de991142b6a067c313aeb530c2b11 (patch)
tree20b43ec46f0b3350ea0a15391150e8f6ede58ffb
parent82af8187566114f55114f1b878562de031e0b9b4 (diff)
bcachefs: bcachefs_metadata_version_directory_size_v2bcachefs-dir-i-size
Co-developed-by: Hongbo Li <lihongbo22@huawei.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/bcachefs_format.h4
-rw-r--r--fs/bcachefs/fs-common.c13
-rw-r--r--fs/bcachefs/fsck.c24
-rw-r--r--fs/bcachefs/sb-downgrade.c5
4 files changed, 40 insertions, 6 deletions
diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h
index 52b05025f7f5..843ac385f841 100644
--- a/fs/bcachefs/bcachefs_format.h
+++ b/fs/bcachefs/bcachefs_format.h
@@ -690,8 +690,8 @@ struct bch_sb_field_ext {
x(cached_backpointers, BCH_VERSION(1, 21)) \
x(stripe_backpointers, BCH_VERSION(1, 22)) \
x(stripe_lru, BCH_VERSION(1, 23)) \
- x(casefolding, BCH_VERSION(1, 24)) \
- x(extent_flags, BCH_VERSION(1, 25))
+ x(extent_flags, BCH_VERSION(1, 25)) \
+ x(directory_size_v2, BCH_VERSION(1, 26))
enum bcachefs_metadata_version {
bcachefs_metadata_version_min = 9,
diff --git a/fs/bcachefs/fs-common.c b/fs/bcachefs/fs-common.c
index fbc3da59536c..ca70a3de805c 100644
--- a/fs/bcachefs/fs-common.c
+++ b/fs/bcachefs/fs-common.c
@@ -268,8 +268,16 @@ int bch2_unlink_trans(struct btree_trans *trans,
dir_hash = bch2_hash_info_init(c, dir_u);
- ret = bch2_dirent_lookup_trans(trans, &dirent_iter, dir, &dir_hash,
- name, &inum, BTREE_ITER_intent);
+ struct bkey_s_c dirent_k =
+ bch2_hash_lookup(trans, &dirent_iter, bch2_dirent_hash_desc,
+ &dir_hash, dir, name, BTREE_ITER_intent);
+ ret = bkey_err(dirent_k);
+ if (ret)
+ goto err;
+
+ ret = bch2_dirent_read_target(trans, dir, bkey_s_c_to_dirent(dirent_k), &inum);
+ if (ret > 0)
+ ret = -ENOENT;
if (ret)
goto err;
@@ -326,6 +334,7 @@ int bch2_unlink_trans(struct btree_trans *trans,
dir_u->bi_mtime = dir_u->bi_ctime = inode_u->bi_ctime = now;
dir_u->bi_nlink -= is_subdir_for_nlink(inode_u);
+ dir_u->bi_size -= bkey_bytes(dirent_k.k);
ret = bch2_hash_delete_at(trans, bch2_dirent_hash_desc,
&dir_hash, &dirent_iter,
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
index 0e85131d0af8..a9480bb308b2 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -1978,10 +1978,31 @@ fsck_err:
return ret;
}
+static int check_dir_i_size_notnested(struct btree_trans *trans, struct inode_walker *w)
+{
+ struct bch_fs *c = trans->c;
+ int ret = 0;
+
+ darray_for_each(w->inodes, i)
+ if (fsck_err_on(i->inode.bi_size != i->i_size,
+ trans, inode_dir_wrong_nlink,
+ "directory %llu:%u with wrong i_size: got %llu, should be %llu",
+ w->last_pos.inode, i->snapshot, i->inode.bi_size, i->i_size)) {
+ i->inode.bi_size = i->i_size;
+ ret = bch2_fsck_write_inode(trans, &i->inode);
+ if (ret)
+ break;
+ }
+fsck_err:
+ bch_err_fn(c, ret);
+ return ret;
+}
+
static int check_subdir_dirents_count(struct btree_trans *trans, struct inode_walker *w)
{
u32 restart_count = trans->restart_count;
return check_subdir_count_notnested(trans, w) ?:
+ check_dir_i_size_notnested(trans, w) ?:
trans_was_restarted(trans, restart_count);
}
@@ -2449,7 +2470,8 @@ int bch2_check_dirents(struct bch_fs *c)
POS(BCACHEFS_ROOT_INO, 0),
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
check_dirent(trans, &iter, k, &hash_info, &dir, &target, &s)) ?:
- check_subdir_count_notnested(trans, &dir));
+ check_subdir_count_notnested(trans, &dir) ?:
+ check_dir_i_size_notnested(trans, &dir));
snapshots_seen_exit(&s);
inode_walker_exit(&dir);
diff --git a/fs/bcachefs/sb-downgrade.c b/fs/bcachefs/sb-downgrade.c
index acb5d845841e..1b31c219e0fa 100644
--- a/fs/bcachefs/sb-downgrade.c
+++ b/fs/bcachefs/sb-downgrade.c
@@ -96,7 +96,10 @@
BCH_FSCK_ERR_ptr_to_missing_backpointer) \
x(stripe_backpointers, \
BIT_ULL(BCH_RECOVERY_PASS_check_extents_to_backpointers),\
- BCH_FSCK_ERR_ptr_to_missing_backpointer)
+ BCH_FSCK_ERR_ptr_to_missing_backpointer) \
+ x(directory_size_v2, \
+ BIT_ULL(BCH_RECOVERY_PASS_check_dirents), \
+ BCH_FSCK_ERR_directory_size_mismatch)
#define DOWNGRADE_TABLE() \
x(bucket_stripe_sectors, \