提交 47188d39 编写于 作者: L Linus Torvalds

Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

Pull ext4 bugfixes from Ted Ts'o:
 "Various regression and bug fixes for ext4"

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: don't allow ext4_free_blocks() to fail due to ENOMEM
  ext4: fix spelling errors and a comment in extent_status tree
  ext4: rate limit printk in buffer_io_error()
  ext4: don't show usrquota/grpquota twice in /proc/mounts
  ext4: fix warning in ext4_evict_inode()
  ext4: fix ext4_get_group_number()
  ext4: silence warning in ext4_writepages()
...@@ -38,8 +38,8 @@ ext4_group_t ext4_get_group_number(struct super_block *sb, ...@@ -38,8 +38,8 @@ ext4_group_t ext4_get_group_number(struct super_block *sb,
ext4_group_t group; ext4_group_t group;
if (test_opt2(sb, STD_GROUP_SIZE)) if (test_opt2(sb, STD_GROUP_SIZE))
group = (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) + group = (block -
block) >> le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) >>
(EXT4_BLOCK_SIZE_BITS(sb) + EXT4_CLUSTER_BITS(sb) + 3); (EXT4_BLOCK_SIZE_BITS(sb) + EXT4_CLUSTER_BITS(sb) + 3);
else else
ext4_get_group_no_and_offset(sb, block, &group, NULL); ext4_get_group_no_and_offset(sb, block, &group, NULL);
......
...@@ -439,7 +439,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode, ...@@ -439,7 +439,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
*/ */
if (!ext4_es_is_written(es) && !ext4_es_is_unwritten(es)) { if (!ext4_es_is_written(es) && !ext4_es_is_unwritten(es)) {
if (in_range(es->es_lblk, ee_block, ee_len)) { if (in_range(es->es_lblk, ee_block, ee_len)) {
pr_warn("ES insert assertation failed for " pr_warn("ES insert assertion failed for "
"inode: %lu we can find an extent " "inode: %lu we can find an extent "
"at block [%d/%d/%llu/%c], but we " "at block [%d/%d/%llu/%c], but we "
"want to add an delayed/hole extent " "want to add an delayed/hole extent "
...@@ -458,7 +458,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode, ...@@ -458,7 +458,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
*/ */
if (es->es_lblk < ee_block || if (es->es_lblk < ee_block ||
ext4_es_pblock(es) != ee_start + es->es_lblk - ee_block) { ext4_es_pblock(es) != ee_start + es->es_lblk - ee_block) {
pr_warn("ES insert assertation failed for inode: %lu " pr_warn("ES insert assertion failed for inode: %lu "
"ex_status [%d/%d/%llu/%c] != " "ex_status [%d/%d/%llu/%c] != "
"es_status [%d/%d/%llu/%c]\n", inode->i_ino, "es_status [%d/%d/%llu/%c]\n", inode->i_ino,
ee_block, ee_len, ee_start, ee_block, ee_len, ee_start,
...@@ -468,7 +468,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode, ...@@ -468,7 +468,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
} }
if (ee_status ^ es_status) { if (ee_status ^ es_status) {
pr_warn("ES insert assertation failed for inode: %lu " pr_warn("ES insert assertion failed for inode: %lu "
"ex_status [%d/%d/%llu/%c] != " "ex_status [%d/%d/%llu/%c] != "
"es_status [%d/%d/%llu/%c]\n", inode->i_ino, "es_status [%d/%d/%llu/%c]\n", inode->i_ino,
ee_block, ee_len, ee_start, ee_block, ee_len, ee_start,
...@@ -481,7 +481,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode, ...@@ -481,7 +481,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
* that we don't want to add an written/unwritten extent. * that we don't want to add an written/unwritten extent.
*/ */
if (!ext4_es_is_delayed(es) && !ext4_es_is_hole(es)) { if (!ext4_es_is_delayed(es) && !ext4_es_is_hole(es)) {
pr_warn("ES insert assertation failed for inode: %lu " pr_warn("ES insert assertion failed for inode: %lu "
"can't find an extent at block %d but we want " "can't find an extent at block %d but we want "
"to add an written/unwritten extent " "to add an written/unwritten extent "
"[%d/%d/%llu/%llx]\n", inode->i_ino, "[%d/%d/%llu/%llx]\n", inode->i_ino,
...@@ -519,7 +519,7 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode, ...@@ -519,7 +519,7 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode,
* We want to add a delayed/hole extent but this * We want to add a delayed/hole extent but this
* block has been allocated. * block has been allocated.
*/ */
pr_warn("ES insert assertation failed for inode: %lu " pr_warn("ES insert assertion failed for inode: %lu "
"We can find blocks but we want to add a " "We can find blocks but we want to add a "
"delayed/hole extent [%d/%d/%llu/%llx]\n", "delayed/hole extent [%d/%d/%llu/%llx]\n",
inode->i_ino, es->es_lblk, es->es_len, inode->i_ino, es->es_lblk, es->es_len,
...@@ -527,13 +527,13 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode, ...@@ -527,13 +527,13 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode,
return; return;
} else if (ext4_es_is_written(es)) { } else if (ext4_es_is_written(es)) {
if (retval != es->es_len) { if (retval != es->es_len) {
pr_warn("ES insert assertation failed for " pr_warn("ES insert assertion failed for "
"inode: %lu retval %d != es_len %d\n", "inode: %lu retval %d != es_len %d\n",
inode->i_ino, retval, es->es_len); inode->i_ino, retval, es->es_len);
return; return;
} }
if (map.m_pblk != ext4_es_pblock(es)) { if (map.m_pblk != ext4_es_pblock(es)) {
pr_warn("ES insert assertation failed for " pr_warn("ES insert assertion failed for "
"inode: %lu m_pblk %llu != " "inode: %lu m_pblk %llu != "
"es_pblk %llu\n", "es_pblk %llu\n",
inode->i_ino, map.m_pblk, inode->i_ino, map.m_pblk,
...@@ -549,7 +549,7 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode, ...@@ -549,7 +549,7 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode,
} }
} else if (retval == 0) { } else if (retval == 0) {
if (ext4_es_is_written(es)) { if (ext4_es_is_written(es)) {
pr_warn("ES insert assertation failed for inode: %lu " pr_warn("ES insert assertion failed for inode: %lu "
"We can't find the block but we want to add " "We can't find the block but we want to add "
"an written extent [%d/%d/%llu/%llx]\n", "an written extent [%d/%d/%llu/%llx]\n",
inode->i_ino, es->es_lblk, es->es_len, inode->i_ino, es->es_lblk, es->es_len,
...@@ -632,10 +632,8 @@ static int __es_insert_extent(struct inode *inode, struct extent_status *newes) ...@@ -632,10 +632,8 @@ static int __es_insert_extent(struct inode *inode, struct extent_status *newes)
} }
/* /*
* ext4_es_insert_extent() adds a space to a extent status tree. * ext4_es_insert_extent() adds information to an inode's extent
* * status tree.
* ext4_es_insert_extent is called by ext4_da_write_begin and
* ext4_es_remove_extent.
* *
* Return 0 on success, error code on failure. * Return 0 on success, error code on failure.
*/ */
......
...@@ -465,7 +465,7 @@ static void ext4_map_blocks_es_recheck(handle_t *handle, ...@@ -465,7 +465,7 @@ static void ext4_map_blocks_es_recheck(handle_t *handle,
if (es_map->m_lblk != map->m_lblk || if (es_map->m_lblk != map->m_lblk ||
es_map->m_flags != map->m_flags || es_map->m_flags != map->m_flags ||
es_map->m_pblk != map->m_pblk) { es_map->m_pblk != map->m_pblk) {
printk("ES cache assertation failed for inode: %lu " printk("ES cache assertion failed for inode: %lu "
"es_cached ex [%d/%d/%llu/%x] != " "es_cached ex [%d/%d/%llu/%x] != "
"found ex [%d/%d/%llu/%x] retval %d flags %x\n", "found ex [%d/%d/%llu/%x] retval %d flags %x\n",
inode->i_ino, es_map->m_lblk, es_map->m_len, inode->i_ino, es_map->m_lblk, es_map->m_len,
...@@ -558,7 +558,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, ...@@ -558,7 +558,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
#ifdef ES_AGGRESSIVE_TEST #ifdef ES_AGGRESSIVE_TEST
if (retval != map->m_len) { if (retval != map->m_len) {
printk("ES len assertation failed for inode: %lu " printk("ES len assertion failed for inode: %lu "
"retval %d != map->m_len %d " "retval %d != map->m_len %d "
"in %s (lookup)\n", inode->i_ino, retval, "in %s (lookup)\n", inode->i_ino, retval,
map->m_len, __func__); map->m_len, __func__);
...@@ -659,7 +659,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, ...@@ -659,7 +659,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
#ifdef ES_AGGRESSIVE_TEST #ifdef ES_AGGRESSIVE_TEST
if (retval != map->m_len) { if (retval != map->m_len) {
printk("ES len assertation failed for inode: %lu " printk("ES len assertion failed for inode: %lu "
"retval %d != map->m_len %d " "retval %d != map->m_len %d "
"in %s (allocation)\n", inode->i_ino, retval, "in %s (allocation)\n", inode->i_ino, retval,
map->m_len, __func__); map->m_len, __func__);
...@@ -1642,7 +1642,7 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, ...@@ -1642,7 +1642,7 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
#ifdef ES_AGGRESSIVE_TEST #ifdef ES_AGGRESSIVE_TEST
if (retval != map->m_len) { if (retval != map->m_len) {
printk("ES len assertation failed for inode: %lu " printk("ES len assertion failed for inode: %lu "
"retval %d != map->m_len %d " "retval %d != map->m_len %d "
"in %s (lookup)\n", inode->i_ino, retval, "in %s (lookup)\n", inode->i_ino, retval,
map->m_len, __func__); map->m_len, __func__);
...@@ -2163,7 +2163,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, ...@@ -2163,7 +2163,7 @@ static int mpage_map_and_submit_extent(handle_t *handle,
mpd->io_submit.io_end->offset = mpd->io_submit.io_end->offset =
((loff_t)map->m_lblk) << inode->i_blkbits; ((loff_t)map->m_lblk) << inode->i_blkbits;
while (map->m_len) { do {
err = mpage_map_one_extent(handle, mpd); err = mpage_map_one_extent(handle, mpd);
if (err < 0) { if (err < 0) {
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
...@@ -2201,7 +2201,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, ...@@ -2201,7 +2201,7 @@ static int mpage_map_and_submit_extent(handle_t *handle,
err = mpage_map_and_submit_buffers(mpd); err = mpage_map_and_submit_buffers(mpd);
if (err < 0) if (err < 0)
return err; return err;
} } while (map->m_len);
/* Update on-disk size after IO is submitted */ /* Update on-disk size after IO is submitted */
disksize = ((loff_t)mpd->first_page) << PAGE_CACHE_SHIFT; disksize = ((loff_t)mpd->first_page) << PAGE_CACHE_SHIFT;
......
...@@ -4740,11 +4740,16 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, ...@@ -4740,11 +4740,16 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
* blocks being freed are metadata. these blocks shouldn't * blocks being freed are metadata. these blocks shouldn't
* be used until this transaction is committed * be used until this transaction is committed
*/ */
retry:
new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS); new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS);
if (!new_entry) { if (!new_entry) {
ext4_mb_unload_buddy(&e4b); /*
err = -ENOMEM; * We use a retry loop because
goto error_return; * ext4_free_blocks() is not allowed to fail.
*/
cond_resched();
congestion_wait(BLK_RW_ASYNC, HZ/50);
goto retry;
} }
new_entry->efd_start_cluster = bit; new_entry->efd_start_cluster = bit;
new_entry->efd_group = block_group; new_entry->efd_group = block_group;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/ratelimit.h>
#include "ext4_jbd2.h" #include "ext4_jbd2.h"
#include "xattr.h" #include "xattr.h"
...@@ -55,7 +56,7 @@ void ext4_exit_pageio(void) ...@@ -55,7 +56,7 @@ void ext4_exit_pageio(void)
static void buffer_io_error(struct buffer_head *bh) static void buffer_io_error(struct buffer_head *bh)
{ {
char b[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE];
printk(KERN_ERR "Buffer I/O error on device %s, logical block %llu\n", printk_ratelimited(KERN_ERR "Buffer I/O error on device %s, logical block %llu\n",
bdevname(bh->b_bdev, b), bdevname(bh->b_bdev, b),
(unsigned long long)bh->b_blocknr); (unsigned long long)bh->b_blocknr);
} }
...@@ -308,6 +309,7 @@ ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end) ...@@ -308,6 +309,7 @@ ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end)
return io_end; return io_end;
} }
/* BIO completion function for page writeback */
static void ext4_end_bio(struct bio *bio, int error) static void ext4_end_bio(struct bio *bio, int error)
{ {
ext4_io_end_t *io_end = bio->bi_private; ext4_io_end_t *io_end = bio->bi_private;
...@@ -318,18 +320,6 @@ static void ext4_end_bio(struct bio *bio, int error) ...@@ -318,18 +320,6 @@ static void ext4_end_bio(struct bio *bio, int error)
if (test_bit(BIO_UPTODATE, &bio->bi_flags)) if (test_bit(BIO_UPTODATE, &bio->bi_flags))
error = 0; error = 0;
if (io_end->flag & EXT4_IO_END_UNWRITTEN) {
/*
* Link bio into list hanging from io_end. We have to do it
* atomically as bio completions can be racing against each
* other.
*/
bio->bi_private = xchg(&io_end->bio, bio);
} else {
ext4_finish_bio(bio);
bio_put(bio);
}
if (error) { if (error) {
struct inode *inode = io_end->inode; struct inode *inode = io_end->inode;
...@@ -341,7 +331,24 @@ static void ext4_end_bio(struct bio *bio, int error) ...@@ -341,7 +331,24 @@ static void ext4_end_bio(struct bio *bio, int error)
(unsigned long long) (unsigned long long)
bi_sector >> (inode->i_blkbits - 9)); bi_sector >> (inode->i_blkbits - 9));
} }
ext4_put_io_end_defer(io_end);
if (io_end->flag & EXT4_IO_END_UNWRITTEN) {
/*
* Link bio into list hanging from io_end. We have to do it
* atomically as bio completions can be racing against each
* other.
*/
bio->bi_private = xchg(&io_end->bio, bio);
ext4_put_io_end_defer(io_end);
} else {
/*
* Drop io_end reference early. Inode can get freed once
* we finish the bio.
*/
ext4_put_io_end_defer(io_end);
ext4_finish_bio(bio);
bio_put(bio);
}
} }
void ext4_io_submit(struct ext4_io_submit *io) void ext4_io_submit(struct ext4_io_submit *io)
......
...@@ -1702,12 +1702,6 @@ static inline void ext4_show_quota_options(struct seq_file *seq, ...@@ -1702,12 +1702,6 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
if (sbi->s_qf_names[GRPQUOTA]) if (sbi->s_qf_names[GRPQUOTA])
seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]); seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
if (test_opt(sb, USRQUOTA))
seq_puts(seq, ",usrquota");
if (test_opt(sb, GRPQUOTA))
seq_puts(seq, ",grpquota");
#endif #endif
} }
...@@ -3624,10 +3618,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3624,10 +3618,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb)); sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb)); sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
/* Do we have standard group size of blocksize * 8 blocks ? */
if (sbi->s_blocks_per_group == blocksize << 3)
set_opt2(sb, STD_GROUP_SIZE);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
sbi->s_def_hash_version = es->s_def_hash_version; sbi->s_def_hash_version = es->s_def_hash_version;
...@@ -3697,6 +3687,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3697,6 +3687,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
goto failed_mount; goto failed_mount;
} }
/* Do we have standard group size of clustersize * 8 blocks ? */
if (sbi->s_blocks_per_group == clustersize << 3)
set_opt2(sb, STD_GROUP_SIZE);
/* /*
* Test whether we have more sectors than will fit in sector_t, * Test whether we have more sectors than will fit in sector_t,
* and whether the max offset is addressable by the page cache. * and whether the max offset is addressable by the page cache.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册