f2fs: don't put dentry page in pagecache into highmem
authorYunlong Song <yunlong.song@huawei.com>
Wed, 28 Feb 2018 12:31:52 +0000 (20:31 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Mon, 12 Mar 2018 23:05:03 +0000 (08:05 +0900)
Previous dentry page uses highmem, which will cause panic in platforms
using highmem (such as arm), since the address space of dentry pages
from highmem directly goes into the decryption path via the function
fscrypt_fname_disk_to_usr. But sg_init_one assumes the address is not
from highmem, and then cause panic since it doesn't call kmap_high but
kunmap_high is triggered at the end. To fix this problem in a simple
way, this patch avoids to put dentry page in pagecache into highmem.

Signed-off-by: Yunlong Song <yunlong.song@huawei.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
[Jaegeuk Kim: fix coding style]
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/dir.c
fs/f2fs/f2fs.h
fs/f2fs/inline.c
fs/f2fs/inode.c
fs/f2fs/namei.c
fs/f2fs/recovery.c
include/linux/f2fs_fs.h

index f00b5ed8c01157e415450d6160b41880d23d5252..797eb05cb53864ddd858f52f29db655830996a00 100644 (file)
@@ -94,14 +94,12 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
        struct f2fs_dir_entry *de;
        struct f2fs_dentry_ptr d;
 
-       dentry_blk = (struct f2fs_dentry_block *)kmap(dentry_page);
+       dentry_blk = (struct f2fs_dentry_block *)page_address(dentry_page);
 
        make_dentry_ptr_block(NULL, &d, dentry_blk);
        de = find_target_dentry(fname, namehash, max_slots, &d);
        if (de)
                *res_page = dentry_page;
-       else
-               kunmap(dentry_page);
 
        return de;
 }
@@ -287,7 +285,6 @@ ino_t f2fs_inode_by_name(struct inode *dir, const struct qstr *qstr,
        de = f2fs_find_entry(dir, qstr, page);
        if (de) {
                res = le32_to_cpu(de->ino);
-               f2fs_dentry_kunmap(dir, *page);
                f2fs_put_page(*page, 0);
        }
 
@@ -302,7 +299,6 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
        f2fs_wait_on_page_writeback(page, type, true);
        de->ino = cpu_to_le32(inode->i_ino);
        set_de_type(de, inode->i_mode);
-       f2fs_dentry_kunmap(dir, page);
        set_page_dirty(page);
 
        dir->i_mtime = dir->i_ctime = current_time(dir);
@@ -350,13 +346,11 @@ static int make_empty_dir(struct inode *inode,
        if (IS_ERR(dentry_page))
                return PTR_ERR(dentry_page);
 
-       dentry_blk = kmap_atomic(dentry_page);
+       dentry_blk = page_address(dentry_page);
 
        make_dentry_ptr_block(NULL, &d, dentry_blk);
        do_make_empty_dir(inode, parent, &d);
 
-       kunmap_atomic(dentry_blk);
-
        set_page_dirty(dentry_page);
        f2fs_put_page(dentry_page, 1);
        return 0;
@@ -547,13 +541,12 @@ start:
                if (IS_ERR(dentry_page))
                        return PTR_ERR(dentry_page);
 
-               dentry_blk = kmap(dentry_page);
+               dentry_blk = page_address(dentry_page);
                bit_pos = room_for_filename(&dentry_blk->dentry_bitmap,
                                                slots, NR_DENTRY_IN_BLOCK);
                if (bit_pos < NR_DENTRY_IN_BLOCK)
                        goto add_dentry;
 
-               kunmap(dentry_page);
                f2fs_put_page(dentry_page, 1);
        }
 
@@ -588,7 +581,6 @@ fail:
        if (inode)
                up_write(&F2FS_I(inode)->i_sem);
 
-       kunmap(dentry_page);
        f2fs_put_page(dentry_page, 1);
 
        return err;
@@ -642,7 +634,6 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name,
                F2FS_I(dir)->task = NULL;
        }
        if (de) {
-               f2fs_dentry_kunmap(dir, page);
                f2fs_put_page(page, 0);
                err = -EEXIST;
        } else if (IS_ERR(page)) {
@@ -730,7 +721,6 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
        bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
                        NR_DENTRY_IN_BLOCK,
                        0);
-       kunmap(page); /* kunmap - pair of f2fs_find_entry */
        set_page_dirty(page);
 
        dir->i_ctime = dir->i_mtime = current_time(dir);
@@ -775,7 +765,7 @@ bool f2fs_empty_dir(struct inode *dir)
                                return false;
                }
 
-               dentry_blk = kmap_atomic(dentry_page);
+               dentry_blk = page_address(dentry_page);
                if (bidx == 0)
                        bit_pos = 2;
                else
