summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-04-24 08:37:40 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-24 08:37:40 -0700
commita4277bf122e907e4fec509fc0bd9bf5fde30b14e (patch)
treeb359e8b0f7895acda1d6331332e69ea5b14d5f0d
parent6ae85d6db4871d8dbcb5cc0e9056f97f1ca07061 (diff)
parentb5451f7b2694b04d9f912f6cf09db1729f291996 (diff)
downloadlinux-a4277bf122e907e4fec509fc0bd9bf5fde30b14e.tar.gz
linux-a4277bf122e907e4fec509fc0bd9bf5fde30b14e.tar.bz2
linux-a4277bf122e907e4fec509fc0bd9bf5fde30b14e.zip
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
* '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
-rw-r--r--fs/ext4/extents.c18
-rw-r--r--fs/ext4/ialloc.c6
-rw-r--r--fs/jbd/commit.c2
-rw-r--r--fs/jbd/revoke.c20
-rw-r--r--fs/jbd2/commit.c3
-rw-r--r--fs/jbd2/revoke.c21
-rw-r--r--include/linux/jbd.h3
-rw-r--r--include/linux/jbd2.h3
8 files changed, 46 insertions, 30 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 2a1cb0979768..e40332158340 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -326,11 +326,14 @@ ext4_ext_max_entries(struct inode *inode, int depth)
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;
@@ -339,10 +342,13 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
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;
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 47b84e8df568..f18e0a08a6b5 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -585,6 +585,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
fallback:
ngroups = sbi->s_groups_count;
avefreei = freei / ngroups;
+fallback_retry:
parent_group = EXT4_I(parent)->i_block_group;
for (i = 0; i < ngroups; i++) {
grp = (parent_group + i) % ngroups;
@@ -602,7 +603,7 @@ fallback:
* filesystems the above test can fail to find any blockgroups
*/
avefreei = 0;
- goto fallback;
+ goto fallback_retry;
}
return -1;
@@ -831,11 +832,12 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
ret2 = find_group_flex(sb, dir, &group);
if (ret2 == -1) {
ret2 = find_group_other(sb, dir, &group, mode);
- if (ret2 == 0 && once)
+ if (ret2 == 0 && once) {
once = 0;
printk(KERN_NOTICE "ext4: find_group_flex "
"failed, fallback succeeded dir %lu\n",
dir->i_ino);
+ }
}
goto got_group;
}
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index a8e8513a78a9..06560c520f49 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -502,7 +502,7 @@ void journal_commit_transaction(journal_t *journal)
err = 0;
}
- journal_write_revoke_records(journal, commit_transaction);
+ journal_write_revoke_records(journal, commit_transaction, write_op);
/*
* If we found any dirty or locked buffers, then we should have
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
index 3e9afc2a91d2..da6cd9bdaabc 100644
--- a/fs/jbd/revoke.c
+++ b/fs/jbd/revoke.c
@@ -86,6 +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 +119,8 @@ struct jbd_revoke_table_s
#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 */
@@ -500,7 +501,7 @@ void journal_switch_revoke_table(journal_t *journal)
* revoke hash, deleting the entries as we go.
*/
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;
@@ -524,14 +525,14 @@ void journal_write_revoke_records(journal_t *journal,
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 +545,8 @@ static void write_one_revoke_record(journal_t *journal,
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;
@@ -563,7 +565,7 @@ static void write_one_revoke_record(journal_t *journal,
/* 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;
}
}
@@ -600,7 +602,7 @@ static void write_one_revoke_record(journal_t *journal,
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);
@@ -615,7 +617,7 @@ static void flush_descriptor(journal_t *journal,
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
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 073c8c3df7cd..0b7d3b8226fd 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -506,7 +506,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
if (err)
jbd2_journal_abort(journal, err);
- jbd2_journal_write_revoke_records(journal, commit_transaction);
+ jbd2_journal_write_revoke_records(journal, commit_transaction,
+ write_op);
jbd_debug(3, "JBD: commit phase 2\n");
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index bbe6d592d8b3..a360b06af2e3 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -86,6 +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 +119,8 @@ struct jbd2_revoke_table_s
#ifdef __KERNEL__
static void write_one_revoke_record(journal_t *, transaction_t *,
struct journal_head **, int *,
- struct jbd2_revoke_record_s *);
-static void flush_descriptor(journal_t *, struct journal_head *, int);
+ struct jbd2_revoke_record_s *, int);
+static void flush_descriptor(journal_t *, struct journal_head *, int, int);
#endif
/* Utility functions to maintain the revoke table */
@@ -499,7 +500,8 @@ void jbd2_journal_switch_revoke_table(journal_t *journal)
* revoke hash, deleting the entries as we go.
*/
void jbd2_journal_write_revoke_records(journal_t *journal,
- transaction_t *transaction)
+ transaction_t *transaction,
+ int write_op)
{
struct journal_head *descriptor;
struct jbd2_revoke_record_s *record;
@@ -523,14 +525,14 @@ void jbd2_journal_write_revoke_records(journal_t *journal,
hash_list->next;
write_one_revoke_record(journal, transaction,
&descriptor, &offset,
- record);
+ record, write_op);
count++;
list_del(&record->hash);
kmem_cache_free(jbd2_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);
}
@@ -543,7 +545,8 @@ static void write_one_revoke_record(journal_t *journal,
transaction_t *transaction,
struct journal_head **descriptorp,
int *offsetp,
- struct jbd2_revoke_record_s *record)
+ struct jbd2_revoke_record_s *record,
+ int write_op)
{
struct journal_head *descriptor;
int offset;
@@ -562,7 +565,7 @@ static void write_one_revoke_record(journal_t *journal,
/* 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;
}
}
@@ -607,7 +610,7 @@ static void write_one_revoke_record(journal_t *journal,
static void flush_descriptor(journal_t *journal,
struct journal_head *descriptor,
- int offset)
+ int offset, int write_op)
{
jbd2_journal_revoke_header_t *header;
struct buffer_head *bh = jh2bh(descriptor);
@@ -622,7 +625,7 @@ static void flush_descriptor(journal_t *journal,
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
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 53ae4399da2d..c2049a04fa0b 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -978,7 +978,8 @@ extern void journal_destroy_revoke(journal_t *);
extern int journal_revoke (handle_t *,
unsigned long, struct buffer_head *);
extern int journal_cancel_revoke(handle_t *, struct journal_head *);
-extern void journal_write_revoke_records(journal_t *, transaction_t *);
+extern void journal_write_revoke_records(journal_t *,
+ transaction_t *, int);
/* Recovery revoke support */
extern int journal_set_revoke(journal_t *, unsigned long, tid_t);
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 8815a3456b3b..cc02393bfce8 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -1193,7 +1193,8 @@ extern int jbd2_journal_init_revoke_caches(void);
extern void jbd2_journal_destroy_revoke(journal_t *);
extern int jbd2_journal_revoke (handle_t *, unsigned long long, struct buffer_head *);
extern int jbd2_journal_cancel_revoke(handle_t *, struct journal_head *);
-extern void jbd2_journal_write_revoke_records(journal_t *, transaction_t *);
+extern void jbd2_journal_write_revoke_records(journal_t *,
+ transaction_t *, int);
/* Recovery revoke support */
extern int jbd2_journal_set_revoke(journal_t *, unsigned long long, tid_t);