u64 last_dir_index_offset;
        };
 
-       /*
-        * Total number of bytes pending defrag, used by stat to check whether
-        * it needs COW. Protected by 'lock'.
-        */
-       u64 defrag_bytes;
+       union {
+               /*
+                * Total number of bytes pending defrag, used by stat to check whether
+                * it needs COW. Protected by 'lock'.
+                * Used by inodes other than the data relocation inode.
+                */
+               u64 defrag_bytes;
+
+               /*
+                * Logical address of the block group being relocated.
+                * Used only by the data relocation inode.
+                */
+               u64 reloc_block_group_start;
+       };
 
        /*
         * The size of the file stored in the metadata on disk.  data=ordered
         */
        u64 disk_i_size;
 
-       /*
-        * If this is a directory then index_cnt is the counter for the index
-        * number for new files that are created. For an empty directory, this
-        * must be initialized to BTRFS_DIR_START_INDEX.
-        */
-       u64 index_cnt;
+       union {
+               /*
+                * If this is a directory then index_cnt is the counter for the
+                * index number for new files that are created. For an empty
+                * directory, this must be initialized to BTRFS_DIR_START_INDEX.
+                */
+               u64 index_cnt;
+
+               /*
+                * If this is not a directory, this is the number of bytes
+                * outstanding that are going to need csums. This is used in
+                * ENOSPC accounting. Protected by 'lock'.
+                */
+               u64 csum_bytes;
+       };
 
        /* Cache the directory index number to speed the dir/file remove */
        u64 dir_index;
         */
        u64 last_reflink_trans;
 
-       /*
-        * Number of bytes outstanding that are going to need csums.  This is
-        * used in ENOSPC accounting. Protected by 'lock'.
-        */
-       u64 csum_bytes;
-
        /* Backwards incompatible flags, lower half of inode_item::flags  */
        u32 flags;
        /* Read-only compatibility flags, upper half of inode_item::flags */
 
        BTRFS_I(inode)->i_otime_nsec = btrfs_stack_timespec_nsec(&inode_item->otime);
 
        inode->i_generation = BTRFS_I(inode)->generation;
-       BTRFS_I(inode)->index_cnt = (u64)-1;
+       if (S_ISDIR(inode->i_mode))
+               BTRFS_I(inode)->index_cnt = (u64)-1;
 
        mutex_unlock(&delayed_node->mutex);
        btrfs_release_delayed_node(delayed_node);
 
        inode->i_rdev = 0;
        rdev = btrfs_inode_rdev(leaf, inode_item);
 
-       BTRFS_I(inode)->index_cnt = (u64)-1;
+       if (S_ISDIR(inode->i_mode))
+               BTRFS_I(inode)->index_cnt = (u64)-1;
+
        btrfs_inode_split_flags(btrfs_inode_flags(leaf, inode_item),
                                &BTRFS_I(inode)->flags, &BTRFS_I(inode)->ro_flags);
 
                if (ret)
                        goto out;
        }
-       /* index_cnt is ignored for everything but a dir. */
-       BTRFS_I(inode)->index_cnt = BTRFS_DIR_START_INDEX;
+
+       if (S_ISDIR(inode->i_mode))
+               BTRFS_I(inode)->index_cnt = BTRFS_DIR_START_INDEX;
+
        BTRFS_I(inode)->generation = trans->transid;
        inode->i_generation = BTRFS_I(inode)->generation;
 
        ei->disk_i_size = 0;
        ei->flags = 0;
        ei->ro_flags = 0;
+       /*
+        * ->index_cnt will be properly initialized later when creating a new
+        * inode (btrfs_create_new_inode()) or when reading an existing inode
+        * from disk (btrfs_read_locked_inode()).
+        */
        ei->csum_bytes = 0;
-       ei->index_cnt = (u64)-1;
        ei->dir_index = 0;
        ei->last_unlink_trans = 0;
        ei->last_reflink_trans = 0;
        if (!S_ISDIR(vfs_inode->i_mode)) {
                WARN_ON(inode->delalloc_bytes);
                WARN_ON(inode->new_delalloc_bytes);
+               WARN_ON(inode->csum_bytes);
        }
-       WARN_ON(inode->csum_bytes);
-       WARN_ON(inode->defrag_bytes);
+       if (!root || !btrfs_is_data_reloc_root(root))
+               WARN_ON(inode->defrag_bytes);
 
        /*
         * This can happen where we create an inode, but somebody else also
 
        if (!path)
                return -ENOMEM;
 
-       bytenr -= BTRFS_I(reloc_inode)->index_cnt;
+       bytenr -= BTRFS_I(reloc_inode)->reloc_block_group_start;
        ret = btrfs_lookup_file_extent(NULL, root, path,
                        btrfs_ino(BTRFS_I(reloc_inode)), bytenr, 0);
        if (ret < 0)
        u64 alloc_hint = 0;
        u64 start;
        u64 end;
-       u64 offset = inode->index_cnt;
+       u64 offset = inode->reloc_block_group_start;
        u64 num_bytes;
        int nr;
        int ret = 0;
                              int *cluster_nr, unsigned long index)
 {
        struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
-       u64 offset = BTRFS_I(inode)->index_cnt;
+       u64 offset = BTRFS_I(inode)->reloc_block_group_start;
        const unsigned long last_index = (cluster->end - offset) >> PAGE_SHIFT;
        gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
        struct folio *folio;
 static int relocate_file_extent_cluster(struct inode *inode,
                                        const struct file_extent_cluster *cluster)
 {
-       u64 offset = BTRFS_I(inode)->index_cnt;
+       u64 offset = BTRFS_I(inode)->reloc_block_group_start;
        unsigned long index;
        unsigned long last_index;
        struct file_ra_state *ra;
                inode = NULL;
                goto out;
        }
-       BTRFS_I(inode)->index_cnt = group->start;
+       BTRFS_I(inode)->reloc_block_group_start = group->start;
 
        ret = btrfs_orphan_add(trans, BTRFS_I(inode));
 out:
 {
        struct btrfs_inode *inode = BTRFS_I(ordered->inode);
        struct btrfs_fs_info *fs_info = inode->root->fs_info;
-       u64 disk_bytenr = ordered->file_offset + inode->index_cnt;
+       u64 disk_bytenr = ordered->file_offset + inode->reloc_block_group_start;
        struct btrfs_root *csum_root = btrfs_csum_root(fs_info, disk_bytenr);
        LIST_HEAD(list);
        int ret;
 
                if (ret)
                        goto out;
        }
-       BTRFS_I(inode)->index_cnt = (u64)-1;
+       if (S_ISDIR(inode->i_mode))
+               BTRFS_I(inode)->index_cnt = (u64)-1;
 
        if (inode->i_nlink == 0) {
                if (S_ISDIR(inode->i_mode)) {