@@ -783,7 +773,6 @@ bool f2fs_empty_dir(struct inode *dir)
                bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
                                                NR_DENTRY_IN_BLOCK,
                                                bit_pos);
-               kunmap_atomic(dentry_blk);
 
                f2fs_put_page(dentry_page, 1);
 
@@ -901,19 +890,17 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
                        }
                }
 
-               dentry_blk = kmap(dentry_page);
+               dentry_blk = page_address(dentry_page);
 
                make_dentry_ptr_block(inode, &d, dentry_blk);
 
                err = f2fs_fill_dentries(ctx, &d,
                                n * NR_DENTRY_IN_BLOCK, &fstr);
                if (err) {
-                       kunmap(dentry_page);
                        f2fs_put_page(dentry_page, 1);
                        break;
                }
 
-               kunmap(dentry_page);
                f2fs_put_page(dentry_page, 1);
        }
 out_free:
index 6300ac5bcbe4950b8154e97f3e52d972e02b8373..8b652e000326da34c8649e8d2a73438c0acc523f 100644 (file)
@@ -2399,12 +2399,6 @@ static inline int f2fs_has_inline_dentry(struct inode *inode)
        return is_inode_flag_set(inode, FI_INLINE_DENTRY);
 }
 
-static inline void f2fs_dentry_kunmap(struct inode *dir, struct page *page)
-{
-       if (!f2fs_has_inline_dentry(dir))
-               kunmap(page);
-}
-
 static inline int is_file(struct inode *inode, int type)
 {
        return F2FS_I(inode)->i_advise & type;
index 90e38d8ea68881778c7835231e5ac5dfd27f46b5..3b77d642121817d3bf81f617fba6d7ae2275ef36 100644 (file)
@@ -369,7 +369,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,
        f2fs_wait_on_page_writeback(page, DATA, true);
        zero_user_segment(page, MAX_INLINE_DATA(dir), PAGE_SIZE);
 
-       dentry_blk = kmap_atomic(page);
+       dentry_blk = page_address(page);
 
        make_dentry_ptr_inline(dir, &src, inline_dentry);
        make_dentry_ptr_block(dir, &dst, dentry_blk);
@@ -386,7 +386,6 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,
        memcpy(dst.dentry, src.dentry, SIZE_OF_DIR_ENTRY * src.max);
        memcpy(dst.filename, src.filename, src.max * F2FS_SLOT_LEN);
 
-       kunmap_atomic(dentry_blk);
        if (!PageUptodate(page))
                SetPageUptodate(page);
        set_page_dirty(page);
index 205add3d0f3a0538751cb0281083e52c8ddd4ef2..4efc815129b12b0a4b6fe91bb0dff42ffe4edaca 100644 (file)
@@ -328,7 +328,7 @@ make_now:
                inode->i_op = &f2fs_dir_inode_operations;
                inode->i_fop = &f2fs_dir_operations;
                inode->i_mapping->a_ops = &f2fs_dblock_aops;
-               mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_HIGH_ZERO);
+               inode_nohighmem(inode);
        } else if (S_ISLNK(inode->i_mode)) {
                if (f2fs_encrypted_inode(inode))
                        inode->i_op = &f2fs_encrypted_symlink_inode_operations;
index b68e7b03959f5b7cc67d2b6f9b94715d517fac14..2ebf3d045dd279e3f869e7cb641ca8c1d030cc70 100644 (file)
@@ -317,7 +317,6 @@ static int __recover_dot_dentries(struct inode *dir, nid_t pino)
 
        de = f2fs_find_entry(dir, &dot, &page);
        if (de) {
-               f2fs_dentry_kunmap(dir, page);
                f2fs_put_page(page, 0);
        } else if (IS_ERR(page)) {
                err = PTR_ERR(page);
@@ -329,14 +328,12 @@ static int __recover_dot_dentries(struct inode *dir, nid_t pino)
        }
 
        de = f2fs_find_entry(dir, &dotdot, &page);
-       if (de) {
-               f2fs_dentry_kunmap(dir, page);
+       if (de)
                f2fs_put_page(page, 0);
-       } else if (IS_ERR(page)) {
+       else if (IS_ERR(page))
                err = PTR_ERR(page);
-       } else {
+       else
                err = __f2fs_add_link(dir, &dotdot, NULL, pino, S_IFDIR);
-       }
 out:
        if (!err)
                clear_inode_flag(dir, FI_INLINE_DOTS);
@@ -377,7 +374,6 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
        }
 
        ino = le32_to_cpu(de->ino);
-       f2fs_dentry_kunmap(dir, page);
        f2fs_put_page(page, 0);
 
        inode = f2fs_iget(dir->i_sb, ino);
