[PATCH 3/6] rpdfs: add basic file data initialization
Valerie Aurora <[email protected]> Thu, 7 May 2026 15:21:50 +0200
| Newsgroups | dev.linux.lists.rpdfs-devel |
|---|---|
| Message-ID | <[email protected]> |
Initialize the file data root, plus a few simple routines to calculate mapping block levels. Rename the field in the inode from "data" to "data_root" to avoid confusion with the "data" member of struct rpdfs_block_handle. Signed-off-by: Valerie Aurora <[email protected]> --- fs/rpdfs/Makefile | 1 + fs/rpdfs/data.c | 93 +++++++++++++++++++++++++++++++++++++++++ fs/rpdfs/data.h | 11 +++++ fs/rpdfs/format-block.h | 32 +++++++------- fs/rpdfs/inode.c | 8 ++++ fs/rpdfs/inode.h | 1 + 6 files changed, 129 insertions(+), 17 deletions(-) create mode 100644 fs/rpdfs/data.c create mode 100644 fs/rpdfs/data.h diff --git a/fs/rpdfs/Makefile b/fs/rpdfs/Makefile index d995103ea5a8..f8301d86682b 100644 --- a/fs/rpdfs/Makefile +++ b/fs/rpdfs/Makefile @@ -12,6 +12,7 @@ rpdfs-y := balloc.o \ block.o \ btree.o \ btree_txn.o \ + data.o \ dir.o \ file.o \ ht.o \ diff --git a/fs/rpdfs/data.c b/fs/rpdfs/data.c new file mode 100644 index 000000000000..65b753886a04 --- /dev/null +++ b/fs/rpdfs/data.c @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <linux/fs.h> +#include <linux/pagemap.h> +#include <linux/gfp.h> +#include <linux/writeback.h> +#include <linux/build_bug.h> + +#include "balloc.h" +#include "inode.h" +#include "format-block.h" +#include "pr.h" +#include "super.h" +#include "data.h" + +/* + * File data is stored in simple tree of mapping blocks with data all + * at the same level of the tree. The topmost block in the tree and its + * level are stored in the inode. The tree is sparse and branches are + * grown as necessary to index newly written data blocks. While + * manipulating the tree, we use levels to identify the blocks at + * various levels of the tree, with the highest levels closer to the + * root. + * + * The data root field in the inode contains both the persistent + * reference (block number, etc.) to the root block of the tree, plus + * the height of the tree (the level of the block it points to, plus 1). + * The root block reference is not part of a mapping block. + * + * The level of a block is: + * + * 0 = data block + * 1 = references to data blocks + * 2 = references to single mapping blocks (pointing to data blocks) + * 3 = references to double mapping blocks + * 4 = references to triple mapping blocks + * + * Thus a data root reference with height 1 points to a block of level 0 + * = a single block of data at logical file offset 0. + */ + +/* + * Return the logical block number containing offset within a file. + */ +static u64 lblk_from_offset(u64 offset) +{ + return offset >> RPDFS_BLOCK_SHIFT; +} + +/* + * Calculate the index of the block reference for this logical block + * within a mapping block at this level. + */ +static u32 calc_ref_ind(u64 lblk, u8 level) +{ + u8 ind; + + BUG_ON(level == 0); + + BUILD_BUG_ON_NOT_POWER_OF_2(RPDFS_DATA_REFS_PER_BLK); + + ind = (lblk >> (level - 1) * RPDFS_DATA_REFS_PER_BLK_SHIFT) & RPDFS_DATA_REFS_PER_BLK_MASK; + + rpdfs_prd("lblk %llu level %u ind %u refs_per_blk %llu", lblk, level, ind, RPDFS_DATA_REFS_PER_BLK); + + return ind; +} + +/* + * Calculate the height of the tree needed to index the logical block + * lblk in this file. This is stored in the inode's data tree root. + */ +static u8 height_from_lblk(u64 lblk) +{ + u8 height; + + if (lblk == 0) + return 1; + + height = ((fls(lblk) - 1)/RPDFS_DATA_REFS_PER_BLK_SHIFT) + 2; + + rpdfs_prd("lblk %llu fls(lblk) - 1 %u refs_per_blk_shift %u + 2 = height %u", + lblk, fls(lblk) - 1, RPDFS_DATA_REFS_PER_BLK_SHIFT, height); + + return height; +} + +void rpdfs_data_root_init(struct rpdfs_data_root *data) +{ + data->height = 0; + data->ref.bnr = 0; + data->ref.alloc_counter = 0; +} diff --git a/fs/rpdfs/data.h b/fs/rpdfs/data.h new file mode 100644 index 000000000000..bb6b0c7dea86 --- /dev/null +++ b/fs/rpdfs/data.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef RPDFS_DATA_H +#define RPDFS_DATA_H + +#include "format-block.h" + +void rpdfs_data_root_init(struct rpdfs_data_root *data); + +extern const struct address_space_operations rpdfs_aops; + +#endif diff --git a/fs/rpdfs/format-block.h b/fs/rpdfs/format-block.h index 395e6d2d17e7..c2879e677084 100644 --- a/fs/rpdfs/format-block.h +++ b/fs/rpdfs/format-block.h @@ -4,9 +4,10 @@ #include <linux/types.h> #include <linux/align.h> +#include <linux/build_bug.h> #define RPDFS_BLOCK_SHIFT 12 -#define RPDFS_BLOCK_SIZE (1 << RPDFS_BLOCK_SHIFT) +#define RPDFS_BLOCK_SIZE (1ULL << RPDFS_BLOCK_SHIFT) #define RPDFS_BLOCK_MASK (RPDFS_BLOCK_SIZE - 1ULL) struct rpdfs_block_ref { @@ -113,9 +114,11 @@ struct rpdfs_ino_gen { }; /* - * Data blocks are pointed to by a simple tree of indirect blocks rooted - * in a single field in the inode. The height is one greater than the - * level of the referenced block. It's 0 for an empty tree. + * Data blocks are pointed to by a simple tree of mapping blocks rooted + * in a single field in the inode. The height of the tree is the number + * of blocks in the mapping chain, including the data block itself. It's + * 0 for a file with no data, 1 for a file with 1 data block at logical + * block 0, 2 for for a file with 2 data blocks at 0 and 1, etc. */ struct rpdfs_data_root { struct rpdfs_block_ref ref; @@ -124,21 +127,16 @@ struct rpdfs_data_root { }; /* - * Indirect blocks are a simple array of block refs. We rely on the - * number of references per indirect block being a power of 2, so check - * that at compile time. + * Mapping blocks are a simple array of block refs. Because blocks per + * ref is based on the size of a struct, we can't do the smart thing and + * define the shift first and then the value, we have to go backwards + * and define the shift from the value instead. */ -#define RPDFS_DATA_REFS_PER_BLK (RPDFS_BLOCK_SIZE / sizeof(struct rpdfs_block_ref)) - -/* - * Because blocks per ref is based on the size of a struct, we can't do - * the smart thing and define the shift first and then the value, we - * have to go backwards and define the shift from the value instead. - */ - +#define RPDFS_DATA_REFS_PER_BLK (RPDFS_BLOCK_SIZE / sizeof(struct rpdfs_block_ref)) #define RPDFS_DATA_REFS_PER_BLK_SHIFT const_ilog2(RPDFS_DATA_REFS_PER_BLK) +#define RPDFS_DATA_REFS_PER_BLK_MASK (RPDFS_DATA_REFS_PER_BLK - 1ULL) -struct rpdfs_indirect_block { +struct rpdfs_map_block { struct rpdfs_block_ref refs[RPDFS_DATA_REFS_PER_BLK]; }; @@ -168,7 +166,7 @@ struct rpdfs_inode { __le64 crtime_nsec; struct rpdfs_btree_root dirents; struct rpdfs_btree_root xattrs; - struct rpdfs_data_root data; + struct rpdfs_data_root data_root; }; #define RPDFS_ROOT_INO 1 diff --git a/fs/rpdfs/inode.c b/fs/rpdfs/inode.c index a2baa862f6a4..fd0913e0e4b6 100644 --- a/fs/rpdfs/inode.c +++ b/fs/rpdfs/inode.c @@ -9,6 +9,7 @@ #include "btree.h" #include "compare.h" +#include "data.h" #include "dir.h" #include "file.h" #include "inode.h" @@ -80,6 +81,8 @@ static void copy_rinode_to_vfs_inode(struct inode *inode, struct rpdfs_inode *ri ri->xattrs = rinode->xattrs; ri->xattr_creates = rinode->xattr_creates; + + ri->data_root = rinode->data_root; } static __le64 cpu_ts64_to_le64_ns(struct timespec64 ts) @@ -122,6 +125,8 @@ static void print_inode_change(struct inode *inode, struct rpdfs_inode *rinode) print_diff64("dirents", le64_to_cpu(ri->dirents.ref.bnr), le64_to_cpu(rinode->dirents.ref.bnr)); print_diff64("xattrs", le64_to_cpu(ri->xattrs.ref.bnr), le64_to_cpu(rinode->xattrs.ref.bnr)); print_diff64("xattr_creates", le64_to_cpu(ri->xattr_creates), le64_to_cpu(rinode->xattr_creates)); + print_diff64("data_root.height", ri->data_root.height, rinode->data_root.height); + print_diff64("data_root.ref.bnr", le64_to_cpu(ri->data_root.ref.bnr), le64_to_cpu(rinode->data_root.ref.bnr)); } static void copy_vfs_inode_to_rinode(struct rpdfs_inode *rinode, struct inode *inode) @@ -144,6 +149,8 @@ static void copy_vfs_inode_to_rinode(struct rpdfs_inode *rinode, struct inode *i rinode->xattrs = ri->xattrs; rinode->xattr_creates = ri->xattr_creates; + + rinode->data_root = ri->data_root; } /* @@ -336,6 +343,7 @@ struct inode *rpdfs_new_inode(struct super_block *sb, struct rpdfs_ino_gen *ig) rpdfs_btree_root_init(&ri->dirents); rpdfs_btree_root_init(&ri->xattrs); + rpdfs_data_root_init(&ri->data_root); ts = inode_set_ctime_current(inode); inode_set_mtime_to_ts(inode, ts); diff --git a/fs/rpdfs/inode.h b/fs/rpdfs/inode.h index 3b0be2d83e61..3892fdcc8b1b 100644 --- a/fs/rpdfs/inode.h +++ b/fs/rpdfs/inode.h @@ -25,6 +25,7 @@ struct rpdfs_inode_info { struct rpdfs_ino_gen ig; struct rpdfs_btree_root dirents; struct rpdfs_btree_root xattrs; + struct rpdfs_data_root data_root; struct inode vfs_inode; }; -- 2.49.0