Commit 0725a704 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'zonefs-6.5-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/zonefs

Pull zonefs fix from Damien Le Moal:

 - The switch to using iomap for executing a direct synchronous write to
   sequential files using a zone append BIO overlooked cases where the
   BIO built by iomap is too large and needs splitting, which is not
   allowed with zone append.

   Fix this by using regular write commands instead. The use of zone
   append commands will be reintroduced later with proper support from
   iomap.

* tag 'zonefs-6.5-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/zonefs:
  zonefs: fix synchronous direct writes to sequential files
parents 5512c33c fe9da61f
......@@ -341,77 +341,6 @@ static loff_t zonefs_file_llseek(struct file *file, loff_t offset, int whence)
return generic_file_llseek_size(file, offset, whence, isize, isize);
}
struct zonefs_zone_append_bio {
/* The target inode of the BIO */
struct inode *inode;
/* For sync writes, the target append write offset */
u64 append_offset;
/*
* This member must come last, bio_alloc_bioset will allocate enough
* bytes for entire zonefs_bio but relies on bio being last.
*/
struct bio bio;
};
static inline struct zonefs_zone_append_bio *
zonefs_zone_append_bio(struct bio *bio)
{
return container_of(bio, struct zonefs_zone_append_bio, bio);
}
static void zonefs_file_zone_append_dio_bio_end_io(struct bio *bio)
{
struct zonefs_zone_append_bio *za_bio = zonefs_zone_append_bio(bio);
struct zonefs_zone *z = zonefs_inode_zone(za_bio->inode);
sector_t za_sector;
if (bio->bi_status != BLK_STS_OK)
goto bio_end;
/*
* If the file zone was written underneath the file system, the zone
* append operation can still succedd (if the zone is not full) but
* the write append location will not be where we expect it to be.
* Check that we wrote where we intended to, that is, at z->z_wpoffset.
*/
za_sector = z->z_sector + (za_bio->append_offset >> SECTOR_SHIFT);
if (bio->bi_iter.bi_sector != za_sector) {
zonefs_warn(za_bio->inode->i_sb,
"Invalid write sector %llu for zone at %llu\n",
bio->bi_iter.bi_sector, z->z_sector);
bio->bi_status = BLK_STS_IOERR;
}
bio_end:
iomap_dio_bio_end_io(bio);
}
static void zonefs_file_zone_append_dio_submit_io(const struct iomap_iter *iter,
struct bio *bio,
loff_t file_offset)
{
struct zonefs_zone_append_bio *za_bio = zonefs_zone_append_bio(bio);
struct inode *inode = iter->inode;
struct zonefs_zone *z = zonefs_inode_zone(inode);
/*
* Issue a zone append BIO to process sync dio writes. The append
* file offset is saved to check the zone append write location
* on completion of the BIO.
*/
za_bio->inode = inode;
za_bio->append_offset = file_offset;
bio->bi_opf &= ~REQ_OP_WRITE;
bio->bi_opf |= REQ_OP_ZONE_APPEND;
bio->bi_iter.bi_sector = z->z_sector;
bio->bi_end_io = zonefs_file_zone_append_dio_bio_end_io;
submit_bio(bio);
}
static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size,
int error, unsigned int flags)
{
......@@ -442,14 +371,6 @@ static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size,
return 0;
}
static struct bio_set zonefs_zone_append_bio_set;
static const struct iomap_dio_ops zonefs_zone_append_dio_ops = {
.submit_io = zonefs_file_zone_append_dio_submit_io,
.end_io = zonefs_file_write_dio_end_io,
.bio_set = &zonefs_zone_append_bio_set,
};
static const struct iomap_dio_ops zonefs_write_dio_ops = {
.end_io = zonefs_file_write_dio_end_io,
};
......@@ -533,9 +454,6 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
struct zonefs_inode_info *zi = ZONEFS_I(inode);
struct zonefs_zone *z = zonefs_inode_zone(inode);
struct super_block *sb = inode->i_sb;
const struct iomap_dio_ops *dio_ops;
bool sync = is_sync_kiocb(iocb);
bool append = false;
ssize_t ret, count;
/*
......@@ -543,7 +461,8 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
* as this can cause write reordering (e.g. the first aio gets EAGAIN
* on the inode lock but the second goes through but is now unaligned).
*/
if (zonefs_zone_is_seq(z) && !sync && (iocb->ki_flags & IOCB_NOWAIT))
if (zonefs_zone_is_seq(z) && !is_sync_kiocb(iocb) &&
(iocb->ki_flags & IOCB_NOWAIT))
return -EOPNOTSUPP;
if (iocb->ki_flags & IOCB_NOWAIT) {
......@@ -573,18 +492,6 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
goto inode_unlock;
}
mutex_unlock(&zi->i_truncate_mutex);
append = sync;
}
if (append) {
unsigned int max = bdev_max_zone_append_sectors(sb->s_bdev);
max = ALIGN_DOWN(max << SECTOR_SHIFT, sb->s_blocksize);
iov_iter_truncate(from, max);
dio_ops = &zonefs_zone_append_dio_ops;
} else {
dio_ops = &zonefs_write_dio_ops;
}
/*
......@@ -593,7 +500,7 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
* the user can make sense of the error.
*/
ret = iomap_dio_rw(iocb, from, &zonefs_write_iomap_ops,
dio_ops, 0, NULL, 0);
&zonefs_write_dio_ops, 0, NULL, 0);
if (ret == -ENOTBLK)
ret = -EBUSY;
......@@ -938,15 +845,3 @@ const struct file_operations zonefs_file_operations = {
.splice_write = iter_file_splice_write,
.iopoll = iocb_bio_iopoll,
};
int zonefs_file_bioset_init(void)
{
return bioset_init(&zonefs_zone_append_bio_set, BIO_POOL_SIZE,
offsetof(struct zonefs_zone_append_bio, bio),
BIOSET_NEED_BVECS);
}
void zonefs_file_bioset_exit(void)
{
bioset_exit(&zonefs_zone_append_bio_set);
}
......@@ -1412,13 +1412,9 @@ static int __init zonefs_init(void)
BUILD_BUG_ON(sizeof(struct zonefs_super) != ZONEFS_SUPER_SIZE);
ret = zonefs_file_bioset_init();
if (ret)
return ret;
ret = zonefs_init_inodecache();
if (ret)
goto destroy_bioset;
return ret;
ret = zonefs_sysfs_init();
if (ret)
......@@ -1434,8 +1430,6 @@ static int __init zonefs_init(void)
zonefs_sysfs_exit();
destroy_inodecache:
zonefs_destroy_inodecache();
destroy_bioset:
zonefs_file_bioset_exit();
return ret;
}
......@@ -1445,7 +1439,6 @@ static void __exit zonefs_exit(void)
unregister_filesystem(&zonefs_type);
zonefs_sysfs_exit();
zonefs_destroy_inodecache();
zonefs_file_bioset_exit();
}
MODULE_AUTHOR("Damien Le Moal");
......
......@@ -279,8 +279,6 @@ extern const struct file_operations zonefs_dir_operations;
extern const struct address_space_operations zonefs_file_aops;
extern const struct file_operations zonefs_file_operations;
int zonefs_file_truncate(struct inode *inode, loff_t isize);
int zonefs_file_bioset_init(void);
void zonefs_file_bioset_exit(void);
/* In sysfs.c */
int zonefs_sysfs_register(struct super_block *sb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment