diff options
author | Richard Weinberger <richard@nod.at> | 2016-09-14 22:28:49 +0200 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2016-10-02 22:55:02 +0200 |
commit | 474b93704f32163af4bfa728fddc570eba357353 (patch) | |
tree | 2d7584f287efa71cbf3f7137c1aa9eb6dbcb1a90 /fs/ubifs/dir.c | |
parent | f7d11b33d4e8cedf19367c09b891bbc705163976 (diff) |
ubifs: Implement O_TMPFILE
This patchs adds O_TMPFILE support to UBIFS.
A temp file is a reference to an unlinked inode, a user
holding the reference can use it. As soon it is being closed
all data vanishes.
Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'fs/ubifs/dir.c')
-rw-r--r-- | fs/ubifs/dir.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 4b86d3a738e1..8460f481eeb9 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -301,6 +301,76 @@ out_budg: return err; } +static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry, + umode_t mode) +{ + struct inode *inode; + struct ubifs_info *c = dir->i_sb->s_fs_info; + struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1}; + struct ubifs_budget_req ino_req = { .dirtied_ino = 1 }; + struct ubifs_inode *ui, *dir_ui = ubifs_inode(dir); + int err, instantiated = 0; + + /* + * Budget request settings: new dirty inode, new direntry, + * budget for dirtied inode will be released via writeback. + */ + + dbg_gen("dent '%pd', mode %#hx in dir ino %lu", + dentry, mode, dir->i_ino); + + err = ubifs_budget_space(c, &req); + if (err) + return err; + + err = ubifs_budget_space(c, &ino_req); + if (err) { + ubifs_release_budget(c, &req); + return err; + } + + inode = ubifs_new_inode(c, dir, mode); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out_budg; + } + ui = ubifs_inode(inode); + + err = ubifs_init_security(dir, inode, &dentry->d_name); + if (err) + goto out_inode; + + mutex_lock(&ui->ui_mutex); + insert_inode_hash(inode); + d_tmpfile(dentry, inode); + ubifs_assert(ui->dirty); + instantiated = 1; + mutex_unlock(&ui->ui_mutex); + + mutex_lock(&dir_ui->ui_mutex); + err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, 0); + if (err) + goto out_cancel; + mutex_unlock(&dir_ui->ui_mutex); + + ubifs_release_budget(c, &req); + + return 0; + +out_cancel: + mutex_unlock(&dir_ui->ui_mutex); +out_inode: + make_bad_inode(inode); + if (!instantiated) + iput(inode); +out_budg: + ubifs_release_budget(c, &req); + if (!instantiated) + ubifs_release_budget(c, &ino_req); + ubifs_err(c, "cannot create temporary file, error %d", err); + return err; +} + /** * vfs_dent_type - get VFS directory entry type. * @type: UBIFS directory entry type @@ -1189,6 +1259,7 @@ const struct inode_operations ubifs_dir_inode_operations = { #ifdef CONFIG_UBIFS_ATIME_SUPPORT .update_time = ubifs_update_time, #endif + .tmpfile = ubifs_tmpfile, }; const struct file_operations ubifs_dir_operations = { |