Add support for STATX_DIOALIGN to nilfs2, so that direct I/O alignment
restrictions are exposed to userspace in a generic way.
By default, nilfs2 uses the default getattr implemented at vfs layer,
so we should implement getattr in nilfs2 to fill the dio_xx_align
members. We have done the following test:
[Before]
```
./statx_test /mnt/nilfs2/testfile
statx(/mnt/nilfs2/test) = 0
dio mem align:0
dio offset align:0
```
[After]
```
./statx_test /mnt/nilfs2/test
statx(/mnt/nilfs2/test) = 0
dio mem align:512
dio offset align:512
```
Signed-off-by: Hongbo Li <lihongbo22@xxxxxxxxxx>
---
fs/nilfs2/file.c | 1 +
fs/nilfs2/inode.c | 20 ++++++++++++++++++++
fs/nilfs2/namei.c | 2 ++
fs/nilfs2/nilfs.h | 2 ++
4 files changed, 25 insertions(+)
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c
index 0e3fc5ba33c7..5528918d4b96 100644
--- a/fs/nilfs2/file.c
+++ b/fs/nilfs2/file.c
@@ -154,6 +154,7 @@ const struct file_operations nilfs_file_operations = {
const struct inode_operations nilfs_file_inode_operations = {
.setattr = nilfs_setattr,
+ .getattr = nilfs_getattr,
.permission = nilfs_permission,
.fiemap = nilfs_fiemap,
.fileattr_get = nilfs_fileattr_get,
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 7340a01d80e1..7bf062793642 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -1001,6 +1001,26 @@ int nilfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
return err;
}
+int nilfs_getattr(struct mnt_idmap *idmap, const struct path *path,
+ struct kstat *stat, u3 request_mask, unsigned int query_flags)
+{
+ struct inode *const inode = d_inode(path->dentry);
+ struct block_device *bdev = inode->i_sb->s_bdev;
+ unsigned int blksize = (1 << inode->i_blkbits);
+
+ if ((request_mask & STATX_DIOALIGN) && S_ISREG(inode->i_mode)) {
+ stat->result_mask |= STATX_DIOALIGN;
+
+ if (bdev)
+ blksize = bdev_logical_block_size(bdev);
+ stat->dio_mem_align = blksize;
+ stat->dio_offset_align = blksize;
+ }
+
+ generic_fillattr(idmap, request_mask, inode, stat);
+ return 0;
+}
+
int nilfs_permission(struct mnt_idmap *idmap, struct inode *inode,
int mask)
{
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index c950139db6ef..ad56f4f8be1f 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -546,6 +546,7 @@ const struct inode_operations nilfs_dir_inode_operations = {
.mknod = nilfs_mknod,
.rename = nilfs_rename,
.setattr = nilfs_setattr,
+ .getattr = nilfs_getattr,
.permission = nilfs_permission,
.fiemap = nilfs_fiemap,
.fileattr_get = nilfs_fileattr_get,
@@ -554,6 +555,7 @@ const struct inode_operations nilfs_dir_inode_operations = {
const struct inode_operations nilfs_special_inode_operations = {
.setattr = nilfs_setattr,
+ .getattr = nilfs_getattr,
.permission = nilfs_permission,
};
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 4017f7856440..c2182bb660bf 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -280,6 +280,8 @@ extern void nilfs_truncate(struct inode *);
extern void nilfs_evict_inode(struct inode *);
extern int nilfs_setattr(struct mnt_idmap *, struct dentry *,
struct iattr *);
+extern int nilfs_getattr(struct mnt_idmap *idmap, const struct path *path,
+ struct kstat *stat, u3 request_mask, unsigned int query_flags);
extern void nilfs_write_failed(struct address_space *mapping, loff_t to);
int nilfs_permission(struct mnt_idmap *idmap, struct inode *inode,
int mask);