diff options
author | Chao Yu <chao2.yu@samsung.com> | 2014-06-19 04:23:19 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-07-09 17:04:24 -0400 |
commit | 50732df02eefb39ab414ef655979c2c9b64ad21c (patch) | |
tree | e8cb6cb0be5951f112ced0406d5bd0c6721aa60e | |
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>
-rw-r--r-- | fs/f2fs/dir.c | 10 | ||||
-rw-r--r-- | fs/f2fs/namei.c | 64 |
2 files changed, 73 insertions, 1 deletions
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index a4addd72ebbd..3677f4124541 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c | |||
@@ -333,10 +333,12 @@ static int make_empty_dir(struct inode *inode, | |||
333 | static struct page *init_inode_metadata(struct inode *inode, | 333 | static struct page *init_inode_metadata(struct inode *inode, |
334 | struct inode *dir, const struct qstr *name) | 334 | struct inode *dir, const struct qstr *name) |
335 | { | 335 | { |
336 | struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); | ||
336 | struct page *page; | 337 | struct page *page; |
337 | int err; | 338 | int err; |
338 | 339 | ||
339 | if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) { | 340 | if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE) && |
341 | inode->i_nlink) { | ||
340 | page = new_inode_page(inode, name); | 342 | page = new_inode_page(inode, name); |
341 | if (IS_ERR(page)) | 343 | if (IS_ERR(page)) |
342 | return page; | 344 | return page; |
@@ -370,6 +372,12 @@ static struct page *init_inode_metadata(struct inode *inode, | |||
370 | */ | 372 | */ |
371 | if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) { | 373 | if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) { |
372 | file_lost_pino(inode); | 374 | file_lost_pino(inode); |
375 | /* | ||
376 | * If link the tmpfile to alias through linkat path, | ||
377 | * we should remove this inode from orphan list. | ||
378 | */ | ||
379 | if (inode->i_nlink == 0) | ||
380 | remove_orphan_inode(sbi, inode->i_ino); | ||
373 | inc_nlink(inode); | 381 | inc_nlink(inode); |
374 | } | 382 | } |
375 | return page; | 383 | return page; |
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 @@ | |||
13 | #include <linux/pagemap.h> | 13 | #include <linux/pagemap.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
16 | #include <linux/dcache.h> | ||
16 | 17 | ||
17 | #include "f2fs.h" | 18 | #include "f2fs.h" |
18 | #include "node.h" | 19 | #include "node.h" |
@@ -487,6 +488,68 @@ out: | |||
487 | return err; | 488 | return err; |
488 | } | 489 | } |
489 | 490 | ||
491 | static int f2fs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) | ||
492 | { | ||
493 | struct super_block *sb = dir->i_sb; | ||
494 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
495 | struct inode *inode; | ||
496 | struct page *page; | ||
497 | int err; | ||
498 | |||
499 | inode = f2fs_new_inode(dir, mode); | ||
500 | if (IS_ERR(inode)) | ||
501 | return PTR_ERR(inode); | ||
502 | |||
503 | inode->i_op = &f2fs_file_inode_operations; | ||
504 | inode->i_fop = &f2fs_file_operations; | ||
505 | inode->i_mapping->a_ops = &f2fs_dblock_aops; | ||
506 | |||
507 | f2fs_lock_op(sbi); | ||
508 | err = acquire_orphan_inode(sbi); | ||
509 | if (err) | ||
510 | goto out; | ||
511 | /* | ||
512 | * add this non-linked tmpfile to orphan list, in this way we could | ||
513 | * remove all unused data of tmpfile after abnormal power-off. | ||
514 | */ | ||
515 | add_orphan_inode(sbi, inode->i_ino); | ||
516 | |||
517 | page = new_inode_page(inode, NULL); | ||
518 | if (IS_ERR(page)) { | ||
519 | err = PTR_ERR(page); | ||
520 | goto remove_out; | ||
521 | } | ||
522 | |||
523 | err = f2fs_init_acl(inode, dir, page); | ||
524 | if (err) | ||
525 | goto unlock_out; | ||
526 | |||
527 | err = f2fs_init_security(inode, dir, NULL, page); | ||
528 | if (err) | ||
529 | goto unlock_out; | ||
530 | |||
531 | f2fs_put_page(page, 1); | ||
532 | f2fs_unlock_op(sbi); | ||
533 | |||
534 | alloc_nid_done(sbi, inode->i_ino); | ||
535 | mark_inode_dirty(inode); | ||
536 | d_tmpfile(dentry, inode); | ||
537 | unlock_new_inode(inode); | ||
538 | return 0; | ||
539 | unlock_out: | ||
540 | f2fs_put_page(page, 1); | ||
541 | remove_out: | ||
542 | remove_orphan_inode(sbi, inode->i_ino); | ||
543 | out: | ||
544 | f2fs_unlock_op(sbi); | ||
545 | clear_nlink(inode); | ||
546 | unlock_new_inode(inode); | ||
547 | make_bad_inode(inode); | ||
548 | iput(inode); | ||
549 | alloc_nid_failed(sbi, inode->i_ino); | ||
550 | return err; | ||
551 | } | ||
552 | |||
490 | const struct inode_operations f2fs_dir_inode_operations = { | 553 | const struct inode_operations f2fs_dir_inode_operations = { |
491 | .create = f2fs_create, | 554 | .create = f2fs_create, |
492 | .lookup = f2fs_lookup, | 555 | .lookup = f2fs_lookup, |
@@ -497,6 +560,7 @@ const struct inode_operations f2fs_dir_inode_operations = { | |||
497 | .rmdir = f2fs_rmdir, | 560 | .rmdir = f2fs_rmdir, |
498 | .mknod = f2fs_mknod, | 561 | .mknod = f2fs_mknod, |
499 | .rename = f2fs_rename, | 562 | .rename = f2fs_rename, |
563 | .tmpfile = f2fs_tmpfile, | ||
500 | .getattr = f2fs_getattr, | 564 | .getattr = f2fs_getattr, |
501 | .setattr = f2fs_setattr, | 565 | .setattr = f2fs_setattr, |
502 | .get_acl = f2fs_get_acl, | 566 | .get_acl = f2fs_get_acl, |