提交 bdbc90fa 编写于 作者: Y Yunlong Song 提交者: Jaegeuk Kim

f2fs: don't put dentry page in pagecache into highmem

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: NYunlong Song <yunlong.song@huawei.com>
Reviewed-by: NChao Yu <yuchao0@huawei.com>
[Jaegeuk Kim: fix coding style]
Signed-off-by: NJaegeuk Kim <jaegeuk@kernel.org>
上级 3664ce2d
...@@ -94,14 +94,12 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, ...@@ -94,14 +94,12 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
struct f2fs_dir_entry *de; struct f2fs_dir_entry *de;
struct f2fs_dentry_ptr d; 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); make_dentry_ptr_block(NULL, &d, dentry_blk);
de = find_target_dentry(fname, namehash, max_slots, &d); de = find_target_dentry(fname, namehash, max_slots, &d);
if (de) if (de)
*res_page = dentry_page; *res_page = dentry_page;
else
kunmap(dentry_page);
return de; return de;
} }
...@@ -287,7 +285,6 @@ ino_t f2fs_inode_by_name(struct inode *dir, const struct qstr *qstr, ...@@ -287,7 +285,6 @@ ino_t f2fs_inode_by_name(struct inode *dir, const struct qstr *qstr,
de = f2fs_find_entry(dir, qstr, page); de = f2fs_find_entry(dir, qstr, page);
if (de) { if (de) {
res = le32_to_cpu(de->ino); res = le32_to_cpu(de->ino);
f2fs_dentry_kunmap(dir, *page);
f2fs_put_page(*page, 0); f2fs_put_page(*page, 0);
} }
...@@ -302,7 +299,6 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de, ...@@ -302,7 +299,6 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
f2fs_wait_on_page_writeback(page, type, true); f2fs_wait_on_page_writeback(page, type, true);
de->ino = cpu_to_le32(inode->i_ino); de->ino = cpu_to_le32(inode->i_ino);
set_de_type(de, inode->i_mode); set_de_type(de, inode->i_mode);
f2fs_dentry_kunmap(dir, page);
set_page_dirty(page); set_page_dirty(page);
dir->i_mtime = dir->i_ctime = current_time(dir); dir->i_mtime = dir->i_ctime = current_time(dir);
...@@ -350,13 +346,11 @@ static int make_empty_dir(struct inode *inode, ...@@ -350,13 +346,11 @@ static int make_empty_dir(struct inode *inode,
if (IS_ERR(dentry_page)) if (IS_ERR(dentry_page))
return PTR_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); make_dentry_ptr_block(NULL, &d, dentry_blk);
do_make_empty_dir(inode, parent, &d); do_make_empty_dir(inode, parent, &d);
kunmap_atomic(dentry_blk);
set_page_dirty(dentry_page); set_page_dirty(dentry_page);
f2fs_put_page(dentry_page, 1); f2fs_put_page(dentry_page, 1);
return 0; return 0;
...@@ -547,13 +541,12 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name, ...@@ -547,13 +541,12 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
if (IS_ERR(dentry_page)) if (IS_ERR(dentry_page))
return PTR_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, bit_pos = room_for_filename(&dentry_blk->dentry_bitmap,
slots, NR_DENTRY_IN_BLOCK); slots, NR_DENTRY_IN_BLOCK);
if (bit_pos < NR_DENTRY_IN_BLOCK) if (bit_pos < NR_DENTRY_IN_BLOCK)
goto add_dentry; goto add_dentry;
kunmap(dentry_page);
f2fs_put_page(dentry_page, 1); f2fs_put_page(dentry_page, 1);
} }
...@@ -588,7 +581,6 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name, ...@@ -588,7 +581,6 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
if (inode) if (inode)
up_write(&F2FS_I(inode)->i_sem); up_write(&F2FS_I(inode)->i_sem);
kunmap(dentry_page);
f2fs_put_page(dentry_page, 1); f2fs_put_page(dentry_page, 1);
return err; return err;
...@@ -642,7 +634,6 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, ...@@ -642,7 +634,6 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name,
F2FS_I(dir)->task = NULL; F2FS_I(dir)->task = NULL;
} }
if (de) { if (de) {
f2fs_dentry_kunmap(dir, page);
f2fs_put_page(page, 0); f2fs_put_page(page, 0);
err = -EEXIST; err = -EEXIST;
} else if (IS_ERR(page)) { } else if (IS_ERR(page)) {
...@@ -730,7 +721,6 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *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, bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
NR_DENTRY_IN_BLOCK, NR_DENTRY_IN_BLOCK,
0); 0);
kunmap(page); /* kunmap - pair of f2fs_find_entry */
set_page_dirty(page); set_page_dirty(page);
dir->i_ctime = dir->i_mtime = current_time(dir); dir->i_ctime = dir->i_mtime = current_time(dir);
...@@ -775,7 +765,7 @@ bool f2fs_empty_dir(struct inode *dir) ...@@ -775,7 +765,7 @@ bool f2fs_empty_dir(struct inode *dir)
return false; return false;
} }
dentry_blk = kmap_atomic(dentry_page); dentry_blk = page_address(dentry_page);
if (bidx == 0) if (bidx == 0)
bit_pos = 2; bit_pos = 2;
else else
...@@ -783,7 +773,6 @@ bool f2fs_empty_dir(struct inode *dir) ...@@ -783,7 +773,6 @@ bool f2fs_empty_dir(struct inode *dir)
bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
NR_DENTRY_IN_BLOCK, NR_DENTRY_IN_BLOCK,
bit_pos); bit_pos);
kunmap_atomic(dentry_blk);
f2fs_put_page(dentry_page, 1); f2fs_put_page(dentry_page, 1);
...@@ -901,19 +890,17 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx) ...@@ -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); make_dentry_ptr_block(inode, &d, dentry_blk);
err = f2fs_fill_dentries(ctx, &d, err = f2fs_fill_dentries(ctx, &d,
n * NR_DENTRY_IN_BLOCK, &fstr); n * NR_DENTRY_IN_BLOCK, &fstr);
if (err) { if (err) {
kunmap(dentry_page);
f2fs_put_page(dentry_page, 1); f2fs_put_page(dentry_page, 1);
break; break;
} }
kunmap(dentry_page);
f2fs_put_page(dentry_page, 1); f2fs_put_page(dentry_page, 1);
} }
out_free: out_free:
......
...@@ -2399,12 +2399,6 @@ static inline int f2fs_has_inline_dentry(struct inode *inode) ...@@ -2399,12 +2399,6 @@ static inline int f2fs_has_inline_dentry(struct inode *inode)
return is_inode_flag_set(inode, FI_INLINE_DENTRY); 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) static inline int is_file(struct inode *inode, int type)
{ {
return F2FS_I(inode)->i_advise & type; return F2FS_I(inode)->i_advise & type;
......
...@@ -369,7 +369,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage, ...@@ -369,7 +369,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,
f2fs_wait_on_page_writeback(page, DATA, true); f2fs_wait_on_page_writeback(page, DATA, true);
zero_user_segment(page, MAX_INLINE_DATA(dir), PAGE_SIZE); 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_inline(dir, &src, inline_dentry);
make_dentry_ptr_block(dir, &dst, dentry_blk); make_dentry_ptr_block(dir, &dst, dentry_blk);
...@@ -386,7 +386,6 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage, ...@@ -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.dentry, src.dentry, SIZE_OF_DIR_ENTRY * src.max);
memcpy(dst.filename, src.filename, src.max * F2FS_SLOT_LEN); memcpy(dst.filename, src.filename, src.max * F2FS_SLOT_LEN);
kunmap_atomic(dentry_blk);
if (!PageUptodate(page)) if (!PageUptodate(page))
SetPageUptodate(page); SetPageUptodate(page);
set_page_dirty(page); set_page_dirty(page);
......
...@@ -328,7 +328,7 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino) ...@@ -328,7 +328,7 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
inode->i_op = &f2fs_dir_inode_operations; inode->i_op = &f2fs_dir_inode_operations;
inode->i_fop = &f2fs_dir_operations; inode->i_fop = &f2fs_dir_operations;
inode->i_mapping->a_ops = &f2fs_dblock_aops; 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)) { } else if (S_ISLNK(inode->i_mode)) {
if (f2fs_encrypted_inode(inode)) if (f2fs_encrypted_inode(inode))
inode->i_op = &f2fs_encrypted_symlink_inode_operations; inode->i_op = &f2fs_encrypted_symlink_inode_operations;
......
...@@ -317,7 +317,6 @@ static int __recover_dot_dentries(struct inode *dir, nid_t pino) ...@@ -317,7 +317,6 @@ static int __recover_dot_dentries(struct inode *dir, nid_t pino)
de = f2fs_find_entry(dir, &dot, &page); de = f2fs_find_entry(dir, &dot, &page);
if (de) { if (de) {
f2fs_dentry_kunmap(dir, page);
f2fs_put_page(page, 0); f2fs_put_page(page, 0);
} else if (IS_ERR(page)) { } else if (IS_ERR(page)) {
err = PTR_ERR(page); err = PTR_ERR(page);
...@@ -329,14 +328,12 @@ static int __recover_dot_dentries(struct inode *dir, nid_t pino) ...@@ -329,14 +328,12 @@ static int __recover_dot_dentries(struct inode *dir, nid_t pino)
} }
de = f2fs_find_entry(dir, &dotdot, &page); de = f2fs_find_entry(dir, &dotdot, &page);
if (de) { if (de)
f2fs_dentry_kunmap(dir, page);
f2fs_put_page(page, 0); f2fs_put_page(page, 0);
} else if (IS_ERR(page)) { else if (IS_ERR(page))
err = PTR_ERR(page); err = PTR_ERR(page);
} else { else
err = __f2fs_add_link(dir, &dotdot, NULL, pino, S_IFDIR); err = __f2fs_add_link(dir, &dotdot, NULL, pino, S_IFDIR);
}
out: out:
if (!err) if (!err)
clear_inode_flag(dir, FI_INLINE_DOTS); clear_inode_flag(dir, FI_INLINE_DOTS);
...@@ -377,7 +374,6 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -377,7 +374,6 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
} }
ino = le32_to_cpu(de->ino); ino = le32_to_cpu(de->ino);
f2fs_dentry_kunmap(dir, page);
f2fs_put_page(page, 0); f2fs_put_page(page, 0);
inode = f2fs_iget(dir->i_sb, ino); inode = f2fs_iget(dir->i_sb, ino);
...@@ -452,7 +448,6 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -452,7 +448,6 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
err = acquire_orphan_inode(sbi); err = acquire_orphan_inode(sbi);
if (err) { if (err) {
f2fs_unlock_op(sbi); f2fs_unlock_op(sbi);
f2fs_dentry_kunmap(dir, page);
f2fs_put_page(page, 0); f2fs_put_page(page, 0);
goto fail; goto fail;
} }
...@@ -579,7 +574,7 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -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_op = &f2fs_dir_inode_operations;
inode->i_fop = &f2fs_dir_operations; inode->i_fop = &f2fs_dir_operations;
inode->i_mapping->a_ops = &f2fs_dblock_aops; 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); set_inode_flag(inode, FI_INC_LINK);
f2fs_lock_op(sbi); f2fs_lock_op(sbi);
...@@ -893,13 +888,11 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -893,13 +888,11 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
} }
if (old_dir_entry) { if (old_dir_entry) {
if (old_dir != new_dir && !whiteout) { if (old_dir != new_dir && !whiteout)
f2fs_set_link(old_inode, old_dir_entry, f2fs_set_link(old_inode, old_dir_entry,
old_dir_page, new_dir); old_dir_page, new_dir);
} else { else
f2fs_dentry_kunmap(old_inode, old_dir_page);
f2fs_put_page(old_dir_page, 0); f2fs_put_page(old_dir_page, 0);
}
f2fs_i_links_write(old_dir, false); f2fs_i_links_write(old_dir, false);
} }
add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO); 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, ...@@ -912,20 +905,15 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
put_out_dir: put_out_dir:
f2fs_unlock_op(sbi); f2fs_unlock_op(sbi);
if (new_page) { if (new_page)
f2fs_dentry_kunmap(new_dir, new_page);
f2fs_put_page(new_page, 0); f2fs_put_page(new_page, 0);
}
out_whiteout: out_whiteout:
if (whiteout) if (whiteout)
iput(whiteout); iput(whiteout);
out_dir: out_dir:
if (old_dir_entry) { if (old_dir_entry)
f2fs_dentry_kunmap(old_inode, old_dir_page);
f2fs_put_page(old_dir_page, 0); f2fs_put_page(old_dir_page, 0);
}
out_old: out_old:
f2fs_dentry_kunmap(old_dir, old_page);
f2fs_put_page(old_page, 0); f2fs_put_page(old_page, 0);
out: out:
return err; return err;
...@@ -1067,19 +1055,15 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1067,19 +1055,15 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
return 0; return 0;
out_new_dir: out_new_dir:
if (new_dir_entry) { if (new_dir_entry) {
f2fs_dentry_kunmap(new_inode, new_dir_page);
f2fs_put_page(new_dir_page, 0); f2fs_put_page(new_dir_page, 0);
} }
out_old_dir: out_old_dir:
if (old_dir_entry) { if (old_dir_entry) {
f2fs_dentry_kunmap(old_inode, old_dir_page);
f2fs_put_page(old_dir_page, 0); f2fs_put_page(old_dir_page, 0);
} }
out_new: out_new:
f2fs_dentry_kunmap(new_dir, new_page);
f2fs_put_page(new_page, 0); f2fs_put_page(new_page, 0);
out_old: out_old:
f2fs_dentry_kunmap(old_dir, old_page);
f2fs_put_page(old_page, 0); f2fs_put_page(old_page, 0);
out: out:
return err; return err;
......
...@@ -144,7 +144,7 @@ static int recover_dentry(struct inode *inode, struct page *ipage, ...@@ -144,7 +144,7 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
retry: retry:
de = __f2fs_find_entry(dir, &fname, &page); de = __f2fs_find_entry(dir, &fname, &page);
if (de && inode->i_ino == le32_to_cpu(de->ino)) if (de && inode->i_ino == le32_to_cpu(de->ino))
goto out_unmap_put; goto out_put;
if (de) { if (de) {
einode = f2fs_iget_retry(inode->i_sb, le32_to_cpu(de->ino)); einode = f2fs_iget_retry(inode->i_sb, le32_to_cpu(de->ino));
...@@ -153,19 +153,19 @@ static int recover_dentry(struct inode *inode, struct page *ipage, ...@@ -153,19 +153,19 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
err = PTR_ERR(einode); err = PTR_ERR(einode);
if (err == -ENOENT) if (err == -ENOENT)
err = -EEXIST; err = -EEXIST;
goto out_unmap_put; goto out_put;
} }
err = dquot_initialize(einode); err = dquot_initialize(einode);
if (err) { if (err) {
iput(einode); iput(einode);
goto out_unmap_put; goto out_put;
} }
err = acquire_orphan_inode(F2FS_I_SB(inode)); err = acquire_orphan_inode(F2FS_I_SB(inode));
if (err) { if (err) {
iput(einode); iput(einode);
goto out_unmap_put; goto out_put;
} }
f2fs_delete_entry(de, page, dir, einode); f2fs_delete_entry(de, page, dir, einode);
iput(einode); iput(einode);
...@@ -180,8 +180,7 @@ static int recover_dentry(struct inode *inode, struct page *ipage, ...@@ -180,8 +180,7 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
goto retry; goto retry;
goto out; goto out;
out_unmap_put: out_put:
f2fs_dentry_kunmap(dir, page);
f2fs_put_page(page, 0); f2fs_put_page(page, 0);
out: out:
if (file_enc_name(inode)) if (file_enc_name(inode))
......
...@@ -46,7 +46,6 @@ ...@@ -46,7 +46,6 @@
/* This flag is used by node and meta inodes, and by recovery */ /* This flag is used by node and meta inodes, and by recovery */
#define GFP_F2FS_ZERO (GFP_NOFS | __GFP_ZERO) #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 * For further optimization on multi-head logs, on-disk layout supports maximum
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册