Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Apr 2009 15:37:40 +0000 (08:37 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Apr 2009 15:37:40 +0000 (08:37 -0700)
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: Fix potential inode allocation soft lockup in Orlov allocator
  ext4: Make the extent validity check more paranoid
  jbd: use SWRITE_SYNC_PLUG when writing synchronous revoke records
  jbd2: use SWRITE_SYNC_PLUG when writing synchronous revoke records
  ext4: really print the find_group_flex fallback warning only once

1  2 
fs/ext4/extents.c
fs/jbd/revoke.c

diff --combined fs/ext4/extents.c
@@@ -326,11 -326,14 +326,14 @@@ ext4_ext_max_entries(struct inode *inod
  
  static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
  {
-       ext4_fsblk_t block = ext_pblock(ext);
+       ext4_fsblk_t block = ext_pblock(ext), valid_block;
        int len = ext4_ext_get_actual_len(ext);
        struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
-       if (unlikely(block < le32_to_cpu(es->s_first_data_block) ||
-                       ((block + len) > ext4_blocks_count(es))))
+       valid_block = le32_to_cpu(es->s_first_data_block) +
+               EXT4_SB(inode->i_sb)->s_gdb_count;
+       if (unlikely(block <= valid_block ||
+                    ((block + len) > ext4_blocks_count(es))))
                return 0;
        else
                return 1;
  static int ext4_valid_extent_idx(struct inode *inode,
                                struct ext4_extent_idx *ext_idx)
  {
-       ext4_fsblk_t block = idx_pblock(ext_idx);
+       ext4_fsblk_t block = idx_pblock(ext_idx), valid_block;
        struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
-       if (unlikely(block < le32_to_cpu(es->s_first_data_block) ||
-                       (block >= ext4_blocks_count(es))))
+       valid_block = le32_to_cpu(es->s_first_data_block) +
+               EXT4_SB(inode->i_sb)->s_gdb_count;
+       if (unlikely(block <= valid_block ||
+                    (block >= ext4_blocks_count(es))))
                return 0;
        else
                return 1;
@@@ -2416,6 -2422,8 +2422,6 @@@ static int ext4_ext_zeroout(struct inod
                        len = ee_len;
  
                bio = bio_alloc(GFP_NOIO, len);
 -              if (!bio)
 -                      return -ENOMEM;
                bio->bi_sector = ee_pblock;
                bio->bi_bdev   = inode->i_sb->s_bdev;
  
diff --combined fs/jbd/revoke.c
   *                    need do nothing.
   * RevokeValid set, Revoked set:
   *                    buffer has been revoked.
 + *
 + * Locking rules:
 + * We keep two hash tables of revoke records. One hashtable belongs to the
 + * running transaction (is pointed to by journal->j_revoke), the other one
 + * belongs to the committing transaction. Accesses to the second hash table
 + * happen only from the kjournald and no other thread touches this table.  Also
 + * journal_switch_revoke_table() which switches which hashtable belongs to the
 + * running and which to the committing transaction is called only from
 + * kjournald. Therefore we need no locks when accessing the hashtable belonging
 + * to the committing transaction.
 + *
 + * All users operating on the hash table belonging to the running transaction
 + * have a handle to the transaction. Therefore they are safe from kjournald
 + * switching hash tables under them. For operations on the lists of entries in
 + * the hash table j_revoke_lock is used.
 + *
 + * Finally, also replay code uses the hash tables but at this moment noone else
 + * can touch them (filesystem isn't mounted yet) and hence no locking is
 + * needed.
   */
  
  #ifndef __KERNEL__
@@@ -86,6 -67,7 +86,7 @@@
  #include <linux/slab.h>
  #include <linux/list.h>
  #include <linux/init.h>
+ #include <linux/bio.h>
  #endif
  #include <linux/log2.h>
  
@@@ -118,8 -100,8 +119,8 @@@ struct jbd_revoke_table_
  #ifdef __KERNEL__
  static void write_one_revoke_record(journal_t *, transaction_t *,
                                    struct journal_head **, int *,
-                                   struct jbd_revoke_record_s *);
- static void flush_descriptor(journal_t *, struct journal_head *, int);
+                                   struct jbd_revoke_record_s *, int);
+ static void flush_descriptor(journal_t *, struct journal_head *, int, int);
  #endif
  
  /* Utility functions to maintain the revoke table */
@@@ -421,6 -403,8 +422,6 @@@ int journal_revoke(handle_t *handle, un
   * the second time we would still have a pending revoke to cancel.  So,
   * do not trust the Revoked bit on buffers unless RevokeValid is also
   * set.
 - *
 - * The caller must have the journal locked.
   */
  int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
  {
@@@ -498,9 -482,12 +499,9 @@@ void journal_switch_revoke_table(journa
  /*
   * Write revoke records to the journal for all entries in the current
   * revoke hash, deleting the entries as we go.
 - *
 - * Called with the journal lock held.
   */
 -
  void journal_write_revoke_records(journal_t *journal,
-                                 transaction_t *transaction)
+                                 transaction_t *transaction, int write_op)
  {
        struct journal_head *descriptor;
        struct jbd_revoke_record_s *record;
                                hash_list->next;
                        write_one_revoke_record(journal, transaction,
                                                &descriptor, &offset,
-                                               record);
+                                               record, write_op);
                        count++;
                        list_del(&record->hash);
                        kmem_cache_free(revoke_record_cache, record);
                }
        }
        if (descriptor)
-               flush_descriptor(journal, descriptor, offset);
+               flush_descriptor(journal, descriptor, offset, write_op);
        jbd_debug(1, "Wrote %d revoke records\n", count);
  }
  
@@@ -544,7 -531,8 +545,8 @@@ static void write_one_revoke_record(jou
                                    transaction_t *transaction,
                                    struct journal_head **descriptorp,
                                    int *offsetp,
-                                   struct jbd_revoke_record_s *record)
+                                   struct jbd_revoke_record_s *record,
+                                   int write_op)
  {
        struct journal_head *descriptor;
        int offset;
        /* Make sure we have a descriptor with space left for the record */
        if (descriptor) {
                if (offset == journal->j_blocksize) {
-                       flush_descriptor(journal, descriptor, offset);
+                       flush_descriptor(journal, descriptor, offset, write_op);
                        descriptor = NULL;
                }
        }
  
  static void flush_descriptor(journal_t *journal,
                             struct journal_head *descriptor,
-                            int offset)
+                            int offset, int write_op)
  {
        journal_revoke_header_t *header;
        struct buffer_head *bh = jh2bh(descriptor);
        set_buffer_jwrite(bh);
        BUFFER_TRACE(bh, "write");
        set_buffer_dirty(bh);
-       ll_rw_block(SWRITE, 1, &bh);
+       ll_rw_block((write_op == WRITE) ? SWRITE : SWRITE_SYNC_PLUG, 1, &bh);
  }
  #endif