Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 309934
b: refs/heads/master
c: a9c4731
h: refs/heads/master
v: v3
  • Loading branch information
Darrick J. Wong authored and Theodore Ts'o committed Apr 29, 2012
1 parent 0608d21 commit 187b631
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0441984a3398970ab4820410b9cf4ff85bf3a6b0
refs/heads/master: a9c4731780544d52b243bf46e4dd635c67fa9f84
10 changes: 10 additions & 0 deletions trunk/fs/ext4/ext4.h
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,9 @@ struct ext4_sb_info {

/* Reference to checksum algorithm driver via cryptoapi */
struct crypto_shash *s_chksum_driver;

/* Precomputed FS UUID checksum for seeding other checksums */
__u32 s_csum_seed;
};

static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
Expand Down Expand Up @@ -2004,6 +2007,10 @@ extern int ext4_group_extend(struct super_block *sb,
extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);

/* super.c */
extern int ext4_superblock_csum_verify(struct super_block *sb,
struct ext4_super_block *es);
extern void ext4_superblock_csum_set(struct super_block *sb,
struct ext4_super_block *es);
extern void *ext4_kvmalloc(size_t size, gfp_t flags);
extern void *ext4_kvzalloc(size_t size, gfp_t flags);
extern void ext4_kvfree(void *ptr);
Expand Down Expand Up @@ -2279,6 +2286,9 @@ static inline void ext4_unlock_group(struct super_block *sb,

static inline void ext4_mark_super_dirty(struct super_block *sb)
{
struct ext4_super_block *es = EXT4_SB(sb)->s_es;

ext4_superblock_csum_set(sb, es);
if (EXT4_SB(sb)->s_journal == NULL)
sb->s_dirt =1;
}
Expand Down
9 changes: 8 additions & 1 deletion trunk/fs/ext4/ext4_jbd2.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,23 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
}

int __ext4_handle_dirty_super(const char *where, unsigned int line,
handle_t *handle, struct super_block *sb)
handle_t *handle, struct super_block *sb,
int now)
{
struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
int err = 0;

if (ext4_handle_valid(handle)) {
ext4_superblock_csum_set(sb,
(struct ext4_super_block *)bh->b_data);
err = jbd2_journal_dirty_metadata(handle, bh);
if (err)
ext4_journal_abort_handle(where, line, __func__,
bh, handle, err);
} else if (now) {
ext4_superblock_csum_set(sb,
(struct ext4_super_block *)bh->b_data);
mark_buffer_dirty(bh);
} else
sb->s_dirt = 1;
return err;
Expand Down
7 changes: 5 additions & 2 deletions trunk/fs/ext4/ext4_jbd2.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
struct buffer_head *bh);

int __ext4_handle_dirty_super(const char *where, unsigned int line,
handle_t *handle, struct super_block *sb);
handle_t *handle, struct super_block *sb,
int now);

#define ext4_journal_get_write_access(handle, bh) \
__ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh))
Expand All @@ -225,8 +226,10 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
#define ext4_handle_dirty_metadata(handle, inode, bh) \
__ext4_handle_dirty_metadata(__func__, __LINE__, (handle), (inode), \
(bh))
#define ext4_handle_dirty_super_now(handle, sb) \
__ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb), 1)
#define ext4_handle_dirty_super(handle, sb) \
__ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb))
__ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb), 0)

handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle);
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/ext4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -3936,7 +3936,7 @@ static int ext4_do_update_inode(handle_t *handle,
EXT4_SET_RO_COMPAT_FEATURE(sb,
EXT4_FEATURE_RO_COMPAT_LARGE_FILE);
ext4_handle_sync(handle);
err = ext4_handle_dirty_super(handle, sb);
err = ext4_handle_dirty_super_now(handle, sb);
}
}
raw_inode->i_generation = cpu_to_le32(inode->i_generation);
Expand Down
4 changes: 2 additions & 2 deletions trunk/fs/ext4/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -2021,7 +2021,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
/* Insert this inode at the head of the on-disk orphan list... */
NEXT_ORPHAN(inode) = le32_to_cpu(EXT4_SB(sb)->s_es->s_last_orphan);
EXT4_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
err = ext4_handle_dirty_super_now(handle, sb);
rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
if (!err)
err = rc;
Expand Down Expand Up @@ -2094,7 +2094,7 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
if (err)
goto out_brelse;
sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
err = ext4_handle_dirty_super_now(handle, inode->i_sb);
} else {
struct ext4_iloc iloc2;
struct inode *i_prev =
Expand Down
4 changes: 3 additions & 1 deletion trunk/fs/ext4/resize.c
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
ext4_kvfree(o_group_desc);

le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
err = ext4_handle_dirty_super_now(handle, sb);
if (err)
ext4_std_error(sb, err);

Expand Down Expand Up @@ -968,6 +968,8 @@ static void update_backups(struct super_block *sb,
goto exit_err;
}

ext4_superblock_csum_set(sb, (struct ext4_super_block *)data);

while ((group = ext4_list_backups(sb, &three, &five, &seven)) < last) {
struct buffer_head *bh;

Expand Down
47 changes: 47 additions & 0 deletions trunk/fs/ext4/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,38 @@ static int ext4_verify_csum_type(struct super_block *sb,
return es->s_checksum_type == EXT4_CRC32C_CHKSUM;
}

static __le32 ext4_superblock_csum(struct super_block *sb,
struct ext4_super_block *es)
{
struct ext4_sb_info *sbi = EXT4_SB(sb);
int offset = offsetof(struct ext4_super_block, s_checksum);
__u32 csum;

csum = ext4_chksum(sbi, ~0, (char *)es, offset);

return cpu_to_le32(csum);
}

int ext4_superblock_csum_verify(struct super_block *sb,
struct ext4_super_block *es)
{
if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
return 1;

return es->s_checksum == ext4_superblock_csum(sb, es);
}

void ext4_superblock_csum_set(struct super_block *sb,
struct ext4_super_block *es)
{
if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
return;

es->s_checksum = ext4_superblock_csum(sb, es);
}

void *ext4_kvmalloc(size_t size, gfp_t flags)
{
void *ret;
Expand Down Expand Up @@ -3057,6 +3089,20 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
}
}

/* Check superblock checksum */
if (!ext4_superblock_csum_verify(sb, es)) {
ext4_msg(sb, KERN_ERR, "VFS: Found ext4 filesystem with "
"invalid superblock checksum. Run e2fsck?");
silent = 1;
goto cantfind_ext4;
}

/* Precompute checksum seed for all metadata */
if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
sbi->s_csum_seed = ext4_chksum(sbi, ~0, es->s_uuid,
sizeof(es->s_uuid));

/* Set defaults before we parse the mount options */
def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
set_opt(sb, INIT_INODE_TABLE);
Expand Down Expand Up @@ -4059,6 +4105,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
&EXT4_SB(sb)->s_freeinodes_counter));
sb->s_dirt = 0;
BUFFER_TRACE(sbh, "marking dirty");
ext4_superblock_csum_set(sb, es);
mark_buffer_dirty(sbh);
if (sync) {
error = sync_dirty_buffer(sbh);
Expand Down

0 comments on commit 187b631

Please sign in to comment.