Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+87 -14
+87 -14
fs/zonefs/super.c
··· 165 165 return iomap_writepages(mapping, wbc, &wpc, &zonefs_writeback_ops); 166 166 } 167 167 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 + 168 183 static const struct address_space_operations zonefs_file_aops = { 169 184 .readpage = zonefs_readpage, 170 185 .readahead = zonefs_readahead, ··· 192 177 .is_partially_uptodate = iomap_is_partially_uptodate, 193 178 .error_remove_page = generic_error_remove_page, 194 179 .direct_IO = noop_direct_IO, 180 + .swap_activate = zonefs_swap_activate, 195 181 }; 196 182 197 183 static void zonefs_update_stats(struct inode *inode, loff_t new_isize) ··· 744 728 } 745 729 746 730 /* 731 + * Do not exceed the LFS limits nor the file zone size. If pos is under the 732 + * limit it becomes a short access. If it exceeds the limit, return -EFBIG. 733 + */ 734 + static loff_t zonefs_write_check_limits(struct file *file, loff_t pos, 735 + loff_t count) 736 + { 737 + struct inode *inode = file_inode(file); 738 + struct zonefs_inode_info *zi = ZONEFS_I(inode); 739 + loff_t limit = rlimit(RLIMIT_FSIZE); 740 + loff_t max_size = zi->i_max_size; 741 + 742 + if (limit != RLIM_INFINITY) { 743 + if (pos >= limit) { 744 + send_sig(SIGXFSZ, current, 0); 745 + return -EFBIG; 746 + } 747 + count = min(count, limit - pos); 748 + } 749 + 750 + if (!(file->f_flags & O_LARGEFILE)) 751 + max_size = min_t(loff_t, MAX_NON_LFS, max_size); 752 + 753 + if (unlikely(pos >= max_size)) 754 + return -EFBIG; 755 + 756 + return min(count, max_size - pos); 757 + } 758 + 759 + static ssize_t zonefs_write_checks(struct kiocb *iocb, struct iov_iter *from) 760 + { 761 + struct file *file = iocb->ki_filp; 762 + struct inode *inode = file_inode(file); 763 + struct zonefs_inode_info *zi = ZONEFS_I(inode); 764 + loff_t count; 765 + 766 + if (IS_SWAPFILE(inode)) 767 + return -ETXTBSY; 768 + 769 + if (!iov_iter_count(from)) 770 + return 0; 771 + 772 + if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT)) 773 + return -EINVAL; 774 + 775 + if (iocb->ki_flags & IOCB_APPEND) { 776 + if (zi->i_ztype != ZONEFS_ZTYPE_SEQ) 777 + return -EINVAL; 778 + mutex_lock(&zi->i_truncate_mutex); 779 + iocb->ki_pos = zi->i_wpoffset; 780 + mutex_unlock(&zi->i_truncate_mutex); 781 + } 782 + 783 + count = zonefs_write_check_limits(file, iocb->ki_pos, 784 + iov_iter_count(from)); 785 + if (count < 0) 786 + return count; 787 + 788 + iov_iter_truncate(from, count); 789 + return iov_iter_count(from); 790 + } 791 + 792 + /* 747 793 * Handle direct writes. For sequential zone files, this is the only possible 748 794 * write path. For these files, check that the user is issuing writes 749 795 * sequentially from the end of the file. This code assumes that the block layer ··· 822 744 struct super_block *sb = inode->i_sb; 823 745 bool sync = is_sync_kiocb(iocb); 824 746 bool append = false; 825 - size_t count; 826 - ssize_t ret; 747 + ssize_t ret, count; 827 748 828 749 /* 829 750 * For async direct IOs to sequential zone files, refuse IOCB_NOWAIT ··· 840 763 inode_lock(inode); 841 764 } 842 765 843 - ret = generic_write_checks(iocb, from); 844 - if (ret <= 0) 766 + count = zonefs_write_checks(iocb, from); 767 + if (count <= 0) { 768 + ret = count; 845 769 goto inode_unlock; 846 - 847 - iov_iter_truncate(from, zi->i_max_size - iocb->ki_pos); 848 - count = iov_iter_count(from); 770 + } 849 771 850 772 if ((iocb->ki_pos | count) & (sb->s_blocksize - 1)) { 851 773 ret = -EINVAL; ··· 904 828 inode_lock(inode); 905 829 } 906 830 907 - ret = generic_write_checks(iocb, from); 831 + ret = zonefs_write_checks(iocb, from); 908 832 if (ret <= 0) 909 833 goto inode_unlock; 910 - 911 - iov_iter_truncate(from, zi->i_max_size - iocb->ki_pos); 912 834 913 835 ret = iomap_file_buffered_write(iocb, from, &zonefs_iomap_ops); 914 836 if (ret > 0) ··· 1040 966 1041 967 mutex_lock(&zi->i_truncate_mutex); 1042 968 1043 - zi->i_wr_refcnt++; 1044 - if (zi->i_wr_refcnt == 1) { 1045 - 969 + if (!zi->i_wr_refcnt) { 1046 970 if (atomic_inc_return(&sbi->s_open_zones) > sbi->s_max_open_zones) { 1047 971 atomic_dec(&sbi->s_open_zones); 1048 972 ret = -EBUSY; ··· 1050 978 if (i_size_read(inode) < zi->i_max_size) { 1051 979 ret = zonefs_zone_mgmt(inode, REQ_OP_ZONE_OPEN); 1052 980 if (ret) { 1053 - zi->i_wr_refcnt--; 1054 981 atomic_dec(&sbi->s_open_zones); 1055 982 goto unlock; 1056 983 } 1057 984 zi->i_flags |= ZONEFS_ZONE_OPEN; 1058 985 } 1059 986 } 987 + 988 + zi->i_wr_refcnt++; 1060 989 1061 990 unlock: 1062 991 mutex_unlock(&zi->i_truncate_mutex);