aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2016-09-14 16:28:49 -0400
committerRichard Weinberger <richard@nod.at>2016-10-02 16:55:02 -0400
commit474b93704f32163af4bfa728fddc570eba357353 (patch)
tree2d7584f287efa71cbf3f7137c1aa9eb6dbcb1a90 /fs
parentf7d11b33d4e8cedf19367c09b891bbc705163976 (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')
-rw-r--r--fs/ubifs/dir.c71
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:
301 return err; 301 return err;
302} 302}
303 303
304static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry,
305 umode_t mode)
306{
307 struct inode *inode;
308 struct ubifs_info *c = dir->i_sb->s_fs_info;
309 struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1};
310 struct ubifs_budget_req ino_req = { .dirtied_ino = 1 };
311 struct ubifs_inode *ui, *dir_ui = ubifs_inode(dir);
312 int err, instantiated = 0;
313
314 /*
315 * Budget request settings: new dirty inode, new direntry,
316 * budget for dirtied inode will be released via writeback.
317 */
318
319 dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
320 dentry, mode, dir->i_ino);
321
322 err = ubifs_budget_space(c, &req);
323 if (err)
324 return err;
325
326 err = ubifs_budget_space(c, &ino_req);
327 if (err) {
328 ubifs_release_budget(c, &req);
329 return err;
330 }
331
332 inode = ubifs_new_inode(c, dir, mode);
333 if (IS_ERR(inode)) {
334 err = PTR_ERR(inode);
335 goto out_budg;
336 }
337 ui = ubifs_inode(inode);
338
339 err = ubifs_init_security(dir, inode, &dentry->d_name);
340 if (err)
341 goto out_inode;
342
343 mutex_lock(&ui->ui_mutex);
344 insert_inode_hash(inode);
345 d_tmpfile(dentry, inode);
346 ubifs_assert(ui->dirty);
347 instantiated = 1;
348 mutex_unlock(&ui->ui_mutex);
349
350 mutex_lock(&dir_ui->ui_mutex);
351 err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, 0);
352 if (err)
353 goto out_cancel;
354 mutex_unlock(&dir_ui->ui_mutex);
355
356 ubifs_release_budget(c, &req);
357
358 return 0;
359
360out_cancel:
361 mutex_unlock(&dir_ui->ui_mutex);
362out_inode:
363 make_bad_inode(inode);
364 if (!instantiated)
365 iput(inode);
366out_budg:
367 ubifs_release_budget(c, &req);
368 if (!instantiated)
369 ubifs_release_budget(c, &ino_req);
370 ubifs_err(c, "cannot create temporary file, error %d", err);
371 return err;
372}
373
304/** 374/**
305 * vfs_dent_type - get VFS directory entry type. 375 * vfs_dent_type - get VFS directory entry type.
306 * @type: UBIFS directory entry type 376 * @type: UBIFS directory entry type
@@ -1189,6 +1259,7 @@ const struct inode_operations ubifs_dir_inode_operations = {
1189#ifdef CONFIG_UBIFS_ATIME_SUPPORT 1259#ifdef CONFIG_UBIFS_ATIME_SUPPORT
1190 .update_time = ubifs_update_time, 1260 .update_time = ubifs_update_time,
1191#endif 1261#endif
1262 .tmpfile = ubifs_tmpfile,
1192}; 1263};
1193 1264
1194const struct file_operations ubifs_dir_operations = { 1265const struct file_operations ubifs_dir_operations = {