From 2046fd1873886e8c774d7c1b0961624c164e7db2 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Tue, 15 Oct 2013 18:45:17 -0500 Subject: ext3: Count journal as bsddf overhead in ext3_statfs ext4 counts journal space as bsddf overhead, but ext3 does not. For some reason when I patched ext4 I thought I should leave ext3 alone, but frankly it makes more sense to fix it, I think. Otherwise we get inconsistent behavior from ext3 under ext3.ko, and ext3 under ext4.ko, which is not at all desirable... This is testable by xfstests shared/289, though it will need modification because it currently special-cases ext3. Signed-off-by: Eric Sandeen Signed-off-by: Jan Kara --- fs/ext3/super.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/ext3/super.c b/fs/ext3/super.c index c50c76190373..37fd31ed16e7 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -2825,6 +2825,10 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf) * bitmap, and an inode table. */ overhead += ngroups * (2 + sbi->s_itb_per_group); + + /* Add the journal blocks as well */ + overhead += sbi->s_journal->j_maxlen; + sbi->s_overhead_last = overhead; smp_wmb(); sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count); -- cgit From 444996027e80f96c9948d8d5b8f067a8aff9861d Mon Sep 17 00:00:00 2001 From: "Peter A. Felvegi" Date: Fri, 18 Oct 2013 20:07:44 +0200 Subject: udf: fix for pathetic mount times in case of invalid file system The UDF driver was not strict enough about checking the IDs in the VSDs when mounting, which resulted in reading through all the sectors of the block device in some unfortunate cases. Eg, trying to mount my uninitialized 200G SSD partition (all 0xFF bytes) took ~350 minutes to fail, because the code expected some of the valid IDs or a zero byte. During this, the mount couldn't be killed, sync from the cmdline blocked, and the machine froze into the shutdown. Valid filesystems (extX, btrfs, ntfs) were rejected by the mere accident of having a zero byte at just the right place in some of their sectors, close enough to the beginning not to generate excess I/O. The fix adds a hard limit on the VSD sector offset, adds the two missing VSD IDs, and stops scanning when encountering an invalid ID. Also replaced the magic number 32768 with a more meaningful #define, and supressed the bogus message about failing to read the first sector if no UDF fs was detected. Signed-off-by: Peter A. Felvegi Signed-off-by: Jan Kara --- fs/udf/super.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index 91219385691d..3306b9f69bed 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -76,6 +76,9 @@ #define UDF_DEFAULT_BLOCKSIZE 2048 +#define VSD_FIRST_SECTOR_OFFSET 32768 +#define VSD_MAX_SECTOR_OFFSET 0x800000 + enum { UDF_MAX_LINKS = 0xffff }; /* These are the "meat" - everything else is stuffing */ @@ -685,7 +688,7 @@ out_unlock: static loff_t udf_check_vsd(struct super_block *sb) { struct volStructDesc *vsd = NULL; - loff_t sector = 32768; + loff_t sector = VSD_FIRST_SECTOR_OFFSET; int sectorsize; struct buffer_head *bh = NULL; int nsr02 = 0; @@ -703,8 +706,18 @@ static loff_t udf_check_vsd(struct super_block *sb) udf_debug("Starting at sector %u (%ld byte sectors)\n", (unsigned int)(sector >> sb->s_blocksize_bits), sb->s_blocksize); - /* Process the sequence (if applicable) */ - for (; !nsr02 && !nsr03; sector += sectorsize) { + /* Process the sequence (if applicable). The hard limit on the sector + * offset is arbitrary, hopefully large enough so that all valid UDF + * filesystems will be recognised. There is no mention of an upper + * bound to the size of the volume recognition area in the standard. + * The limit will prevent the code to read all the sectors of a + * specially crafted image (like a bluray disc full of CD001 sectors), + * potentially causing minutes or even hours of uninterruptible I/O + * activity. This actually happened with uninitialised SSD partitions + * (all 0xFF) before the check for the limit and all valid IDs were + * added */ + for (; !nsr02 && !nsr03 && sector < VSD_MAX_SECTOR_OFFSET; + sector += sectorsize) { /* Read a block */ bh = udf_tread(sb, sector >> sb->s_blocksize_bits); if (!bh) @@ -714,10 +727,7 @@ static loff_t udf_check_vsd(struct super_block *sb) vsd = (struct volStructDesc *)(bh->b_data + (sector & (sb->s_blocksize - 1))); - if (vsd->stdIdent[0] == 0) { - brelse(bh); - break; - } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, + if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, VSD_STD_ID_LEN)) { switch (vsd->structType) { case 0: @@ -753,6 +763,17 @@ static loff_t udf_check_vsd(struct super_block *sb) else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR03, VSD_STD_ID_LEN)) nsr03 = sector; + else if (!strncmp(vsd->stdIdent, VSD_STD_ID_BOOT2, + VSD_STD_ID_LEN)) + ; /* nothing */ + else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CDW02, + VSD_STD_ID_LEN)) + ; /* nothing */ + else { + /* invalid id : end of volume recognition area */ + brelse(bh); + break; + } brelse(bh); } @@ -760,7 +781,8 @@ static loff_t udf_check_vsd(struct super_block *sb) return nsr03; else if (nsr02) return nsr02; - else if (sector - (sbi->s_session << sb->s_blocksize_bits) == 32768) + else if (!bh && sector - (sbi->s_session << sb->s_blocksize_bits) == + VSD_FIRST_SECTOR_OFFSET) return -1; else return 0; @@ -1270,6 +1292,9 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) * PHYSICAL partitions are already set up */ type1_idx = i; +#ifdef UDFFS_DEBUG + map = NULL; /* supress 'maybe used uninitialized' warning */ +#endif for (i = 0; i < sbi->s_partitions; i++) { map = &sbi->s_partmaps[i]; @@ -1891,7 +1916,9 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt, return 0; } if (nsr_off == -1) - udf_debug("Failed to read byte 32768. Assuming open disc. Skipping validity check\n"); + udf_debug("Failed to read sector at offset %d. " + "Assuming open disc. Skipping validity " + "check\n", VSD_FIRST_SECTOR_OFFSET); if (!sbi->s_last_block) sbi->s_last_block = udf_get_last_block(sb); } else { -- cgit From 1ce0aa802c4cbe6dfe2c7fa95c839d75a509c9a5 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 31 Oct 2013 20:37:15 +0100 Subject: jbd: Revert "jbd: remove dependency on __GFP_NOFAIL" This reverts commit 05713082ab7690a2b22b044cfc867f346c39cd2d. The idea to remove __GFP_NOFAIL was opposed by Andrew Morton. Although mm guys do want to get rid of __GFP_NOFAIL users, opencoding the allocation retry is even worse. See emails following http://www.gossamer-threads.com/lists/linux/kernel/1809153#1809153 Signed-off-by: Jan Kara --- fs/jbd/transaction.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index be0c39b66fe0..aa603e017d22 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -26,7 +26,6 @@ #include #include #include -#include static void __journal_temp_unlink_buffer(struct journal_head *jh); @@ -100,10 +99,11 @@ static int start_this_handle(journal_t *journal, handle_t *handle) alloc_transaction: if (!journal->j_running_transaction) { - new_transaction = kzalloc(sizeof(*new_transaction), GFP_NOFS); + new_transaction = kzalloc(sizeof(*new_transaction), + GFP_NOFS|__GFP_NOFAIL); if (!new_transaction) { - congestion_wait(BLK_RW_ASYNC, HZ/50); - goto alloc_transaction; + ret = -ENOMEM; + goto out; } } -- cgit From 18da65e7d30a76ab3ca0ccd2b7ca0690f80f28e4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 1 Nov 2013 13:21:54 +0300 Subject: quota: info leak in quota_getquota() The if_dqblk struct has a 4 byte hole at the end of the struct so uninitialized stack information is leaked to user space. Signed-off-by: Dan Carpenter Signed-off-by: Jan Kara --- fs/quota/quota.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/quota/quota.c b/fs/quota/quota.c index dea86e8967ee..2b363e23f36e 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -117,6 +117,7 @@ static int quota_setinfo(struct super_block *sb, int type, void __user *addr) static void copy_to_if_dqblk(struct if_dqblk *dst, struct fs_disk_quota *src) { + memset(dst, 0, sizeof(*dst)); dst->dqb_bhardlimit = src->d_blk_hardlimit; dst->dqb_bsoftlimit = src->d_blk_softlimit; dst->dqb_curspace = src->d_bcount; -- cgit From 7ba3ec5749ddb61f79f7be17b5fd7720eebc52de Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 5 Nov 2013 01:15:38 +0100 Subject: ext2: Fix fs corruption in ext2_get_xip_mem() Commit 8e3dffc651cb "Ext2: mark inode dirty after the function dquot_free_block_nodirty is called" unveiled a bug in __ext2_get_block() called from ext2_get_xip_mem(). That function called ext2_get_block() mistakenly asking it to map 0 blocks while 1 was intended. Before the above mentioned commit things worked out fine by luck but after that commit we started returning that we allocated 0 blocks while we in fact allocated 1 block and thus allocation was looping until all blocks in the filesystem were exhausted. Fix the problem by properly asking for one block and also add assertion in ext2_get_blocks() to catch similar problems. Reported-and-tested-by: Andiry Xu Signed-off-by: Jan Kara --- fs/ext2/inode.c | 2 ++ fs/ext2/xip.c | 1 + 2 files changed, 3 insertions(+) diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index c260de6d7b6d..8a337640a46a 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -632,6 +632,8 @@ static int ext2_get_blocks(struct inode *inode, int count = 0; ext2_fsblk_t first_block = 0; + BUG_ON(maxblocks == 0); + depth = ext2_block_to_path(inode,iblock,offsets,&blocks_to_boundary); if (depth == 0) diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c index 1c3312858fcf..e98171a11cfe 100644 --- a/fs/ext2/xip.c +++ b/fs/ext2/xip.c @@ -35,6 +35,7 @@ __ext2_get_block(struct inode *inode, pgoff_t pgoff, int create, int rc; memset(&tmp, 0, sizeof(struct buffer_head)); + tmp.b_size = 1 << inode->i_blkbits; rc = ext2_get_block(inode, pgoff, &tmp, create); *result = tmp.b_blocknr; -- cgit