Commit a4277bf1 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 6ae85d6d b5451f7b
...@@ -326,10 +326,13 @@ ext4_ext_max_entries(struct inode *inode, int depth) ...@@ -326,10 +326,13 @@ ext4_ext_max_entries(struct inode *inode, int depth)
static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext) 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); int len = ext4_ext_get_actual_len(ext);
struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
if (unlikely(block < le32_to_cpu(es->s_first_data_block) ||
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)))) ((block + len) > ext4_blocks_count(es))))
return 0; return 0;
else else
...@@ -339,9 +342,12 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext) ...@@ -339,9 +342,12 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
static int ext4_valid_extent_idx(struct inode *inode, static int ext4_valid_extent_idx(struct inode *inode,
struct ext4_extent_idx *ext_idx) 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; struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
if (unlikely(block < le32_to_cpu(es->s_first_data_block) ||
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)))) (block >= ext4_blocks_count(es))))
return 0; return 0;
else else
......
...@@ -585,6 +585,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, ...@@ -585,6 +585,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
fallback: fallback:
ngroups = sbi->s_groups_count; ngroups = sbi->s_groups_count;
avefreei = freei / ngroups; avefreei = freei / ngroups;
fallback_retry:
parent_group = EXT4_I(parent)->i_block_group; parent_group = EXT4_I(parent)->i_block_group;
for (i = 0; i < ngroups; i++) { for (i = 0; i < ngroups; i++) {
grp = (parent_group + i) % ngroups; grp = (parent_group + i) % ngroups;
...@@ -602,7 +603,7 @@ fallback: ...@@ -602,7 +603,7 @@ fallback:
* filesystems the above test can fail to find any blockgroups * filesystems the above test can fail to find any blockgroups
*/ */
avefreei = 0; avefreei = 0;
goto fallback; goto fallback_retry;
} }
return -1; return -1;
...@@ -831,12 +832,13 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode) ...@@ -831,12 +832,13 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
ret2 = find_group_flex(sb, dir, &group); ret2 = find_group_flex(sb, dir, &group);
if (ret2 == -1) { if (ret2 == -1) {
ret2 = find_group_other(sb, dir, &group, mode); ret2 = find_group_other(sb, dir, &group, mode);
if (ret2 == 0 && once) if (ret2 == 0 && once) {
once = 0; once = 0;
printk(KERN_NOTICE "ext4: find_group_flex " printk(KERN_NOTICE "ext4: find_group_flex "
"failed, fallback succeeded dir %lu\n", "failed, fallback succeeded dir %lu\n",
dir->i_ino); dir->i_ino);
} }
}
goto got_group; goto got_group;
} }
......
...@@ -502,7 +502,7 @@ void journal_commit_transaction(journal_t *journal) ...@@ -502,7 +502,7 @@ void journal_commit_transaction(journal_t *journal)
err = 0; 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 * If we found any dirty or locked buffers, then we should have
......
...@@ -86,6 +86,7 @@ ...@@ -86,6 +86,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/bio.h>
#endif #endif
#include <linux/log2.h> #include <linux/log2.h>
...@@ -118,8 +119,8 @@ struct jbd_revoke_table_s ...@@ -118,8 +119,8 @@ struct jbd_revoke_table_s
#ifdef __KERNEL__ #ifdef __KERNEL__
static void write_one_revoke_record(journal_t *, transaction_t *, static void write_one_revoke_record(journal_t *, transaction_t *,
struct journal_head **, int *, struct journal_head **, int *,
struct jbd_revoke_record_s *); struct jbd_revoke_record_s *, int);
static void flush_descriptor(journal_t *, struct journal_head *, int); static void flush_descriptor(journal_t *, struct journal_head *, int, int);
#endif #endif
/* Utility functions to maintain the revoke table */ /* Utility functions to maintain the revoke table */
...@@ -500,7 +501,7 @@ void journal_switch_revoke_table(journal_t *journal) ...@@ -500,7 +501,7 @@ void journal_switch_revoke_table(journal_t *journal)
* revoke hash, deleting the entries as we go. * revoke hash, deleting the entries as we go.
*/ */
void journal_write_revoke_records(journal_t *journal, void journal_write_revoke_records(journal_t *journal,
transaction_t *transaction) transaction_t *transaction, int write_op)
{ {
struct journal_head *descriptor; struct journal_head *descriptor;
struct jbd_revoke_record_s *record; struct jbd_revoke_record_s *record;
...@@ -524,14 +525,14 @@ void journal_write_revoke_records(journal_t *journal, ...@@ -524,14 +525,14 @@ void journal_write_revoke_records(journal_t *journal,
hash_list->next; hash_list->next;
write_one_revoke_record(journal, transaction, write_one_revoke_record(journal, transaction,
&descriptor, &offset, &descriptor, &offset,
record); record, write_op);
count++; count++;
list_del(&record->hash); list_del(&record->hash);
kmem_cache_free(revoke_record_cache, record); kmem_cache_free(revoke_record_cache, record);
} }
} }
if (descriptor) if (descriptor)
flush_descriptor(journal, descriptor, offset); flush_descriptor(journal, descriptor, offset, write_op);
jbd_debug(1, "Wrote %d revoke records\n", count); jbd_debug(1, "Wrote %d revoke records\n", count);
} }
...@@ -544,7 +545,8 @@ static void write_one_revoke_record(journal_t *journal, ...@@ -544,7 +545,8 @@ static void write_one_revoke_record(journal_t *journal,
transaction_t *transaction, transaction_t *transaction,
struct journal_head **descriptorp, struct journal_head **descriptorp,
int *offsetp, int *offsetp,
struct jbd_revoke_record_s *record) struct jbd_revoke_record_s *record,
int write_op)
{ {
struct journal_head *descriptor; struct journal_head *descriptor;
int offset; int offset;
...@@ -563,7 +565,7 @@ static void write_one_revoke_record(journal_t *journal, ...@@ -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 */ /* Make sure we have a descriptor with space left for the record */
if (descriptor) { if (descriptor) {
if (offset == journal->j_blocksize) { if (offset == journal->j_blocksize) {
flush_descriptor(journal, descriptor, offset); flush_descriptor(journal, descriptor, offset, write_op);
descriptor = NULL; descriptor = NULL;
} }
} }
...@@ -600,7 +602,7 @@ static void write_one_revoke_record(journal_t *journal, ...@@ -600,7 +602,7 @@ static void write_one_revoke_record(journal_t *journal,
static void flush_descriptor(journal_t *journal, static void flush_descriptor(journal_t *journal,
struct journal_head *descriptor, struct journal_head *descriptor,
int offset) int offset, int write_op)
{ {
journal_revoke_header_t *header; journal_revoke_header_t *header;
struct buffer_head *bh = jh2bh(descriptor); struct buffer_head *bh = jh2bh(descriptor);
...@@ -615,7 +617,7 @@ static void flush_descriptor(journal_t *journal, ...@@ -615,7 +617,7 @@ static void flush_descriptor(journal_t *journal,
set_buffer_jwrite(bh); set_buffer_jwrite(bh);
BUFFER_TRACE(bh, "write"); BUFFER_TRACE(bh, "write");
set_buffer_dirty(bh); set_buffer_dirty(bh);
ll_rw_block(SWRITE, 1, &bh); ll_rw_block((write_op == WRITE) ? SWRITE : SWRITE_SYNC_PLUG, 1, &bh);
} }
#endif #endif
......
...@@ -506,7 +506,8 @@ void jbd2_journal_commit_transaction(journal_t *journal) ...@@ -506,7 +506,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
if (err) if (err)
jbd2_journal_abort(journal, 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"); jbd_debug(3, "JBD: commit phase 2\n");
......
...@@ -86,6 +86,7 @@ ...@@ -86,6 +86,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/bio.h>
#endif #endif
#include <linux/log2.h> #include <linux/log2.h>
...@@ -118,8 +119,8 @@ struct jbd2_revoke_table_s ...@@ -118,8 +119,8 @@ struct jbd2_revoke_table_s
#ifdef __KERNEL__ #ifdef __KERNEL__
static void write_one_revoke_record(journal_t *, transaction_t *, static void write_one_revoke_record(journal_t *, transaction_t *,
struct journal_head **, int *, struct journal_head **, int *,
struct jbd2_revoke_record_s *); struct jbd2_revoke_record_s *, int);
static void flush_descriptor(journal_t *, struct journal_head *, int); static void flush_descriptor(journal_t *, struct journal_head *, int, int);
#endif #endif
/* Utility functions to maintain the revoke table */ /* Utility functions to maintain the revoke table */
...@@ -499,7 +500,8 @@ void jbd2_journal_switch_revoke_table(journal_t *journal) ...@@ -499,7 +500,8 @@ void jbd2_journal_switch_revoke_table(journal_t *journal)
* revoke hash, deleting the entries as we go. * revoke hash, deleting the entries as we go.
*/ */
void jbd2_journal_write_revoke_records(journal_t *journal, void jbd2_journal_write_revoke_records(journal_t *journal,
transaction_t *transaction) transaction_t *transaction,
int write_op)
{ {
struct journal_head *descriptor; struct journal_head *descriptor;
struct jbd2_revoke_record_s *record; struct jbd2_revoke_record_s *record;
...@@ -523,14 +525,14 @@ void jbd2_journal_write_revoke_records(journal_t *journal, ...@@ -523,14 +525,14 @@ void jbd2_journal_write_revoke_records(journal_t *journal,
hash_list->next; hash_list->next;
write_one_revoke_record(journal, transaction, write_one_revoke_record(journal, transaction,
&descriptor, &offset, &descriptor, &offset,
record); record, write_op);
count++; count++;
list_del(&record->hash); list_del(&record->hash);
kmem_cache_free(jbd2_revoke_record_cache, record); kmem_cache_free(jbd2_revoke_record_cache, record);
} }
} }
if (descriptor) if (descriptor)
flush_descriptor(journal, descriptor, offset); flush_descriptor(journal, descriptor, offset, write_op);
jbd_debug(1, "Wrote %d revoke records\n", count); jbd_debug(1, "Wrote %d revoke records\n", count);
} }
...@@ -543,7 +545,8 @@ static void write_one_revoke_record(journal_t *journal, ...@@ -543,7 +545,8 @@ static void write_one_revoke_record(journal_t *journal,
transaction_t *transaction, transaction_t *transaction,
struct journal_head **descriptorp, struct journal_head **descriptorp,
int *offsetp, int *offsetp,
struct jbd2_revoke_record_s *record) struct jbd2_revoke_record_s *record,
int write_op)
{ {
struct journal_head *descriptor; struct journal_head *descriptor;
int offset; int offset;
...@@ -562,7 +565,7 @@ static void write_one_revoke_record(journal_t *journal, ...@@ -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 */ /* Make sure we have a descriptor with space left for the record */
if (descriptor) { if (descriptor) {
if (offset == journal->j_blocksize) { if (offset == journal->j_blocksize) {
flush_descriptor(journal, descriptor, offset); flush_descriptor(journal, descriptor, offset, write_op);
descriptor = NULL; descriptor = NULL;
} }
} }
...@@ -607,7 +610,7 @@ static void write_one_revoke_record(journal_t *journal, ...@@ -607,7 +610,7 @@ static void write_one_revoke_record(journal_t *journal,
static void flush_descriptor(journal_t *journal, static void flush_descriptor(journal_t *journal,
struct journal_head *descriptor, struct journal_head *descriptor,
int offset) int offset, int write_op)
{ {
jbd2_journal_revoke_header_t *header; jbd2_journal_revoke_header_t *header;
struct buffer_head *bh = jh2bh(descriptor); struct buffer_head *bh = jh2bh(descriptor);
...@@ -622,7 +625,7 @@ static void flush_descriptor(journal_t *journal, ...@@ -622,7 +625,7 @@ static void flush_descriptor(journal_t *journal,
set_buffer_jwrite(bh); set_buffer_jwrite(bh);
BUFFER_TRACE(bh, "write"); BUFFER_TRACE(bh, "write");
set_buffer_dirty(bh); set_buffer_dirty(bh);
ll_rw_block(SWRITE, 1, &bh); ll_rw_block((write_op == WRITE) ? SWRITE : SWRITE_SYNC_PLUG, 1, &bh);
} }
#endif #endif
......
...@@ -978,7 +978,8 @@ extern void journal_destroy_revoke(journal_t *); ...@@ -978,7 +978,8 @@ extern void journal_destroy_revoke(journal_t *);
extern int journal_revoke (handle_t *, extern int journal_revoke (handle_t *,
unsigned long, struct buffer_head *); unsigned long, struct buffer_head *);
extern int journal_cancel_revoke(handle_t *, struct journal_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 */ /* Recovery revoke support */
extern int journal_set_revoke(journal_t *, unsigned long, tid_t); extern int journal_set_revoke(journal_t *, unsigned long, tid_t);
......
...@@ -1193,7 +1193,8 @@ extern int jbd2_journal_init_revoke_caches(void); ...@@ -1193,7 +1193,8 @@ extern int jbd2_journal_init_revoke_caches(void);
extern void jbd2_journal_destroy_revoke(journal_t *); 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_revoke (handle_t *, unsigned long long, struct buffer_head *);
extern int jbd2_journal_cancel_revoke(handle_t *, struct journal_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 */ /* Recovery revoke support */
extern int jbd2_journal_set_revoke(journal_t *, unsigned long long, tid_t); extern int jbd2_journal_set_revoke(journal_t *, unsigned long long, tid_t);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment