btrfs: remove objectid from struct btrfs_inode on 64 bits platforms
authorFilipe Manana <fdmanana@suse.com>
Sun, 5 May 2024 12:47:02 +0000 (13:47 +0100)
committerDavid Sterba <dsterba@suse.com>
Thu, 11 Jul 2024 13:33:17 +0000 (15:33 +0200)
On 64 bits platforms we don't really need to have a dedicated member (the
objectid field) for the inode's number since we store in the VFS inode's
i_ino member, which is an unsigned long and this type is 64 bits wide on
64 bits platforms. We only need that field in case we are on a 32 bits
platform because the unsigned long type is 32 bits wide on such platforms
See commit 33345d01522f ("Btrfs: Always use 64bit inode number") regarding
this 64/32 bits detail.

The objectid field of struct btrfs_inode is also used to store the ID of
a root for directories that are stubs for unreferenced roots. In such
cases the inode is a directory and has the BTRFS_INODE_ROOT_STUB runtime
flag set.

So in order to reduce the size of btrfs_inode structure on 64 bits
platforms we can remove the objectid member and use the VFS inode's i_ino
member instead whenever we need to get the inode number. In case the inode
is a root stub (BTRFS_INODE_ROOT_STUB set) we can use the member
last_reflink_trans to store the ID of the unreferenced root, since such
inode is a directory and reflinks can't be done against directories.

So remove the objectid fields for 64 bits platforms and alias the
last_reflink_trans field with a name of ref_root_id in a union.
On a release kernel config, this reduces the size of struct btrfs_inode
from 1040 bytes down to 1032 bytes.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/btrfs_inode.h
fs/btrfs/disk-io.c
fs/btrfs/export.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/tests/btrfs-tests.c

index 754671a73333a6043bd88a4b272020d13c00d068..21bd17d84f59356498ea549733a68422114e61e5 100644 (file)
@@ -129,15 +129,14 @@ struct btrfs_inode {
        /* which subvolume this inode belongs to */
        struct btrfs_root *root;
 
+#if BITS_PER_LONG == 32
        /*
-        * This is either:
-        *
-        * 1) The objectid of the corresponding BTRFS_INODE_ITEM_KEY;
-        *
-        * 2) In case this a root stub inode (BTRFS_INODE_ROOT_STUB flag set),
-        *    the ID of that root.
+        * The objectid of the corresponding BTRFS_INODE_ITEM_KEY.
+        * On 64 bits platforms we can get it from vfs_inode.i_ino, which is an
+        * unsigned long and therefore 64 bits on such platforms.
         */
        u64 objectid;
+#endif
 
        /* Cached value of inode property 'compression'. */
        u8 prop_compress;
@@ -301,16 +300,25 @@ struct btrfs_inode {
         */
        u64 last_unlink_trans;
 
-       /*
-        * The id/generation of the last transaction where this inode was
-        * either the source or the destination of a clone/dedupe operation.
-        * Used when logging an inode to know if there are shared extents that
-        * need special care when logging checksum items, to avoid duplicate
-        * checksum items in a log (which can lead to a corruption where we end
-        * up with missing checksum ranges after log replay).
-        * Protected by the vfs inode lock.
-        */
-       u64 last_reflink_trans;
+       union {
+               /*
+                * The id/generation of the last transaction where this inode
+                * was either the source or the destination of a clone/dedupe
+                * operation. Used when logging an inode to know if there are
+                * shared extents that need special care when logging checksum
+                * items, to avoid duplicate checksum items in a log (which can
+                * lead to a corruption where we end up with missing checksum
+                * ranges after log replay). Protected by the VFS inode lock.
+                * Used for regular files only.
+                */
+               u64 last_reflink_trans;
+
+               /*
+                * In case this a root stub inode (BTRFS_INODE_ROOT_STUB flag set),
+                * the ID of that root.
+                */
+               u64 ref_root_id;
+       };
 
        /* Backwards incompatible flags, lower half of inode_item::flags  */
        u32 flags;
@@ -387,11 +395,19 @@ static inline u64 btrfs_ino(const struct btrfs_inode *inode)
 static inline void btrfs_get_inode_key(const struct btrfs_inode *inode,
                                       struct btrfs_key *key)
 {
-       key->objectid = inode->objectid;
+       key->objectid = btrfs_ino(inode);
        key->type = BTRFS_INODE_ITEM_KEY;
        key->offset = 0;
 }
 
+static inline void btrfs_set_inode_number(struct btrfs_inode *inode, u64 ino)
+{
+#if BITS_PER_LONG == 32
+       inode->objectid = ino;
+#endif
+       inode->vfs_inode.i_ino = ino;
+}
+
 static inline void btrfs_i_size_write(struct btrfs_inode *inode, u64 size)
 {
        i_size_write(&inode->vfs_inode, size);
index f5d8e448a0c4ea8e8414f398fe3a05b91e676f30..1ab9169f1dc9a78e7e4a2c2b80e9346ee032ebba 100644 (file)
@@ -1928,7 +1928,7 @@ static int btrfs_init_btree_inode(struct super_block *sb)
        if (!inode)
                return -ENOMEM;
 
-       inode->i_ino = BTRFS_BTREE_INODE_OBJECTID;
+       btrfs_set_inode_number(BTRFS_I(inode), BTRFS_BTREE_INODE_OBJECTID);
        set_nlink(inode, 1);
        /*
         * we set the i_size on the btree inode to the max possible int.
@@ -1944,7 +1944,6 @@ static int btrfs_init_btree_inode(struct super_block *sb)
        extent_map_tree_init(&BTRFS_I(inode)->extent_tree);
 
        BTRFS_I(inode)->root = btrfs_grab_root(fs_info->tree_root);
-       BTRFS_I(inode)->objectid = BTRFS_BTREE_INODE_OBJECTID;
        set_bit(BTRFS_INODE_DUMMY, &BTRFS_I(inode)->runtime_flags);
        __insert_inode_hash(inode, hash);
        fs_info->btree_inode = inode;
index 5526e25ebb3fb8b1d54d867f0421ee19769a29a6..5da56e21ff738c420a280f38d0494f4588e7d908 100644 (file)
@@ -40,7 +40,7 @@ static int btrfs_encode_fh(struct inode *inode, u32 *fh, int *max_len,
        if (parent) {
                u64 parent_root_id;
 
-               fid->parent_objectid = BTRFS_I(parent)->objectid;
+               fid->parent_objectid = btrfs_ino(BTRFS_I(parent));
                fid->parent_gen = parent->i_generation;
                parent_root_id = btrfs_root_id(BTRFS_I(parent)->root);
 
index c460322e3aa36eba28624840c5d186365c8f181a..655d63748545b6e7027b2642785efce76cf41c21 100644 (file)
@@ -4340,7 +4340,7 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
        if (btrfs_ino(inode) == BTRFS_FIRST_FREE_OBJECTID) {
                objectid = btrfs_root_id(inode->root);
        } else if (btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) {
-               objectid = inode->objectid;
+               objectid = inode->ref_root_id;
        } else {
                WARN_ON(1);
                fscrypt_free_filename(&fname);
@@ -5581,8 +5581,7 @@ static int btrfs_init_locked_inode(struct inode *inode, void *p)
 {
        struct btrfs_iget_args *args = p;
 
-       inode->i_ino = args->ino;
-       BTRFS_I(inode)->objectid = args->ino;
+       btrfs_set_inode_number(BTRFS_I(inode), args->ino);
        BTRFS_I(inode)->root = btrfs_grab_root(args->root);
 
        if (args->root && args->root == args->root->fs_info->tree_root &&
@@ -5596,7 +5595,7 @@ static int btrfs_find_actor(struct inode *inode, void *opaque)
 {
        struct btrfs_iget_args *args = opaque;
 
-       return args->ino == BTRFS_I(inode)->objectid &&
+       return args->ino == btrfs_ino(BTRFS_I(inode)) &&
                args->root == BTRFS_I(inode)->root;
 }
 
@@ -5673,11 +5672,11 @@ static struct inode *new_simple_dir(struct inode *dir,
                return ERR_PTR(-ENOMEM);
 
        BTRFS_I(inode)->root = btrfs_grab_root(root);
-       BTRFS_I(inode)->objectid = key->objectid;
+       BTRFS_I(inode)->ref_root_id = key->objectid;
        set_bit(BTRFS_INODE_ROOT_STUB, &BTRFS_I(inode)->runtime_flags);
        set_bit(BTRFS_INODE_DUMMY, &BTRFS_I(inode)->runtime_flags);
 
-       inode->i_ino = BTRFS_EMPTY_SUBVOL_DIR_OBJECTID;
+       btrfs_set_inode_number(BTRFS_I(inode), BTRFS_EMPTY_SUBVOL_DIR_OBJECTID);
        /*
         * We only need lookup, the rest is read-only and there's no inode
         * associated with the dentry
@@ -6150,7 +6149,7 @@ static int btrfs_insert_inode_locked(struct inode *inode)
 {
        struct btrfs_iget_args args;
 
-       args.ino = BTRFS_I(inode)->objectid;
+       args.ino = btrfs_ino(BTRFS_I(inode));
        args.root = BTRFS_I(inode)->root;
 
        return insert_inode_locked4(inode,
@@ -6282,7 +6281,7 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans,
        ret = btrfs_get_free_objectid(root, &objectid);
        if (ret)
                goto out;
-       inode->i_ino = objectid;
+       btrfs_set_inode_number(BTRFS_I(inode), objectid);
 
        ret = xa_reserve(&root->inodes, objectid, GFP_NOFS);
        if (ret)
@@ -6332,8 +6331,6 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans,
                                BTRFS_INODE_NODATASUM;
        }
 
-       BTRFS_I(inode)->objectid = objectid;
-
        ret = btrfs_insert_inode_locked(inode);
        if (ret < 0) {
                if (!args->orphan)
index 79a5ccb27b921776a34defac77120b8ab9ce9e44..968e256003af40ccb735f28d8145da6eb1842e78 100644 (file)
@@ -1918,7 +1918,7 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap,
 {
        struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
        struct super_block *sb = inode->i_sb;
-       u64 upper_limit = BTRFS_I(inode)->objectid;
+       u64 upper_limit = btrfs_ino(BTRFS_I(inode));
        u64 treeid = btrfs_root_id(BTRFS_I(inode)->root);
        u64 dirid = args->dirid;
        unsigned long item_off;
@@ -2140,7 +2140,7 @@ static int btrfs_ioctl_ino_lookup_user(struct file *file, void __user *argp)
        inode = file_inode(file);
 
        if (args->dirid == BTRFS_FIRST_FREE_OBJECTID &&
-           BTRFS_I(inode)->objectid != BTRFS_FIRST_FREE_OBJECTID) {
+           btrfs_ino(BTRFS_I(inode)) != BTRFS_FIRST_FREE_OBJECTID) {
                /*
                 * The subvolume does not exist under fd with which this is
                 * called
index b28a79935d8ef5ea3d64605534103fd93792cfc9..ce50847e1e01a4245ba1e5ff6a414b7a66f4de02 100644 (file)
@@ -61,8 +61,7 @@ struct inode *btrfs_new_test_inode(void)
                return NULL;
 
        inode->i_mode = S_IFREG;
-       inode->i_ino = BTRFS_FIRST_FREE_OBJECTID;
-       BTRFS_I(inode)->objectid = BTRFS_FIRST_FREE_OBJECTID;
+       btrfs_set_inode_number(BTRFS_I(inode), BTRFS_FIRST_FREE_OBJECTID);
        inode_init_owner(&nop_mnt_idmap, inode, NULL, S_IFREG);
 
        return inode;