@@ -5,6 +5,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*/
+#include <linux/blkdev.h>
#include <linux/export.h>
#include <linux/mm.h>
#include <linux/errno.h>
@@ -198,6 +199,35 @@ int getname_statx_lookup_flags(int flags)
return lookup_flags;
}
+/* Handle STATX_DIOALIGN for block devices. */
+static inline void handle_bdev_dioalign(struct path *path, u32 request_mask,
+ struct kstat *stat)
+{
+#ifdef CONFIG_BLOCK
+ struct inode *inode;
+ struct block_device *bdev;
+ unsigned int lbs;
+
+ if (likely(!(request_mask & STATX_DIOALIGN)))
+ return;
+
+ inode = d_backing_inode(path->dentry);
+ if (!S_ISBLK(inode->i_mode))
+ return;
+
+ bdev = blkdev_get_no_open(inode->i_rdev);
+ if (!bdev)
+ return;
+
+ lbs = bdev_logical_block_size(bdev);
+ stat->dio_mem_align = lbs;
+ stat->dio_offset_align = lbs;
+ stat->result_mask |= STATX_DIOALIGN;
+
+ blkdev_put_no_open(bdev);
+#endif /* CONFIG_BLOCK */
+}
+
/**
* vfs_statx - Get basic and extra attributes by filename
* @dfd: A file descriptor representing the base dir for a relative filename
@@ -230,11 +260,16 @@ static int vfs_statx(int dfd, struct filename *filename, int flags,
goto out;
error = vfs_getattr(&path, stat, request_mask, flags);
+
stat->mnt_id = real_mount(path.mnt)->mnt_id;
stat->result_mask |= STATX_MNT_ID;
+
if (path.mnt->mnt_root == path.dentry)
stat->attributes |= STATX_ATTR_MOUNT_ROOT;
stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
+
+ handle_bdev_dioalign(&path, request_mask, stat);
+
path_put(&path);
if (retry_estale(error, lookup_flags)) {
lookup_flags |= LOOKUP_REVAL;