Skip to content

Commit aa7f243

Browse files
author
Damien Le Moal
committed
zonefs: Separate zone information from inode information
In preparation for adding dynamic inode allocation, separate an inode zone information from the zonefs inode structure. The new data structure zonefs_zone is introduced to store in memory information about a zone that must be kept throughout the lifetime of the device mount. Linking between a zone file inode and its zone information is done by setting the inode i_private field to point to a struct zonefs_zone. Using the i_private pointer avoids the need for adding a pointer in struct zonefs_inode_info. Beside the vfs inode, this structure is reduced to a mutex and a write open counter. One struct zonefs_zone is created per file inode on mount. These structures are organized in an array using the new struct zonefs_zone_group data structure to represent zone groups. The zonefs_zone arrays are indexed per file number (the index of a struct zonefs_zone in its array directly gives the file number/name for that zone file inode). Signed-off-by: Damien Le Moal <[email protected]> Reviewed-by: Johannes Thumshirn <[email protected]>
1 parent 3442291 commit aa7f243

File tree

4 files changed

+449
-304
lines changed

4 files changed

+449
-304
lines changed

fs/zonefs/file.c

Lines changed: 55 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ static int zonefs_read_iomap_begin(struct inode *inode, loff_t offset,
2929
struct iomap *iomap, struct iomap *srcmap)
3030
{
3131
struct zonefs_inode_info *zi = ZONEFS_I(inode);
32+
struct zonefs_zone *z = zonefs_inode_zone(inode);
3233
struct super_block *sb = inode->i_sb;
3334
loff_t isize;
3435

@@ -46,7 +47,7 @@ static int zonefs_read_iomap_begin(struct inode *inode, loff_t offset,
4647
iomap->length = length;
4748
} else {
4849
iomap->type = IOMAP_MAPPED;
49-
iomap->addr = (zi->i_zsector << SECTOR_SHIFT) + iomap->offset;
50+
iomap->addr = (z->z_sector << SECTOR_SHIFT) + iomap->offset;
5051
iomap->length = isize - iomap->offset;
5152
}
5253
mutex_unlock(&zi->i_truncate_mutex);
@@ -65,19 +66,20 @@ static int zonefs_write_iomap_begin(struct inode *inode, loff_t offset,
6566
struct iomap *iomap, struct iomap *srcmap)
6667
{
6768
struct zonefs_inode_info *zi = ZONEFS_I(inode);
69+
struct zonefs_zone *z = zonefs_inode_zone(inode);
6870
struct super_block *sb = inode->i_sb;
6971
loff_t isize;
7072

7173
/* All write I/Os should always be within the file maximum size */
72-
if (WARN_ON_ONCE(offset + length > zi->i_max_size))
74+
if (WARN_ON_ONCE(offset + length > z->z_capacity))
7375
return -EIO;
7476

7577
/*
7678
* Sequential zones can only accept direct writes. This is already
7779
* checked when writes are issued, so warn if we see a page writeback
7880
* operation.
7981
*/
80-
if (WARN_ON_ONCE(zonefs_zone_is_seq(zi) && !(flags & IOMAP_DIRECT)))
82+
if (WARN_ON_ONCE(zonefs_zone_is_seq(z) && !(flags & IOMAP_DIRECT)))
8183
return -EIO;
8284

8385
/*
@@ -88,11 +90,11 @@ static int zonefs_write_iomap_begin(struct inode *inode, loff_t offset,
8890
mutex_lock(&zi->i_truncate_mutex);
8991
iomap->bdev = inode->i_sb->s_bdev;
9092
iomap->offset = ALIGN_DOWN(offset, sb->s_blocksize);
91-
iomap->addr = (zi->i_zsector << SECTOR_SHIFT) + iomap->offset;
93+
iomap->addr = (z->z_sector << SECTOR_SHIFT) + iomap->offset;
9294
isize = i_size_read(inode);
9395
if (iomap->offset >= isize) {
9496
iomap->type = IOMAP_UNWRITTEN;
95-
iomap->length = zi->i_max_size - iomap->offset;
97+
iomap->length = z->z_capacity - iomap->offset;
9698
} else {
9799
iomap->type = IOMAP_MAPPED;
98100
iomap->length = isize - iomap->offset;
@@ -125,9 +127,9 @@ static void zonefs_readahead(struct readahead_control *rac)
125127
static int zonefs_write_map_blocks(struct iomap_writepage_ctx *wpc,
126128
struct inode *inode, loff_t offset)
127129
{
128-
struct zonefs_inode_info *zi = ZONEFS_I(inode);
130+
struct zonefs_zone *z = zonefs_inode_zone(inode);
129131

130-
if (WARN_ON_ONCE(zonefs_zone_is_seq(zi)))
132+
if (WARN_ON_ONCE(zonefs_zone_is_seq(z)))
131133
return -EIO;
132134
if (WARN_ON_ONCE(offset >= i_size_read(inode)))
133135
return -EIO;
@@ -137,7 +139,8 @@ static int zonefs_write_map_blocks(struct iomap_writepage_ctx *wpc,
137139
offset < wpc->iomap.offset + wpc->iomap.length)
138140
return 0;
139141

140-
return zonefs_write_iomap_begin(inode, offset, zi->i_max_size - offset,
142+
return zonefs_write_iomap_begin(inode, offset,
143+
z->z_capacity - offset,
141144
IOMAP_WRITE, &wpc->iomap, NULL);
142145
}
143146

@@ -185,6 +188,7 @@ const struct address_space_operations zonefs_file_aops = {
185188
int zonefs_file_truncate(struct inode *inode, loff_t isize)
186189
{
187190
struct zonefs_inode_info *zi = ZONEFS_I(inode);
191+
struct zonefs_zone *z = zonefs_inode_zone(inode);
188192
loff_t old_isize;
189193
enum req_op op;
190194
int ret = 0;
@@ -194,12 +198,12 @@ int zonefs_file_truncate(struct inode *inode, loff_t isize)
194198
* only down to a 0 size, which is equivalent to a zone reset, and to
195199
* the maximum file size, which is equivalent to a zone finish.
196200
*/
197-
if (!zonefs_zone_is_seq(zi))
201+
if (!zonefs_zone_is_seq(z))
198202
return -EPERM;
199203

200204
if (!isize)
201205
op = REQ_OP_ZONE_RESET;
202-
else if (isize == zi->i_max_size)
206+
else if (isize == z->z_capacity)
203207
op = REQ_OP_ZONE_FINISH;
204208
else
205209
return -EPERM;
@@ -216,15 +220,15 @@ int zonefs_file_truncate(struct inode *inode, loff_t isize)
216220
if (isize == old_isize)
217221
goto unlock;
218222

219-
ret = zonefs_zone_mgmt(inode, op);
223+
ret = zonefs_inode_zone_mgmt(inode, op);
220224
if (ret)
221225
goto unlock;
222226

223227
/*
224228
* If the mount option ZONEFS_MNTOPT_EXPLICIT_OPEN is set,
225229
* take care of open zones.
226230
*/
227-
if (zi->i_flags & ZONEFS_ZONE_OPEN) {
231+
if (z->z_flags & ZONEFS_ZONE_OPEN) {
228232
/*
229233
* Truncating a zone to EMPTY or FULL is the equivalent of
230234
* closing the zone. For a truncation to 0, we need to
@@ -234,15 +238,15 @@ int zonefs_file_truncate(struct inode *inode, loff_t isize)
234238
* the open flag.
235239
*/
236240
if (!isize)
237-
ret = zonefs_zone_mgmt(inode, REQ_OP_ZONE_OPEN);
241+
ret = zonefs_inode_zone_mgmt(inode, REQ_OP_ZONE_OPEN);
238242
else
239-
zi->i_flags &= ~ZONEFS_ZONE_OPEN;
243+
z->z_flags &= ~ZONEFS_ZONE_OPEN;
240244
}
241245

242246
zonefs_update_stats(inode, isize);
243247
truncate_setsize(inode, isize);
244-
zi->i_wpoffset = isize;
245-
zonefs_account_active(inode);
248+
z->z_wpoffset = isize;
249+
zonefs_inode_account_active(inode);
246250

247251
unlock:
248252
mutex_unlock(&zi->i_truncate_mutex);
@@ -349,7 +353,7 @@ static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size,
349353
return error;
350354
}
351355

352-
if (size && zonefs_zone_is_seq(zi)) {
356+
if (size && zonefs_inode_is_seq(inode)) {
353357
/*
354358
* Note that we may be seeing completions out of order,
355359
* but that is not a problem since a write completed
@@ -375,7 +379,7 @@ static const struct iomap_dio_ops zonefs_write_dio_ops = {
375379
static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
376380
{
377381
struct inode *inode = file_inode(iocb->ki_filp);
378-
struct zonefs_inode_info *zi = ZONEFS_I(inode);
382+
struct zonefs_zone *z = zonefs_inode_zone(inode);
379383
struct block_device *bdev = inode->i_sb->s_bdev;
380384
unsigned int max = bdev_max_zone_append_sectors(bdev);
381385
struct bio *bio;
@@ -392,7 +396,7 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
392396

393397
bio = bio_alloc(bdev, nr_pages,
394398
REQ_OP_ZONE_APPEND | REQ_SYNC | REQ_IDLE, GFP_NOFS);
395-
bio->bi_iter.bi_sector = zi->i_zsector;
399+
bio->bi_iter.bi_sector = z->z_sector;
396400
bio->bi_ioprio = iocb->ki_ioprio;
397401
if (iocb_is_dsync(iocb))
398402
bio->bi_opf |= REQ_FUA;
@@ -417,12 +421,12 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
417421
*/
418422
if (!ret) {
419423
sector_t wpsector =
420-
zi->i_zsector + (zi->i_wpoffset >> SECTOR_SHIFT);
424+
z->z_sector + (z->z_wpoffset >> SECTOR_SHIFT);
421425

422426
if (bio->bi_iter.bi_sector != wpsector) {
423427
zonefs_warn(inode->i_sb,
424428
"Corrupted write pointer %llu for zone at %llu\n",
425-
wpsector, zi->i_zsector);
429+
wpsector, z->z_sector);
426430
ret = -EIO;
427431
}
428432
}
@@ -450,9 +454,9 @@ static loff_t zonefs_write_check_limits(struct file *file, loff_t pos,
450454
loff_t count)
451455
{
452456
struct inode *inode = file_inode(file);
453-
struct zonefs_inode_info *zi = ZONEFS_I(inode);
457+
struct zonefs_zone *z = zonefs_inode_zone(inode);
454458
loff_t limit = rlimit(RLIMIT_FSIZE);
455-
loff_t max_size = zi->i_max_size;
459+
loff_t max_size = z->z_capacity;
456460

457461
if (limit != RLIM_INFINITY) {
458462
if (pos >= limit) {
@@ -476,6 +480,7 @@ static ssize_t zonefs_write_checks(struct kiocb *iocb, struct iov_iter *from)
476480
struct file *file = iocb->ki_filp;
477481
struct inode *inode = file_inode(file);
478482
struct zonefs_inode_info *zi = ZONEFS_I(inode);
483+
struct zonefs_zone *z = zonefs_inode_zone(inode);
479484
loff_t count;
480485

481486
if (IS_SWAPFILE(inode))
@@ -488,10 +493,10 @@ static ssize_t zonefs_write_checks(struct kiocb *iocb, struct iov_iter *from)
488493
return -EINVAL;
489494

490495
if (iocb->ki_flags & IOCB_APPEND) {
491-
if (zonefs_zone_is_cnv(zi))
496+
if (zonefs_zone_is_cnv(z))
492497
return -EINVAL;
493498
mutex_lock(&zi->i_truncate_mutex);
494-
iocb->ki_pos = zi->i_wpoffset;
499+
iocb->ki_pos = z->z_wpoffset;
495500
mutex_unlock(&zi->i_truncate_mutex);
496501
}
497502

@@ -518,6 +523,7 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
518523
{
519524
struct inode *inode = file_inode(iocb->ki_filp);
520525
struct zonefs_inode_info *zi = ZONEFS_I(inode);
526+
struct zonefs_zone *z = zonefs_inode_zone(inode);
521527
struct super_block *sb = inode->i_sb;
522528
bool sync = is_sync_kiocb(iocb);
523529
bool append = false;
@@ -528,7 +534,7 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
528534
* as this can cause write reordering (e.g. the first aio gets EAGAIN
529535
* on the inode lock but the second goes through but is now unaligned).
530536
*/
531-
if (zonefs_zone_is_seq(zi) && !sync && (iocb->ki_flags & IOCB_NOWAIT))
537+
if (zonefs_zone_is_seq(z) && !sync && (iocb->ki_flags & IOCB_NOWAIT))
532538
return -EOPNOTSUPP;
533539

534540
if (iocb->ki_flags & IOCB_NOWAIT) {
@@ -550,9 +556,9 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
550556
}
551557

552558
/* Enforce sequential writes (append only) in sequential zones */
553-
if (zonefs_zone_is_seq(zi)) {
559+
if (zonefs_zone_is_seq(z)) {
554560
mutex_lock(&zi->i_truncate_mutex);
555-
if (iocb->ki_pos != zi->i_wpoffset) {
561+
if (iocb->ki_pos != z->z_wpoffset) {
556562
mutex_unlock(&zi->i_truncate_mutex);
557563
ret = -EINVAL;
558564
goto inode_unlock;
@@ -566,7 +572,7 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
566572
else
567573
ret = iomap_dio_rw(iocb, from, &zonefs_write_iomap_ops,
568574
&zonefs_write_dio_ops, 0, NULL, 0);
569-
if (zonefs_zone_is_seq(zi) &&
575+
if (zonefs_zone_is_seq(z) &&
570576
(ret > 0 || ret == -EIOCBQUEUED)) {
571577
if (ret > 0)
572578
count = ret;
@@ -577,8 +583,8 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
577583
* will correct it. Also do active seq file accounting.
578584
*/
579585
mutex_lock(&zi->i_truncate_mutex);
580-
zi->i_wpoffset += count;
581-
zonefs_account_active(inode);
586+
z->z_wpoffset += count;
587+
zonefs_inode_account_active(inode);
582588
mutex_unlock(&zi->i_truncate_mutex);
583589
}
584590

@@ -629,15 +635,16 @@ static ssize_t zonefs_file_buffered_write(struct kiocb *iocb,
629635
static ssize_t zonefs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
630636
{
631637
struct inode *inode = file_inode(iocb->ki_filp);
638+
struct zonefs_zone *z = zonefs_inode_zone(inode);
632639

633640
if (unlikely(IS_IMMUTABLE(inode)))
634641
return -EPERM;
635642

636643
if (sb_rdonly(inode->i_sb))
637644
return -EROFS;
638645

639-
/* Write operations beyond the zone size are not allowed */
640-
if (iocb->ki_pos >= ZONEFS_I(inode)->i_max_size)
646+
/* Write operations beyond the zone capacity are not allowed */
647+
if (iocb->ki_pos >= z->z_capacity)
641648
return -EFBIG;
642649

643650
if (iocb->ki_flags & IOCB_DIRECT) {
@@ -669,6 +676,7 @@ static ssize_t zonefs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
669676
{
670677
struct inode *inode = file_inode(iocb->ki_filp);
671678
struct zonefs_inode_info *zi = ZONEFS_I(inode);
679+
struct zonefs_zone *z = zonefs_inode_zone(inode);
672680
struct super_block *sb = inode->i_sb;
673681
loff_t isize;
674682
ssize_t ret;
@@ -677,7 +685,7 @@ static ssize_t zonefs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
677685
if (unlikely(IS_IMMUTABLE(inode) && !(inode->i_mode & 0777)))
678686
return -EPERM;
679687

680-
if (iocb->ki_pos >= zi->i_max_size)
688+
if (iocb->ki_pos >= z->z_capacity)
681689
return 0;
682690

683691
if (iocb->ki_flags & IOCB_NOWAIT) {
@@ -738,6 +746,7 @@ static inline bool zonefs_seq_file_need_wro(struct inode *inode,
738746
static int zonefs_seq_file_write_open(struct inode *inode)
739747
{
740748
struct zonefs_inode_info *zi = ZONEFS_I(inode);
749+
struct zonefs_zone *z = zonefs_inode_zone(inode);
741750
int ret = 0;
742751

743752
mutex_lock(&zi->i_truncate_mutex);
@@ -755,14 +764,15 @@ static int zonefs_seq_file_write_open(struct inode *inode)
755764
goto unlock;
756765
}
757766

758-
if (i_size_read(inode) < zi->i_max_size) {
759-
ret = zonefs_zone_mgmt(inode, REQ_OP_ZONE_OPEN);
767+
if (i_size_read(inode) < z->z_capacity) {
768+
ret = zonefs_inode_zone_mgmt(inode,
769+
REQ_OP_ZONE_OPEN);
760770
if (ret) {
761771
atomic_dec(&sbi->s_wro_seq_files);
762772
goto unlock;
763773
}
764-
zi->i_flags |= ZONEFS_ZONE_OPEN;
765-
zonefs_account_active(inode);
774+
z->z_flags |= ZONEFS_ZONE_OPEN;
775+
zonefs_inode_account_active(inode);
766776
}
767777
}
768778
}
@@ -792,6 +802,7 @@ static int zonefs_file_open(struct inode *inode, struct file *file)
792802
static void zonefs_seq_file_write_close(struct inode *inode)
793803
{
794804
struct zonefs_inode_info *zi = ZONEFS_I(inode);
805+
struct zonefs_zone *z = zonefs_inode_zone(inode);
795806
struct super_block *sb = inode->i_sb;
796807
struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
797808
int ret = 0;
@@ -807,8 +818,8 @@ static void zonefs_seq_file_write_close(struct inode *inode)
807818
* its maximum size or it was fully written). For this case, we only
808819
* need to decrement the write open count.
809820
*/
810-
if (zi->i_flags & ZONEFS_ZONE_OPEN) {
811-
ret = zonefs_zone_mgmt(inode, REQ_OP_ZONE_CLOSE);
821+
if (z->z_flags & ZONEFS_ZONE_OPEN) {
822+
ret = zonefs_inode_zone_mgmt(inode, REQ_OP_ZONE_CLOSE);
812823
if (ret) {
813824
__zonefs_io_error(inode, false);
814825
/*
@@ -817,20 +828,20 @@ static void zonefs_seq_file_write_close(struct inode *inode)
817828
* exhausted). So take preventive action by remounting
818829
* read-only.
819830
*/
820-
if (zi->i_flags & ZONEFS_ZONE_OPEN &&
831+
if (z->z_flags & ZONEFS_ZONE_OPEN &&
821832
!(sb->s_flags & SB_RDONLY)) {
822833
zonefs_warn(sb,
823834
"closing zone at %llu failed %d\n",
824-
zi->i_zsector, ret);
835+
z->z_sector, ret);
825836
zonefs_warn(sb,
826837
"remounting filesystem read-only\n");
827838
sb->s_flags |= SB_RDONLY;
828839
}
829840
goto unlock;
830841
}
831842

832-
zi->i_flags &= ~ZONEFS_ZONE_OPEN;
833-
zonefs_account_active(inode);
843+
z->z_flags &= ~ZONEFS_ZONE_OPEN;
844+
zonefs_inode_account_active(inode);
834845
}
835846

836847
atomic_dec(&sbi->s_wro_seq_files);

0 commit comments

Comments
 (0)