Message ID | 20250415003308.GE25675@frogsfrogsfrogs (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [RF[CRAP] 2/2] xfs: stop using set_blocksize | expand |
On Mon, Apr 14, 2025 at 05:33:08PM -0700, Darrick J. Wong wrote: > +/* > + * For bdev filesystems that do not use buffer heads, check that this block > + * size is acceptable and flush dirty pagecache to disk. > + */ Can you turn this into a full fledged kerneldoc comment? > +int bdev_use_blocksize(struct file *file, int size) > +{ > + struct inode *inode = file->f_mapping->host; > + struct block_device *bdev = I_BDEV(inode); > + > + if (blk_validate_block_size(size)) > + return -EINVAL; > + > + /* Size cannot be smaller than the size supported by the device */ > + if (size < bdev_logical_block_size(bdev)) > + return -EINVAL; > + > + if (!file->private_data) > + return -EINVAL; This private_data check looks really confusing. Looking it up I see that it is directly copied from set_blocksize, but it could really use a comment. Or in fact be removed here and kept in set_blocksize only as we don't care about an exclusive opener at all. Even there a comment would be rather helpful, though. > + > + return sync_blockdev(bdev); > +} I don't think we need sync_blockdev here as we don't touch the bdev page cache. Maybe XFS wants to still call it, but it feels wrong in a helper just validating the block size. So maybe drop it, rename the helper to bdev_validate_block_size and use it in set_blocksize instead of duplicating the logic? > + error = bdev_use_blocksize(btp->bt_bdev_file, sectorsize); .. and then split using it in XFS into a separate patch from adding the block layer helper.
On Tue, Apr 15, 2025 at 09:46:09PM -0700, Christoph Hellwig wrote: > On Mon, Apr 14, 2025 at 05:33:08PM -0700, Darrick J. Wong wrote: > > +/* > > + * For bdev filesystems that do not use buffer heads, check that this block > > + * size is acceptable and flush dirty pagecache to disk. > > + */ > > Can you turn this into a full fledged kerneldoc comment? Ok. > > +int bdev_use_blocksize(struct file *file, int size) > > +{ > > + struct inode *inode = file->f_mapping->host; > > + struct block_device *bdev = I_BDEV(inode); > > + > > + if (blk_validate_block_size(size)) > > + return -EINVAL; > > + > > + /* Size cannot be smaller than the size supported by the device */ > > + if (size < bdev_logical_block_size(bdev)) > > + return -EINVAL; > > + > > + if (!file->private_data) > > + return -EINVAL; > > This private_data check looks really confusing. Looking it up I see > that it is directly copied from set_blocksize, but it could really > use a comment. Or in fact be removed here and kept in set_blocksize > only as we don't care about an exclusive opener at all. Even there > a comment would be rather helpful, though. When even is it null? I thought it would either be the holder or bdev_inode if not. > > + > > + return sync_blockdev(bdev); > > +} > > I don't think we need sync_blockdev here as we don't touch the > bdev page cache. Maybe XFS wants to still call it, but it feels > wrong in a helper just validating the block size. > > So maybe drop it, rename the helper to bdev_validate_block_size > and use it in set_blocksize instead of duplicating the logic? Ok. bdev_validate_block_size is a much better name for a tighter function... > > + error = bdev_use_blocksize(btp->bt_bdev_file, sectorsize); > > .. and then split using it in XFS into a separate patch from adding > the block layer helper. ...and xfs can call sync_blockdev directly from xfs_setsize_buftarg. I imagine we still want any dirty pagecache to get flushed before we start submitting our own read bios. --D
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index f442639dfae224..ae83dd12351c2e 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1618,6 +1618,7 @@ static inline void bio_end_io_acct(struct bio *bio, unsigned long start_time) return bio_end_io_acct_remapped(bio, start_time, bio->bi_bdev); } +int bdev_use_blocksize(struct file *file, int size); int set_blocksize(struct file *file, int size); int lookup_bdev(const char *pathname, dev_t *dev); diff --git a/block/bdev.c b/block/bdev.c index 0cbdac46d98d86..201d61d743592e 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -152,6 +152,29 @@ static void set_init_blocksize(struct block_device *bdev) get_order(bsize), get_order(bsize)); } +/* + * For bdev filesystems that do not use buffer heads, check that this block + * size is acceptable and flush dirty pagecache to disk. + */ +int bdev_use_blocksize(struct file *file, int size) +{ + struct inode *inode = file->f_mapping->host; + struct block_device *bdev = I_BDEV(inode); + + if (blk_validate_block_size(size)) + return -EINVAL; + + /* Size cannot be smaller than the size supported by the device */ + if (size < bdev_logical_block_size(bdev)) + return -EINVAL; + + if (!file->private_data) + return -EINVAL; + + return sync_blockdev(bdev); +} +EXPORT_SYMBOL_GPL(bdev_use_blocksize); + int set_blocksize(struct file *file, int size) { struct inode *inode = file->f_mapping->host; diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 8e7f1b324b3bea..2c8531103c01bb 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1718,14 +1718,17 @@ xfs_setsize_buftarg( struct xfs_buftarg *btp, unsigned int sectorsize) { + int error; + /* Set up metadata sector size info */ btp->bt_meta_sectorsize = sectorsize; btp->bt_meta_sectormask = sectorsize - 1; - if (set_blocksize(btp->bt_bdev_file, sectorsize)) { + error = bdev_use_blocksize(btp->bt_bdev_file, sectorsize); + if (error) { xfs_warn(btp->bt_mount, - "Cannot set_blocksize to %u on device %pg", - sectorsize, btp->bt_bdev); + "Cannot use blocksize %u on device %pg, err %d", + sectorsize, btp->bt_bdev, error); return -EINVAL; }