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