diff options
author | Richard Weinberger <richard@nod.at> | 2016-09-14 16:28:49 -0400 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2016-10-02 16:55:02 -0400 |
commit | 474b93704f32163af4bfa728fddc570eba357353 (patch) | |
tree | 2d7584f287efa71cbf3f7137c1aa9eb6dbcb1a90 /fs | |
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')
-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: | |||
301 | return err; | 301 | return err; |
302 | } | 302 | } |
303 | 303 | ||
304 | static 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 | |||
360 | out_cancel: | ||
361 | mutex_unlock(&dir_ui->ui_mutex); | ||
362 | out_inode: | ||
363 | make_bad_inode(inode); | ||
364 | if (!instantiated) | ||
365 | iput(inode); | ||
366 | out_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 | ||
1194 | const struct file_operations ubifs_dir_operations = { | 1265 | const struct file_operations ubifs_dir_operations = { |