[PATCH 5/8] rpdfs: add basic file data initialization

Valerie Aurora <[email protected]> Fri, 24 Apr 2026 16:05:17 +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         | 90 +++++++++++++++++++++++++++++++++++++++++
 fs/rpdfs/data.h         | 11 +++++
 fs/rpdfs/format-block.h |  6 +--
 fs/rpdfs/inode.c        |  8 ++++
 fs/rpdfs/inode.h        |  1 +
 6 files changed, 114 insertions(+), 3 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..b7538004d14a
--- /dev/null
+++ b/fs/rpdfs/data.c
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/gfp.h>
+#include <linux/writeback.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 an 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 an mapping block at this level (1 = pointers to data blocks).
+ */
+static u32 calc_ref_ind(u64 lblk, int level)
+{
+	u32 ind;
+	int i;
+
+	BUG_ON(level < 1);
+
+	for (i = 1; i < level; i++)
+		lblk >>= RPDFS_DATA_REFS_PER_BLK_SHIFT;
+
+	ind = lblk & (RPDFS_DATA_REFS_PER_BLK - 1ULL);
+
+	return ind;
+}
+
+/*
+ * Calculate the height of the tree (level of the root pointer) needed
+ * to index the logical block lblk in this file.
+ */
+static u8 height_from_lblk(u64 lblk)
+{
+	u8 height = 2;
+
+	if (lblk == 0)
+		return 1;
+
+	while (lblk >>= 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..04b4ddf5d614 100644
--- a/fs/rpdfs/format-block.h
+++ b/fs/rpdfs/format-block.h
@@ -6,7 +6,7 @@
 #include <linux/align.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 {
@@ -138,7 +138,7 @@ struct rpdfs_data_root {
 
 #define RPDFS_DATA_REFS_PER_BLK_SHIFT const_ilog2(RPDFS_DATA_REFS_PER_BLK)
 
-struct rpdfs_indirect_block {
+struct rpdfs_map_block {
 	struct rpdfs_block_ref refs[RPDFS_DATA_REFS_PER_BLK];
 };
 
@@ -168,7 +168,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 7abd2c58373f..947a8f1703a3 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;
 }
 
 __always_unused
@@ -118,6 +121,8 @@ static void print_inode_change(struct inode *inode, struct rpdfs_inode *rinode)
 	print_diff64("dirents", ri->dirents.ref.bnr, rinode->dirents.ref.bnr);
 	print_diff64("xattrs", ri->xattrs.ref.bnr, rinode->xattrs.ref.bnr);
 	print_diff64("xattr_creates", ri->xattr_creates, rinode->xattr_creates);
+	print_diff64("data_root.height", ri->data_root.height, rinode->data_root.height);
+	print_diff64("data_root.ref.bnr", ri->data_root.ref.bnr, rinode->data_root.ref.bnr);
 }
 
 static __le64 cpu_ts64_to_le64_ns(struct timespec64 ts)
@@ -145,6 +150,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;
 }
 
 /*
@@ -342,6 +349,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