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, |
