diff options
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r-- | fs/9p/vfs_inode.c | 114 |
1 files changed, 113 insertions, 1 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 39dc79567322..2ac245902a4f 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -642,6 +642,118 @@ error: | |||
642 | } | 642 | } |
643 | 643 | ||
644 | /** | 644 | /** |
645 | * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol. | ||
646 | * @dir: directory inode that is being created | ||
647 | * @dentry: dentry that is being deleted | ||
648 | * @mode: create permissions | ||
649 | * @nd: path information | ||
650 | * | ||
651 | */ | ||
652 | |||
653 | static int | ||
654 | v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, | ||
655 | struct nameidata *nd) | ||
656 | { | ||
657 | int err = 0; | ||
658 | char *name = NULL; | ||
659 | gid_t gid; | ||
660 | int flags; | ||
661 | struct v9fs_session_info *v9ses; | ||
662 | struct p9_fid *fid = NULL; | ||
663 | struct p9_fid *dfid, *ofid; | ||
664 | struct file *filp; | ||
665 | struct p9_qid qid; | ||
666 | struct inode *inode; | ||
667 | |||
668 | v9ses = v9fs_inode2v9ses(dir); | ||
669 | if (nd && nd->flags & LOOKUP_OPEN) | ||
670 | flags = nd->intent.open.flags - 1; | ||
671 | else | ||
672 | flags = O_RDWR; | ||
673 | |||
674 | name = (char *) dentry->d_name.name; | ||
675 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x " | ||
676 | "mode:0x%x\n", name, flags, mode); | ||
677 | |||
678 | dfid = v9fs_fid_lookup(dentry->d_parent); | ||
679 | if (IS_ERR(dfid)) { | ||
680 | err = PTR_ERR(dfid); | ||
681 | P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); | ||
682 | return err; | ||
683 | } | ||
684 | |||
685 | /* clone a fid to use for creation */ | ||
686 | ofid = p9_client_walk(dfid, 0, NULL, 1); | ||
687 | if (IS_ERR(ofid)) { | ||
688 | err = PTR_ERR(ofid); | ||
689 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); | ||
690 | return err; | ||
691 | } | ||
692 | |||
693 | gid = v9fs_get_fsgid_for_create(dir); | ||
694 | err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); | ||
695 | if (err < 0) { | ||
696 | P9_DPRINTK(P9_DEBUG_VFS, | ||
697 | "p9_client_open_dotl failed in creat %d\n", | ||
698 | err); | ||
699 | goto error; | ||
700 | } | ||
701 | |||
702 | /* No need to populate the inode if we are not opening the file AND | ||
703 | * not in cached mode. | ||
704 | */ | ||
705 | if (!v9ses->cache && !(nd && nd->flags & LOOKUP_OPEN)) { | ||
706 | /* Not in cached mode. No need to populate inode with stat */ | ||
707 | dentry->d_op = &v9fs_dentry_operations; | ||
708 | p9_client_clunk(ofid); | ||
709 | d_instantiate(dentry, NULL); | ||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | /* Now walk from the parent so we can get an unopened fid. */ | ||
714 | fid = p9_client_walk(dfid, 1, &name, 1); | ||
715 | if (IS_ERR(fid)) { | ||
716 | err = PTR_ERR(fid); | ||
717 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); | ||
718 | fid = NULL; | ||
719 | goto error; | ||
720 | } | ||
721 | |||
722 | /* instantiate inode and assign the unopened fid to dentry */ | ||
723 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); | ||
724 | if (IS_ERR(inode)) { | ||
725 | err = PTR_ERR(inode); | ||
726 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); | ||
727 | goto error; | ||
728 | } | ||
729 | dentry->d_op = &v9fs_cached_dentry_operations; | ||
730 | d_instantiate(dentry, inode); | ||
731 | err = v9fs_fid_add(dentry, fid); | ||
732 | if (err < 0) | ||
733 | goto error; | ||
734 | |||
735 | /* if we are opening a file, assign the open fid to the file */ | ||
736 | if (nd && nd->flags & LOOKUP_OPEN) { | ||
737 | filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); | ||
738 | if (IS_ERR(filp)) { | ||
739 | p9_client_clunk(ofid); | ||
740 | return PTR_ERR(filp); | ||
741 | } | ||
742 | filp->private_data = ofid; | ||
743 | } else | ||
744 | p9_client_clunk(ofid); | ||
745 | |||
746 | return 0; | ||
747 | |||
748 | error: | ||
749 | if (ofid) | ||
750 | p9_client_clunk(ofid); | ||
751 | if (fid) | ||
752 | p9_client_clunk(fid); | ||
753 | return err; | ||
754 | } | ||
755 | |||
756 | /** | ||
645 | * v9fs_vfs_create - VFS hook to create files | 757 | * v9fs_vfs_create - VFS hook to create files |
646 | * @dir: directory inode that is being created | 758 | * @dir: directory inode that is being created |
647 | * @dentry: dentry that is being deleted | 759 | * @dentry: dentry that is being deleted |
@@ -1808,7 +1920,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = { | |||
1808 | }; | 1920 | }; |
1809 | 1921 | ||
1810 | static const struct inode_operations v9fs_dir_inode_operations_dotl = { | 1922 | static const struct inode_operations v9fs_dir_inode_operations_dotl = { |
1811 | .create = v9fs_vfs_create, | 1923 | .create = v9fs_vfs_create_dotl, |
1812 | .lookup = v9fs_vfs_lookup, | 1924 | .lookup = v9fs_vfs_lookup, |
1813 | .link = v9fs_vfs_link_dotl, | 1925 | .link = v9fs_vfs_link_dotl, |
1814 | .symlink = v9fs_vfs_symlink_dotl, | 1926 | .symlink = v9fs_vfs_symlink_dotl, |