diff options
Diffstat (limited to 'fs/ext3/super.c')
-rw-r--r-- | fs/ext3/super.c | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 377768009106..db87413d3479 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -1301,9 +1301,9 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es, ext3_msg(sb, KERN_WARNING, "warning: mounting fs with errors, " "running e2fsck is recommended"); - else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 && + else if ((__s16) le16_to_cpu(es->s_max_mnt_count) > 0 && le16_to_cpu(es->s_mnt_count) >= - (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count)) + le16_to_cpu(es->s_max_mnt_count)) ext3_msg(sb, KERN_WARNING, "warning: maximal mount count reached, " "running e2fsck is recommended"); @@ -1320,7 +1320,7 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es, valid forever! :) */ es->s_state &= cpu_to_le16(~EXT3_VALID_FS); #endif - if (!(__s16) le16_to_cpu(es->s_max_mnt_count)) + if (!le16_to_cpu(es->s_max_mnt_count)) es->s_max_mnt_count = cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT); le16_add_cpu(&es->s_mnt_count, 1); es->s_mtime = cpu_to_le32(get_seconds()); @@ -1647,7 +1647,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) * Note: s_es must be initialized as soon as possible because * some ext3 macro-instructions depend on its value */ - es = (struct ext3_super_block *) (((char *)bh->b_data) + offset); + es = (struct ext3_super_block *) (bh->b_data + offset); sbi->s_es = es; sb->s_magic = le16_to_cpu(es->s_magic); if (sb->s_magic != EXT3_SUPER_MAGIC) @@ -1758,7 +1758,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) "error: can't read superblock on 2nd try"); goto failed_mount; } - es = (struct ext3_super_block *)(((char *)bh->b_data) + offset); + es = (struct ext3_super_block *)(bh->b_data + offset); sbi->s_es = es; if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) { ext3_msg(sb, KERN_ERR, @@ -1857,13 +1857,13 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) - le32_to_cpu(es->s_first_data_block) - 1) / EXT3_BLOCKS_PER_GROUP(sb)) + 1; - db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) / - EXT3_DESC_PER_BLOCK(sb); + db_count = DIV_ROUND_UP(sbi->s_groups_count, EXT3_DESC_PER_BLOCK(sb)); sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *), GFP_KERNEL); if (sbi->s_group_desc == NULL) { ext3_msg(sb, KERN_ERR, "error: not enough memory"); + ret = -ENOMEM; goto failed_mount; } @@ -1951,6 +1951,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) } if (err) { ext3_msg(sb, KERN_ERR, "error: insufficient memory"); + ret = err; goto failed_mount3; } @@ -2159,7 +2160,7 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb, goto out_bdev; } - es = (struct ext3_super_block *) (((char *)bh->b_data) + offset); + es = (struct ext3_super_block *) (bh->b_data + offset); if ((le16_to_cpu(es->s_magic) != EXT3_SUPER_MAGIC) || !(le32_to_cpu(es->s_feature_incompat) & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { @@ -2352,6 +2353,21 @@ static int ext3_commit_super(struct super_block *sb, if (!sbh) return error; + + if (buffer_write_io_error(sbh)) { + /* + * Oh, dear. A previous attempt to write the + * superblock failed. This could happen because the + * USB device was yanked out. Or it could happen to + * be a transient write error and maybe the block will + * be remapped. Nothing we can do but to retry the + * write and hope for the best. + */ + ext3_msg(sb, KERN_ERR, "previous I/O error to " + "superblock detected"); + clear_buffer_write_io_error(sbh); + set_buffer_uptodate(sbh); + } /* * If the file system is mounted read-only, don't update the * superblock write time. This avoids updating the superblock @@ -2368,8 +2384,15 @@ static int ext3_commit_super(struct super_block *sb, es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb)); BUFFER_TRACE(sbh, "marking dirty"); mark_buffer_dirty(sbh); - if (sync) + if (sync) { error = sync_dirty_buffer(sbh); + if (buffer_write_io_error(sbh)) { + ext3_msg(sb, KERN_ERR, "I/O error while writing " + "superblock"); + clear_buffer_write_io_error(sbh); + set_buffer_uptodate(sbh); + } + } return error; } |