@@ -452,7 +448,6 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
        err = acquire_orphan_inode(sbi);
        if (err) {
                f2fs_unlock_op(sbi);
-               f2fs_dentry_kunmap(dir, page);
                f2fs_put_page(page, 0);
                goto fail;
        }
@@ -579,7 +574,7 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        inode->i_op = &f2fs_dir_inode_operations;
        inode->i_fop = &f2fs_dir_operations;
        inode->i_mapping->a_ops = &f2fs_dblock_aops;
-       mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_HIGH_ZERO);
+       inode_nohighmem(inode);
 
        set_inode_flag(inode, FI_INC_LINK);
        f2fs_lock_op(sbi);
@@ -893,13 +888,11 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
        }
 
        if (old_dir_entry) {
-               if (old_dir != new_dir && !whiteout) {
+               if (old_dir != new_dir && !whiteout)
                        f2fs_set_link(old_inode, old_dir_entry,
                                                old_dir_page, new_dir);
-               } else {
-                       f2fs_dentry_kunmap(old_inode, old_dir_page);
+               else
                        f2fs_put_page(old_dir_page, 0);
-               }
                f2fs_i_links_write(old_dir, false);
        }
        add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO);
@@ -912,20 +905,15 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 put_out_dir:
        f2fs_unlock_op(sbi);
-       if (new_page) {
-               f2fs_dentry_kunmap(new_dir, new_page);
+       if (new_page)
                f2fs_put_page(new_page, 0);
-       }
 out_whiteout:
        if (whiteout)
                iput(whiteout);
 out_dir:
-       if (old_dir_entry) {
-               f2fs_dentry_kunmap(old_inode, old_dir_page);
+       if (old_dir_entry)
                f2fs_put_page(old_dir_page, 0);
-       }
 out_old:
-       f2fs_dentry_kunmap(old_dir, old_page);
        f2fs_put_page(old_page, 0);
 out:
        return err;
@@ -1067,19 +1055,15 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
        return 0;
 out_new_dir:
        if (new_dir_entry) {
-               f2fs_dentry_kunmap(new_inode, new_dir_page);
                f2fs_put_page(new_dir_page, 0);
        }
 out_old_dir:
        if (old_dir_entry) {
-               f2fs_dentry_kunmap(old_inode, old_dir_page);
                f2fs_put_page(old_dir_page, 0);
        }
 out_new:
-       f2fs_dentry_kunmap(new_dir, new_page);
        f2fs_put_page(new_page, 0);
 out_old:
-       f2fs_dentry_kunmap(old_dir, old_page);
        f2fs_put_page(old_page, 0);
 out:
        return err;
index 337f3363f48f6c2946a91c9877f38328a9406002..c5e5c45130b5e880a8cd980f8d601f2300a809fa 100644 (file)
@@ -144,7 +144,7 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
 retry:
        de = __f2fs_find_entry(dir, &fname, &page);
        if (de && inode->i_ino == le32_to_cpu(de->ino))
-               goto out_unmap_put;
+               goto out_put;
 
        if (de) {
                einode = f2fs_iget_retry(inode->i_sb, le32_to_cpu(de->ino));
@@ -153,19 +153,19 @@ retry:
                        err = PTR_ERR(einode);
                        if (err == -ENOENT)
                                err = -EEXIST;
-                       goto out_unmap_put;
+                       goto out_put;
                }
 
                err = dquot_initialize(einode);
                if (err) {
                        iput(einode);
-                       goto out_unmap_put;
+                       goto out_put;
                }
 
                err = acquire_orphan_inode(F2FS_I_SB(inode));
                if (err) {
                        iput(einode);
-                       goto out_unmap_put;
+                       goto out_put;
                }
                f2fs_delete_entry(de, page, dir, einode);
                iput(einode);
@@ -180,8 +180,7 @@ retry:
                goto retry;
        goto out;
 
-out_unmap_put:
-       f2fs_dentry_kunmap(dir, page);
+out_put:
        f2fs_put_page(page, 0);
 out:
        if (file_enc_name(inode))
index 58aecb60ea51b90eaf3a447a1f25c21d137a145b..393b880afc9a49888a1705d83584c54a67d4f594 100644 (file)
@@ -46,7 +46,6 @@
 
 /* This flag is used by node and meta inodes, and by recovery */
 #define GFP_F2FS_ZERO          (GFP_NOFS | __GFP_ZERO)
-#define GFP_F2FS_HIGH_ZERO     (GFP_NOFS | __GFP_ZERO | __GFP_HIGHMEM)
 
 /*
  * For further optimization on multi-head logs, on-disk layout supports maximum