[PATCH 1/1] rpdfs: Add basic getattr and setattr support.

Chris Kirby <[email protected]> Tue, 24 Feb 2026 14:56:43 -0600
Newsgroups dev.linux.lists.rpdfs-devel
Message-ID <54a592917350a76c96d28afdb6ac5b7d4fb6d061.1771966471.git.ckirby@versity.com>
Add basic getattr and setattr support.

For now, the only statx request supported by getattr is
STATX_BTIME. All other stat info is filled in from the
vfs inode using generic_fillattr().

setattr lacks support for ATTR_SIZE, since we don't have
a truncate operation yet.

Signed-off-by: Chris Kirby <[email protected]>
---
 fs/rpdfs/balloc.c |  2 +-
 fs/rpdfs/dir.c    |  2 ++
 fs/rpdfs/file.c   |  3 ++
 fs/rpdfs/inode.c  | 71 +++++++++++++++++++++++++++++++++++++++++++++++
 fs/rpdfs/inode.h  |  7 +++++
 5 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/fs/rpdfs/balloc.c b/fs/rpdfs/balloc.c
index ab14b812297c..09ed17d995f0 100644
--- a/fs/rpdfs/balloc.c
+++ b/fs/rpdfs/balloc.c
@@ -96,7 +96,7 @@ void rpdfs_balloc_start_apply(struct rpdfs_fs_info *rfi, struct rpdfs_transactio
 
 /*
  * Apply and return the result of an allocation that was prepared by
- * _prepare_alloc.  The caller can use _txn_use_prepare() to get the
+ * _prepare_alloc.  The caller can use _txn_use_prepared() to get the
  * allocated block.
  */
 int rpdfs_balloc_apply_alloc(struct rpdfs_fs_info *rfi, struct rpdfs_transaction *txn,
diff --git a/fs/rpdfs/dir.c b/fs/rpdfs/dir.c
index 115f879d8fb1..7ae8faf74161 100644
--- a/fs/rpdfs/dir.c
+++ b/fs/rpdfs/dir.c
@@ -677,9 +677,11 @@ static int rpdfs_readdir(struct file *file, struct dir_context *ctx)
 
 const struct inode_operations rpdfs_dir_iops = {
 	.create		= rpdfs_create,
+	.getattr	= rpdfs_getattr,
 	.lookup		= rpdfs_lookup,
 	.mkdir		= rpdfs_mkdir,
 	.rename		= rpdfs_rename,
+	.setattr	= rpdfs_setattr,
 };
 
 const struct file_operations rpdfs_dir_fops = {
diff --git a/fs/rpdfs/file.c b/fs/rpdfs/file.c
index 4c62d5e85caf..22532d8cdf63 100644
--- a/fs/rpdfs/file.c
+++ b/fs/rpdfs/file.c
@@ -3,8 +3,11 @@
 #include <linux/fs.h>
 
 #include "file.h"
+#include "inode.h"
 
 const struct inode_operations rpdfs_file_iops = {
+	.getattr	= rpdfs_getattr,
+	.setattr	= rpdfs_setattr,
 };
 
 const struct file_operations rpdfs_file_fops = {
diff --git a/fs/rpdfs/inode.c b/fs/rpdfs/inode.c
index 02d6b6b07c14..3f9a8e9d993f 100644
--- a/fs/rpdfs/inode.c
+++ b/fs/rpdfs/inode.c
@@ -4,6 +4,7 @@
 #include <linux/slab.h>
 #include <linux/rcupdate.h>
 #include <linux/writeback.h>
+#include <linux/iversion.h>
 
 #include "dir.h"
 #include "file.h"
@@ -116,6 +117,7 @@ void rpdfs_inode_init_ops(struct inode *inode)
 		break;
 	default:
 		init_special_inode(inode, inode->i_mode, inode->i_rdev);
+		break;
 	}
 }
 
@@ -364,6 +366,75 @@ int rpdfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 	return ret;
 }
 
+int rpdfs_getattr(struct mnt_idmap *idmap, const struct path *path,
+		  struct kstat *stat, u32 request_mask,
+		  unsigned int query_flags)
+{
+	struct inode *inode = d_inode(path->dentry);
+	struct rpdfs_fs_info *rfi = RPDFS_INODE_FS(inode);
+	struct rpdfs_block_handle *hnd = NULL;
+	DECLARE_RPDFS_TXN(txn);
+	int ret;
+
+	do {
+		ret = rpdfs_inode_txn_prepare(rfi, &txn, inode, 0);
+	} while (rpdfs_txn_retry(rfi, &txn, &ret));
+
+	if (ret < 0)
+		goto out;
+
+	if (request_mask & STATX_BTIME) {
+		struct rpdfs_inode *rinode;
+
+		ret = rpdfs_txn_use_prepared(rfi, &txn, rpdfs_inode_bnr(inode),
+					     &hnd, 0);
+		if (ret < 0)
+			goto out;
+
+		rinode = hnd->data;
+
+		stat->result_mask |= STATX_BTIME;
+		stat->btime = ns_to_timespec64(le64_to_cpu(rinode->crtime_nsec));
+	}
+
+	generic_fillattr(idmap, request_mask, inode, stat);
+
+out:
+	rpdfs_txn_reset(rfi, &txn);
+
+	return ret;
+}
+
+int rpdfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+		  struct iattr *attr)
+{
+	struct inode *inode = d_inode(dentry);
+	struct rpdfs_fs_info *rfi = RPDFS_INODE_FS(inode);
+	DECLARE_RPDFS_TXN(txn);
+	int ret;
+
+	do {
+		ret = rpdfs_inode_txn_prepare(rfi, &txn, inode, RBAF_WRITE);
+	} while (rpdfs_txn_retry(rfi, &txn, &ret));
+
+	if (ret < 0)
+		goto out;
+
+	ret = setattr_prepare(idmap, dentry, attr);
+	if (ret)
+		goto out;
+
+	setattr_copy(idmap, inode, attr);
+	inode_inc_iversion(inode);
+
+	rpdfs_inode_txn_update(rfi, &txn, inode);
+
+out:
+	rpdfs_txn_reset(rfi, &txn);
+
+	return ret;
+}
+
 int rpdfs_inode_init(void)
 {
 	rpdfs_inode_cache = kmem_cache_create("rpdfs_inode_cache", sizeof(struct rpdfs_inode_info),
diff --git a/fs/rpdfs/inode.h b/fs/rpdfs/inode.h
index 28edaf01f542..a57017a4fca0 100644
--- a/fs/rpdfs/inode.h
+++ b/fs/rpdfs/inode.h
@@ -52,6 +52,13 @@ int rpdfs_write_inode(struct inode *inode, struct writeback_control *wbc);
 
 void rpdfs_inode_init_ops(struct inode *inode);
 
+int rpdfs_getattr(struct mnt_idmap *idmap, const struct path *path,
+		  struct kstat *stat, u32 request_mask,
+		  unsigned int query_flags);
+
+int rpdfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+		  struct iattr *attr);
+
 struct inode *rpdfs_iget(struct super_block *sb, struct rpdfs_ino_gen *ig);
 struct inode *rpdfs_new_inode(struct super_block *sb, struct rpdfs_ino_gen *ig);
 int rpdfs_inode_txn_prepare(struct rpdfs_fs_info *rfi, struct rpdfs_transaction *txn,
-- 
2.53.0