Skip to content

Commit

Permalink
fs: move the bdex_statx call to vfs_getattr_nosec
Browse files Browse the repository at this point in the history
Currently bdex_statx is only called from the very high-level
vfs_statx_path function, and thus bypassing it for in-kernel calls
to vfs_getattr or vfs_getattr_nosec.

This breaks querying the block ѕize of the underlying device in the
loop driver and also is a pitfall for any other new kernel caller.

Move the call into the lowest level helper to ensure all callers get
the right results.

Fixes: 2d985f8 ("vfs: support STATX_DIOALIGN on block devices")
Fixes: f4774e9 ("loop: take the file system minimum dio alignment into account")
Reported-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/20250417064042.712140-1-hch@lst.de
Signed-off-by: Christian Brauner <brauner@kernel.org>
  • Loading branch information
Christoph Hellwig authored and Christian Brauner committed Apr 17, 2025
1 parent 58db1c3 commit 777d096
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 19 deletions.
3 changes: 1 addition & 2 deletions block/bdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1272,8 +1272,7 @@ void sync_bdevs(bool wait)
/*
* Handle STATX_{DIOALIGN, WRITE_ATOMIC} for block devices.
*/
void bdev_statx(struct path *path, struct kstat *stat,
u32 request_mask)
void bdev_statx(const struct path *path, struct kstat *stat, u32 request_mask)
{
struct inode *backing_inode;
struct block_device *bdev;
Expand Down
32 changes: 18 additions & 14 deletions fs/stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,25 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
STATX_ATTR_DAX);

idmap = mnt_idmap(path->mnt);
if (inode->i_op->getattr)
return inode->i_op->getattr(idmap, path, stat,
request_mask,
query_flags);
if (inode->i_op->getattr) {
int ret;

ret = inode->i_op->getattr(idmap, path, stat, request_mask,
query_flags);
if (ret)
return ret;
} else {
generic_fillattr(idmap, request_mask, inode, stat);
}

/*
* If this is a block device inode, override the filesystem attributes
* with the block device specific parameters that need to be obtained
* from the bdev backing inode.
*/
if (S_ISBLK(stat->mode))
bdev_statx(path, stat, request_mask);

generic_fillattr(idmap, request_mask, inode, stat);
return 0;
}
EXPORT_SYMBOL(vfs_getattr_nosec);
Expand Down Expand Up @@ -295,15 +308,6 @@ static int vfs_statx_path(struct path *path, int flags, struct kstat *stat,
if (path_mounted(path))
stat->attributes |= STATX_ATTR_MOUNT_ROOT;
stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;

/*
* If this is a block device inode, override the filesystem
* attributes with the block device specific parameters that need to be
* obtained from the bdev backing inode.
*/
if (S_ISBLK(stat->mode))
bdev_statx(path, stat, request_mask);

return 0;
}

Expand Down
6 changes: 3 additions & 3 deletions include/linux/blkdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -1685,7 +1685,7 @@ int sync_blockdev(struct block_device *bdev);
int sync_blockdev_range(struct block_device *bdev, loff_t lstart, loff_t lend);
int sync_blockdev_nowait(struct block_device *bdev);
void sync_bdevs(bool wait);
void bdev_statx(struct path *, struct kstat *, u32);
void bdev_statx(const struct path *path, struct kstat *stat, u32 request_mask);
void printk_all_partitions(void);
int __init early_lookup_bdev(const char *pathname, dev_t *dev);
#else
Expand All @@ -1703,8 +1703,8 @@ static inline int sync_blockdev_nowait(struct block_device *bdev)
static inline void sync_bdevs(bool wait)
{
}
static inline void bdev_statx(struct path *path, struct kstat *stat,
u32 request_mask)
static inline void bdev_statx(const struct path *path, struct kstat *stat,
u32 request_mask)
{
}
static inline void printk_all_partitions(void)
Expand Down

0 comments on commit 777d096

Please sign in to comment.