|
@@ -1301,9 +1301,9 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
|
|
ext3_msg(sb, KERN_WARNING,
|
|
ext3_msg(sb, KERN_WARNING,
|
|
"warning: mounting fs with errors, "
|
|
"warning: mounting fs with errors, "
|
|
"running e2fsck is recommended");
|
|
"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) >=
|
|
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,
|
|
ext3_msg(sb, KERN_WARNING,
|
|
"warning: maximal mount count reached, "
|
|
"warning: maximal mount count reached, "
|
|
"running e2fsck is recommended");
|
|
"running e2fsck is recommended");
|
|
@@ -1320,7 +1320,7 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
|
|
valid forever! :) */
|
|
valid forever! :) */
|
|
es->s_state &= cpu_to_le16(~EXT3_VALID_FS);
|
|
es->s_state &= cpu_to_le16(~EXT3_VALID_FS);
|
|
#endif
|
|
#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);
|
|
es->s_max_mnt_count = cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT);
|
|
le16_add_cpu(&es->s_mnt_count, 1);
|
|
le16_add_cpu(&es->s_mnt_count, 1);
|
|
es->s_mtime = cpu_to_le32(get_seconds());
|
|
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
|
|
* Note: s_es must be initialized as soon as possible because
|
|
* some ext3 macro-instructions depend on its value
|
|
* 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;
|
|
sbi->s_es = es;
|
|
sb->s_magic = le16_to_cpu(es->s_magic);
|
|
sb->s_magic = le16_to_cpu(es->s_magic);
|
|
if (sb->s_magic != EXT3_SUPER_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");
|
|
"error: can't read superblock on 2nd try");
|
|
goto failed_mount;
|
|
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;
|
|
sbi->s_es = es;
|
|
if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) {
|
|
if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) {
|
|
ext3_msg(sb, KERN_ERR,
|
|
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) -
|
|
sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
|
|
le32_to_cpu(es->s_first_data_block) - 1)
|
|
le32_to_cpu(es->s_first_data_block) - 1)
|
|
/ EXT3_BLOCKS_PER_GROUP(sb)) + 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 *),
|
|
sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
|
|
GFP_KERNEL);
|
|
GFP_KERNEL);
|
|
if (sbi->s_group_desc == NULL) {
|
|
if (sbi->s_group_desc == NULL) {
|
|
ext3_msg(sb, KERN_ERR,
|
|
ext3_msg(sb, KERN_ERR,
|
|
"error: not enough memory");
|
|
"error: not enough memory");
|
|
|
|
+ ret = -ENOMEM;
|
|
goto failed_mount;
|
|
goto failed_mount;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1951,6 +1951,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
|
|
}
|
|
}
|
|
if (err) {
|
|
if (err) {
|
|
ext3_msg(sb, KERN_ERR, "error: insufficient memory");
|
|
ext3_msg(sb, KERN_ERR, "error: insufficient memory");
|
|
|
|
+ ret = err;
|
|
goto failed_mount3;
|
|
goto failed_mount3;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2159,7 +2160,7 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
|
|
goto out_bdev;
|
|
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) ||
|
|
if ((le16_to_cpu(es->s_magic) != EXT3_SUPER_MAGIC) ||
|
|
!(le32_to_cpu(es->s_feature_incompat) &
|
|
!(le32_to_cpu(es->s_feature_incompat) &
|
|
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
|
|
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
|
|
@@ -2352,6 +2353,21 @@ static int ext3_commit_super(struct super_block *sb,
|
|
|
|
|
|
if (!sbh)
|
|
if (!sbh)
|
|
return error;
|
|
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
|
|
* If the file system is mounted read-only, don't update the
|
|
* superblock write time. This avoids updating the superblock
|
|
* 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));
|
|
es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb));
|
|
BUFFER_TRACE(sbh, "marking dirty");
|
|
BUFFER_TRACE(sbh, "marking dirty");
|
|
mark_buffer_dirty(sbh);
|
|
mark_buffer_dirty(sbh);
|
|
- if (sync)
|
|
|
|
|
|
+ if (sync) {
|
|
error = sync_dirty_buffer(sbh);
|
|
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;
|
|
return error;
|
|
}
|
|
}
|
|
|
|
|