Skip to content

Commit 1c273e1

Browse files
committed
Merge tag 'zonefs-5.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/zonefs
Pull zonefs fixes from Damien Le Moal: - fix inode write open reference count (Chao) - Fix wrong write offset for asynchronous O_APPEND writes (me) - Prevent use of sequential zone file as swap files (me) * tag 'zonefs-5.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/zonefs: zonefs: fix to update .i_wr_refcnt correctly in zonefs_open_zone() zonefs: Fix O_APPEND async write handling zonefs: prevent use of seq files as swap file
2 parents d626c69 + 6980d29 commit 1c273e1

File tree

1 file changed

+87
-14
lines changed

1 file changed

+87
-14
lines changed

fs/zonefs/super.c

Lines changed: 87 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,21 @@ static int zonefs_writepages(struct address_space *mapping,
165165
return iomap_writepages(mapping, wbc, &wpc, &zonefs_writeback_ops);
166166
}
167167

168+
static int zonefs_swap_activate(struct swap_info_struct *sis,
169+
struct file *swap_file, sector_t *span)
170+
{
171+
struct inode *inode = file_inode(swap_file);
172+
struct zonefs_inode_info *zi = ZONEFS_I(inode);
173+
174+
if (zi->i_ztype != ZONEFS_ZTYPE_CNV) {
175+
zonefs_err(inode->i_sb,
176+
"swap file: not a conventional zone file\n");
177+
return -EINVAL;
178+
}
179+
180+
return iomap_swapfile_activate(sis, swap_file, span, &zonefs_iomap_ops);
181+
}
182+
168183
static const struct address_space_operations zonefs_file_aops = {
169184
.readpage = zonefs_readpage,
170185
.readahead = zonefs_readahead,
@@ -177,6 +192,7 @@ static const struct address_space_operations zonefs_file_aops = {
177192
.is_partially_uptodate = iomap_is_partially_uptodate,
178193
.error_remove_page = generic_error_remove_page,
179194
.direct_IO = noop_direct_IO,
195+
.swap_activate = zonefs_swap_activate,
180196
};
181197

182198
static void zonefs_update_stats(struct inode *inode, loff_t new_isize)
@@ -727,6 +743,68 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
727743
return ret;
728744
}
729745

746+
/*
747+
* Do not exceed the LFS limits nor the file zone size. If pos is under the
748+
* limit it becomes a short access. If it exceeds the limit, return -EFBIG.
749+
*/
750+
static loff_t zonefs_write_check_limits(struct file *file, loff_t pos,
751+
loff_t count)
752+
{
753+
struct inode *inode = file_inode(file);
754+
struct zonefs_inode_info *zi = ZONEFS_I(inode);
755+
loff_t limit = rlimit(RLIMIT_FSIZE);
756+
loff_t max_size = zi->i_max_size;
757+
758+
if (limit != RLIM_INFINITY) {
759+
if (pos >= limit) {
760+
send_sig(SIGXFSZ, current, 0);
761+
return -EFBIG;
762+
}
763+
count = min(count, limit - pos);
764+
}
765+
766+
if (!(file->f_flags & O_LARGEFILE))
767+
max_size = min_t(loff_t, MAX_NON_LFS, max_size);
768+
769+
if (unlikely(pos >= max_size))
770+
return -EFBIG;
771+
772+
return min(count, max_size - pos);
773+
}
774+
775+
static ssize_t zonefs_write_checks(struct kiocb *iocb, struct iov_iter *from)
776+
{
777+
struct file *file = iocb->ki_filp;
778+
struct inode *inode = file_inode(file);
779+
struct zonefs_inode_info *zi = ZONEFS_I(inode);
780+
loff_t count;
781+
782+
if (IS_SWAPFILE(inode))
783+
return -ETXTBSY;
784+
785+
if (!iov_iter_count(from))
786+
return 0;
787+
788+
if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT))
789+
return -EINVAL;
790+
791+
if (iocb->ki_flags & IOCB_APPEND) {
792+
if (zi->i_ztype != ZONEFS_ZTYPE_SEQ)
793+
return -EINVAL;
794+
mutex_lock(&zi->i_truncate_mutex);
795+
iocb->ki_pos = zi->i_wpoffset;
796+
mutex_unlock(&zi->i_truncate_mutex);
797+
}
798+
799+
count = zonefs_write_check_limits(file, iocb->ki_pos,
800+
iov_iter_count(from));
801+
if (count < 0)
802+
return count;
803+
804+
iov_iter_truncate(from, count);
805+
return iov_iter_count(from);
806+
}
807+
730808
/*
731809
* Handle direct writes. For sequential zone files, this is the only possible
732810
* write path. For these files, check that the user is issuing writes
@@ -744,8 +822,7 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
744822
struct super_block *sb = inode->i_sb;
745823
bool sync = is_sync_kiocb(iocb);
746824
bool append = false;
747-
size_t count;
748-
ssize_t ret;
825+
ssize_t ret, count;
749826

750827
/*
751828
* For async direct IOs to sequential zone files, refuse IOCB_NOWAIT
@@ -763,12 +840,11 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
763840
inode_lock(inode);
764841
}
765842

766-
ret = generic_write_checks(iocb, from);
767-
if (ret <= 0)
843+
count = zonefs_write_checks(iocb, from);
844+
if (count <= 0) {
845+
ret = count;
768846
goto inode_unlock;
769-
770-
iov_iter_truncate(from, zi->i_max_size - iocb->ki_pos);
771-
count = iov_iter_count(from);
847+
}
772848

773849
if ((iocb->ki_pos | count) & (sb->s_blocksize - 1)) {
774850
ret = -EINVAL;
@@ -828,12 +904,10 @@ static ssize_t zonefs_file_buffered_write(struct kiocb *iocb,
828904
inode_lock(inode);
829905
}
830906

831-
ret = generic_write_checks(iocb, from);
907+
ret = zonefs_write_checks(iocb, from);
832908
if (ret <= 0)
833909
goto inode_unlock;
834910

835-
iov_iter_truncate(from, zi->i_max_size - iocb->ki_pos);
836-
837911
ret = iomap_file_buffered_write(iocb, from, &zonefs_iomap_ops);
838912
if (ret > 0)
839913
iocb->ki_pos += ret;
@@ -966,9 +1040,7 @@ static int zonefs_open_zone(struct inode *inode)
9661040

9671041
mutex_lock(&zi->i_truncate_mutex);
9681042

969-
zi->i_wr_refcnt++;
970-
if (zi->i_wr_refcnt == 1) {
971-
1043+
if (!zi->i_wr_refcnt) {
9721044
if (atomic_inc_return(&sbi->s_open_zones) > sbi->s_max_open_zones) {
9731045
atomic_dec(&sbi->s_open_zones);
9741046
ret = -EBUSY;
@@ -978,14 +1050,15 @@ static int zonefs_open_zone(struct inode *inode)
9781050
if (i_size_read(inode) < zi->i_max_size) {
9791051
ret = zonefs_zone_mgmt(inode, REQ_OP_ZONE_OPEN);
9801052
if (ret) {
981-
zi->i_wr_refcnt--;
9821053
atomic_dec(&sbi->s_open_zones);
9831054
goto unlock;
9841055
}
9851056
zi->i_flags |= ZONEFS_ZONE_OPEN;
9861057
}
9871058
}
9881059

1060+
zi->i_wr_refcnt++;
1061+
9891062
unlock:
9901063
mutex_unlock(&zi->i_truncate_mutex);
9911064

0 commit comments

Comments
 (0)