Skip to content

Commit 9abcfbd

Browse files
npsingamsettyaxboe
authored andcommitted
block: Add atomic write support for statx
Extend statx system call to return additional info for atomic write support support if the specified file is a block device. Reviewed-by: Martin K. Petersen <[email protected]> Signed-off-by: Prasad Singamsetty <[email protected]> Signed-off-by: John Garry <[email protected]> Reviewed-by: Keith Busch <[email protected]> Acked-by: Darrick J. Wong <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Reviewed-by: Luis Chamberlain <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 9da3d1e commit 9abcfbd

File tree

3 files changed

+39
-19
lines changed

3 files changed

+39
-19
lines changed

block/bdev.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,23 +1260,39 @@ void sync_bdevs(bool wait)
12601260
}
12611261

12621262
/*
1263-
* Handle STATX_DIOALIGN for block devices.
1264-
*
1265-
* Note that the inode passed to this is the inode of a block device node file,
1266-
* not the block device's internal inode. Therefore it is *not* valid to use
1267-
* I_BDEV() here; the block device has to be looked up by i_rdev instead.
1263+
* Handle STATX_{DIOALIGN, WRITE_ATOMIC} for block devices.
12681264
*/
1269-
void bdev_statx_dioalign(struct inode *inode, struct kstat *stat)
1265+
void bdev_statx(struct inode *backing_inode, struct kstat *stat,
1266+
u32 request_mask)
12701267
{
12711268
struct block_device *bdev;
12721269

1273-
bdev = blkdev_get_no_open(inode->i_rdev);
1270+
if (!(request_mask & (STATX_DIOALIGN | STATX_WRITE_ATOMIC)))
1271+
return;
1272+
1273+
/*
1274+
* Note that backing_inode is the inode of a block device node file,
1275+
* not the block device's internal inode. Therefore it is *not* valid
1276+
* to use I_BDEV() here; the block device has to be looked up by i_rdev
1277+
* instead.
1278+
*/
1279+
bdev = blkdev_get_no_open(backing_inode->i_rdev);
12741280
if (!bdev)
12751281
return;
12761282

1277-
stat->dio_mem_align = bdev_dma_alignment(bdev) + 1;
1278-
stat->dio_offset_align = bdev_logical_block_size(bdev);
1279-
stat->result_mask |= STATX_DIOALIGN;
1283+
if (request_mask & STATX_DIOALIGN) {
1284+
stat->dio_mem_align = bdev_dma_alignment(bdev) + 1;
1285+
stat->dio_offset_align = bdev_logical_block_size(bdev);
1286+
stat->result_mask |= STATX_DIOALIGN;
1287+
}
1288+
1289+
if (request_mask & STATX_WRITE_ATOMIC && bdev_can_atomic_write(bdev)) {
1290+
struct request_queue *bd_queue = bdev->bd_queue;
1291+
1292+
generic_fill_statx_atomic_writes(stat,
1293+
queue_atomic_write_unit_min_bytes(bd_queue),
1294+
queue_atomic_write_unit_max_bytes(bd_queue));
1295+
}
12801296

12811297
blkdev_put_no_open(bdev);
12821298
}

fs/stat.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ static int vfs_statx(int dfd, struct filename *filename, int flags,
265265
{
266266
struct path path;
267267
unsigned int lookup_flags = getname_statx_lookup_flags(flags);
268+
struct inode *backing_inode;
268269
int error;
269270

270271
if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH |
@@ -290,13 +291,14 @@ static int vfs_statx(int dfd, struct filename *filename, int flags,
290291
stat->attributes |= STATX_ATTR_MOUNT_ROOT;
291292
stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
292293

293-
/* Handle STATX_DIOALIGN for block devices. */
294-
if (request_mask & STATX_DIOALIGN) {
295-
struct inode *inode = d_backing_inode(path.dentry);
296-
297-
if (S_ISBLK(inode->i_mode))
298-
bdev_statx_dioalign(inode, stat);
299-
}
294+
/*
295+
* If this is a block device inode, override the filesystem
296+
* attributes with the block device specific parameters that need to be
297+
* obtained from the bdev backing inode.
298+
*/
299+
backing_inode = d_backing_inode(path.dentry);
300+
if (S_ISBLK(backing_inode->i_mode))
301+
bdev_statx(backing_inode, stat, request_mask);
300302

301303
path_put(&path);
302304
if (retry_estale(error, lookup_flags)) {

include/linux/blkdev.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,7 +1638,8 @@ int sync_blockdev(struct block_device *bdev);
16381638
int sync_blockdev_range(struct block_device *bdev, loff_t lstart, loff_t lend);
16391639
int sync_blockdev_nowait(struct block_device *bdev);
16401640
void sync_bdevs(bool wait);
1641-
void bdev_statx_dioalign(struct inode *inode, struct kstat *stat);
1641+
void bdev_statx(struct inode *backing_inode, struct kstat *stat,
1642+
u32 request_mask);
16421643
void printk_all_partitions(void);
16431644
int __init early_lookup_bdev(const char *pathname, dev_t *dev);
16441645
#else
@@ -1656,7 +1657,8 @@ static inline int sync_blockdev_nowait(struct block_device *bdev)
16561657
static inline void sync_bdevs(bool wait)
16571658
{
16581659
}
1659-
static inline void bdev_statx_dioalign(struct inode *inode, struct kstat *stat)
1660+
static inline void bdev_statx(struct inode *backing_inode, struct kstat *stat,
1661+
u32 request_mask)
16601662
{
16611663
}
16621664
static inline void printk_all_partitions(void)

0 commit comments

Comments
 (0)