diff options
-rw-r--r-- | fs/f2fs/f2fs.h | 2 | ||||
-rw-r--r-- | fs/f2fs/file.c | 8 | ||||
-rw-r--r-- | fs/f2fs/super.c | 81 |
3 files changed, 38 insertions, 53 deletions
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 21048edb72cb..37cf04b3ff37 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -715,8 +715,8 @@ enum { struct f2fs_sb_info { struct super_block *sb; /* pointer to VFS super block */ struct proc_dir_entry *s_proc; /* proc entry */ - struct buffer_head *raw_super_buf; /* buffer head of raw sb */ struct f2fs_super_block *raw_super; /* raw super block pointer */ + int valid_super_block; /* valid super block no */ int s_flag; /* flags for sbi */ /* for node-related operations */ diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 1f5892f38018..7f8ca47be0af 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1591,20 +1591,16 @@ static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg) return err; /* update superblock with uuid */ - lock_buffer(sbi->raw_super_buf); generate_random_uuid(sbi->raw_super->encrypt_pw_salt); - unlock_buffer(sbi->raw_super_buf); err = f2fs_commit_super(sbi, false); - - mnt_drop_write_file(filp); if (err) { /* undo new data */ - lock_buffer(sbi->raw_super_buf); memset(sbi->raw_super->encrypt_pw_salt, 0, 16); - unlock_buffer(sbi->raw_super_buf); + mnt_drop_write_file(filp); return err; } + mnt_drop_write_file(filp); got_it: if (copy_to_user((__u8 __user *)arg, sbi->raw_super->encrypt_pw_salt, 16)) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 6dfe0d32ad88..8c8b4673a5db 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -567,7 +567,6 @@ static void f2fs_put_super(struct super_block *sb) wait_for_completion(&sbi->s_kobj_unregister); sb->s_fs_info = NULL; - brelse(sbi->raw_super_buf); kfree(sbi->raw_super); kfree(sbi); } @@ -1132,65 +1131,53 @@ static void init_sb_info(struct f2fs_sb_info *sbi) */ static int read_raw_super_block(struct super_block *sb, struct f2fs_super_block **raw_super, - struct buffer_head **raw_super_buf, - int *recovery) + int *valid_super_block, int *recovery) { int block = 0; - struct buffer_head *buffer; - struct f2fs_super_block *super; + struct buffer_head *bh; + struct f2fs_super_block *super, *buf; int err = 0; super = kzalloc(sizeof(struct f2fs_super_block), GFP_KERNEL); if (!super) return -ENOMEM; retry: - buffer = sb_bread(sb, block); - if (!buffer) { + bh = sb_bread(sb, block); + if (!bh) { *recovery = 1; f2fs_msg(sb, KERN_ERR, "Unable to read %dth superblock", block + 1); - if (block == 0) { - block++; - goto retry; - } else { - err = -EIO; - goto out; - } + err = -EIO; + goto next; } - memcpy(super, buffer->b_data + F2FS_SUPER_OFFSET, sizeof(*super)); + buf = (struct f2fs_super_block *)(bh->b_data + F2FS_SUPER_OFFSET); /* sanity checking of raw super */ - if (sanity_check_raw_super(sb, super)) { - brelse(buffer); + if (sanity_check_raw_super(sb, buf)) { + brelse(bh); *recovery = 1; f2fs_msg(sb, KERN_ERR, "Can't find valid F2FS filesystem in %dth superblock", block + 1); - if (block == 0) { - block++; - goto retry; - } else { - err = -EINVAL; - goto out; - } + err = -EINVAL; + goto next; } if (!*raw_super) { - *raw_super_buf = buffer; + memcpy(super, buf, sizeof(*super)); + *valid_super_block = block; *raw_super = super; - } else { - /* already have a valid superblock */ - brelse(buffer); } + brelse(bh); +next: /* check the validity of the second superblock */ if (block == 0) { block++; goto retry; } -out: /* No valid superblock */ if (!*raw_super) { kfree(super); @@ -1203,18 +1190,16 @@ out: int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) { struct f2fs_super_block *super = F2FS_RAW_SUPER(sbi); - struct buffer_head *sbh = sbi->raw_super_buf; struct buffer_head *bh; int err; /* write back-up superblock first */ - bh = sb_getblk(sbi->sb, sbh->b_blocknr ? 0 : 1); + bh = sb_getblk(sbi->sb, sbi->valid_super_block ? 0 : 1); if (!bh) return -EIO; lock_buffer(bh); memcpy(bh->b_data + F2FS_SUPER_OFFSET, super, sizeof(*super)); - WARN_ON(sbh->b_size != F2FS_BLKSIZE); set_buffer_uptodate(bh); set_buffer_dirty(bh); unlock_buffer(bh); @@ -1227,33 +1212,37 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) if (recover || err) return err; + bh = sb_getblk(sbi->sb, sbi->valid_super_block); + if (!bh) + return -EIO; + /* write current valid superblock */ - lock_buffer(sbh); - if (memcmp(sbh->b_data + F2FS_SUPER_OFFSET, super, sizeof(*super))) { - f2fs_msg(sbi->sb, KERN_INFO, "Write modified valid superblock"); - memcpy(sbh->b_data + F2FS_SUPER_OFFSET, super, sizeof(*super)); - } - set_buffer_dirty(sbh); - unlock_buffer(sbh); + lock_buffer(bh); + memcpy(bh->b_data + F2FS_SUPER_OFFSET, super, sizeof(*super)); + set_buffer_uptodate(bh); + set_buffer_dirty(bh); + unlock_buffer(bh); - return __sync_dirty_buffer(sbh, WRITE_FLUSH_FUA); + err = __sync_dirty_buffer(bh, WRITE_FLUSH_FUA); + brelse(bh); + + return err; } static int f2fs_fill_super(struct super_block *sb, void *data, int silent) { struct f2fs_sb_info *sbi; struct f2fs_super_block *raw_super; - struct buffer_head *raw_super_buf; struct inode *root; long err; bool retry = true, need_fsck = false; char *options = NULL; - int recovery, i; + int recovery, i, valid_super_block; try_onemore: err = -EINVAL; raw_super = NULL; - raw_super_buf = NULL; + valid_super_block = -1; recovery = 0; /* allocate memory for f2fs-specific super block info */ @@ -1267,7 +1256,8 @@ try_onemore: goto free_sbi; } - err = read_raw_super_block(sb, &raw_super, &raw_super_buf, &recovery); + err = read_raw_super_block(sb, &raw_super, &valid_super_block, + &recovery); if (err) goto free_sbi; @@ -1300,7 +1290,7 @@ try_onemore: /* init f2fs-specific super block info */ sbi->sb = sb; sbi->raw_super = raw_super; - sbi->raw_super_buf = raw_super_buf; + sbi->valid_super_block = valid_super_block; mutex_init(&sbi->gc_mutex); mutex_init(&sbi->writepages); mutex_init(&sbi->cp_mutex); @@ -1506,7 +1496,6 @@ free_meta_inode: free_options: kfree(options); free_sb_buf: - brelse(raw_super_buf); kfree(raw_super); free_sbi: kfree(sbi); |