Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 31 Oct 2014 23:22:29 +0000 (16:22 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 31 Oct 2014 23:22:29 +0000 (16:22 -0700)
Pull ext4 bugfixes from Ted Ts'o:
 "A set of miscellaneous ext4 bug fixes for 3.18"

* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: make ext4_ext_convert_to_initialized() return proper number of blocks
  ext4: bail early when clearing inode journal flag fails
  ext4: bail out from make_indexed_dir() on first error
  jbd2: use a better hash function for the revoke table
  ext4: prevent bugon on race between write/fcntl
  ext4: remove extent status procfs files if journal load fails
  ext4: disallow changing journal_csum option during remount
  ext4: enable journal checksum when metadata checksum feature enabled
  ext4: fix oops when loading block bitmap failed
  ext4: fix overflow when updating superblock backups after resize

fs/ext4/extents.c
fs/ext4/file.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
fs/jbd2/revoke.c

index 37043d0..0b16fb4 100644 (file)
@@ -3603,11 +3603,10 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
                }
        }
 
-       allocated = ext4_split_extent(handle, inode, ppath,
-                                     &split_map, split_flag, flags);
-       if (allocated < 0)
-               err = allocated;
-
+       err = ext4_split_extent(handle, inode, ppath, &split_map, split_flag,
+                               flags);
+       if (err > 0)
+               err = 0;
 out:
        /* If we have gotten a failure, don't zero out status tree */
        if (!err)
index aca7b24..8131be8 100644 (file)
@@ -137,10 +137,10 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
                        iov_iter_truncate(from, sbi->s_bitmap_maxbytes - pos);
        }
 
+       iocb->private = &overwrite;
        if (o_direct) {
                blk_start_plug(&plug);
 
-               iocb->private = &overwrite;
 
                /* check whether we do a DIO overwrite or not */
                if (ext4_should_dioread_nolock(inode) && !aio_mutex &&
index 8012a5d..ac644c3 100644 (file)
@@ -887,6 +887,10 @@ got:
                struct buffer_head *block_bitmap_bh;
 
                block_bitmap_bh = ext4_read_block_bitmap(sb, group);
+               if (!block_bitmap_bh) {
+                       err = -EIO;
+                       goto out;
+               }
                BUFFER_TRACE(block_bitmap_bh, "get block bitmap access");
                err = ext4_journal_get_write_access(handle, block_bitmap_bh);
                if (err) {
index e9777f9..3356ab5 100644 (file)
@@ -4959,7 +4959,12 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
        if (val)
                ext4_set_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);
        else {
-               jbd2_journal_flush(journal);
+               err = jbd2_journal_flush(journal);
+               if (err < 0) {
+                       jbd2_journal_unlock_updates(journal);
+                       ext4_inode_resume_unlocked_dio(inode);
+                       return err;
+               }
                ext4_clear_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);
        }
        ext4_set_aops(inode);
index 123798c..4262118 100644 (file)
@@ -1816,31 +1816,39 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
                hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
        hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
        ext4fs_dirhash(name, namelen, &hinfo);
+       memset(frames, 0, sizeof(frames));
        frame = frames;
        frame->entries = entries;
        frame->at = entries;
        frame->bh = bh;
        bh = bh2;
 
-       ext4_handle_dirty_dx_node(handle, dir, frame->bh);
-       ext4_handle_dirty_dirent_node(handle, dir, bh);
+       retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
+       if (retval)
+               goto out_frames;        
+       retval = ext4_handle_dirty_dirent_node(handle, dir, bh);
+       if (retval)
+               goto out_frames;        
 
        de = do_split(handle,dir, &bh, frame, &hinfo);
        if (IS_ERR(de)) {
-               /*
-                * Even if the block split failed, we have to properly write
-                * out all the changes we did so far. Otherwise we can end up
-                * with corrupted filesystem.
-                */
-               ext4_mark_inode_dirty(handle, dir);
-               dx_release(frames);
-               return PTR_ERR(de);
+               retval = PTR_ERR(de);
+               goto out_frames;
        }
        dx_release(frames);
 
        retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
        brelse(bh);
        return retval;
+out_frames:
+       /*
+        * Even if the block split failed, we have to properly write
+        * out all the changes we did so far. Otherwise we can end up
+        * with corrupted filesystem.
+        */
+       ext4_mark_inode_dirty(handle, dir);
+       dx_release(frames);
+       return retval;
 }
 
 /*
index f298c60..ca45883 100644 (file)
@@ -1081,7 +1081,7 @@ static void update_backups(struct super_block *sb, int blk_off, char *data,
                        break;
 
                if (meta_bg == 0)
-                       backup_block = group * bpg + blk_off;
+                       backup_block = ((ext4_fsblk_t)group) * bpg + blk_off;
                else
                        backup_block = (ext4_group_first_block_no(sb, group) +
                                        ext4_bg_has_super(sb, group));
index 1eda6ab..2c9e686 100644 (file)
@@ -3526,6 +3526,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 #ifdef CONFIG_EXT4_FS_POSIX_ACL
        set_opt(sb, POSIX_ACL);
 #endif
+       /* don't forget to enable journal_csum when metadata_csum is enabled. */
+       if (ext4_has_metadata_csum(sb))
+               set_opt(sb, JOURNAL_CHECKSUM);
+
        if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA)
                set_opt(sb, JOURNAL_DATA);
        else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED)
