]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 3 Sep 2015 19:52:19 +0000 (12:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 3 Sep 2015 19:52:19 +0000 (12:52 -0700)
Pull ext4 updates from Ted Ts'o:
 "Pretty much all bug fixes and clean ups for 4.3, after a lot of
  features and other churn going into 4.2"

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  Revert "ext4: remove block_device_ejected"
  ext4: ratelimit the file system mounted message
  ext4: silence a format string false positive
  ext4: simplify some code in read_mmp_block()
  ext4: don't manipulate recovery flag when freezing no-journal fs
  jbd2: limit number of reserved credits
  ext4 crypto: remove duplicate header file
  ext4: update c/mtime on truncate up
  jbd2: avoid infinite loop when destroying aborted journal
  ext4, jbd2: add REQ_FUA flag when recording an error in the superblock
  ext4 crypto: fix spelling typo in comment
  ext4 crypto: exit cleanly if ext4_derive_key_aes() fails
  ext4: reject journal options for ext2 mounts
  ext4: implement cgroup writeback support
  ext4: replace ext4_io_submit->io_op with ->io_wbc
  ext4 crypto: check for too-short encrypted file names
  ext4 crypto: use a jbd2 transaction when adding a crypto policy
  jbd2: speedup jbd2_journal_dirty_metadata()

1  2 
fs/ext4/inode.c
fs/ext4/page-io.c
fs/ext4/super.c
include/linux/jbd2.h

diff --combined fs/ext4/inode.c
index fed7ee7ea6e8cb46416c0caa421be2e5a66cb7d2,2442eb065e1961029c2cacc0230ac7b49f03fc67..29f1af7c2cab9e97b514b9ea4459f36ec8e7415b
@@@ -4661,11 -4661,8 +4661,11 @@@ int ext4_setattr(struct dentry *dentry
        if (error)
                return error;
  
 -      if (is_quota_modification(inode, attr))
 -              dquot_initialize(inode);
 +      if (is_quota_modification(inode, attr)) {
 +              error = dquot_initialize(inode);
 +              if (error)
 +                      return error;
 +      }
        if ((ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, inode->i_uid)) ||
            (ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, inode->i_gid))) {
                handle_t *handle;
                                error = ext4_orphan_add(handle, inode);
                                orphan = 1;
                        }
+                       /*
+                        * Update c/mtime on truncate up, ext4_truncate() will
+                        * update c/mtime in shrink case below
+                        */
+                       if (!shrink) {
+                               inode->i_mtime = ext4_current_time(inode);
+                               inode->i_ctime = inode->i_mtime;
+                       }
                        down_write(&EXT4_I(inode)->i_data_sem);
                        EXT4_I(inode)->i_disksize = attr->ia_size;
                        rc = ext4_mark_inode_dirty(handle, inode);
