Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
fs/9p: Add hardlink support to .u extension
9P2010.L handshake: .L protocol negotiation
9P2010.L handshake: Remove "dotu" variable
9P2010.L handshake: Add mount option
9P2010.L handshake: Add VFS flags
net/9p: Handle mount errors correctly.
net/9p: Remove MAX_9P_CHAN limit
net/9p: Add multi channel support.

+238 -144
+1 -1
fs/9p/fid.c
··· 151 if (access == V9FS_ACCESS_SINGLE) 152 return ERR_PTR(-EPERM); 153 154 - if (v9fs_extended(v9ses)) 155 uname = NULL; 156 else 157 uname = v9ses->uname;
··· 151 if (access == V9FS_ACCESS_SINGLE) 152 return ERR_PTR(-EPERM); 153 154 + if (v9fs_proto_dotu(v9ses)) 155 uname = NULL; 156 else 157 uname = v9ses->uname;
+4 -4
fs/9p/v9fs.c
··· 241 list_add(&v9ses->slist, &v9fs_sessionlist); 242 spin_unlock(&v9fs_sessionlist_lock); 243 244 - v9ses->flags = V9FS_EXTENDED | V9FS_ACCESS_USER; 245 strcpy(v9ses->uname, V9FS_DEFUSER); 246 strcpy(v9ses->aname, V9FS_DEFANAME); 247 v9ses->uid = ~0; ··· 262 goto error; 263 } 264 265 - if (!v9ses->clnt->dotu) 266 - v9ses->flags &= ~V9FS_EXTENDED; 267 268 v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ; 269 270 /* for legacy mode, fall back to V9FS_ACCESS_ANY */ 271 - if (!v9fs_extended(v9ses) && 272 ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) { 273 274 v9ses->flags &= ~V9FS_ACCESS_MASK;
··· 241 list_add(&v9ses->slist, &v9fs_sessionlist); 242 spin_unlock(&v9fs_sessionlist_lock); 243 244 + v9ses->flags = V9FS_PROTO_2000U | V9FS_ACCESS_USER; 245 strcpy(v9ses->uname, V9FS_DEFUSER); 246 strcpy(v9ses->aname, V9FS_DEFANAME); 247 v9ses->uid = ~0; ··· 262 goto error; 263 } 264 265 + if (!p9_is_proto_dotu(v9ses->clnt)) 266 + v9ses->flags &= ~V9FS_PROTO_2000U; 267 268 v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ; 269 270 /* for legacy mode, fall back to V9FS_ACCESS_ANY */ 271 + if (!v9fs_proto_dotu(v9ses) && 272 ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) { 273 274 v9ses->flags &= ~V9FS_ACCESS_MASK;
+15 -8
fs/9p/v9fs.h
··· 23 24 /** 25 * enum p9_session_flags - option flags for each 9P session 26 - * @V9FS_EXTENDED: whether or not to use 9P2000.u extensions 27 * @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy 28 * @V9FS_ACCESS_USER: a new attach will be issued for every user (default) 29 * @V9FS_ACCESS_ANY: use a single attach for all users ··· 33 * Session flags reflect options selected by users at mount time 34 */ 35 enum p9_session_flags { 36 - V9FS_EXTENDED = 0x01, 37 - V9FS_ACCESS_SINGLE = 0x02, 38 - V9FS_ACCESS_USER = 0x04, 39 - V9FS_ACCESS_ANY = 0x06, 40 - V9FS_ACCESS_MASK = 0x06, 41 }; 42 43 /* possible values of ->cache */ ··· 123 return (inode->i_sb->s_fs_info); 124 } 125 126 - static inline int v9fs_extended(struct v9fs_session_info *v9ses) 127 { 128 - return v9ses->flags & V9FS_EXTENDED; 129 }
··· 23 24 /** 25 * enum p9_session_flags - option flags for each 9P session 26 + * @V9FS_PROTO_2000U: whether or not to use 9P2000.u extensions 27 + * @V9FS_PROTO_2010L: whether or not to use 9P2010.l extensions 28 * @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy 29 * @V9FS_ACCESS_USER: a new attach will be issued for every user (default) 30 * @V9FS_ACCESS_ANY: use a single attach for all users ··· 32 * Session flags reflect options selected by users at mount time 33 */ 34 enum p9_session_flags { 35 + V9FS_PROTO_2000U = 0x01, 36 + V9FS_PROTO_2010L = 0x02, 37 + V9FS_ACCESS_SINGLE = 0x04, 38 + V9FS_ACCESS_USER = 0x08, 39 + V9FS_ACCESS_ANY = 0x0C, 40 + V9FS_ACCESS_MASK = 0x0C, 41 }; 42 43 /* possible values of ->cache */ ··· 121 return (inode->i_sb->s_fs_info); 122 } 123 124 + static inline int v9fs_proto_dotu(struct v9fs_session_info *v9ses) 125 { 126 + return v9ses->flags & V9FS_PROTO_2000U; 127 + } 128 + 129 + static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses) 130 + { 131 + return v9ses->flags & V9FS_PROTO_2010L; 132 }
+1 -1
fs/9p/vfs_dir.c
··· 135 while (rdir->head < rdir->tail) { 136 err = p9stat_read(rdir->buf + rdir->head, 137 buflen - rdir->head, &st, 138 - fid->clnt->dotu); 139 if (err) { 140 P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); 141 err = -EIO;
··· 135 while (rdir->head < rdir->tail) { 136 err = p9stat_read(rdir->buf + rdir->head, 137 buflen - rdir->head, &st, 138 + fid->clnt->proto_version); 139 if (err) { 140 P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); 141 err = -EIO;
+2 -2
fs/9p/vfs_file.c
··· 61 62 P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p \n", inode, file); 63 v9ses = v9fs_inode2v9ses(inode); 64 - omode = v9fs_uflags2omode(file->f_flags, v9fs_extended(v9ses)); 65 fid = file->private_data; 66 if (!fid) { 67 fid = v9fs_fid_clone(file->f_path.dentry); ··· 77 i_size_write(inode, 0); 78 inode->i_blocks = 0; 79 } 80 - if ((file->f_flags & O_APPEND) && (!v9fs_extended(v9ses))) 81 generic_file_llseek(file, 0, SEEK_END); 82 } 83
··· 61 62 P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p \n", inode, file); 63 v9ses = v9fs_inode2v9ses(inode); 64 + omode = v9fs_uflags2omode(file->f_flags, v9fs_proto_dotu(v9ses)); 65 fid = file->private_data; 66 if (!fid) { 67 fid = v9fs_fid_clone(file->f_path.dentry); ··· 77 i_size_write(inode, 0); 78 inode->i_blocks = 0; 79 } 80 + if ((file->f_flags & O_APPEND) && (!v9fs_proto_dotu(v9ses))) 81 generic_file_llseek(file, 0, SEEK_END); 82 } 83
+33 -15
fs/9p/vfs_inode.c
··· 60 res = mode & 0777; 61 if (S_ISDIR(mode)) 62 res |= P9_DMDIR; 63 - if (v9fs_extended(v9ses)) { 64 if (S_ISLNK(mode)) 65 res |= P9_DMSYMLINK; 66 if (v9ses->nodev == 0) { ··· 102 103 if ((mode & P9_DMDIR) == P9_DMDIR) 104 res |= S_IFDIR; 105 - else if ((mode & P9_DMSYMLINK) && (v9fs_extended(v9ses))) 106 res |= S_IFLNK; 107 - else if ((mode & P9_DMSOCKET) && (v9fs_extended(v9ses)) 108 && (v9ses->nodev == 0)) 109 res |= S_IFSOCK; 110 - else if ((mode & P9_DMNAMEDPIPE) && (v9fs_extended(v9ses)) 111 && (v9ses->nodev == 0)) 112 res |= S_IFIFO; 113 - else if ((mode & P9_DMDEVICE) && (v9fs_extended(v9ses)) 114 && (v9ses->nodev == 0)) 115 res |= S_IFBLK; 116 else 117 res |= S_IFREG; 118 119 - if (v9fs_extended(v9ses)) { 120 if ((mode & P9_DMSETUID) == P9_DMSETUID) 121 res |= S_ISUID; 122 ··· 265 case S_IFBLK: 266 case S_IFCHR: 267 case S_IFSOCK: 268 - if (!v9fs_extended(v9ses)) { 269 P9_DPRINTK(P9_DEBUG_ERROR, 270 "special files without extended mode\n"); 271 err = -EINVAL; ··· 278 inode->i_fop = &v9fs_file_operations; 279 break; 280 case S_IFLNK: 281 - if (!v9fs_extended(v9ses)) { 282 P9_DPRINTK(P9_DEBUG_ERROR, 283 "extended modes used w/o 9P2000.u\n"); 284 err = -EINVAL; ··· 288 break; 289 case S_IFDIR: 290 inc_nlink(inode); 291 - if (v9fs_extended(v9ses)) 292 inode->i_op = &v9fs_dir_inode_operations_ext; 293 else 294 inode->i_op = &v9fs_dir_inode_operations; ··· 575 flags = O_RDWR; 576 577 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, 578 - v9fs_uflags2omode(flags, v9fs_extended(v9ses))); 579 if (IS_ERR(fid)) { 580 err = PTR_ERR(fid); 581 fid = NULL; ··· 859 if (iattr->ia_valid & ATTR_SIZE) 860 wstat.length = iattr->ia_size; 861 862 - if (v9fs_extended(v9ses)) { 863 if (iattr->ia_valid & ATTR_UID) 864 wstat.n_uid = iattr->ia_uid; 865 ··· 887 struct super_block *sb) 888 { 889 char ext[32]; 890 struct v9fs_session_info *v9ses = sb->s_fs_info; 891 892 inode->i_nlink = 1; ··· 900 inode->i_uid = v9ses->dfltuid; 901 inode->i_gid = v9ses->dfltgid; 902 903 - if (v9fs_extended(v9ses)) { 904 inode->i_uid = stat->n_uid; 905 inode->i_gid = stat->n_gid; 906 } 907 - 908 inode->i_mode = p9mode2unixmode(v9ses, stat->mode); 909 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) { 910 char type = 0; ··· 994 if (IS_ERR(fid)) 995 return PTR_ERR(fid); 996 997 - if (!v9fs_extended(v9ses)) 998 return -EBADF; 999 1000 st = p9_client_stat(fid); ··· 1084 struct p9_fid *fid; 1085 1086 v9ses = v9fs_inode2v9ses(dir); 1087 - if (!v9fs_extended(v9ses)) { 1088 P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n"); 1089 return -EPERM; 1090 }
··· 60 res = mode & 0777; 61 if (S_ISDIR(mode)) 62 res |= P9_DMDIR; 63 + if (v9fs_proto_dotu(v9ses)) { 64 if (S_ISLNK(mode)) 65 res |= P9_DMSYMLINK; 66 if (v9ses->nodev == 0) { ··· 102 103 if ((mode & P9_DMDIR) == P9_DMDIR) 104 res |= S_IFDIR; 105 + else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses))) 106 res |= S_IFLNK; 107 + else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses)) 108 && (v9ses->nodev == 0)) 109 res |= S_IFSOCK; 110 + else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses)) 111 && (v9ses->nodev == 0)) 112 res |= S_IFIFO; 113 + else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses)) 114 && (v9ses->nodev == 0)) 115 res |= S_IFBLK; 116 else 117 res |= S_IFREG; 118 119 + if (v9fs_proto_dotu(v9ses)) { 120 if ((mode & P9_DMSETUID) == P9_DMSETUID) 121 res |= S_ISUID; 122 ··· 265 case S_IFBLK: 266 case S_IFCHR: 267 case S_IFSOCK: 268 + if (!v9fs_proto_dotu(v9ses)) { 269 P9_DPRINTK(P9_DEBUG_ERROR, 270 "special files without extended mode\n"); 271 err = -EINVAL; ··· 278 inode->i_fop = &v9fs_file_operations; 279 break; 280 case S_IFLNK: 281 + if (!v9fs_proto_dotu(v9ses)) { 282 P9_DPRINTK(P9_DEBUG_ERROR, 283 "extended modes used w/o 9P2000.u\n"); 284 err = -EINVAL; ··· 288 break; 289 case S_IFDIR: 290 inc_nlink(inode); 291 + if (v9fs_proto_dotu(v9ses)) 292 inode->i_op = &v9fs_dir_inode_operations_ext; 293 else 294 inode->i_op = &v9fs_dir_inode_operations; ··· 575 flags = O_RDWR; 576 577 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, 578 + v9fs_uflags2omode(flags, 579 + v9fs_proto_dotu(v9ses))); 580 if (IS_ERR(fid)) { 581 err = PTR_ERR(fid); 582 fid = NULL; ··· 858 if (iattr->ia_valid & ATTR_SIZE) 859 wstat.length = iattr->ia_size; 860 861 + if (v9fs_proto_dotu(v9ses)) { 862 if (iattr->ia_valid & ATTR_UID) 863 wstat.n_uid = iattr->ia_uid; 864 ··· 886 struct super_block *sb) 887 { 888 char ext[32]; 889 + char tag_name[14]; 890 + unsigned int i_nlink; 891 struct v9fs_session_info *v9ses = sb->s_fs_info; 892 893 inode->i_nlink = 1; ··· 897 inode->i_uid = v9ses->dfltuid; 898 inode->i_gid = v9ses->dfltgid; 899 900 + if (v9fs_proto_dotu(v9ses)) { 901 inode->i_uid = stat->n_uid; 902 inode->i_gid = stat->n_gid; 903 } 904 + if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) { 905 + if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) { 906 + /* 907 + * Hadlink support got added later to 908 + * to the .u extension. So there can be 909 + * server out there that doesn't support 910 + * this even with .u extension. So check 911 + * for non NULL stat->extension 912 + */ 913 + strncpy(ext, stat->extension, sizeof(ext)); 914 + /* HARDLINKCOUNT %u */ 915 + sscanf(ext, "%13s %u", tag_name, &i_nlink); 916 + if (!strncmp(tag_name, "HARDLINKCOUNT", 13)) 917 + inode->i_nlink = i_nlink; 918 + } 919 + } 920 inode->i_mode = p9mode2unixmode(v9ses, stat->mode); 921 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) { 922 char type = 0; ··· 976 if (IS_ERR(fid)) 977 return PTR_ERR(fid); 978 979 + if (!v9fs_proto_dotu(v9ses)) 980 return -EBADF; 981 982 st = p9_client_stat(fid); ··· 1066 struct p9_fid *fid; 1067 1068 v9ses = v9fs_inode2v9ses(dir); 1069 + if (!v9fs_proto_dotu(v9ses)) { 1070 P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n"); 1071 return -EPERM; 1072 }
-3
include/linux/virtio_9p.h
··· 5 #include <linux/virtio_ids.h> 6 #include <linux/virtio_config.h> 7 8 - /* Maximum number of virtio channels per partition (1 for now) */ 9 - #define MAX_9P_CHAN 1 10 - 11 #endif /* _LINUX_VIRTIO_9P_H */
··· 5 #include <linux/virtio_ids.h> 6 #include <linux/virtio_config.h> 7 8 #endif /* _LINUX_VIRTIO_9P_H */
+17 -1
include/net/9p/client.h
··· 29 /* Number of requests per row */ 30 #define P9_ROW_MAXTAG 255 31 32 /** 33 * enum p9_trans_status - different states of underlying transports 34 * @Connected: transport is connected and healthy ··· 124 * @lock: protect @fidlist 125 * @msize: maximum data size negotiated by protocol 126 * @dotu: extension flags negotiated by protocol 127 * @trans_mod: module API instantiated with this client 128 * @trans: tranport instance state and API 129 * @conn: connection state information used by trans_fd ··· 151 struct p9_client { 152 spinlock_t lock; /* protect client structure */ 153 int msize; 154 - unsigned char dotu; 155 struct p9_trans_module *trans_mod; 156 enum p9_trans_status status; 157 void *trans; ··· 223 int p9stat_read(char *, int, struct p9_wstat *, int); 224 void p9stat_free(struct p9_wstat *); 225 226 227 #endif /* NET_9P_CLIENT_H */
··· 29 /* Number of requests per row */ 30 #define P9_ROW_MAXTAG 255 31 32 + /** enum p9_proto_versions - 9P protocol versions 33 + * @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u 34 + * @p9_proto_2000u: 9P2000.u extension 35 + * @p9_proto_2010L: 9P2010.L extension 36 + */ 37 + 38 + enum p9_proto_versions{ 39 + p9_proto_legacy = 0, 40 + p9_proto_2000u = 1, 41 + p9_proto_2010L = 2, 42 + }; 43 + 44 + 45 /** 46 * enum p9_trans_status - different states of underlying transports 47 * @Connected: transport is connected and healthy ··· 111 * @lock: protect @fidlist 112 * @msize: maximum data size negotiated by protocol 113 * @dotu: extension flags negotiated by protocol 114 + * @proto_version: 9P protocol version to use 115 * @trans_mod: module API instantiated with this client 116 * @trans: tranport instance state and API 117 * @conn: connection state information used by trans_fd ··· 137 struct p9_client { 138 spinlock_t lock; /* protect client structure */ 139 int msize; 140 + unsigned char proto_version; 141 struct p9_trans_module *trans_mod; 142 enum p9_trans_status status; 143 void *trans; ··· 209 int p9stat_read(char *, int, struct p9_wstat *, int); 210 void p9stat_free(struct p9_wstat *); 211 212 + int p9_is_proto_dotu(struct p9_client *clnt); 213 + int p9_is_proto_dotl(struct p9_client *clnt); 214 215 #endif /* NET_9P_CLIENT_H */
+87 -27
net/9p/client.c
··· 46 Opt_msize, 47 Opt_trans, 48 Opt_legacy, 49 Opt_err, 50 }; 51 ··· 54 {Opt_msize, "msize=%u"}, 55 {Opt_legacy, "noextend"}, 56 {Opt_trans, "trans=%s"}, 57 {Opt_err, NULL}, 58 }; 59 60 static struct p9_req_t * 61 p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); ··· 109 int option; 110 int ret = 0; 111 112 - clnt->dotu = 1; 113 clnt->msize = 8192; 114 115 if (!opts) ··· 152 } 153 break; 154 case Opt_legacy: 155 - clnt->dotu = 0; 156 break; 157 default: 158 continue; ··· 450 int ecode; 451 char *ename; 452 453 - err = p9pdu_readf(req->rc, c->dotu, "s?d", &ename, &ecode); 454 if (err) { 455 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", 456 err); 457 return err; 458 } 459 460 - if (c->dotu) 461 err = -ecode; 462 463 if (!err || !IS_ERR_VALUE(err)) ··· 556 /* marshall the data */ 557 p9pdu_prepare(req->tc, tag, type); 558 va_start(ap, fmt); 559 - err = p9pdu_vwritef(req->tc, c->dotu, fmt, ap); 560 va_end(ap); 561 p9pdu_finalize(req->tc); 562 ··· 668 char *version; 669 int msize; 670 671 - P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d extended %d\n", 672 - c->msize, c->dotu); 673 - req = p9_client_rpc(c, P9_TVERSION, "ds", c->msize, 674 - c->dotu ? "9P2000.u" : "9P2000"); 675 if (IS_ERR(req)) 676 return PTR_ERR(req); 677 678 - err = p9pdu_readf(req->rc, c->dotu, "ds", &msize, &version); 679 if (err) { 680 P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err); 681 p9pdu_dump(1, req->rc); ··· 700 } 701 702 P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); 703 - if (!memcmp(version, "9P2000.u", 8)) 704 - c->dotu = 1; 705 - else if (!memcmp(version, "9P2000", 6)) 706 - c->dotu = 0; 707 else { 708 err = -EREMOTEIO; 709 goto error; ··· 760 goto put_trans; 761 } 762 763 - P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n", 764 - clnt, clnt->trans_mod, clnt->msize, clnt->dotu); 765 766 err = clnt->trans_mod->create(clnt, dev_name, options); 767 if (err) ··· 844 goto error; 845 } 846 847 - err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid); 848 if (err) { 849 p9pdu_dump(1, req->rc); 850 p9_free_req(clnt, req); ··· 893 goto error; 894 } 895 896 - err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid); 897 if (err) { 898 p9pdu_dump(1, req->rc); 899 p9_free_req(clnt, req); ··· 951 goto error; 952 } 953 954 - err = p9pdu_readf(req->rc, clnt->dotu, "R", &nwqids, &wqids); 955 if (err) { 956 p9pdu_dump(1, req->rc); 957 p9_free_req(clnt, req); ··· 1012 goto error; 1013 } 1014 1015 - err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit); 1016 if (err) { 1017 p9pdu_dump(1, req->rc); 1018 goto free_and_error; ··· 1057 goto error; 1058 } 1059 1060 - err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit); 1061 if (err) { 1062 p9pdu_dump(1, req->rc); 1063 goto free_and_error; ··· 1158 goto error; 1159 } 1160 1161 - err = p9pdu_readf(req->rc, clnt->dotu, "D", &count, &dataptr); 1162 if (err) { 1163 p9pdu_dump(1, req->rc); 1164 goto free_and_error; ··· 1219 goto error; 1220 } 1221 1222 - err = p9pdu_readf(req->rc, clnt->dotu, "d", &count); 1223 if (err) { 1224 p9pdu_dump(1, req->rc); 1225 goto free_and_error; ··· 1259 goto error; 1260 } 1261 1262 - err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret); 1263 if (err) { 1264 p9pdu_dump(1, req->rc); 1265 p9_free_req(clnt, req); ··· 1286 } 1287 EXPORT_SYMBOL(p9_client_stat); 1288 1289 - static int p9_client_statsize(struct p9_wstat *wst, int optional) 1290 { 1291 int ret; 1292 ··· 1305 if (wst->muid) 1306 ret += strlen(wst->muid); 1307 1308 - if (optional) { 1309 ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ 1310 if (wst->extension) 1311 ret += strlen(wst->extension); ··· 1322 1323 err = 0; 1324 clnt = fid->clnt; 1325 - wst->size = p9_client_statsize(wst, clnt->dotu); 1326 P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); 1327 P9_DPRINTK(P9_DEBUG_9P, 1328 " sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
··· 46 Opt_msize, 47 Opt_trans, 48 Opt_legacy, 49 + Opt_version, 50 Opt_err, 51 }; 52 ··· 53 {Opt_msize, "msize=%u"}, 54 {Opt_legacy, "noextend"}, 55 {Opt_trans, "trans=%s"}, 56 + {Opt_version, "version=%s"}, 57 {Opt_err, NULL}, 58 }; 59 + 60 + inline int p9_is_proto_dotl(struct p9_client *clnt) 61 + { 62 + return (clnt->proto_version == p9_proto_2010L); 63 + } 64 + EXPORT_SYMBOL(p9_is_proto_dotl); 65 + 66 + inline int p9_is_proto_dotu(struct p9_client *clnt) 67 + { 68 + return (clnt->proto_version == p9_proto_2000u); 69 + } 70 + EXPORT_SYMBOL(p9_is_proto_dotu); 71 + 72 + /* Interpret mount option for protocol version */ 73 + static unsigned char get_protocol_version(const substring_t *name) 74 + { 75 + unsigned char version = -EINVAL; 76 + if (!strncmp("9p2000", name->from, name->to-name->from)) { 77 + version = p9_proto_legacy; 78 + P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n"); 79 + } else if (!strncmp("9p2000.u", name->from, name->to-name->from)) { 80 + version = p9_proto_2000u; 81 + P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n"); 82 + } else if (!strncmp("9p2010.L", name->from, name->to-name->from)) { 83 + version = p9_proto_2010L; 84 + P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2010.L\n"); 85 + } else { 86 + P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ", 87 + name->from); 88 + } 89 + return version; 90 + } 91 92 static struct p9_req_t * 93 p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); ··· 75 int option; 76 int ret = 0; 77 78 + clnt->proto_version = p9_proto_2000u; 79 clnt->msize = 8192; 80 81 if (!opts) ··· 118 } 119 break; 120 case Opt_legacy: 121 + clnt->proto_version = p9_proto_legacy; 122 + break; 123 + case Opt_version: 124 + ret = get_protocol_version(&args[0]); 125 + if (ret == -EINVAL) 126 + goto free_and_return; 127 + clnt->proto_version = ret; 128 break; 129 default: 130 continue; ··· 410 int ecode; 411 char *ename; 412 413 + err = p9pdu_readf(req->rc, c->proto_version, "s?d", 414 + &ename, &ecode); 415 if (err) { 416 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", 417 err); 418 return err; 419 } 420 421 + if (p9_is_proto_dotu(c)) 422 err = -ecode; 423 424 if (!err || !IS_ERR_VALUE(err)) ··· 515 /* marshall the data */ 516 p9pdu_prepare(req->tc, tag, type); 517 va_start(ap, fmt); 518 + err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); 519 va_end(ap); 520 p9pdu_finalize(req->tc); 521 ··· 627 char *version; 628 int msize; 629 630 + P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n", 631 + c->msize, c->proto_version); 632 + 633 + switch (c->proto_version) { 634 + case p9_proto_2010L: 635 + req = p9_client_rpc(c, P9_TVERSION, "ds", 636 + c->msize, "9P2010.L"); 637 + break; 638 + case p9_proto_2000u: 639 + req = p9_client_rpc(c, P9_TVERSION, "ds", 640 + c->msize, "9P2000.u"); 641 + break; 642 + case p9_proto_legacy: 643 + req = p9_client_rpc(c, P9_TVERSION, "ds", 644 + c->msize, "9P2000"); 645 + break; 646 + default: 647 + return -EINVAL; 648 + break; 649 + } 650 + 651 if (IS_ERR(req)) 652 return PTR_ERR(req); 653 654 + err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version); 655 if (err) { 656 P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err); 657 p9pdu_dump(1, req->rc); ··· 642 } 643 644 P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); 645 + if (!strncmp(version, "9P2010.L", 8)) 646 + c->proto_version = p9_proto_2010L; 647 + else if (!strncmp(version, "9P2000.u", 8)) 648 + c->proto_version = p9_proto_2000u; 649 + else if (!strncmp(version, "9P2000", 6)) 650 + c->proto_version = p9_proto_legacy; 651 else { 652 err = -EREMOTEIO; 653 goto error; ··· 700 goto put_trans; 701 } 702 703 + P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n", 704 + clnt, clnt->trans_mod, clnt->msize, clnt->proto_version); 705 706 err = clnt->trans_mod->create(clnt, dev_name, options); 707 if (err) ··· 784 goto error; 785 } 786 787 + err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); 788 if (err) { 789 p9pdu_dump(1, req->rc); 790 p9_free_req(clnt, req); ··· 833 goto error; 834 } 835 836 + err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); 837 if (err) { 838 p9pdu_dump(1, req->rc); 839 p9_free_req(clnt, req); ··· 891 goto error; 892 } 893 894 + err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids); 895 if (err) { 896 p9pdu_dump(1, req->rc); 897 p9_free_req(clnt, req); ··· 952 goto error; 953 } 954 955 + err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); 956 if (err) { 957 p9pdu_dump(1, req->rc); 958 goto free_and_error; ··· 997 goto error; 998 } 999 1000 + err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); 1001 if (err) { 1002 p9pdu_dump(1, req->rc); 1003 goto free_and_error; ··· 1098 goto error; 1099 } 1100 1101 + err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); 1102 if (err) { 1103 p9pdu_dump(1, req->rc); 1104 goto free_and_error; ··· 1159 goto error; 1160 } 1161 1162 + err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count); 1163 if (err) { 1164 p9pdu_dump(1, req->rc); 1165 goto free_and_error; ··· 1199 goto error; 1200 } 1201 1202 + err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret); 1203 if (err) { 1204 p9pdu_dump(1, req->rc); 1205 p9_free_req(clnt, req); ··· 1226 } 1227 EXPORT_SYMBOL(p9_client_stat); 1228 1229 + static int p9_client_statsize(struct p9_wstat *wst, int proto_version) 1230 { 1231 int ret; 1232 ··· 1245 if (wst->muid) 1246 ret += strlen(wst->muid); 1247 1248 + if (proto_version == p9_proto_2000u) { 1249 ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ 1250 if (wst->extension) 1251 ret += strlen(wst->extension); ··· 1262 1263 err = 0; 1264 clnt = fid->clnt; 1265 + wst->size = p9_client_statsize(wst, clnt->proto_version); 1266 P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); 1267 P9_DPRINTK(P9_DEBUG_9P, 1268 " sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
+41 -33
net/9p/protocol.c
··· 52 #endif 53 54 static int 55 - p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...); 56 57 #ifdef CONFIG_NET_9P_DEBUG 58 void ··· 144 */ 145 146 static int 147 - p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) 148 { 149 const char *ptr; 150 int errcode = 0; ··· 195 int16_t len; 196 int size; 197 198 - errcode = p9pdu_readf(pdu, optional, "w", &len); 199 if (errcode) 200 break; 201 ··· 219 struct p9_qid *qid = 220 va_arg(ap, struct p9_qid *); 221 222 - errcode = p9pdu_readf(pdu, optional, "bdq", 223 &qid->type, &qid->version, 224 &qid->path); 225 } ··· 232 stbuf->n_uid = stbuf->n_gid = stbuf->n_muid = 233 -1; 234 errcode = 235 - p9pdu_readf(pdu, optional, 236 "wwdQdddqssss?sddd", 237 &stbuf->size, &stbuf->type, 238 &stbuf->dev, &stbuf->qid, ··· 252 void **data = va_arg(ap, void **); 253 254 errcode = 255 - p9pdu_readf(pdu, optional, "d", count); 256 if (!errcode) { 257 *count = 258 MIN(*count, ··· 265 int16_t *nwname = va_arg(ap, int16_t *); 266 char ***wnames = va_arg(ap, char ***); 267 268 - errcode = 269 - p9pdu_readf(pdu, optional, "w", nwname); 270 if (!errcode) { 271 *wnames = 272 kmalloc(sizeof(char *) * *nwname, ··· 280 281 for (i = 0; i < *nwname; i++) { 282 errcode = 283 - p9pdu_readf(pdu, optional, 284 "s", 285 &(*wnames)[i]); 286 if (errcode) ··· 309 *wqids = NULL; 310 311 errcode = 312 - p9pdu_readf(pdu, optional, "w", nwqid); 313 if (!errcode) { 314 *wqids = 315 kmalloc(*nwqid * ··· 324 325 for (i = 0; i < *nwqid; i++) { 326 errcode = 327 - p9pdu_readf(pdu, optional, 328 "Q", 329 &(*wqids)[i]); 330 if (errcode) ··· 340 } 341 break; 342 case '?': 343 - if (!optional) 344 return 0; 345 break; 346 default: ··· 356 } 357 358 int 359 - p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) 360 { 361 const char *ptr; 362 int errcode = 0; ··· 394 if (sptr) 395 len = MIN(strlen(sptr), USHORT_MAX); 396 397 - errcode = p9pdu_writef(pdu, optional, "w", len); 398 if (!errcode && pdu_write(pdu, sptr, len)) 399 errcode = -EFAULT; 400 } ··· 404 const struct p9_qid *qid = 405 va_arg(ap, const struct p9_qid *); 406 errcode = 407 - p9pdu_writef(pdu, optional, "bdq", 408 qid->type, qid->version, 409 qid->path); 410 } break; ··· 412 const struct p9_wstat *stbuf = 413 va_arg(ap, const struct p9_wstat *); 414 errcode = 415 - p9pdu_writef(pdu, optional, 416 "wwdQdddqssss?sddd", 417 stbuf->size, stbuf->type, 418 stbuf->dev, &stbuf->qid, ··· 427 int32_t count = va_arg(ap, int32_t); 428 const void *data = va_arg(ap, const void *); 429 430 - errcode = 431 - p9pdu_writef(pdu, optional, "d", count); 432 if (!errcode && pdu_write(pdu, data, count)) 433 errcode = -EFAULT; 434 } ··· 437 int32_t count = va_arg(ap, int32_t); 438 const char __user *udata = 439 va_arg(ap, const void __user *); 440 - errcode = 441 - p9pdu_writef(pdu, optional, "d", count); 442 if (!errcode && pdu_write_u(pdu, udata, count)) 443 errcode = -EFAULT; 444 } ··· 447 int16_t nwname = va_arg(ap, int); 448 const char **wnames = va_arg(ap, const char **); 449 450 - errcode = 451 - p9pdu_writef(pdu, optional, "w", nwname); 452 if (!errcode) { 453 int i; 454 455 for (i = 0; i < nwname; i++) { 456 errcode = 457 - p9pdu_writef(pdu, optional, 458 "s", 459 wnames[i]); 460 if (errcode) ··· 469 struct p9_qid *wqids = 470 va_arg(ap, struct p9_qid *); 471 472 - errcode = 473 - p9pdu_writef(pdu, optional, "w", nwqid); 474 if (!errcode) { 475 int i; 476 477 for (i = 0; i < nwqid; i++) { 478 errcode = 479 - p9pdu_writef(pdu, optional, 480 "Q", 481 &wqids[i]); 482 if (errcode) ··· 487 } 488 break; 489 case '?': 490 - if (!optional) 491 return 0; 492 break; 493 default: ··· 502 return errcode; 503 } 504 505 - int p9pdu_readf(struct p9_fcall *pdu, int optional, const char *fmt, ...) 506 { 507 va_list ap; 508 int ret; 509 510 va_start(ap, fmt); 511 - ret = p9pdu_vreadf(pdu, optional, fmt, ap); 512 va_end(ap); 513 514 return ret; 515 } 516 517 static int 518 - p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...) 519 { 520 va_list ap; 521 int ret; 522 523 va_start(ap, fmt); 524 - ret = p9pdu_vwritef(pdu, optional, fmt, ap); 525 va_end(ap); 526 527 return ret; 528 } 529 530 - int p9stat_read(char *buf, int len, struct p9_wstat *st, int dotu) 531 { 532 struct p9_fcall fake_pdu; 533 int ret; ··· 537 fake_pdu.sdata = buf; 538 fake_pdu.offset = 0; 539 540 - ret = p9pdu_readf(&fake_pdu, dotu, "S", st); 541 if (ret) { 542 P9_DPRINTK(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); 543 p9pdu_dump(1, &fake_pdu);
··· 52 #endif 53 54 static int 55 + p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); 56 57 #ifdef CONFIG_NET_9P_DEBUG 58 void ··· 144 */ 145 146 static int 147 + p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, 148 + va_list ap) 149 { 150 const char *ptr; 151 int errcode = 0; ··· 194 int16_t len; 195 int size; 196 197 + errcode = p9pdu_readf(pdu, proto_version, 198 + "w", &len); 199 if (errcode) 200 break; 201 ··· 217 struct p9_qid *qid = 218 va_arg(ap, struct p9_qid *); 219 220 + errcode = p9pdu_readf(pdu, proto_version, "bdq", 221 &qid->type, &qid->version, 222 &qid->path); 223 } ··· 230 stbuf->n_uid = stbuf->n_gid = stbuf->n_muid = 231 -1; 232 errcode = 233 + p9pdu_readf(pdu, proto_version, 234 "wwdQdddqssss?sddd", 235 &stbuf->size, &stbuf->type, 236 &stbuf->dev, &stbuf->qid, ··· 250 void **data = va_arg(ap, void **); 251 252 errcode = 253 + p9pdu_readf(pdu, proto_version, "d", count); 254 if (!errcode) { 255 *count = 256 MIN(*count, ··· 263 int16_t *nwname = va_arg(ap, int16_t *); 264 char ***wnames = va_arg(ap, char ***); 265 266 + errcode = p9pdu_readf(pdu, proto_version, 267 + "w", nwname); 268 if (!errcode) { 269 *wnames = 270 kmalloc(sizeof(char *) * *nwname, ··· 278 279 for (i = 0; i < *nwname; i++) { 280 errcode = 281 + p9pdu_readf(pdu, 282 + proto_version, 283 "s", 284 &(*wnames)[i]); 285 if (errcode) ··· 306 *wqids = NULL; 307 308 errcode = 309 + p9pdu_readf(pdu, proto_version, "w", nwqid); 310 if (!errcode) { 311 *wqids = 312 kmalloc(*nwqid * ··· 321 322 for (i = 0; i < *nwqid; i++) { 323 errcode = 324 + p9pdu_readf(pdu, 325 + proto_version, 326 "Q", 327 &(*wqids)[i]); 328 if (errcode) ··· 336 } 337 break; 338 case '?': 339 + if (proto_version != p9_proto_2000u) 340 return 0; 341 break; 342 default: ··· 352 } 353 354 int 355 + p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, 356 + va_list ap) 357 { 358 const char *ptr; 359 int errcode = 0; ··· 389 if (sptr) 390 len = MIN(strlen(sptr), USHORT_MAX); 391 392 + errcode = p9pdu_writef(pdu, proto_version, 393 + "w", len); 394 if (!errcode && pdu_write(pdu, sptr, len)) 395 errcode = -EFAULT; 396 } ··· 398 const struct p9_qid *qid = 399 va_arg(ap, const struct p9_qid *); 400 errcode = 401 + p9pdu_writef(pdu, proto_version, "bdq", 402 qid->type, qid->version, 403 qid->path); 404 } break; ··· 406 const struct p9_wstat *stbuf = 407 va_arg(ap, const struct p9_wstat *); 408 errcode = 409 + p9pdu_writef(pdu, proto_version, 410 "wwdQdddqssss?sddd", 411 stbuf->size, stbuf->type, 412 stbuf->dev, &stbuf->qid, ··· 421 int32_t count = va_arg(ap, int32_t); 422 const void *data = va_arg(ap, const void *); 423 424 + errcode = p9pdu_writef(pdu, proto_version, "d", 425 + count); 426 if (!errcode && pdu_write(pdu, data, count)) 427 errcode = -EFAULT; 428 } ··· 431 int32_t count = va_arg(ap, int32_t); 432 const char __user *udata = 433 va_arg(ap, const void __user *); 434 + errcode = p9pdu_writef(pdu, proto_version, "d", 435 + count); 436 if (!errcode && pdu_write_u(pdu, udata, count)) 437 errcode = -EFAULT; 438 } ··· 441 int16_t nwname = va_arg(ap, int); 442 const char **wnames = va_arg(ap, const char **); 443 444 + errcode = p9pdu_writef(pdu, proto_version, "w", 445 + nwname); 446 if (!errcode) { 447 int i; 448 449 for (i = 0; i < nwname; i++) { 450 errcode = 451 + p9pdu_writef(pdu, 452 + proto_version, 453 "s", 454 wnames[i]); 455 if (errcode) ··· 462 struct p9_qid *wqids = 463 va_arg(ap, struct p9_qid *); 464 465 + errcode = p9pdu_writef(pdu, proto_version, "w", 466 + nwqid); 467 if (!errcode) { 468 int i; 469 470 for (i = 0; i < nwqid; i++) { 471 errcode = 472 + p9pdu_writef(pdu, 473 + proto_version, 474 "Q", 475 &wqids[i]); 476 if (errcode) ··· 479 } 480 break; 481 case '?': 482 + if (proto_version != p9_proto_2000u) 483 return 0; 484 break; 485 default: ··· 494 return errcode; 495 } 496 497 + int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) 498 { 499 va_list ap; 500 int ret; 501 502 va_start(ap, fmt); 503 + ret = p9pdu_vreadf(pdu, proto_version, fmt, ap); 504 va_end(ap); 505 506 return ret; 507 } 508 509 static int 510 + p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) 511 { 512 va_list ap; 513 int ret; 514 515 va_start(ap, fmt); 516 + ret = p9pdu_vwritef(pdu, proto_version, fmt, ap); 517 va_end(ap); 518 519 return ret; 520 } 521 522 + int p9stat_read(char *buf, int len, struct p9_wstat *st, int proto_version) 523 { 524 struct p9_fcall fake_pdu; 525 int ret; ··· 529 fake_pdu.sdata = buf; 530 fake_pdu.offset = 0; 531 532 + ret = p9pdu_readf(&fake_pdu, proto_version, "S", st); 533 if (ret) { 534 P9_DPRINTK(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); 535 p9pdu_dump(1, &fake_pdu);
+3 -3
net/9p/protocol.h
··· 25 * 26 */ 27 28 - int 29 - p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap); 30 - int p9pdu_readf(struct p9_fcall *pdu, int optional, const char *fmt, ...); 31 int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type); 32 int p9pdu_finalize(struct p9_fcall *pdu); 33 void p9pdu_dump(int, struct p9_fcall *);
··· 25 * 26 */ 27 28 + int p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, 29 + va_list ap); 30 + int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); 31 int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type); 32 int p9pdu_finalize(struct p9_fcall *pdu); 33 void p9pdu_dump(int, struct p9_fcall *);
+34 -46
net/9p/trans_virtio.c
··· 49 50 /* a single mutex to manage channel initialization and attachment */ 51 static DEFINE_MUTEX(virtio_9p_lock); 52 - /* global which tracks highest initialized channel */ 53 - static int chan_index; 54 55 /** 56 * struct virtio_chan - per-instance transport information ··· 66 * 67 */ 68 69 - static struct virtio_chan { 70 - bool initialized; 71 bool inuse; 72 73 spinlock_t lock; ··· 77 78 /* Scatterlist: can be too big for stack. */ 79 struct scatterlist sg[VIRTQUEUE_NUM]; 80 - } channels[MAX_9P_CHAN]; 81 82 /* How many bytes left in this page. */ 83 static unsigned int rest_of_page(void *data) ··· 218 * p9_virtio_probe - probe for existence of 9P virtio channels 219 * @vdev: virtio device to probe 220 * 221 - * This probes for existing virtio channels. At present only 222 - * a single channel is in use, so in the future more work may need 223 - * to be done here. 224 * 225 */ 226 ··· 226 { 227 int err; 228 struct virtio_chan *chan; 229 - int index; 230 231 - mutex_lock(&virtio_9p_lock); 232 - index = chan_index++; 233 - chan = &channels[index]; 234 - mutex_unlock(&virtio_9p_lock); 235 - 236 - if (chan_index > MAX_9P_CHAN) { 237 - printk(KERN_ERR "9p: virtio: Maximum channels exceeded\n"); 238 - BUG(); 239 err = -ENOMEM; 240 goto fail; 241 } ··· 248 sg_init_table(chan->sg, VIRTQUEUE_NUM); 249 250 chan->inuse = false; 251 - chan->initialized = true; 252 return 0; 253 254 out_free_vq: 255 vdev->config->del_vqs(vdev); 256 fail: 257 - mutex_lock(&virtio_9p_lock); 258 - chan_index--; 259 - mutex_unlock(&virtio_9p_lock); 260 return err; 261 } 262 ··· 273 * We use a simple reference count mechanism to ensure that only a single 274 * mount has a channel open at a time. 275 * 276 - * Bugs: doesn't allow identification of a specific channel 277 - * to allocate, channels are allocated sequentially. This was 278 - * a pragmatic decision to get things rolling, but ideally some 279 - * way of identifying the channel to attach to would be nice 280 - * if we are going to support multiple channels. 281 - * 282 */ 283 284 static int 285 p9_virtio_create(struct p9_client *client, const char *devname, char *args) 286 { 287 - struct virtio_chan *chan = channels; 288 - int index = 0; 289 290 mutex_lock(&virtio_9p_lock); 291 - while (index < MAX_9P_CHAN) { 292 - if (chan->initialized && !chan->inuse) { 293 - chan->inuse = true; 294 - break; 295 - } else { 296 - index++; 297 - chan = &channels[index]; 298 } 299 } 300 mutex_unlock(&virtio_9p_lock); 301 302 - if (index >= MAX_9P_CHAN) { 303 printk(KERN_ERR "9p: no channels available\n"); 304 - return -ENODEV; 305 } 306 307 client->trans = (void *)chan; ··· 318 struct virtio_chan *chan = vdev->priv; 319 320 BUG_ON(chan->inuse); 321 322 - if (chan->initialized) { 323 - vdev->config->del_vqs(vdev); 324 - chan->initialized = false; 325 - } 326 } 327 328 static struct virtio_device_id id_table[] = { ··· 355 /* The standard init function */ 356 static int __init p9_virtio_init(void) 357 { 358 - int count; 359 - 360 - for (count = 0; count < MAX_9P_CHAN; count++) 361 - channels[count].initialized = false; 362 363 v9fs_register_trans(&p9_virtio_trans); 364 return register_virtio_driver(&p9_virtio_drv);
··· 49 50 /* a single mutex to manage channel initialization and attachment */ 51 static DEFINE_MUTEX(virtio_9p_lock); 52 53 /** 54 * struct virtio_chan - per-instance transport information ··· 68 * 69 */ 70 71 + struct virtio_chan { 72 bool inuse; 73 74 spinlock_t lock; ··· 80 81 /* Scatterlist: can be too big for stack. */ 82 struct scatterlist sg[VIRTQUEUE_NUM]; 83 + 84 + struct list_head chan_list; 85 + }; 86 + 87 + static struct list_head virtio_chan_list; 88 89 /* How many bytes left in this page. */ 90 static unsigned int rest_of_page(void *data) ··· 217 * p9_virtio_probe - probe for existence of 9P virtio channels 218 * @vdev: virtio device to probe 219 * 220 + * This probes for existing virtio channels. 221 * 222 */ 223 ··· 227 { 228 int err; 229 struct virtio_chan *chan; 230 231 + chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL); 232 + if (!chan) { 233 + printk(KERN_ERR "9p: Failed to allocate virtio 9P channel\n"); 234 err = -ENOMEM; 235 goto fail; 236 } ··· 255 sg_init_table(chan->sg, VIRTQUEUE_NUM); 256 257 chan->inuse = false; 258 + mutex_lock(&virtio_9p_lock); 259 + list_add_tail(&chan->chan_list, &virtio_chan_list); 260 + mutex_unlock(&virtio_9p_lock); 261 return 0; 262 263 out_free_vq: 264 vdev->config->del_vqs(vdev); 265 + kfree(chan); 266 fail: 267 return err; 268 } 269 ··· 280 * We use a simple reference count mechanism to ensure that only a single 281 * mount has a channel open at a time. 282 * 283 */ 284 285 static int 286 p9_virtio_create(struct p9_client *client, const char *devname, char *args) 287 { 288 + struct virtio_chan *chan; 289 + int ret = -ENOENT; 290 + int found = 0; 291 292 mutex_lock(&virtio_9p_lock); 293 + list_for_each_entry(chan, &virtio_chan_list, chan_list) { 294 + if (!strcmp(devname, dev_name(&chan->vdev->dev))) { 295 + if (!chan->inuse) { 296 + chan->inuse = true; 297 + found = 1; 298 + break; 299 + } 300 + ret = -EBUSY; 301 } 302 } 303 mutex_unlock(&virtio_9p_lock); 304 305 + if (!found) { 306 printk(KERN_ERR "9p: no channels available\n"); 307 + return ret; 308 } 309 310 client->trans = (void *)chan; ··· 329 struct virtio_chan *chan = vdev->priv; 330 331 BUG_ON(chan->inuse); 332 + vdev->config->del_vqs(vdev); 333 334 + mutex_lock(&virtio_9p_lock); 335 + list_del(&chan->chan_list); 336 + mutex_unlock(&virtio_9p_lock); 337 + kfree(chan); 338 + 339 } 340 341 static struct virtio_device_id id_table[] = { ··· 364 /* The standard init function */ 365 static int __init p9_virtio_init(void) 366 { 367 + INIT_LIST_HEAD(&virtio_chan_list); 368 369 v9fs_register_trans(&p9_virtio_trans); 370 return register_virtio_driver(&p9_virtio_drv);