f2fs: support ->tmpfile()
Add function f2fs_tmpfile() to support O_TMPFILE file creation, and modify logic of init_inode_metadata to enable linkat temp file. Signed-off-by: Chao Yu <chao2.yu@samsung.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
ca0a81b397
commit
50732df02e
|
@ -333,10 +333,12 @@ static int make_empty_dir(struct inode *inode,
|
|||
static struct page *init_inode_metadata(struct inode *inode,
|
||||
struct inode *dir, const struct qstr *name)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
|
||||
struct page *page;
|
||||
int err;
|
||||
|
||||
if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) {
|
||||
if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE) &&
|
||||
inode->i_nlink) {
|
||||
page = new_inode_page(inode, name);
|
||||
if (IS_ERR(page))
|
||||
return page;
|
||||
|
@ -370,6 +372,12 @@ static struct page *init_inode_metadata(struct inode *inode,
|
|||
*/
|
||||
if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) {
|
||||
file_lost_pino(inode);
|
||||
/*
|
||||
* If link the tmpfile to alias through linkat path,
|
||||
* we should remove this inode from orphan list.
|
||||
*/
|
||||
if (inode->i_nlink == 0)
|
||||
remove_orphan_inode(sbi, inode->i_ino);
|
||||
inc_nlink(inode);
|
||||
}
|
||||
return page;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/pagemap.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/dcache.h>
|
||||
|
||||
#include "f2fs.h"
|
||||
#include "node.h"
|
||||
|
@ -487,6 +488,68 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int f2fs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct f2fs_sb_info *sbi = F2FS_SB(sb);
|
||||
struct inode *inode;
|
||||
struct page *page;
|
||||
int err;
|
||||
|
||||
inode = f2fs_new_inode(dir, mode);
|
||||
if (IS_ERR(inode))
|
||||
return PTR_ERR(inode);
|
||||
|
||||
inode->i_op = &f2fs_file_inode_operations;
|
||||
inode->i_fop = &f2fs_file_operations;
|
||||
inode->i_mapping->a_ops = &f2fs_dblock_aops;
|
||||
|
||||
f2fs_lock_op(sbi);
|
||||
err = acquire_orphan_inode(sbi);
|
||||
if (err)
|
||||
goto out;
|
||||
/*
|
||||
* add this non-linked tmpfile to orphan list, in this way we could
|
||||
* remove all unused data of tmpfile after abnormal power-off.
|
||||
*/
|
||||
add_orphan_inode(sbi, inode->i_ino);
|
||||
|
||||
page = new_inode_page(inode, NULL);
|
||||
if (IS_ERR(page)) {
|
||||
err = PTR_ERR(page);
|
||||
goto remove_out;
|
||||
}
|
||||
|
||||
err = f2fs_init_acl(inode, dir, page);
|
||||
if (err)
|
||||
goto unlock_out;
|
||||
|
||||
err = f2fs_init_security(inode, dir, NULL, page);
|
||||
if (err)
|
||||
goto unlock_out;
|
||||
|
||||
f2fs_put_page(page, 1);
|
||||
f2fs_unlock_op(sbi);
|
||||
|
||||
alloc_nid_done(sbi, inode->i_ino);
|
||||
mark_inode_dirty(inode);
|
||||
d_tmpfile(dentry, inode);
|
||||
unlock_new_inode(inode);
|
||||
return 0;
|
||||
unlock_out:
|
||||
f2fs_put_page(page, 1);
|
||||
remove_out:
|
||||
remove_orphan_inode(sbi, inode->i_ino);
|
||||
out:
|
||||
f2fs_unlock_op(sbi);
|
||||
clear_nlink(inode);
|
||||
unlock_new_inode(inode);
|
||||
make_bad_inode(inode);
|
||||
iput(inode);
|
||||
alloc_nid_failed(sbi, inode->i_ino);
|
||||
return err;
|
||||
}
|
||||
|
||||
const struct inode_operations f2fs_dir_inode_operations = {
|
||||
.create = f2fs_create,
|
||||
.lookup = f2fs_lookup,
|
||||
|
@ -497,6 +560,7 @@ const struct inode_operations f2fs_dir_inode_operations = {
|
|||
.rmdir = f2fs_rmdir,
|
||||
.mknod = f2fs_mknod,
|
||||
.rename = f2fs_rename,
|
||||
.tmpfile = f2fs_tmpfile,
|
||||
.getattr = f2fs_getattr,
|
||||
.setattr = f2fs_setattr,
|
||||
.get_acl = f2fs_get_acl,
|
||||
|
|
Loading…
Reference in New Issue