diff --combined fs/ext4/page-io.c
index 8a9d63a0c0710378a46c62ca532734c77fd53291,58ab2e3dd11471abee971bc44026a68072cb38a0..84ba4d2b3a35f58158b8e1c49b57ed74d806c569
@@@ -61,6 -61,7 +61,6 @@@ static void buffer_io_error(struct buff
  static void ext4_finish_bio(struct bio *bio)
  {
        int i;
 -      int error = !test_bit(BIO_UPTODATE, &bio->bi_flags);
        struct bio_vec *bvec;
  
        bio_for_each_segment_all(bvec, bio, i) {
@@@ -87,7 -88,7 +87,7 @@@
                }
  #endif
  
 -              if (error) {
 +              if (bio->bi_error) {
                        SetPageError(page);
                        set_bit(AS_EIO, &page->mapping->flags);
                }
                                continue;
                        }
                        clear_buffer_async_write(bh);
 -                      if (error)
 +                      if (bio->bi_error)
                                buffer_io_error(bh);
                } while ((bh = bh->b_this_page) != head);
                bit_spin_unlock(BH_Uptodate_Lock, &head->b_state);
@@@ -309,25 -310,27 +309,25 @@@ ext4_io_end_t *ext4_get_io_end(ext4_io_
  }
  
  /* BIO completion function for page writeback */
 -static void ext4_end_bio(struct bio *bio, int error)
 +static void ext4_end_bio(struct bio *bio)
  {
        ext4_io_end_t *io_end = bio->bi_private;
        sector_t bi_sector = bio->bi_iter.bi_sector;
  
        BUG_ON(!io_end);
        bio->bi_end_io = NULL;
 -      if (test_bit(BIO_UPTODATE, &bio->bi_flags))
 -              error = 0;
  
 -      if (error) {
 +      if (bio->bi_error) {
                struct inode *inode = io_end->inode;
  
                ext4_warning(inode->i_sb, "I/O error %d writing to inode %lu "
                             "(offset %llu size %ld starting block %llu)",
 -                           error, inode->i_ino,
 +                           bio->bi_error, inode->i_ino,
                             (unsigned long long) io_end->offset,
                             (long) io_end->size,
                             (unsigned long long)
                             bi_sector >> (inode->i_blkbits - 9));
 -              mapping_set_error(inode->i_mapping, error);
 +              mapping_set_error(inode->i_mapping, bio->bi_error);
        }
  
        if (io_end->flag & EXT4_IO_END_UNWRITTEN) {
@@@ -354,8 -357,10 +354,10 @@@ void ext4_io_submit(struct ext4_io_subm
        struct bio *bio = io->io_bio;
  
        if (bio) {
+               int io_op = io->io_wbc->sync_mode == WB_SYNC_ALL ?
+                           WRITE_SYNC : WRITE;
                bio_get(io->io_bio);
-               submit_bio(io->io_op, io->io_bio);
+               submit_bio(io_op, io->io_bio);
                bio_put(io->io_bio);
        }
        io->io_bio = NULL;
  void ext4_io_submit_init(struct ext4_io_submit *io,
                         struct writeback_control *wbc)
  {
-       io->io_op = (wbc->sync_mode == WB_SYNC_ALL ?  WRITE_SYNC : WRITE);
+       io->io_wbc = wbc;
        io->io_bio = NULL;
        io->io_end = NULL;
  }
  static int io_submit_init_bio(struct ext4_io_submit *io,
                              struct buffer_head *bh)
  {
 -      int nvecs = bio_get_nr_vecs(bh->b_bdev);
        struct bio *bio;
  
 -      bio = bio_alloc(GFP_NOIO, min(nvecs, BIO_MAX_PAGES));
 +      bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES);
        if (!bio)
                return -ENOMEM;
+       wbc_init_bio(io->io_wbc, bio);
        bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
        bio->bi_bdev = bh->b_bdev;
        bio->bi_end_io = ext4_end_bio;
@@@ -405,6 -412,7 +408,7 @@@ submit_and_retry
        ret = bio_add_page(io->io_bio, page, bh->b_size, bh_offset(bh));
        if (ret != bh->b_size)
                goto submit_and_retry;
+       wbc_account_io(io->io_wbc, page, bh->b_size);
        io->io_next_block++;
        return 0;
  }
diff --combined fs/ext4/super.c
index 06b4b14e8aa0233e14332ceb8b7aa85bd5c1bfb1,bd3ff923dd59cd88d5339ed509f47f93c699869c..ee3878262a495cfa57d20c4fbafac7b73b2e743a
@@@ -60,6 -60,7 +60,7 @@@ static struct ext4_lazy_init *ext4_li_i
  static struct mutex ext4_li_mtx;
  static struct ext4_features *ext4_feat;
  static int ext4_mballoc_ready;
+ static struct ratelimit_state ext4_mount_msg_ratelimit;
  
  static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
                             unsigned long journal_devnum);
@@@ -84,7 -85,7 +85,7 @@@ static void ext4_unregister_li_request(
  static void ext4_clear_request_list(void);
  static int ext4_reserve_clusters(struct ext4_sb_info *, ext4_fsblk_t);
  
 -#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
 +#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2)
  static struct file_system_type ext2_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "ext2",
@@@ -100,6 -101,7 +101,6 @@@ MODULE_ALIAS("ext2")
  #endif
  
  
 -#if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
  static struct file_system_type ext3_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "ext3",
  MODULE_ALIAS_FS("ext3");
  MODULE_ALIAS("ext3");
  #define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type)
 -#else
 -#define IS_EXT3_SB(sb) (0)
 -#endif
  
  static int ext4_verify_csum_type(struct super_block *sb,
                                 struct ext4_super_block *es)
@@@ -321,6 -326,22 +322,22 @@@ static void save_error_info(struct supe
        ext4_commit_super(sb, 1);
  }
  
+ /*
+  * The del_gendisk() function uninitializes the disk-specific data
+  * structures, including the bdi structure, without telling anyone
+  * else.  Once this happens, any attempt to call mark_buffer_dirty()
+  * (for example, by ext4_commit_super), will cause a kernel OOPS.
+  * This is a kludge to prevent these oops until we can put in a proper
+  * hook in del_gendisk() to inform the VFS and file system layers.
+  */
+ static int block_device_ejected(struct super_block *sb)
+ {
+       struct inode *bd_inode = sb->s_bdev->bd_inode;
+       struct backing_dev_info *bdi = inode_to_bdi(bd_inode);
+       return bdi->dev == NULL;
+ }
  static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
  {
        struct super_block              *sb = journal->j_private;
@@@ -1390,9 -1411,9 +1407,9 @@@ static const struct mount_opts 
        {Opt_stripe, 0, MOPT_GTE0},
        {Opt_resuid, 0, MOPT_GTE0},
        {Opt_resgid, 0, MOPT_GTE0},
-       {Opt_journal_dev, 0, MOPT_GTE0},
-       {Opt_journal_path, 0, MOPT_STRING},
-       {Opt_journal_ioprio, 0, MOPT_GTE0},
+       {Opt_journal_dev, 0, MOPT_NO_EXT2 | MOPT_GTE0},
+       {Opt_journal_path, 0, MOPT_NO_EXT2 | MOPT_STRING},
+       {Opt_journal_ioprio, 0, MOPT_NO_EXT2 | MOPT_GTE0},
        {Opt_data_journal, EXT4_MOUNT_JOURNAL_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},
        {Opt_data_ordered, EXT4_MOUNT_ORDERED_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},
        {Opt_data_writeback, EXT4_MOUNT_WRITEBACK_DATA,
@@@ -3639,6 -3660,8 +3656,8 @@@ static int ext4_fill_super(struct super
                }
                if (test_opt(sb, DELALLOC))
                        clear_opt(sb, DELALLOC);
+       } else {
+               sb->s_iflags |= SB_I_CGROUPWB;
        }
  
        sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
@@@ -4271,9 -4294,10 +4290,10 @@@ no_journal
                                 "the device does not support discard");
        }
  
-       ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
-                "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
-                *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
+       if (___ratelimit(&ext4_mount_msg_ratelimit, "EXT4-fs mount"))
+               ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
+                        "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
+                        *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
  
        if (es->s_error_count)
                mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
@@@ -4613,7 -4637,7 +4633,7 @@@ static int ext4_commit_super(struct sup
        struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
        int error = 0;
  
-       if (!sbh)
+       if (!sbh || block_device_ejected(sb))
                return error;
        if (buffer_write_io_error(sbh)) {
                /*
        ext4_superblock_csum_set(sb);
        mark_buffer_dirty(sbh);
        if (sync) {
-               error = sync_dirty_buffer(sbh);
+               error = __sync_dirty_buffer(sbh,
+                       test_opt(sb, BARRIER) ? WRITE_FUA : WRITE_SYNC);
                if (error)
                        return error;
  
@@@ -4829,10 -4854,11 +4850,11 @@@ static int ext4_freeze(struct super_blo
                error = jbd2_journal_flush(journal);
                if (error < 0)
                        goto out;
+               /* Journal blocked and flushed, clear needs_recovery flag. */
+               EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
        }
  
-       /* Journal blocked and flushed, clear needs_recovery flag. */
-       EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
        error = ext4_commit_super(sb, 1);
  out:
        if (journal)
@@@ -4850,8 -4876,11 +4872,11 @@@ static int ext4_unfreeze(struct super_b
        if (sb->s_flags & MS_RDONLY)
                return 0;
  
-       /* Reset the needs_recovery flag before the fs is unlocked. */
-       EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+       if (EXT4_SB(sb)->s_journal) {
+               /* Reset the needs_recovery flag before the fs is unlocked. */
+               EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+       }
        ext4_commit_super(sb, 1);
        return 0;
  }
@@@ -5496,7 -5525,7 +5521,7 @@@ static struct dentry *ext4_mount(struc
        return mount_bdev(fs_type, flags, dev_name, data, ext4_fill_super);
  }
  
 -#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
 +#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2)
  static inline void register_as_ext2(void)
  {
        int err = register_filesystem(&ext2_fs_type);
@@@ -5526,6 -5555,7 +5551,6 @@@ static inline void unregister_as_ext2(v
  static inline int ext2_feature_set_ok(struct super_block *sb) { return 0; }
  #endif
  
 -#if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
  static inline void register_as_ext3(void)
  {
        int err = register_filesystem(&ext3_fs_type);
@@@ -5551,6 -5581,11 +5576,6 @@@ static inline int ext3_feature_set_ok(s
                return 0;
        return 1;
  }
 -#else
 -static inline void register_as_ext3(void) { }
 -static inline void unregister_as_ext3(void) { }
 -static inline int ext3_feature_set_ok(struct super_block *sb) { return 0; }
 -#endif
  
  static struct file_system_type ext4_fs_type = {
        .owner          = THIS_MODULE,
@@@ -5600,6 -5635,7 +5625,7 @@@ static int __init ext4_init_fs(void
  {
        int i, err;
  
+       ratelimit_state_init(&ext4_mount_msg_ratelimit, 30 * HZ, 64);
        ext4_li_info = NULL;
        mutex_init(&ext4_li_mtx);
  
diff --combined include/linux/jbd2.h
index ad4b28647298a886815c9da16953779455f6b99c,eb1cebed3f36e84a6d93791670797749f65a73fa..df07e78487d560f1e2d96b5e5249a57a080c4ed2
@@@ -29,7 -29,6 +29,7 @@@
  #include <linux/mutex.h>
  #include <linux/timer.h>
  #include <linux/slab.h>
 +#include <linux/bit_spinlock.h>
  #include <crypto/hash.h>
  #endif
  
@@@ -337,45 -336,7 +337,45 @@@ BUFFER_FNS(Freed, freed
  BUFFER_FNS(Shadow, shadow)
  BUFFER_FNS(Verified, verified)
  
 -#include <linux/jbd_common.h>
 +static inline struct buffer_head *jh2bh(struct journal_head *jh)
 +{
 +      return jh->b_bh;
 +}
 +
 +static inline struct journal_head *bh2jh(struct buffer_head *bh)
 +{
 +      return bh->b_private;
 +}
 +
 +static inline void jbd_lock_bh_state(struct buffer_head *bh)
 +{
 +      bit_spin_lock(BH_State, &bh->b_state);
 +}
 +
 +static inline int jbd_trylock_bh_state(struct buffer_head *bh)
 +{
 +      return bit_spin_trylock(BH_State, &bh->b_state);
 +}
 +
 +static inline int jbd_is_locked_bh_state(struct buffer_head *bh)
 +{
 +      return bit_spin_is_locked(BH_State, &bh->b_state);
 +}
 +
 +static inline void jbd_unlock_bh_state(struct buffer_head *bh)
 +{
 +      bit_spin_unlock(BH_State, &bh->b_state);
 +}
 +
 +static inline void jbd_lock_bh_journal_head(struct buffer_head *bh)
 +{
 +      bit_spin_lock(BH_JournalHead, &bh->b_state);
 +}
 +
 +static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh)
 +{
 +      bit_spin_unlock(BH_JournalHead, &bh->b_state);
 +}
  
  #define J_ASSERT(assert)      BUG_ON(!(assert))
  
@@@ -1081,8 -1042,9 +1081,9 @@@ void jbd2_update_log_tail(journal_t *jo
  extern void jbd2_journal_commit_transaction(journal_t *);
  
  /* Checkpoint list management */
- void __jbd2_journal_clean_checkpoint_list(journal_t *journal);
+ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy);
  int __jbd2_journal_remove_checkpoint(struct journal_head *);
+ void jbd2_journal_destroy_checkpoint(journal_t *journal);
  void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *);