aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenkateswararao Jujjuri (JV) <jvrao@linux.vnet.ibm.com>2010-06-17 21:27:46 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2010-08-02 15:28:32 -0400
commit5643135a28464e7c19d8d23a9e0804697a62c84b (patch)
treed7141110fab0f3d71a95fe18b0b77cbaca645c80
parent01a622bd7409bb7af38e784cff814e5e723f7951 (diff)
fs/9p: This patch implements TLCREATE for 9p2000.L protocol.
SYNOPSIS size[4] Tlcreate tag[2] fid[4] name[s] flags[4] mode[4] gid[4] size[4] Rlcreate tag[2] qid[13] iounit[4] DESCRIPTION The Tlreate request asks the file server to create a new regular file with the name supplied, in the directory (dir) represented by fid. The mode argument specifies the permissions to use. New file is created with the uid if the fid and with supplied gid. The flags argument represent Linux access mode flags with which the caller is requesting to open the file with. Protocol allows all the Linux access modes but it is upto the server to allow/disallow any of these acess modes. If the server doesn't support any of the access mode, it is expected to return error. Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-rw-r--r--fs/9p/vfs_inode.c114
-rw-r--r--include/net/9p/9p.h4
-rw-r--r--include/net/9p/client.h2
-rw-r--r--net/9p/client.c44
4 files changed, 163 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
653static int
654v9fs_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
748error:
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
1810static const struct inode_operations v9fs_dir_inode_operations_dotl = { 1922static 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,
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index 091b471d8f05..06d111d61038 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -92,6 +92,8 @@ do { \
92 * @P9_RSYMLINK: make symlink response 92 * @P9_RSYMLINK: make symlink response
93 * @P9_TMKNOD: create a special file object request 93 * @P9_TMKNOD: create a special file object request
94 * @P9_RMKNOD: create a special file object response 94 * @P9_RMKNOD: create a special file object response
95 * @P9_TLCREATE: prepare a handle for I/O on an new file for 9P2000.L
96 * @P9_RLCREATE: response with file access information for 9P2000.L
95 * @P9_TRENAME: rename request 97 * @P9_TRENAME: rename request
96 * @P9_RRENAME: rename response 98 * @P9_RRENAME: rename response
97 * @P9_TMKDIR: create a directory request 99 * @P9_TMKDIR: create a directory request
@@ -137,6 +139,8 @@ do { \
137enum p9_msg_t { 139enum p9_msg_t {
138 P9_TSTATFS = 8, 140 P9_TSTATFS = 8,
139 P9_RSTATFS, 141 P9_RSTATFS,
142 P9_TLCREATE = 14,
143 P9_RLCREATE,
140 P9_TSYMLINK = 16, 144 P9_TSYMLINK = 16,
141 P9_RSYMLINK, 145 P9_RSYMLINK,
142 P9_TMKNOD = 18, 146 P9_TMKNOD = 18,
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 55d913a9b797..d755c0ed6750 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -229,6 +229,8 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
229int p9_client_link(struct p9_fid *fid, struct p9_fid *oldfid, char *newname); 229int p9_client_link(struct p9_fid *fid, struct p9_fid *oldfid, char *newname);
230int p9_client_symlink(struct p9_fid *fid, char *name, char *symname, gid_t gid, 230int p9_client_symlink(struct p9_fid *fid, char *name, char *symname, gid_t gid,
231 struct p9_qid *qid); 231 struct p9_qid *qid);
232int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
233 gid_t gid, struct p9_qid *qid);
232int p9_client_clunk(struct p9_fid *fid); 234int p9_client_clunk(struct p9_fid *fid);
233int p9_client_remove(struct p9_fid *fid); 235int p9_client_remove(struct p9_fid *fid);
234int p9_client_read(struct p9_fid *fid, char *data, char __user *udata, 236int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
diff --git a/net/9p/client.c b/net/9p/client.c
index a3bdd341f2ac..e580409b1052 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1050,6 +1050,50 @@ error:
1050} 1050}
1051EXPORT_SYMBOL(p9_client_open); 1051EXPORT_SYMBOL(p9_client_open);
1052 1052
1053int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
1054 gid_t gid, struct p9_qid *qid)
1055{
1056 int err = 0;
1057 struct p9_client *clnt;
1058 struct p9_req_t *req;
1059 int iounit;
1060
1061 P9_DPRINTK(P9_DEBUG_9P,
1062 ">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n",
1063 ofid->fid, name, flags, mode, gid);
1064 clnt = ofid->clnt;
1065
1066 if (ofid->mode != -1)
1067 return -EINVAL;
1068
1069 req = p9_client_rpc(clnt, P9_TLCREATE, "dsddd", ofid->fid, name, flags,
1070 mode, gid);
1071 if (IS_ERR(req)) {
1072 err = PTR_ERR(req);
1073 goto error;
1074 }
1075
1076 err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", qid, &iounit);
1077 if (err) {
1078 p9pdu_dump(1, req->rc);
1079 goto free_and_error;
1080 }
1081
1082 P9_DPRINTK(P9_DEBUG_9P, "<<< RLCREATE qid %x.%llx.%x iounit %x\n",
1083 qid->type,
1084 (unsigned long long)qid->path,
1085 qid->version, iounit);
1086
1087 ofid->mode = mode;
1088 ofid->iounit = iounit;
1089
1090free_and_error:
1091 p9_free_req(clnt, req);
1092error:
1093 return err;
1094}
1095EXPORT_SYMBOL(p9_client_create_dotl);
1096
1053int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, 1097int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
1054 char *extension) 1098 char *extension)
1055{ 1099{