Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 May 2013 15:04:12 +0000 (08:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 May 2013 15:04:12 +0000 (08:04 -0700)
Pull ext4 updates from Ted Ts'o:
 "Mostly performance and bug fixes, plus some cleanups.  The one new
  feature this merge window is a new ioctl EXT4_IOC_SWAP_BOOT which
  allows installation of a hidden inode designed for boot loaders."

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (50 commits)
  ext4: fix type-widening bug in inode table readahead code
  ext4: add check for inodes_count overflow in new resize ioctl
  ext4: fix Kconfig documentation for CONFIG_EXT4_DEBUG
  ext4: fix online resizing for ext3-compat file systems
  jbd2: trace when lock_buffer in do_get_write_access takes a long time
  ext4: mark metadata blocks using bh flags
  buffer: add BH_Prio and BH_Meta flags
  ext4: mark all metadata I/O with REQ_META
  ext4: fix readdir error in case inline_data+^dir_index.
  ext4: fix readdir error in the case of inline_data+dir_index
  jbd2: use kmem_cache_zalloc instead of kmem_cache_alloc/memset
  ext4: mext_insert_extents should update extent block checksum
  ext4: move quota initialization out of inode allocation transaction
  ext4: reserve xattr index for Rich ACL support
  jbd2: reduce journal_head size
  ext4: clear buffer_uninit flag when submitting IO
  ext4: use io_end for multiple bios
  ext4: make ext4_bio_write_page() use BH_Async_Write flags
  ext4: Use kstrtoul() instead of parse_strtoul()
  ext4: defragmentation code cleanup
  ...

1  2 
fs/buffer.c
fs/jbd2/journal.c
include/linux/buffer_head.h

diff --combined fs/buffer.c
index 10ef81e10b207aefea70fee5a5a413b23b83a5c5,a15575c0b9eeab681c008bd85d9ab023a81b36ce..bc1fe14aaa3e4583aa351298fc9faa4f42d2d6a9
@@@ -865,6 -865,8 +865,6 @@@ try_again
  
                /* Link the buffer to its page */
                set_bh_page(bh, page, offset);
 -
 -              init_buffer(bh, NULL, NULL);
        }
        return head;
  /*
@@@ -2947,7 -2949,7 +2947,7 @@@ static void guard_bh_eod(int rw, struc
        }
  }
  
 -int submit_bh(int rw, struct buffer_head * bh)
 +int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
  {
        struct bio *bio;
        int ret = 0;
  
        bio->bi_end_io = end_bio_bh_io_sync;
        bio->bi_private = bh;
 +      bio->bi_flags |= bio_flags;
  
        /* Take care of bh's that straddle the end of the device */
        guard_bh_eod(rw, bio, bh);
  
+       if (buffer_meta(bh))
+               rw |= REQ_META;
+       if (buffer_prio(bh))
+               rw |= REQ_PRIO;
        bio_get(bio);
        submit_bio(rw, bio);
  
        bio_put(bio);
        return ret;
  }
 +EXPORT_SYMBOL_GPL(_submit_bh);
 +
 +int submit_bh(int rw, struct buffer_head *bh)
 +{
 +      return _submit_bh(rw, bh, 0);
 +}
  EXPORT_SYMBOL(submit_bh);
  
  /**
diff --combined fs/jbd2/journal.c
index 8b220f1ab54f337a0c0abef513e5280c7d2966ce,886ec2faa9b419a28f8f657dec3a56ccc26a07f8..f6c5ba027f4f613f655f703de222449a45c6c9c3
@@@ -367,6 -367,8 +367,6 @@@ retry_alloc
        }
  
        /* keep subsequent assertions sane */
 -      new_bh->b_state = 0;
 -      init_buffer(new_bh, NULL, NULL);
        atomic_set(&new_bh->b_count, 1);
        new_jh = jbd2_journal_add_journal_head(new_bh); /* This sleeps */
  
@@@ -707,6 -709,37 +707,37 @@@ int jbd2_log_wait_commit(journal_t *jou
        return err;
  }
  
+ /*
+  * When this function returns the transaction corresponding to tid
+  * will be completed.  If the transaction has currently running, start
+  * committing that transaction before waiting for it to complete.  If
+  * the transaction id is stale, it is by definition already completed,
+  * so just return SUCCESS.
+  */
+ int jbd2_complete_transaction(journal_t *journal, tid_t tid)
+ {
+       int     need_to_wait = 1;
+       read_lock(&journal->j_state_lock);
+       if (journal->j_running_transaction &&
+           journal->j_running_transaction->t_tid == tid) {
+               if (journal->j_commit_request != tid) {
+                       /* transaction not yet started, so request it */
+                       read_unlock(&journal->j_state_lock);
+                       jbd2_log_start_commit(journal, tid);
+                       goto wait_commit;
+               }
+       } else if (!(journal->j_committing_transaction &&
+                    journal->j_committing_transaction->t_tid == tid))
+               need_to_wait = 0;
+       read_unlock(&journal->j_state_lock);
+       if (!need_to_wait)
+               return 0;
+ wait_commit:
+       return jbd2_log_wait_commit(journal, tid);
+ }
+ EXPORT_SYMBOL(jbd2_complete_transaction);
  /*
   * Log buffer allocation routines:
   */
index 4c16c4a88d477cecff3434f49d4c15e4cb399302,33c0f8103fe4ac0786d83074c3ac2722a9169090..9e52b0626b39461bf21a3b71b32b0e7b2fadaf5c
@@@ -34,6 -34,8 +34,8 @@@ enum bh_state_bits 
        BH_Write_EIO,   /* I/O error on write */
        BH_Unwritten,   /* Buffer is allocated on disk but not written */
        BH_Quiet,       /* Buffer Error Prinks to be quiet */
+       BH_Meta,        /* Buffer contains metadata */
+       BH_Prio,        /* Buffer should be submitted with REQ_PRIO */
  
        BH_PrivateStart,/* not a state bit, but the first bit available
                         * for private allocation by other entities
@@@ -124,6 -126,8 +126,8 @@@ BUFFER_FNS(Delay, delay
  BUFFER_FNS(Boundary, boundary)
  BUFFER_FNS(Write_EIO, write_io_error)
  BUFFER_FNS(Unwritten, unwritten)
+ BUFFER_FNS(Meta, meta)
+ BUFFER_FNS(Prio, prio)
  
  #define bh_offset(bh)         ((unsigned long)(bh)->b_data & ~PAGE_MASK)
  
@@@ -181,7 -185,6 +185,7 @@@ void ll_rw_block(int, int, struct buffe
  int sync_dirty_buffer(struct buffer_head *bh);
  int __sync_dirty_buffer(struct buffer_head *bh, int rw);
  void write_dirty_buffer(struct buffer_head *bh, int rw);
 +int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags);
  int submit_bh(int, struct buffer_head *);
  void write_boundary_block(struct block_device *bdev,
                        sector_t bblock, unsigned blocksize);