@@ -3943,7 +3947,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_MMP) &&
            !(sb->s_flags & MS_RDONLY))
                if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block)))
-                       goto failed_mount3;
+                       goto failed_mount3a;
 
        /*
         * The first inode we look at is the journal inode.  Don't try
@@ -3952,7 +3956,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        if (!test_opt(sb, NOLOAD) &&
            EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) {
                if (ext4_load_journal(sb, es, journal_devnum))
-                       goto failed_mount3;
+                       goto failed_mount3a;
        } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) &&
              EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) {
                ext4_msg(sb, KERN_ERR, "required journal recovery "
@@ -4240,6 +4244,7 @@ failed_mount_wq:
                jbd2_journal_destroy(sbi->s_journal);
                sbi->s_journal = NULL;
        }
+failed_mount3a:
        ext4_es_unregister_shrinker(sbi);
 failed_mount3:
        del_timer_sync(&sbi->s_err_report);
@@ -4841,6 +4846,14 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                goto restore_opts;
        }
 
+       if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
+           test_opt(sb, JOURNAL_CHECKSUM)) {
+               ext4_msg(sb, KERN_ERR, "changing journal_checksum "
+                        "during remount not supported");
+               err = -EINVAL;
+               goto restore_opts;
+       }
+
        if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
                if (test_opt2(sb, EXPLICIT_DELALLOC)) {
                        ext4_msg(sb, KERN_ERR, "can't mount with "
index d5e95a1..c6cbaef 100644 (file)
@@ -92,6 +92,7 @@
 #include <linux/init.h>
 #include <linux/bio.h>
 #include <linux/log2.h>
+#include <linux/hash.h>
 #endif
 
 static struct kmem_cache *jbd2_revoke_record_cache;
@@ -130,16 +131,9 @@ static void flush_descriptor(journal_t *, struct buffer_head *, int, int);
 
 /* Utility functions to maintain the revoke table */
 
-/* Borrowed from buffer.c: this is a tried and tested block hash function */
 static inline int hash(journal_t *journal, unsigned long long block)
 {
-       struct jbd2_revoke_table_s *table = journal->j_revoke;
-       int hash_shift = table->hash_shift;
-       int hash = (int)block ^ (int)((block >> 31) >> 1);
-
-       return ((hash << (hash_shift - 6)) ^
-               (hash >> 13) ^
-               (hash << (hash_shift - 12))) & (table->hash_size - 1);
+       return hash_64(block, journal->j_revoke->hash_shift);
 }
 
 static int insert_revoke_hash(journal_t *journal, unsigned long long blocknr,