From e9cd1d9a34131fb56bef469d4e1cd31bd1b515e2 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Mar 2023 12:02:08 +0100 Subject: [PATCH 01/13] ext2: Correct maximum ext2 filesystem block size Ext2 has traditionally supported filesystem block sizes upto page size or upto 65536. Macro EXT2_MAX_BLOCK_SIZE is set to 4096, however that is never used in ext2 so practically we always allowed whatever sb_set_blocksize() accepted. Fix value of EXT2_MAX_BLOCK_SIZE because it will be used in the next patch. Signed-off-by: Jan Kara --- fs/ext2/ext2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index cb78d7dcfb95..6c8e838bb278 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -178,7 +178,7 @@ static inline struct ext2_sb_info *EXT2_SB(struct super_block *sb) * Macro-instructions used to manage several block sizes */ #define EXT2_MIN_BLOCK_SIZE 1024 -#define EXT2_MAX_BLOCK_SIZE 4096 +#define EXT2_MAX_BLOCK_SIZE 65536 #define EXT2_MIN_BLOCK_LOG_SIZE 10 #define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize) #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) From 62aeb94433fcec80241754b70d0d1836d5926b0a Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Mar 2023 11:59:39 +0100 Subject: [PATCH 02/13] ext2: Check block size validity during mount Check that log of block size stored in the superblock has sensible value. Otherwise the shift computing the block size can overflow leading to undefined behavior. Reported-by: syzbot+4fec412f59eba8c01b77@syzkaller.appspotmail.com Signed-off-by: Jan Kara --- fs/ext2/ext2.h | 1 + fs/ext2/super.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 6c8e838bb278..8244366862e4 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -180,6 +180,7 @@ static inline struct ext2_sb_info *EXT2_SB(struct super_block *sb) #define EXT2_MIN_BLOCK_SIZE 1024 #define EXT2_MAX_BLOCK_SIZE 65536 #define EXT2_MIN_BLOCK_LOG_SIZE 10 +#define EXT2_MAX_BLOCK_LOG_SIZE 16 #define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize) #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) #define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 69c88facfe90..f342f347a695 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -945,6 +945,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount; } + if (le32_to_cpu(es->s_log_block_size) > + (EXT2_MAX_BLOCK_LOG_SIZE - BLOCK_SIZE_BITS)) { + ext2_msg(sb, KERN_ERR, + "Invalid log block size: %u", + le32_to_cpu(es->s_log_block_size)); + goto failed_mount; + } blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size); if (test_opt(sb, DAX)) { From 96acbef66b44c0fb25d3ab9c632a9a750e678ce7 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Wed, 8 Mar 2023 18:55:18 +0100 Subject: [PATCH 03/13] udf: Use folios in udf_adinicb_writepage() Make udf_adinicb_writepage() fully converted to using the passed folio instead of converting it to the page. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Jan Kara --- fs/udf/inode.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 2210e5eb1ea0..1e71e04ae8f6 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -188,14 +188,14 @@ static void udf_write_failed(struct address_space *mapping, loff_t to) static int udf_adinicb_writepage(struct folio *folio, struct writeback_control *wbc, void *data) { - struct page *page = &folio->page; - struct inode *inode = page->mapping->host; + struct inode *inode = folio->mapping->host; struct udf_inode_info *iinfo = UDF_I(inode); - BUG_ON(!PageLocked(page)); - memcpy_from_page(iinfo->i_data + iinfo->i_lenEAttr, page, 0, + BUG_ON(!folio_test_locked(folio)); + BUG_ON(folio->index != 0); + memcpy_from_file_folio(iinfo->i_data + iinfo->i_lenEAttr, folio, 0, i_size_read(inode)); - unlock_page(page); + folio_unlock(folio); mark_inode_dirty(inode); return 0; From f768dc3cf74983107464bcd773167c92b85cb8f2 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Fri, 10 Mar 2023 11:08:20 +0800 Subject: [PATCH 04/13] udf: use wrapper i_blocksize() in udf_discard_prealloc() Convert to use i_blocksize() for readability. Signed-off-by: Yangtao Li Signed-off-by: Jan Kara Message-Id: <20230310030821.66090-2-frank.li@vivo.com> --- fs/udf/truncate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c index 871856c69df5..2e7ba234bab8 100644 --- a/fs/udf/truncate.c +++ b/fs/udf/truncate.c @@ -127,7 +127,7 @@ void udf_discard_prealloc(struct inode *inode) uint64_t lbcount = 0; int8_t etype = -1; struct udf_inode_info *iinfo = UDF_I(inode); - int bsize = 1 << inode->i_blkbits; + int bsize = i_blocksize(inode); if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB || ALIGN(inode->i_size, bsize) == ALIGN(iinfo->i_lenExtents, bsize)) @@ -149,7 +149,7 @@ void udf_discard_prealloc(struct inode *inode) lbcount -= elen; udf_delete_aext(inode, prev_epos); udf_free_blocks(inode->i_sb, inode, &eloc, 0, - DIV_ROUND_UP(elen, 1 << inode->i_blkbits)); + DIV_ROUND_UP(elen, bsize)); } /* This inode entry is in-memory only and thus we don't have to mark * the inode dirty */ From dced733d7fa9386f7c96bbf7721360472c0aed47 Mon Sep 17 00:00:00 2001 From: Luis Chamberlain Date: Fri, 10 Mar 2023 15:12:04 -0800 Subject: [PATCH 05/13] quota: simplify two-level sysctl registration for fs_dqstats_table There is no need to declare two tables to just create directories, this can be easily be done with a prefix path with register_sysctl(). Simplify this registration. Signed-off-by: Luis Chamberlain Signed-off-by: Jan Kara Message-Id: <20230310231206.3952808-4-mcgrof@kernel.org> --- fs/quota/dquot.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index a6357f728034..90cb70c82012 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -2948,24 +2948,6 @@ static struct ctl_table fs_dqstats_table[] = { { }, }; -static struct ctl_table fs_table[] = { - { - .procname = "quota", - .mode = 0555, - .child = fs_dqstats_table, - }, - { }, -}; - -static struct ctl_table sys_table[] = { - { - .procname = "fs", - .mode = 0555, - .child = fs_table, - }, - { }, -}; - static int __init dquot_init(void) { int i, ret; @@ -2973,7 +2955,7 @@ static int __init dquot_init(void) printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__); - register_sysctl_table(sys_table); + register_sysctl("fs/quota", fs_dqstats_table); dquot_cachep = kmem_cache_create("dquot", sizeof(struct dquot), sizeof(unsigned long) * 4, From f8107c996f5419a5b964b9796d736c7b81f099a0 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Mon, 27 Feb 2023 20:02:15 +0800 Subject: [PATCH 06/13] quota: fixup *_write_file_info() to return proper error code For v1_write_file_info function, when quota_write() returns 0, it should be considered an EIO error. And for v2_write_file_info(), fix to proper error return code instead of raw number. Signed-off-by: Yangtao Li Signed-off-by: Jan Kara Message-Id: <20230227120216.31306-1-frank.li@vivo.com> --- fs/quota/quota_v1.c | 2 +- fs/quota/quota_v2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/quota/quota_v1.c b/fs/quota/quota_v1.c index cd92e5fa0062..a0db3f195e95 100644 --- a/fs/quota/quota_v1.c +++ b/fs/quota/quota_v1.c @@ -206,7 +206,7 @@ static int v1_write_file_info(struct super_block *sb, int type) sizeof(struct v1_disk_dqblk), v1_dqoff(0)); if (ret == sizeof(struct v1_disk_dqblk)) ret = 0; - else if (ret > 0) + else if (ret >= 0) ret = -EIO; out: up_write(&dqopt->dqio_sem); diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c index b1467f3921c2..ae99e7b88205 100644 --- a/fs/quota/quota_v2.c +++ b/fs/quota/quota_v2.c @@ -212,7 +212,7 @@ static int v2_write_file_info(struct super_block *sb, int type) up_write(&dqopt->dqio_sem); if (size != sizeof(struct v2_disk_dqinfo)) { quota_error(sb, "Can't write info structure"); - return -1; + return size < 0 ? size : -EIO; } return 0; } From c87d175d0ae715a1cdd9a315253f3fb410fb0421 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Mon, 27 Feb 2023 20:02:16 +0800 Subject: [PATCH 07/13] quota: make dquot_set_dqinfo return errors from ->write_info dquot_set_dqinfo() ignores the return code from the ->write_info call, which means that quotacalls like Q_SETINFO never see the error. This doesn't seem right, so fix that. Signed-off-by: Yangtao Li Signed-off-by: Jan Kara Message-Id: <20230227120216.31306-2-frank.li@vivo.com> --- fs/quota/dquot.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 90cb70c82012..78c9977549ef 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -2819,7 +2819,6 @@ EXPORT_SYMBOL(dquot_get_state); int dquot_set_dqinfo(struct super_block *sb, int type, struct qc_info *ii) { struct mem_dqinfo *mi; - int err = 0; if ((ii->i_fieldmask & QC_WARNS_MASK) || (ii->i_fieldmask & QC_RT_SPC_TIMER)) @@ -2846,8 +2845,7 @@ int dquot_set_dqinfo(struct super_block *sb, int type, struct qc_info *ii) spin_unlock(&dq_data_lock); mark_info_dirty(sb, type); /* Force write to disk */ - sb->dq_op->write_info(sb, type); - return err; + return sb->dq_op->write_info(sb, type); } EXPORT_SYMBOL(dquot_set_dqinfo); From fae0a2b2077c30f567b6b32c2467e7dda8e1d270 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 17 Mar 2023 14:34:20 +0000 Subject: [PATCH 08/13] ext2: remove redundant assignment to pointer end Pointer is assigned a value that is never read, the assignment is redundant and can be removed. Cleans up clang-scan warning: fs/ext2/xattr.c:555:3: warning: Value stored to 'end' is never read [deadcode.DeadStores] end = (char *)header + sb->s_blocksize; Signed-off-by: Colin Ian King Signed-off-by: Jan Kara Message-Id: <20230317143420.419005-1-colin.i.king@gmail.com> --- fs/ext2/xattr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 641abfa4b718..d4015e675c24 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -553,7 +553,6 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name, error = -ENOMEM; if (header == NULL) goto cleanup; - end = (char *)header + sb->s_blocksize; header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC); header->h_blocks = header->h_refcount = cpu_to_le32(1); last = here = ENTRY(header+1); From 8ace883815a2a9f5ef638807f6133c1720ac325a Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sun, 26 Mar 2023 16:44:59 -0400 Subject: [PATCH 09/13] reiserfs: remove unused sched_count variable clang with W=1 reports fs/reiserfs/journal.c:3034:6: error: variable 'sched_count' set but not used [-Werror,-Wunused-but-set-variable] int sched_count = 0; ^ This variable is not used so remove it. Signed-off-by: Tom Rix Signed-off-by: Jan Kara Message-Id: <20230326204459.1358553-1-trix@redhat.com> --- fs/reiserfs/journal.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 9ce4ec296b74..4d11d60f493c 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -3031,7 +3031,6 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th, unsigned int old_trans_id; struct reiserfs_journal *journal = SB_JOURNAL(sb); struct reiserfs_transaction_handle myth; - int sched_count = 0; int retval; int depth; @@ -3088,7 +3087,6 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th, ((journal->j_len + nblocks + 2) * 100) < (journal->j_len_alloc * 75)) { if (atomic_read(&journal->j_wcount) > 10) { - sched_count++; queue_log_writer(sb); goto relock; } From 9e1fb91bcbad7e329a93f66c150e8bb607b418f7 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 29 Mar 2023 11:45:00 +0200 Subject: [PATCH 10/13] quota: Use register_sysctl_init() for registering fs_dqstats_table register_sysctl_init() also prints information that may be useful for further debugging when we fail to register sysctl table. Use it when registering fs_dqstats_table. Suggested-by: Luis Chamberlain Signed-off-by: Jan Kara --- fs/quota/dquot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 78c9977549ef..ffd40dc3e4e9 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -2953,7 +2953,7 @@ static int __init dquot_init(void) printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__); - register_sysctl("fs/quota", fs_dqstats_table); + register_sysctl_init("fs/quota", fs_dqstats_table); dquot_cachep = kmem_cache_create("dquot", sizeof(struct dquot), sizeof(unsigned long) * 4, From 74b7d42300a8aabf975ac48d077c6a57e7811df3 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Fri, 31 Mar 2023 08:03:25 -0400 Subject: [PATCH 11/13] reiserfs: remove unused iter variable clang with W=1 reports fs/reiserfs/stree.c:1265:6: error: variable 'iter' set but not used [-Werror,-Wunused-but-set-variable] int iter = 0; ^ This variable is not used so remove it. Signed-off-by: Tom Rix Signed-off-by: Jan Kara Message-Id: <20230331120325.1855111-1-trix@redhat.com> --- fs/reiserfs/stree.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 84c12a1947b2..ce5003986789 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -1262,7 +1262,6 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th, #ifdef CONFIG_REISERFS_CHECK char mode; - int iter = 0; #endif BUG_ON(!th->t_trans_id); @@ -1274,7 +1273,6 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th, removed = 0; #ifdef CONFIG_REISERFS_CHECK - iter++; mode = #endif prepare_for_delete_or_cut(th, inode, path, From f4251e371d179e0009981e5f4619bfbdf893090e Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Thu, 13 Apr 2023 23:14:12 +0800 Subject: [PATCH 12/13] quota: update Kconfig comment f2fs support quota since commit 0abd675e97e6 ("f2fs: support plain user/group quota"), let's document it. Signed-off-by: Yangtao Li Signed-off-by: Jan Kara Message-Id: <20230413151412.30059-1-frank.li@vivo.com> --- fs/quota/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/quota/Kconfig b/fs/quota/Kconfig index d5a85a8062d0..df522f423aad 100644 --- a/fs/quota/Kconfig +++ b/fs/quota/Kconfig @@ -9,7 +9,7 @@ config QUOTA help If you say Y here, you will be able to set per user limits for disk usage (also called disk quotas). Currently, it works for the - ext2, ext3, ext4, jfs, ocfs2 and reiserfs file systems. + ext2, ext3, ext4, f2fs, jfs, ocfs2 and reiserfs file systems. Note that gfs2 and xfs use their own quota system. Ext3, ext4 and reiserfs also support journaled quotas for which you don't need to run quotacheck(8) after an unclean shutdown. From 36d532d713db5797b844fb8bd61a068d3cd4ee3f Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Fri, 14 Apr 2023 00:38:32 +0800 Subject: [PATCH 13/13] quota: mark PRINT_QUOTA_WARNING as BROKEN PRINT_QUOTA_WARNING is deprecated since commit 8e8934695dfd ("quota: send messages via netlink") merged in 2007. Users should rather be using notification over netlink socket if they are interested about explicit notification in addition to plain EDQUOT error. Since printing to console from deep inside filesystem code is problematic, mark the feature as BROKEN now and see who complains. Signed-off-by: Yangtao Li Signed-off-by: Jan Kara Message-Id: <20230413163833.43913-1-frank.li@vivo.com> --- fs/quota/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/quota/Kconfig b/fs/quota/Kconfig index df522f423aad..4c925e55dbcd 100644 --- a/fs/quota/Kconfig +++ b/fs/quota/Kconfig @@ -28,7 +28,7 @@ config QUOTA_NETLINK_INTERFACE config PRINT_QUOTA_WARNING bool "Print quota warnings to console (OBSOLETE)" - depends on QUOTA + depends on QUOTA && BROKEN default y help If you say Y here, quota warnings (about exceeding softlimit, reaching