f2fs: don't grab super block buffer header all the time
authorChao Yu <chao2.yu@samsung.com>
Tue, 15 Dec 2015 09:19:26 +0000 (17:19 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Wed, 16 Dec 2015 16:58:06 +0000 (08:58 -0800)
We have already got one copy of valid super block in memory, do not grab
buffer header of super block all the time.

Signed-off-by: Chao Yu <chao2.yu@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/super.c

index 21048edb72cb3d15bd32bb8030446ae70c4f0da4..37cf04b3ff37902d12b8960ce44ba460e66e09ce 100644 (file)
@@ -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 */
index 1f5892f38018951d53c702d5c48161fe24ba1fb0..7f8ca47be0afd77c174d8dc773328f801e606d16 100644 (file)
@@ -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))
index 6dfe0d32ad885365f3151f74f6769ec3da5cd780..8c8b4673a5db3d067a5ba69a2ec3ba1e03c931c2 100644 (file)
@@ -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);