diff options
author | Chao Yu <chao2.yu@samsung.com> | 2014-06-19 16:23:19 +0800 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-07-09 14:04:24 -0700 |
commit | 50732df02eefb39ab414ef655979c2c9b64ad21c (patch) | |
tree | e8cb6cb0be5951f112ced0406d5bd0c6721aa60e /fs/f2fs/namei.c | |
parent | ca0a81b397b5f153ac2a9880c5e85b08b0447e4e (diff) |
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>
Diffstat (limited to 'fs/f2fs/namei.c')
-rw-r--r-- | fs/f2fs/namei.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index a6bdddc33ce2..5c08c546e4c8 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -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, |