]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 13 Nov 2013 06:25:47 +0000 (15:25 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 13 Nov 2013 06:25:47 +0000 (15:25 +0900)
Pull ext[23], udf and quota fixes from Jan Kara:
 "Assorted fixes in quota, ext2, ext3 & udf.

  Probably the most important is a fix of fs corruption issue in ext2
  XIP support (OTOH xip is rarely used)"

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  ext2: Fix fs corruption in ext2_get_xip_mem()
  quota: info leak in quota_getquota()
  jbd: Revert "jbd: remove dependency on __GFP_NOFAIL"
  udf: fix for pathetic mount times in case of invalid file system
  ext3: Count journal as bsddf overhead in ext3_statfs

fs/ext2/inode.c
fs/ext2/xip.c
fs/ext3/super.c
fs/jbd/transaction.c
fs/quota/quota.c
fs/udf/super.c

index c260de6d7b6df9e5350ecfc019f41ed6def75470..8a337640a46a06fec154fe9ae1fef1e054000c23 100644 (file)
@@ -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)
index 1c3312858fcf42703b7bb1c6be52f24c9b1a5b47..e98171a11cfe19ef92aef9c516bfd6c1fc42cad8 100644 (file)
@@ -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;
 
index c50c76190373a06bdb1a7971a935e7a5d00d9888..37fd31ed16e781fd525773e2f9dc0a2e7b274ab0 100644 (file)
@@ -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);
index be0c39b66fe082402435673cab806426ba3a165e..aa603e017d22f3a1ef75dd0839a399653db8800a 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/hrtimer.h>
-#include <linux/backing-dev.h>
 
 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;
                }
        }
 
index dea86e8967ee2c354d489384a83d1492b1dbcba3..2b363e23f36e73d9e8c0bec8a85f61cb6134def6 100644 (file)
@@ -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;
index 91219385691d8f80d1db9aed3973183bb931a48d..3306b9f69bedbb5ba2cb4e11b180b2b75e947dd5 100644 (file)
@@ -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 {