]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bcachefs: make directory i_size meaningful
authorHongbo Li <lihongbo22@huawei.com>
Tue, 7 Jan 2025 13:18:40 +0000 (13:18 +0000)
committerKent Overstreet <kent.overstreet@linux.dev>
Mon, 13 Jan 2025 19:58:38 +0000 (14:58 -0500)
The isize of directory is 0 in bcachefs if the directory is empty.
With more child dirents created, its size ought to change. Many
other filesystems changed as that (ie. xfs and btrfs). And many of
them changed as the size of child dirent name. Although the directory
size may not seem to convey much, we can still give it some meaning.

The formula of dentry size as follow:
    occupied_size = 40 + ALIGN(9 + namelen, 8)

Signed-off-by: Hongbo Li <lihongbo22@huawei.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/dirent.h
fs/bcachefs/fs-common.c
fs/bcachefs/fs.c

index 362b3b2f2f2e38f4b06e666960c51daf26c4551e..a633f83c1ac787574af56094f33637ab5c52aa14 100644 (file)
@@ -31,6 +31,11 @@ static inline unsigned dirent_val_u64s(unsigned len)
                            sizeof(u64));
 }
 
+static inline unsigned int dirent_occupied_size(const struct qstr *name)
+{
+       return (BKEY_U64s + dirent_val_u64s(name->len)) * sizeof(u64);
+}
+
 int bch2_dirent_read_target(struct btree_trans *, subvol_inum,
                            struct bkey_s_c_dirent, subvol_inum *);
 
index 2c3d46ac70c61353ede8988443b8a55dc5386fb6..d70d9f634cea9f93ef8d8d8c9ef9b1d848e3cbc5 100644 (file)
@@ -152,6 +152,7 @@ int bch2_create_trans(struct btree_trans *trans,
                if (is_subdir_for_nlink(new_inode))
                        dir_u->bi_nlink++;
                dir_u->bi_mtime = dir_u->bi_ctime = now;
+               dir_u->bi_size += dirent_occupied_size(name);
 
                ret = bch2_inode_write(trans, &dir_iter, dir_u);
                if (ret)
@@ -220,6 +221,7 @@ int bch2_link_trans(struct btree_trans *trans,
        }
 
        dir_u->bi_mtime = dir_u->bi_ctime = now;
+       dir_u->bi_size += dirent_occupied_size(name);
 
        dir_hash = bch2_hash_info_init(c, dir_u);
 
@@ -322,6 +324,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  -= dirent_occupied_size(name);
 
        ret =   bch2_hash_delete_at(trans, bch2_dirent_hash_desc,
                                    &dir_hash, &dirent_iter,
@@ -460,6 +463,14 @@ int bch2_rename_trans(struct btree_trans *trans,
                goto err;
        }
 
+       if (mode == BCH_RENAME) {
+               src_dir_u->bi_size -= dirent_occupied_size(src_name);
+               dst_dir_u->bi_size += dirent_occupied_size(dst_name);
+       }
+
+       if (mode == BCH_RENAME_OVERWRITE)
+               src_dir_u->bi_size -= dirent_occupied_size(src_name);
+
        if (src_inode_u->bi_parent_subvol)
                src_inode_u->bi_parent_subvol = dst_dir.subvol;
 
index 3f83f131d0e818bfca7688ec68b66bf4394e2f03..90ade8f648d96b6f1bbb362581f8faa415121a93 100644 (file)
@@ -67,6 +67,9 @@ void bch2_inode_update_after_write(struct btree_trans *trans,
        i_gid_write(&inode->v, bi->bi_gid);
        inode->v.i_mode = bi->bi_mode;
 
+       if (fields & ATTR_SIZE)
+               i_size_write(&inode->v, bi->bi_size);
+
        if (fields & ATTR_ATIME)
                inode_set_atime_to_ts(&inode->v, bch2_time_to_timespec(c, bi->bi_atime));
        if (fields & ATTR_MTIME)
@@ -582,7 +585,7 @@ err_before_quota:
 
        if (!(flags & BCH_CREATE_TMPFILE)) {
                bch2_inode_update_after_write(trans, dir, &dir_u,
-                                             ATTR_MTIME|ATTR_CTIME);
+                                             ATTR_MTIME|ATTR_CTIME|ATTR_SIZE);
                mutex_unlock(&dir->ei_update_lock);
        }
 
@@ -739,7 +742,7 @@ static int __bch2_link(struct bch_fs *c,
 
        if (likely(!ret)) {
                bch2_inode_update_after_write(trans, dir, &dir_u,
-                                             ATTR_MTIME|ATTR_CTIME);
+                                             ATTR_MTIME|ATTR_CTIME|ATTR_SIZE);
                bch2_inode_update_after_write(trans, inode, &inode_u, ATTR_CTIME);
        }
 
@@ -792,7 +795,7 @@ int __bch2_unlink(struct inode *vdir, struct dentry *dentry,
                goto err;
 
        bch2_inode_update_after_write(trans, dir, &dir_u,
-                                     ATTR_MTIME|ATTR_CTIME);
+                                     ATTR_MTIME|ATTR_CTIME|ATTR_SIZE);
        bch2_inode_update_after_write(trans, inode, &inode_u,
                                      ATTR_MTIME);
 
@@ -970,11 +973,11 @@ err_tx_restart:
               dst_inode->v.i_ino != dst_inode_u.bi_inum);
 
        bch2_inode_update_after_write(trans, src_dir, &src_dir_u,
-                                     ATTR_MTIME|ATTR_CTIME);
+                                     ATTR_MTIME|ATTR_CTIME|ATTR_SIZE);
 
        if (src_dir != dst_dir)
                bch2_inode_update_after_write(trans, dst_dir, &dst_dir_u,
-                                             ATTR_MTIME|ATTR_CTIME);
+                                             ATTR_MTIME|ATTR_CTIME|ATTR_SIZE);
 
        bch2_inode_update_after_write(trans, src_inode, &src_inode_u,
                                      ATTR_CTIME);