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
This commit is contained in:
commit
a4277bf122
8 changed files with 46 additions and 30 deletions
|
@ -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;
|
||||
|
|
|
@ -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 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
|||
* 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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue