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

* 'for-linus' of ssh://master.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
9p: fix error path during early mount
9p: make cryptic unknown error from server less scary
9p: fix flags length in net
9p: Correct fidpool creation failure in p9_client_create
9p: use struct mutex instead of struct semaphore
9p: propagate parse_option changes to client and transports
fs/9p/v9fs.c (v9fs_parse_options): Handle kstrdup and match_strdup failure.
9p: Documentation updates
add match_strlcpy() us it to make v9fs make uname and remotename parsing more robust

+1012 -213
+15
fs/9p/fid.h
··· 22 22 23 23 #include <linux/list.h> 24 24 25 + /** 26 + * struct v9fs_dentry - 9p private data stored in dentry d_fsdata 27 + * @lock: protects the fidlist 28 + * @fidlist: list of FIDs currently associated with this dentry 29 + * 30 + * This structure defines the 9p private data associated with 31 + * a particular dentry. In particular, this private data is used 32 + * to lookup which 9P FID handle should be used for a particular VFS 33 + * operation. FID handles are associated with dentries instead of 34 + * inodes in order to more closely map functionality to the Plan 9 35 + * expected behavior for FID reclaimation and tracking. 36 + * 37 + * See Also: Mapping FIDs to Linux VFS model in 38 + * Design and Implementation of the Linux 9P File System documentation 39 + */ 25 40 struct v9fs_dentry { 26 41 spinlock_t lock; /* protect fidlist */ 27 42 struct list_head fidlist;
+44 -13
fs/9p/v9fs.c
··· 71 71 72 72 /** 73 73 * v9fs_parse_options - parse mount options into session structure 74 - * @options: options string passed from mount 75 74 * @v9ses: existing v9fs session information 76 75 * 76 + * Return 0 upon success, -ERRNO upon failure. 77 77 */ 78 78 79 - static void v9fs_parse_options(struct v9fs_session_info *v9ses) 79 + static int v9fs_parse_options(struct v9fs_session_info *v9ses) 80 80 { 81 81 char *options; 82 82 substring_t args[MAX_OPT_ARGS]; 83 83 char *p; 84 84 int option = 0; 85 85 char *s, *e; 86 - int ret; 86 + int ret = 0; 87 87 88 88 /* setup defaults */ 89 89 v9ses->afid = ~0; ··· 91 91 v9ses->cache = 0; 92 92 93 93 if (!v9ses->options) 94 - return; 94 + return 0; 95 95 96 96 options = kstrdup(v9ses->options, GFP_KERNEL); 97 + if (!options) { 98 + P9_DPRINTK(P9_DEBUG_ERROR, 99 + "failed to allocate copy of option string\n"); 100 + return -ENOMEM; 101 + } 102 + 97 103 while ((p = strsep(&options, ",")) != NULL) { 98 104 int token; 99 105 if (!*p) 100 106 continue; 101 107 token = match_token(p, tokens, args); 102 108 if (token < Opt_uname) { 103 - ret = match_int(&args[0], &option); 104 - if (ret < 0) { 109 + int r = match_int(&args[0], &option); 110 + if (r < 0) { 105 111 P9_DPRINTK(P9_DEBUG_ERROR, 106 112 "integer field, but no integer?\n"); 113 + ret = r; 107 114 continue; 108 115 } 109 116 } ··· 132 125 v9ses->afid = option; 133 126 break; 134 127 case Opt_uname: 135 - match_strcpy(v9ses->uname, &args[0]); 128 + match_strlcpy(v9ses->uname, &args[0], PATH_MAX); 136 129 break; 137 130 case Opt_remotename: 138 - match_strcpy(v9ses->aname, &args[0]); 131 + match_strlcpy(v9ses->aname, &args[0], PATH_MAX); 139 132 break; 140 133 case Opt_nodevmap: 141 134 v9ses->nodev = 1; ··· 146 139 147 140 case Opt_access: 148 141 s = match_strdup(&args[0]); 142 + if (!s) { 143 + P9_DPRINTK(P9_DEBUG_ERROR, 144 + "failed to allocate copy" 145 + " of option argument\n"); 146 + ret = -ENOMEM; 147 + break; 148 + } 149 149 v9ses->flags &= ~V9FS_ACCESS_MASK; 150 150 if (strcmp(s, "user") == 0) 151 151 v9ses->flags |= V9FS_ACCESS_USER; ··· 172 158 } 173 159 } 174 160 kfree(options); 161 + return ret; 175 162 } 176 163 177 164 /** ··· 188 173 { 189 174 int retval = -EINVAL; 190 175 struct p9_fid *fid; 176 + int rc; 191 177 192 178 v9ses->uname = __getname(); 193 179 if (!v9ses->uname) ··· 206 190 v9ses->uid = ~0; 207 191 v9ses->dfltuid = V9FS_DEFUID; 208 192 v9ses->dfltgid = V9FS_DEFGID; 209 - v9ses->options = kstrdup(data, GFP_KERNEL); 210 - v9fs_parse_options(v9ses); 193 + if (data) { 194 + v9ses->options = kstrdup(data, GFP_KERNEL); 195 + if (!v9ses->options) { 196 + P9_DPRINTK(P9_DEBUG_ERROR, 197 + "failed to allocate copy of option string\n"); 198 + retval = -ENOMEM; 199 + goto error; 200 + } 201 + } 202 + 203 + rc = v9fs_parse_options(v9ses); 204 + if (rc < 0) { 205 + retval = rc; 206 + goto error; 207 + } 211 208 212 209 v9ses->clnt = p9_client_create(dev_name, v9ses->options); 213 210 ··· 262 233 return fid; 263 234 264 235 error: 265 - v9fs_session_close(v9ses); 266 236 return ERR_PTR(retval); 267 237 } 268 238 ··· 284 256 } 285 257 286 258 /** 287 - * v9fs_session_cancel - mark transport as disconnected 288 - * and cancel all pending requests. 259 + * v9fs_session_cancel - terminate a session 260 + * @v9ses: session to terminate 261 + * 262 + * mark transport as disconnected and cancel all pending requests. 289 263 */ 264 + 290 265 void v9fs_session_cancel(struct v9fs_session_info *v9ses) { 291 266 P9_DPRINTK(P9_DEBUG_ERROR, "cancel session %p\n", v9ses); 292 267 p9_client_disconnect(v9ses->clnt);
+60 -25
fs/9p/v9fs.h
··· 21 21 * 22 22 */ 23 23 24 - /* 25 - * Session structure provides information for an opened session 26 - * 27 - */ 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 30 + * @V9FS_ACCESS_MASK: bit mask of different ACCESS options 31 + * 32 + * Session flags reflect options selected by users at mount time 33 + */ 34 + enum p9_session_flags { 35 + V9FS_EXTENDED = 0x01, 36 + V9FS_ACCESS_SINGLE = 0x02, 37 + V9FS_ACCESS_USER = 0x04, 38 + V9FS_ACCESS_ANY = 0x06, 39 + V9FS_ACCESS_MASK = 0x06, 40 + }; 41 + 42 + /* possible values of ->cache */ 43 + /** 44 + * enum p9_cache_modes - user specified cache preferences 45 + * @CACHE_NONE: do not cache data, dentries, or directory contents (default) 46 + * @CACHE_LOOSE: cache data, dentries, and directory contents w/no consistency 47 + * 48 + * eventually support loose, tight, time, session, default always none 49 + */ 50 + 51 + enum p9_cache_modes { 52 + CACHE_NONE, 53 + CACHE_LOOSE, 54 + }; 55 + 56 + /** 57 + * struct v9fs_session_info - per-instance session information 58 + * @flags: session options of type &p9_session_flags 59 + * @nodev: set to 1 to disable device mapping 60 + * @debug: debug level 61 + * @afid: authentication handle 62 + * @cache: cache mode of type &p9_cache_modes 63 + * @options: copy of options string given by user 64 + * @uname: string user name to mount hierarchy as 65 + * @aname: mount specifier for remote hierarchy 66 + * @maxdata: maximum data to be sent/recvd per protocol message 67 + * @dfltuid: default numeric userid to mount hierarchy as 68 + * @dfltgid: default numeric groupid to mount hierarchy as 69 + * @uid: if %V9FS_ACCESS_SINGLE, the numeric uid which mounted the hierarchy 70 + * @clnt: reference to 9P network client instantiated for this session 71 + * @debugfs_dir: reference to debugfs_dir which can be used for add'l debug 72 + * 73 + * This structure holds state for each session instance established during 74 + * a sys_mount() . 75 + * 76 + * Bugs: there seems to be a lot of state which could be condensed and/or 77 + * removed. 78 + */ 28 79 29 80 struct v9fs_session_info { 30 81 /* options */ 31 - unsigned char flags; /* session flags */ 32 - unsigned char nodev; /* set to 1 if no disable device mapping */ 33 - unsigned short debug; /* debug level */ 34 - unsigned int afid; /* authentication fid */ 35 - unsigned int cache; /* cache mode */ 82 + unsigned char flags; 83 + unsigned char nodev; 84 + unsigned short debug; 85 + unsigned int afid; 86 + unsigned int cache; 36 87 37 88 char *options; /* copy of mount options */ 38 89 char *uname; /* user name to mount as */ ··· 94 43 u32 uid; /* if ACCESS_SINGLE, the uid that has access */ 95 44 struct p9_client *clnt; /* 9p client */ 96 45 struct dentry *debugfs_dir; 97 - }; 98 - 99 - /* session flags */ 100 - enum { 101 - V9FS_EXTENDED = 0x01, /* 9P2000.u */ 102 - V9FS_ACCESS_MASK = 0x06, /* access mask */ 103 - V9FS_ACCESS_SINGLE = 0x02, /* only one user can access the files */ 104 - V9FS_ACCESS_USER = 0x04, /* attache per user */ 105 - V9FS_ACCESS_ANY = 0x06, /* use the same attach for all users */ 106 - }; 107 - 108 - /* possible values of ->cache */ 109 - /* eventually support loose, tight, time, session, default always none */ 110 - enum { 111 - CACHE_NONE, /* default */ 112 - CACHE_LOOSE, /* no consistency */ 113 46 }; 114 47 115 48 extern struct dentry *v9fs_debugfs_root;
+1 -1
fs/9p/vfs_addr.c
··· 43 43 /** 44 44 * v9fs_vfs_readpage - read an entire page in from 9P 45 45 * 46 - * @file: file being read 46 + * @filp: file being read 47 47 * @page: structure to page 48 48 * 49 49 */
+1 -1
fs/9p/vfs_dir.c
··· 60 60 61 61 /** 62 62 * v9fs_dir_readdir - read a directory 63 - * @filep: opened file structure 63 + * @filp: opened file structure 64 64 * @dirent: directory structure ??? 65 65 * @filldir: function to populate directory structure ??? 66 66 *
+6 -5
fs/9p/vfs_file.c
··· 90 90 91 91 /** 92 92 * v9fs_file_lock - lock a file (or directory) 93 - * @inode: inode to be opened 94 - * @file: file being opened 93 + * @filp: file to be locked 94 + * @cmd: lock command 95 + * @fl: file lock structure 95 96 * 96 - * XXX - this looks like a local only lock, we should extend into 9P 97 + * Bugs: this looks like a local only lock, we should extend into 9P 97 98 * by using open exclusive 98 99 */ 99 100 ··· 119 118 120 119 /** 121 120 * v9fs_file_read - read from a file 122 - * @filep: file pointer to read 121 + * @filp: file pointer to read 123 122 * @data: data buffer to read data into 124 123 * @count: size of buffer 125 124 * @offset: offset at which to read data ··· 143 142 144 143 /** 145 144 * v9fs_file_write - write to a file 146 - * @filep: file pointer to write 145 + * @filp: file pointer to write 147 146 * @data: data buffer to write data from 148 147 * @count: size of buffer 149 148 * @offset: offset at which to write data
+37 -13
fs/9p/vfs_inode.c
··· 129 129 return res; 130 130 } 131 131 132 + /** 133 + * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits 134 + * @uflags: flags to convert 135 + * 136 + */ 137 + 132 138 int v9fs_uflags2omode(int uflags) 133 139 { 134 140 int ret; ··· 318 312 } 319 313 */ 320 314 315 + /** 316 + * v9fs_inode_from_fid - populate an inode by issuing a attribute request 317 + * @v9ses: session information 318 + * @fid: fid to issue attribute request for 319 + * @sb: superblock on which to create inode 320 + * 321 + */ 322 + 321 323 static struct inode * 322 324 v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, 323 325 struct super_block *sb) ··· 398 384 399 385 /** 400 386 * v9fs_create - Create a file 387 + * @v9ses: session information 388 + * @dir: directory that dentry is being created in 401 389 * @dentry: dentry that is being created 402 390 * @perm: create permissions 403 391 * @mode: open mode 392 + * @extension: 9p2000.u extension string to support devices, etc. 404 393 * 405 394 */ 406 395 static struct p9_fid * ··· 478 461 479 462 /** 480 463 * v9fs_vfs_create - VFS hook to create files 481 - * @inode: directory inode that is being created 464 + * @dir: directory inode that is being created 482 465 * @dentry: dentry that is being deleted 483 466 * @mode: create permissions 484 467 * @nd: path information ··· 536 519 537 520 /** 538 521 * v9fs_vfs_mkdir - VFS mkdir hook to create a directory 539 - * @inode: inode that is being unlinked 522 + * @dir: inode that is being unlinked 540 523 * @dentry: dentry that is being unlinked 541 524 * @mode: mode for new directory 542 525 * ··· 720 703 721 704 /** 722 705 * v9fs_vfs_getattr - retrieve file metadata 723 - * @mnt - mount information 724 - * @dentry - file to get attributes on 725 - * @stat - metadata structure to populate 706 + * @mnt: mount information 707 + * @dentry: file to get attributes on 708 + * @stat: metadata structure to populate 726 709 * 727 710 */ 728 711 ··· 945 928 /** 946 929 * v9fs_vfs_readlink - read a symlink's location 947 930 * @dentry: dentry for symlink 948 - * @buf: buffer to load symlink location into 931 + * @buffer: buffer to load symlink location into 949 932 * @buflen: length of buffer 950 933 * 951 934 */ ··· 1013 996 * v9fs_vfs_put_link - release a symlink path 1014 997 * @dentry: dentry for symlink 1015 998 * @nd: nameidata 999 + * @p: unused 1016 1000 * 1017 1001 */ 1018 1002 1019 - static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) 1003 + static void 1004 + v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) 1020 1005 { 1021 1006 char *s = nd_get_link(nd); 1022 1007 ··· 1026 1007 if (!IS_ERR(s)) 1027 1008 __putname(s); 1028 1009 } 1010 + 1011 + /** 1012 + * v9fs_vfs_mkspecial - create a special file 1013 + * @dir: inode to create special file in 1014 + * @dentry: dentry to create 1015 + * @mode: mode to create special file 1016 + * @extension: 9p2000.u format extension string representing special file 1017 + * 1018 + */ 1029 1019 1030 1020 static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, 1031 1021 int mode, const char *extension) ··· 1065 1037 * @dentry: dentry for symlink 1066 1038 * @symname: symlink data 1067 1039 * 1068 - * See 9P2000.u RFC for more information 1040 + * See Also: 9P2000.u RFC for more information 1069 1041 * 1070 1042 */ 1071 1043 ··· 1084 1056 * @dir: inode destination for new link 1085 1057 * @dentry: dentry for link 1086 1058 * 1087 - */ 1088 - 1089 - /* XXX - lots of code dup'd from symlink and creates, 1090 - * figure out a better reuse strategy 1091 1059 */ 1092 1060 1093 1061 static int ··· 1122 1098 * @dir: inode destination for new link 1123 1099 * @dentry: dentry for file 1124 1100 * @mode: mode for creation 1125 - * @dev_t: device associated with special file 1101 + * @rdev: device associated with special file 1126 1102 * 1127 1103 */ 1128 1104
+17 -18
fs/9p/vfs_super.c
··· 75 75 * v9fs_fill_super - populate superblock with info 76 76 * @sb: superblock 77 77 * @v9ses: session information 78 + * @flags: flags propagated from v9fs_get_sb() 78 79 * 79 80 */ 80 81 ··· 128 127 fid = v9fs_session_init(v9ses, dev_name, data); 129 128 if (IS_ERR(fid)) { 130 129 retval = PTR_ERR(fid); 131 - fid = NULL; 132 - kfree(v9ses); 133 - v9ses = NULL; 134 - goto error; 130 + goto close_session; 135 131 } 136 132 137 133 st = p9_client_stat(fid); 138 134 if (IS_ERR(st)) { 139 135 retval = PTR_ERR(st); 140 - goto error; 136 + goto clunk_fid; 141 137 } 142 138 143 139 sb = sget(fs_type, NULL, v9fs_set_super, v9ses); 144 140 if (IS_ERR(sb)) { 145 141 retval = PTR_ERR(sb); 146 - goto error; 142 + goto free_stat; 147 143 } 148 144 v9fs_fill_super(sb, v9ses, flags); 149 145 150 146 inode = v9fs_get_inode(sb, S_IFDIR | mode); 151 147 if (IS_ERR(inode)) { 152 148 retval = PTR_ERR(inode); 153 - goto error; 149 + goto release_sb; 154 150 } 155 151 156 152 inode->i_uid = uid; ··· 156 158 root = d_alloc_root(inode); 157 159 if (!root) { 158 160 retval = -ENOMEM; 159 - goto error; 161 + goto release_sb; 160 162 } 161 163 162 164 sb->s_root = root; ··· 167 169 168 170 return simple_set_mnt(mnt, sb); 169 171 170 - error: 171 - kfree(st); 172 - if (fid) 173 - p9_client_clunk(fid); 174 - 175 - if (v9ses) { 176 - v9fs_session_close(v9ses); 177 - kfree(v9ses); 178 - } 179 - 172 + release_sb: 180 173 if (sb) { 181 174 up_write(&sb->s_umount); 182 175 deactivate_super(sb); 183 176 } 177 + 178 + free_stat: 179 + kfree(st); 180 + 181 + clunk_fid: 182 + p9_client_clunk(fid); 183 + 184 + close_session: 185 + v9fs_session_close(v9ses); 186 + kfree(v9ses); 184 187 185 188 return retval; 186 189 }
+1 -1
include/linux/parser.h
··· 29 29 int match_int(substring_t *, int *result); 30 30 int match_octal(substring_t *, int *result); 31 31 int match_hex(substring_t *, int *result); 32 - void match_strcpy(char *, const substring_t *); 32 + size_t match_strlcpy(char *, const substring_t *, size_t); 33 33 char *match_strdup(const substring_t *);
+208 -28
include/net/9p/9p.h
··· 29 29 30 30 #ifdef CONFIG_NET_9P_DEBUG 31 31 32 - #define P9_DEBUG_ERROR (1<<0) 33 - #define P9_DEBUG_9P (1<<2) 34 - #define P9_DEBUG_VFS (1<<3) 35 - #define P9_DEBUG_CONV (1<<4) 36 - #define P9_DEBUG_MUX (1<<5) 37 - #define P9_DEBUG_TRANS (1<<6) 38 - #define P9_DEBUG_SLABS (1<<7) 39 - #define P9_DEBUG_FCALL (1<<8) 32 + /** 33 + * enum p9_debug_flags - bits for mount time debug parameter 34 + * @P9_DEBUG_ERROR: more verbose error messages including original error string 35 + * @P9_DEBUG_9P: 9P protocol tracing 36 + * @P9_DEBUG_VFS: VFS API tracing 37 + * @P9_DEBUG_CONV: protocol conversion tracing 38 + * @P9_DEBUG_MUX: trace management of concurrent transactions 39 + * @P9_DEBUG_TRANS: transport tracing 40 + * @P9_DEBUG_SLABS: memory management tracing 41 + * @P9_DEBUG_FCALL: verbose dump of protocol messages 42 + * 43 + * These flags are passed at mount time to turn on various levels of 44 + * verbosity and tracing which will be output to the system logs. 45 + */ 46 + 47 + enum p9_debug_flags { 48 + P9_DEBUG_ERROR = (1<<0), 49 + P9_DEBUG_9P = (1<<2), 50 + P9_DEBUG_VFS = (1<<3), 51 + P9_DEBUG_CONV = (1<<4), 52 + P9_DEBUG_MUX = (1<<5), 53 + P9_DEBUG_TRANS = (1<<6), 54 + P9_DEBUG_SLABS = (1<<7), 55 + P9_DEBUG_FCALL = (1<<8), 56 + }; 40 57 41 58 extern unsigned int p9_debug_level; 42 59 ··· 79 62 format , __FUNCTION__, task_pid_nr(current), ## arg); \ 80 63 } while (0) 81 64 65 + /** 66 + * enum p9_msg_t - 9P message types 67 + * @P9_TVERSION: version handshake request 68 + * @P9_RVERSION: version handshake response 69 + * @P9_TAUTH: request to establish authentication channel 70 + * @P9_RAUTH: response with authentication information 71 + * @P9_TATTACH: establish user access to file service 72 + * @P9_RATTACH: response with top level handle to file hierarchy 73 + * @P9_TERROR: not used 74 + * @P9_RERROR: response for any failed request 75 + * @P9_TFLUSH: request to abort a previous request 76 + * @P9_RFLUSH: response when previous request has been cancelled 77 + * @P9_TWALK: descend a directory hierarchy 78 + * @P9_RWALK: response with new handle for position within hierarchy 79 + * @P9_TOPEN: prepare a handle for I/O on an existing file 80 + * @P9_ROPEN: response with file access information 81 + * @P9_TCREATE: prepare a handle for I/O on a new file 82 + * @P9_RCREATE: response with file access information 83 + * @P9_TREAD: request to transfer data from a file or directory 84 + * @P9_RREAD: response with data requested 85 + * @P9_TWRITE: reuqest to transfer data to a file 86 + * @P9_RWRITE: response with out much data was transfered to file 87 + * @P9_TCLUNK: forget about a handle to an entity within the file system 88 + * @P9_RCLUNK: response when server has forgotten about the handle 89 + * @P9_TREMOVE: request to remove an entity from the hierarchy 90 + * @P9_RREMOVE: response when server has removed the entity 91 + * @P9_TSTAT: request file entity attributes 92 + * @P9_RSTAT: response with file entity attributes 93 + * @P9_TWSTAT: request to update file entity attributes 94 + * @P9_RWSTAT: response when file entity attributes are updated 95 + * 96 + * There are 14 basic operations in 9P2000, paired as 97 + * requests and responses. The one special case is ERROR 98 + * as there is no @P9_TERROR request for clients to transmit to 99 + * the server, but the server may respond to any other request 100 + * with an @P9_RERROR. 101 + * 102 + * See Also: http://plan9.bell-labs.com/sys/man/5/INDEX.html 103 + */ 82 104 83 - /* Message Types */ 84 - enum { 105 + enum p9_msg_t { 85 106 P9_TVERSION = 100, 86 107 P9_RVERSION, 87 108 P9_TAUTH = 102, ··· 150 95 P9_RWSTAT, 151 96 }; 152 97 153 - /* open modes */ 154 - enum { 98 + /** 99 + * enum p9_open_mode_t - 9P open modes 100 + * @P9_OREAD: open file for reading only 101 + * @P9_OWRITE: open file for writing only 102 + * @P9_ORDWR: open file for reading or writing 103 + * @P9_OEXEC: open file for execution 104 + * @P9_OTRUNC: truncate file to zero-length before opening it 105 + * @P9_OREXEC: close the file when an exec(2) system call is made 106 + * @P9_ORCLOSE: remove the file when the file is closed 107 + * @P9_OAPPEND: open the file and seek to the end 108 + * @P9_OEXCL: only create a file, do not open it 109 + * 110 + * 9P open modes differ slightly from Posix standard modes. 111 + * In particular, there are extra modes which specify different 112 + * semantic behaviors than may be available on standard Posix 113 + * systems. For example, @P9_OREXEC and @P9_ORCLOSE are modes that 114 + * most likely will not be issued from the Linux VFS client, but may 115 + * be supported by servers. 116 + * 117 + * See Also: http://plan9.bell-labs.com/magic/man2html/2/open 118 + */ 119 + 120 + enum p9_open_mode_t { 155 121 P9_OREAD = 0x00, 156 122 P9_OWRITE = 0x01, 157 123 P9_ORDWR = 0x02, 158 124 P9_OEXEC = 0x03, 159 - P9_OEXCL = 0x04, 160 125 P9_OTRUNC = 0x10, 161 126 P9_OREXEC = 0x20, 162 127 P9_ORCLOSE = 0x40, 163 128 P9_OAPPEND = 0x80, 129 + P9_OEXCL = 0x1000, 164 130 }; 165 131 166 - /* permissions */ 167 - enum { 132 + /** 133 + * enum p9_perm_t - 9P permissions 134 + * @P9_DMDIR: mode bite for directories 135 + * @P9_DMAPPEND: mode bit for is append-only 136 + * @P9_DMEXCL: mode bit for excluse use (only one open handle allowed) 137 + * @P9_DMMOUNT: mode bite for mount points 138 + * @P9_DMAUTH: mode bit for authentication file 139 + * @P9_DMTMP: mode bit for non-backed-up files 140 + * @P9_DMSYMLINK: mode bit for symbolic links (9P2000.u) 141 + * @P9_DMLINK: mode bit for hard-link (9P2000.u) 142 + * @P9_DMDEVICE: mode bit for device files (9P2000.u) 143 + * @P9_DMNAMEDPIPE: mode bit for named pipe (9P2000.u) 144 + * @P9_DMSOCKET: mode bit for socket (9P2000.u) 145 + * @P9_DMSETUID: mode bit for setuid (9P2000.u) 146 + * @P9_DMSETGID: mode bit for setgid (9P2000.u) 147 + * @P9_DMSETVTX: mode bit for sticky bit (9P2000.u) 148 + * 149 + * 9P permissions differ slightly from Posix standard modes. 150 + * 151 + * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat 152 + */ 153 + enum p9_perm_t { 168 154 P9_DMDIR = 0x80000000, 169 155 P9_DMAPPEND = 0x40000000, 170 156 P9_DMEXCL = 0x20000000, 171 157 P9_DMMOUNT = 0x10000000, 172 158 P9_DMAUTH = 0x08000000, 173 159 P9_DMTMP = 0x04000000, 160 + /* 9P2000.u extensions */ 174 161 P9_DMSYMLINK = 0x02000000, 175 162 P9_DMLINK = 0x01000000, 176 - /* 9P2000.u extensions */ 177 163 P9_DMDEVICE = 0x00800000, 178 164 P9_DMNAMEDPIPE = 0x00200000, 179 165 P9_DMSOCKET = 0x00100000, ··· 223 127 P9_DMSETVTX = 0x00010000, 224 128 }; 225 129 226 - /* qid.types */ 227 - enum { 130 + /** 131 + * enum p9_qid_t - QID types 132 + * @P9_QTDIR: directory 133 + * @P9_QTAPPEND: append-only 134 + * @P9_QTEXCL: excluse use (only one open handle allowed) 135 + * @P9_QTMOUNT: mount points 136 + * @P9_QTAUTH: authentication file 137 + * @P9_QTTMP: non-backed-up files 138 + * @P9_QTSYMLINK: symbolic links (9P2000.u) 139 + * @P9_QTLINK: hard-link (9P2000.u) 140 + * @P9_QTFILE: normal files 141 + * 142 + * QID types are a subset of permissions - they are primarily 143 + * used to differentiate semantics for a file system entity via 144 + * a jump-table. Their value is also the most signifigant 16 bits 145 + * of the permission_t 146 + * 147 + * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat 148 + */ 149 + enum p9_qid_t { 228 150 P9_QTDIR = 0x80, 229 151 P9_QTAPPEND = 0x40, 230 152 P9_QTEXCL = 0x20, ··· 254 140 P9_QTFILE = 0x00, 255 141 }; 256 142 143 + /* 9P Magic Numbers */ 257 144 #define P9_NOTAG (u16)(~0) 258 145 #define P9_NOFID (u32)(~0) 259 146 #define P9_MAXWELEM 16 ··· 262 147 /* ample room for Twrite/Rread header */ 263 148 #define P9_IOHDRSZ 24 264 149 150 + /** 151 + * struct p9_str - length prefixed string type 152 + * @len: length of the string 153 + * @str: the string 154 + * 155 + * The protocol uses length prefixed strings for all 156 + * string data, so we replicate that for our internal 157 + * string members. 158 + */ 159 + 265 160 struct p9_str { 266 161 u16 len; 267 162 char *str; 268 163 }; 269 164 270 - /* qids are the unique ID for a file (like an inode */ 165 + /** 166 + * struct p9_qid - file system entity information 167 + * @type: 8-bit type &p9_qid_t 168 + * @version: 16-bit monotonically incrementing version number 169 + * @path: 64-bit per-server-unique ID for a file system element 170 + * 171 + * qids are identifiers used by 9P servers to track file system 172 + * entities. The type is used to differentiate semantics for operations 173 + * on the entity (ie. read means something different on a directory than 174 + * on a file). The path provides a server unique index for an entity 175 + * (roughly analogous to an inode number), while the version is updated 176 + * every time a file is modified and can be used to maintain cache 177 + * coherency between clients and serves. 178 + * Servers will often differentiate purely synthetic entities by setting 179 + * their version to 0, signaling that they should never be cached and 180 + * should be accessed synchronously. 181 + * 182 + * See Also://plan9.bell-labs.com/magic/man2html/2/stat 183 + */ 184 + 271 185 struct p9_qid { 272 186 u8 type; 273 187 u32 version; 274 188 u64 path; 275 189 }; 276 190 277 - /* Plan 9 file metadata (stat) structure */ 191 + /** 192 + * struct p9_stat - file system metadata information 193 + * @size: length prefix for this stat structure instance 194 + * @type: the type of the server (equivilent to a major number) 195 + * @dev: the sub-type of the server (equivilent to a minor number) 196 + * @qid: unique id from the server of type &p9_qid 197 + * @mode: Plan 9 format permissions of type &p9_perm_t 198 + * @atime: Last access/read time 199 + * @mtime: Last modify/write time 200 + * @length: file length 201 + * @name: last element of path (aka filename) in type &p9_str 202 + * @uid: owner name in type &p9_str 203 + * @gid: group owner in type &p9_str 204 + * @muid: last modifier in type &p9_str 205 + * @extension: area used to encode extended UNIX support in type &p9_str 206 + * @n_uid: numeric user id of owner (part of 9p2000.u extension) 207 + * @n_gid: numeric group id (part of 9p2000.u extension) 208 + * @n_muid: numeric user id of laster modifier (part of 9p2000.u extension) 209 + * 210 + * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat 211 + */ 212 + 278 213 struct p9_stat { 279 214 u16 size; 280 215 u16 type; ··· 344 179 u32 n_muid; /* 9p2000.u extensions */ 345 180 }; 346 181 347 - /* file metadata (stat) structure used to create Twstat message 348 - The is similar to p9_stat, but the strings don't point to 349 - the same memory block and should be freed separately 350 - */ 182 + /* 183 + * file metadata (stat) structure used to create Twstat message 184 + * The is identical to &p9_stat, but the strings don't point to 185 + * the same memory block and should be freed separately 186 + * 187 + * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat 188 + */ 189 + 351 190 struct p9_wstat { 352 191 u16 size; 353 192 u16 type; ··· 504 335 struct p9_rwstat { 505 336 }; 506 337 507 - /* 508 - * fcall is the primary packet structure 509 - * 510 - */ 338 + /** 339 + * struct p9_fcall - primary packet structure 340 + * @size: prefixed length of the structure 341 + * @id: protocol operating identifier of type &p9_msg_t 342 + * @tag: transaction id of the request 343 + * @sdata: payload 344 + * @params: per-operation parameters 345 + * 346 + * &p9_fcall represents the structure for all 9P RPC 347 + * transactions. Requests are packaged into fcalls, and reponses 348 + * must be extracted from them. 349 + * 350 + * See Also: http://plan9.bell-labs.com/magic/man2html/2/fcall 351 + */ 511 352 512 353 struct p9_fcall { 513 354 u32 size; ··· 595 416 596 417 int p9_error_init(void); 597 418 int p9_errstr2errno(char *, int); 419 + int p9_trans_fd_init(void); 598 420 #endif /* NET_9P_H */
+35
include/net/9p/client.h
··· 26 26 #ifndef NET_9P_CLIENT_H 27 27 #define NET_9P_CLIENT_H 28 28 29 + /** 30 + * struct p9_client - per client instance state 31 + * @lock: protect @fidlist 32 + * @msize: maximum data size negotiated by protocol 33 + * @dotu: extension flags negotiated by protocol 34 + * @trans_mod: module API instantiated with this client 35 + * @trans: tranport instance state and API 36 + * @conn: connection state information used by trans_fd 37 + * @fidpool: fid handle accounting for session 38 + * @fidlist: List of active fid handles 39 + * 40 + * The client structure is used to keep track of various per-client 41 + * state that has been instantiated. 42 + * 43 + * Bugs: duplicated data and potentially unnecessary elements. 44 + */ 45 + 29 46 struct p9_client { 30 47 spinlock_t lock; /* protect client structure */ 31 48 int msize; ··· 54 37 struct p9_idpool *fidpool; 55 38 struct list_head fidlist; 56 39 }; 40 + 41 + /** 42 + * struct p9_fid - file system entity handle 43 + * @clnt: back pointer to instantiating &p9_client 44 + * @fid: numeric identifier for this handle 45 + * @mode: current mode of this fid (enum?) 46 + * @qid: the &p9_qid server identifier this handle points to 47 + * @iounit: the server reported maximum transaction size for this file 48 + * @uid: the numeric uid of the local user who owns this handle 49 + * @aux: transport specific information (unused?) 50 + * @rdir_fpos: tracks offset of file position when reading directory contents 51 + * @rdir_pos: (unused?) 52 + * @rdir_fcall: holds response of last directory read request 53 + * @flist: per-client-instance fid tracking 54 + * @dlist: per-dentry fid tracking 55 + * 56 + * TODO: This needs lots of explanation. 57 + */ 57 58 58 59 struct p9_fid { 59 60 struct p9_client *clnt;
+43 -1
include/net/9p/transport.h
··· 26 26 #ifndef NET_9P_TRANSPORT_H 27 27 #define NET_9P_TRANSPORT_H 28 28 29 + /** 30 + * enum p9_trans_status - different states of underlying transports 31 + * @Connected: transport is connected and healthy 32 + * @Disconnected: transport has been disconnected 33 + * @Hung: transport is connected by wedged 34 + * 35 + * This enumeration details the various states a transport 36 + * instatiation can be in. 37 + */ 38 + 29 39 enum p9_trans_status { 30 40 Connected, 31 41 Disconnected, 32 42 Hung, 33 43 }; 44 + 45 + /** 46 + * struct p9_trans - per-transport state and API 47 + * @status: transport &p9_trans_status 48 + * @msize: negotiated maximum packet size (duplicate from client) 49 + * @extended: negotiated protocol extensions (duplicate from client) 50 + * @priv: transport private data 51 + * @close: member function to disconnect and close the transport 52 + * @rpc: member function to issue a request to the transport 53 + * 54 + * This is the basic API for a transport instance. It is used as 55 + * a handle by the client to issue requests. This interface is currently 56 + * in flux during reorganization. 57 + * 58 + * Bugs: there is lots of duplicated data here and its not clear that 59 + * the member functions need to be per-instance versus per transport 60 + * module. 61 + */ 34 62 35 63 struct p9_trans { 36 64 enum p9_trans_status status; ··· 69 41 int (*rpc) (struct p9_trans *t, struct p9_fcall *tc, 70 42 struct p9_fcall **rc); 71 43 }; 44 + 45 + /** 46 + * struct p9_trans_module - transport module interface 47 + * @list: used to maintain a list of currently available transports 48 + * @name: the human-readable name of the transport 49 + * @maxsize: transport provided maximum packet size 50 + * @def: set if this transport should be considered the default 51 + * @create: member function to create a new connection on this transport 52 + * 53 + * This is the basic API for a transport module which is registered by the 54 + * transport module with the 9P core network module and used by the client 55 + * to instantiate a new connection on a transport. 56 + * 57 + * Bugs: the transport module list isn't protected. 58 + */ 72 59 73 60 struct p9_trans_module { 74 61 struct list_head list; ··· 96 53 void v9fs_register_trans(struct p9_trans_module *m); 97 54 struct p9_trans_module *v9fs_match_trans(const substring_t *name); 98 55 struct p9_trans_module *v9fs_default_trans(void); 99 - 100 56 #endif /* NET_9P_TRANSPORT_H */
+20 -12
lib/parser.c
··· 182 182 } 183 183 184 184 /** 185 - * match_strcpy: - copies the characters from a substring_t to a string 186 - * @to: string to copy characters to. 187 - * @s: &substring_t to copy 185 + * match_strlcpy: - Copy the characters from a substring_t to a sized buffer 186 + * @dest: where to copy to 187 + * @src: &substring_t to copy 188 + * @size: size of destination buffer 188 189 * 189 - * Description: Copies the set of characters represented by the given 190 - * &substring_t @s to the c-style string @to. Caller guarantees that @to is 191 - * large enough to hold the characters of @s. 190 + * Description: Copy the characters in &substring_t @src to the 191 + * c-style string @dest. Copy no more than @size - 1 characters, plus 192 + * the terminating NUL. Return length of @src. 192 193 */ 193 - void match_strcpy(char *to, const substring_t *s) 194 + size_t match_strlcpy(char *dest, const substring_t *src, size_t size) 194 195 { 195 - memcpy(to, s->from, s->to - s->from); 196 - to[s->to - s->from] = '\0'; 196 + size_t ret = src->to - src->from; 197 + 198 + if (size) { 199 + size_t len = ret >= size ? size - 1 : ret; 200 + memcpy(dest, src->from, len); 201 + dest[len] = '\0'; 202 + } 203 + return ret; 197 204 } 198 205 199 206 /** ··· 213 206 */ 214 207 char *match_strdup(const substring_t *s) 215 208 { 216 - char *p = kmalloc(s->to - s->from + 1, GFP_KERNEL); 209 + size_t sz = s->to - s->from + 1; 210 + char *p = kmalloc(sz, GFP_KERNEL); 217 211 if (p) 218 - match_strcpy(p, s); 212 + match_strlcpy(p, s, sz); 219 213 return p; 220 214 } 221 215 ··· 224 216 EXPORT_SYMBOL(match_int); 225 217 EXPORT_SYMBOL(match_octal); 226 218 EXPORT_SYMBOL(match_hex); 227 - EXPORT_SYMBOL(match_strcpy); 219 + EXPORT_SYMBOL(match_strlcpy); 228 220 EXPORT_SYMBOL(match_strdup);
-10
net/9p/Kconfig
··· 13 13 14 14 If unsure, say N. 15 15 16 - config NET_9P_FD 17 - depends on NET_9P 18 - default y if NET_9P 19 - tristate "9P File Descriptor Transports (Experimental)" 20 - help 21 - This builds support for file descriptor transports for 9p 22 - which includes support for TCP/IP, named pipes, or passed 23 - file descriptors. TCP/IP is the default transport for 9p, 24 - so if you are going to use 9p, you'll likely want this. 25 - 26 16 config NET_9P_VIRTIO 27 17 depends on NET_9P && EXPERIMENTAL && VIRTIO 28 18 tristate "9P Virtio Transport (Experimental)"
-3
net/9p/Makefile
··· 1 1 obj-$(CONFIG_NET_9P) := 9pnet.o 2 - obj-$(CONFIG_NET_9P_FD) += 9pnet_fd.o 3 2 obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o 4 3 5 4 9pnet-objs := \ ··· 8 9 error.o \ 9 10 fcprint.o \ 10 11 util.o \ 11 - 12 - 9pnet_fd-objs := \ 13 12 trans_fd.o \ 14 13 15 14 9pnet_virtio-objs := \
+24 -8
net/9p/client.c
··· 64 64 * @options: options string passed from mount 65 65 * @v9ses: existing v9fs session information 66 66 * 67 + * Return 0 upon success, -ERRNO upon failure 67 68 */ 68 69 69 - static void parse_opts(char *options, struct p9_client *clnt) 70 + static int parse_opts(char *opts, struct p9_client *clnt) 70 71 { 72 + char *options; 71 73 char *p; 72 74 substring_t args[MAX_OPT_ARGS]; 73 75 int option; 74 - int ret; 76 + int ret = 0; 75 77 76 78 clnt->trans_mod = v9fs_default_trans(); 77 79 clnt->dotu = 1; 78 80 clnt->msize = 8192; 79 81 80 - if (!options) 81 - return; 82 + if (!opts) 83 + return 0; 84 + 85 + options = kstrdup(opts, GFP_KERNEL); 86 + if (!options) { 87 + P9_DPRINTK(P9_DEBUG_ERROR, 88 + "failed to allocate copy of option string\n"); 89 + return -ENOMEM; 90 + } 82 91 83 92 while ((p = strsep(&options, ",")) != NULL) { 84 93 int token; ··· 95 86 continue; 96 87 token = match_token(p, tokens, args); 97 88 if (token < Opt_trans) { 98 - ret = match_int(&args[0], &option); 99 - if (ret < 0) { 89 + int r = match_int(&args[0], &option); 90 + if (r < 0) { 100 91 P9_DPRINTK(P9_DEBUG_ERROR, 101 92 "integer field, but no integer?\n"); 93 + ret = r; 102 94 continue; 103 95 } 104 96 } ··· 117 107 continue; 118 108 } 119 109 } 110 + kfree(options); 111 + return ret; 120 112 } 121 113 122 114 ··· 150 138 if (!clnt) 151 139 return ERR_PTR(-ENOMEM); 152 140 141 + clnt->trans = NULL; 153 142 spin_lock_init(&clnt->lock); 154 143 INIT_LIST_HEAD(&clnt->fidlist); 155 144 clnt->fidpool = p9_idpool_create(); 156 - if (!clnt->fidpool) { 145 + if (IS_ERR(clnt->fidpool)) { 157 146 err = PTR_ERR(clnt->fidpool); 158 147 clnt->fidpool = NULL; 159 148 goto error; 160 149 } 161 150 162 - parse_opts(options, clnt); 151 + err = parse_opts(options, clnt); 152 + if (err < 0) 153 + goto error; 154 + 163 155 if (clnt->trans_mod == NULL) { 164 156 err = -EPROTONOSUPPORT; 165 157 P9_DPRINTK(P9_DEBUG_ERROR,
+127 -1
net/9p/conv.c
··· 197 197 198 198 /** 199 199 * p9_size_wstat - calculate the size of a variable length stat struct 200 - * @stat: metadata (stat) structure 200 + * @wstat: metadata (stat) structure 201 201 * @dotu: non-zero if 9P2000.u 202 202 * 203 203 */ ··· 511 511 return fc; 512 512 } 513 513 514 + /** 515 + * p9_set_tag - set the tag field of an &p9_fcall structure 516 + * @fc: fcall structure to set tag within 517 + * @tag: tag id to set 518 + */ 519 + 514 520 void p9_set_tag(struct p9_fcall *fc, u16 tag) 515 521 { 516 522 fc->tag = tag; ··· 524 518 } 525 519 EXPORT_SYMBOL(p9_set_tag); 526 520 521 + /** 522 + * p9_create_tversion - allocates and creates a T_VERSION request 523 + * @msize: requested maximum data size 524 + * @version: version string to negotiate 525 + * 526 + */ 527 527 struct p9_fcall *p9_create_tversion(u32 msize, char *version) 528 528 { 529 529 int size; ··· 553 541 return fc; 554 542 } 555 543 EXPORT_SYMBOL(p9_create_tversion); 544 + 545 + /** 546 + * p9_create_tauth - allocates and creates a T_AUTH request 547 + * @afid: handle to use for authentication protocol 548 + * @uname: user name attempting to authenticate 549 + * @aname: mount specifier for remote server 550 + * @n_uname: numeric id for user attempting to authneticate 551 + * @dotu: 9P2000.u extension flag 552 + * 553 + */ 556 554 557 555 struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname, 558 556 u32 n_uname, int dotu) ··· 602 580 } 603 581 EXPORT_SYMBOL(p9_create_tauth); 604 582 583 + /** 584 + * p9_create_tattach - allocates and creates a T_ATTACH request 585 + * @fid: handle to use for the new mount point 586 + * @afid: handle to use for authentication protocol 587 + * @uname: user name attempting to attach 588 + * @aname: mount specifier for remote server 589 + * @n_uname: numeric id for user attempting to attach 590 + * @n_uname: numeric id for user attempting to attach 591 + * @dotu: 9P2000.u extension flag 592 + * 593 + */ 594 + 605 595 struct p9_fcall * 606 596 p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname, 607 597 u32 n_uname, int dotu) ··· 650 616 } 651 617 EXPORT_SYMBOL(p9_create_tattach); 652 618 619 + /** 620 + * p9_create_tflush - allocates and creates a T_FLUSH request 621 + * @oldtag: tag id for the transaction we are attempting to cancel 622 + * 623 + */ 624 + 653 625 struct p9_fcall *p9_create_tflush(u16 oldtag) 654 626 { 655 627 int size; ··· 678 638 return fc; 679 639 } 680 640 EXPORT_SYMBOL(p9_create_tflush); 641 + 642 + /** 643 + * p9_create_twalk - allocates and creates a T_FLUSH request 644 + * @fid: handle we are traversing from 645 + * @newfid: a new handle for this transaction 646 + * @nwname: number of path elements to traverse 647 + * @wnames: array of path elements 648 + * 649 + */ 681 650 682 651 struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname, 683 652 char **wnames) ··· 726 677 } 727 678 EXPORT_SYMBOL(p9_create_twalk); 728 679 680 + /** 681 + * p9_create_topen - allocates and creates a T_OPEN request 682 + * @fid: handle we are trying to open 683 + * @mode: what mode we are trying to open the file in 684 + * 685 + */ 686 + 729 687 struct p9_fcall *p9_create_topen(u32 fid, u8 mode) 730 688 { 731 689 int size; ··· 756 700 return fc; 757 701 } 758 702 EXPORT_SYMBOL(p9_create_topen); 703 + 704 + /** 705 + * p9_create_tcreate - allocates and creates a T_CREATE request 706 + * @fid: handle of directory we are trying to create in 707 + * @name: name of the file we are trying to create 708 + * @perm: permissions for the file we are trying to create 709 + * @mode: what mode we are trying to open the file in 710 + * @extension: 9p2000.u extension string (for special files) 711 + * @dotu: 9p2000.u enabled flag 712 + * 713 + * Note: Plan 9 create semantics include opening the resulting file 714 + * which is why mode is included. 715 + */ 759 716 760 717 struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, 761 718 char *extension, int dotu) ··· 805 736 } 806 737 EXPORT_SYMBOL(p9_create_tcreate); 807 738 739 + /** 740 + * p9_create_tread - allocates and creates a T_READ request 741 + * @fid: handle of the file we are trying to read 742 + * @offset: offset to start reading from 743 + * @count: how many bytes to read 744 + */ 745 + 808 746 struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count) 809 747 { 810 748 int size; ··· 836 760 return fc; 837 761 } 838 762 EXPORT_SYMBOL(p9_create_tread); 763 + 764 + /** 765 + * p9_create_twrite - allocates and creates a T_WRITE request from the kernel 766 + * @fid: handle of the file we are trying to write 767 + * @offset: offset to start writing at 768 + * @count: how many bytes to write 769 + * @data: data to write 770 + * 771 + * This function will create a requst with data buffers from the kernel 772 + * such as the page cache. 773 + */ 839 774 840 775 struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count, 841 776 const char *data) ··· 881 794 } 882 795 EXPORT_SYMBOL(p9_create_twrite); 883 796 797 + /** 798 + * p9_create_twrite_u - allocates and creates a T_WRITE request from userspace 799 + * @fid: handle of the file we are trying to write 800 + * @offset: offset to start writing at 801 + * @count: how many bytes to write 802 + * @data: data to write 803 + * 804 + * This function will create a request with data buffers from userspace 805 + */ 806 + 884 807 struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count, 885 808 const char __user *data) 886 809 { ··· 924 827 } 925 828 EXPORT_SYMBOL(p9_create_twrite_u); 926 829 830 + /** 831 + * p9_create_tclunk - allocate a request to forget about a file handle 832 + * @fid: handle of the file we closing or forgetting about 833 + * 834 + * clunk is used both to close open files and to discard transient handles 835 + * which may be created during meta-data operations and hierarchy traversal. 836 + */ 837 + 927 838 struct p9_fcall *p9_create_tclunk(u32 fid) 928 839 { 929 840 int size; ··· 954 849 return fc; 955 850 } 956 851 EXPORT_SYMBOL(p9_create_tclunk); 852 + 853 + /** 854 + * p9_create_tremove - allocate and create a request to remove a file 855 + * @fid: handle of the file or directory we are removing 856 + * 857 + */ 957 858 958 859 struct p9_fcall *p9_create_tremove(u32 fid) 959 860 { ··· 984 873 } 985 874 EXPORT_SYMBOL(p9_create_tremove); 986 875 876 + /** 877 + * p9_create_tstat - allocate and populate a request for attributes 878 + * @fid: handle of the file or directory we are trying to get the attributes of 879 + * 880 + */ 881 + 987 882 struct p9_fcall *p9_create_tstat(u32 fid) 988 883 { 989 884 int size; ··· 1012 895 return fc; 1013 896 } 1014 897 EXPORT_SYMBOL(p9_create_tstat); 898 + 899 + /** 900 + * p9_create_tstat - allocate and populate a request to change attributes 901 + * @fid: handle of the file or directory we are trying to change 902 + * @wstat: &p9_stat structure with attributes we wish to set 903 + * @dotu: 9p2000.u enabled flag 904 + * 905 + */ 1015 906 1016 907 struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat, 1017 908 int dotu) ··· 1047 922 return fc; 1048 923 } 1049 924 EXPORT_SYMBOL(p9_create_twstat); 925 +
+11 -4
net/9p/error.c
··· 33 33 #include <linux/errno.h> 34 34 #include <net/9p/9p.h> 35 35 36 + /** 37 + * struct errormap - map string errors from Plan 9 to Linux numeric ids 38 + * @name: string sent over 9P 39 + * @val: numeric id most closely representing @name 40 + * @namelen: length of string 41 + * @list: hash-table list for string lookup 42 + */ 36 43 struct errormap { 37 44 char *name; 38 45 int val; ··· 184 177 }; 185 178 186 179 /** 187 - * p9_error_init - preload 188 - * @errstr: error string 180 + * p9_error_init - preload mappings into hash list 189 181 * 190 182 */ 191 183 ··· 212 206 /** 213 207 * errstr2errno - convert error string to error number 214 208 * @errstr: error string 209 + * @len: length of error string 215 210 * 216 211 */ 217 212 ··· 237 230 if (errno == 0) { 238 231 /* TODO: if error isn't found, add it dynamically */ 239 232 errstr[len] = 0; 240 - printk(KERN_ERR "%s: errstr :%s: not found\n", __func__, 241 - errstr); 233 + printk(KERN_ERR "%s: server reported unknown error %s\n", 234 + __func__, errstr); 242 235 errno = 1; 243 236 } 244 237
+8
net/9p/fcprint.c
··· 142 142 return p9_dumpdata(buf, buflen, data, datalen < 16?datalen:16); 143 143 } 144 144 145 + /** 146 + * p9_printfcall - decode and print a protocol structure into a buffer 147 + * @buf: buffer to deposit decoded structure into 148 + * @buflen: available space in buffer 149 + * @fc: protocol rpc structure of type &p9_fcall 150 + * @extended: whether or not session is operating with extended protocol 151 + */ 152 + 145 153 int 146 154 p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended) 147 155 {
+3 -5
net/9p/mod.c
··· 39 39 MODULE_PARM_DESC(debug, "9P debugging level"); 40 40 #endif 41 41 42 - extern int p9_mux_global_init(void); 43 - extern void p9_mux_global_exit(void); 44 - 45 42 /* 46 43 * Dynamic Transport Registration Routines 47 44 * ··· 49 52 50 53 /** 51 54 * v9fs_register_trans - register a new transport with 9p 52 - * @m - structure describing the transport module and entry points 55 + * @m: structure describing the transport module and entry points 53 56 * 54 57 */ 55 58 void v9fs_register_trans(struct p9_trans_module *m) ··· 62 65 63 66 /** 64 67 * v9fs_match_trans - match transport versus registered transports 65 - * @arg: string identifying transport 68 + * @name: string identifying transport 66 69 * 67 70 */ 68 71 struct p9_trans_module *v9fs_match_trans(const substring_t *name) ··· 107 110 108 111 p9_error_init(); 109 112 printk(KERN_INFO "Installing 9P2000 support\n"); 113 + p9_trans_fd_init(); 110 114 111 115 return ret; 112 116 }
+168 -36
net/9p/trans_fd.c
··· 47 47 #define SCHED_TIMEOUT 10 48 48 #define MAXPOLLWADDR 2 49 49 50 + /** 51 + * struct p9_fd_opts - per-transport options 52 + * @rfd: file descriptor for reading (trans=fd) 53 + * @wfd: file descriptor for writing (trans=fd) 54 + * @port: port to connect to (trans=tcp) 55 + * 56 + */ 57 + 50 58 struct p9_fd_opts { 51 59 int rfd; 52 60 int wfd; 53 61 u16 port; 54 62 }; 63 + 64 + 65 + /** 66 + * struct p9_trans_fd - transport state 67 + * @rd: reference to file to read from 68 + * @wr: reference of file to write to 69 + * @conn: connection state reference 70 + * 71 + */ 55 72 56 73 struct p9_trans_fd { 57 74 struct file *rd; ··· 107 90 }; 108 91 109 92 struct p9_req; 110 - 111 93 typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a); 94 + 95 + /** 96 + * struct p9_req - fd mux encoding of an rpc transaction 97 + * @lock: protects req_list 98 + * @tag: numeric tag for rpc transaction 99 + * @tcall: request &p9_fcall structure 100 + * @rcall: response &p9_fcall structure 101 + * @err: error state 102 + * @cb: callback for when response is received 103 + * @cba: argument to pass to callback 104 + * @flush: flag to indicate RPC has been flushed 105 + * @req_list: list link for higher level objects to chain requests 106 + * 107 + */ 108 + 112 109 struct p9_req { 113 - spinlock_t lock; /* protect request structure */ 110 + spinlock_t lock; 114 111 int tag; 115 112 struct p9_fcall *tcall; 116 113 struct p9_fcall *rcall; ··· 135 104 struct list_head req_list; 136 105 }; 137 106 138 - struct p9_mux_poll_task; 107 + struct p9_mux_poll_task { 108 + struct task_struct *task; 109 + struct list_head mux_list; 110 + int muxnum; 111 + }; 112 + 113 + /** 114 + * struct p9_conn - fd mux connection state information 115 + * @lock: protects mux_list (?) 116 + * @mux_list: list link for mux to manage multiple connections (?) 117 + * @poll_task: task polling on this connection 118 + * @msize: maximum size for connection (dup) 119 + * @extended: 9p2000.u flag (dup) 120 + * @trans: reference to transport instance for this connection 121 + * @tagpool: id accounting for transactions 122 + * @err: error state 123 + * @equeue: event wait_q (?) 124 + * @req_list: accounting for requests which have been sent 125 + * @unsent_req_list: accounting for requests that haven't been sent 126 + * @rcall: current response &p9_fcall structure 127 + * @rpos: read position in current frame 128 + * @rbuf: current read buffer 129 + * @wpos: write position for current frame 130 + * @wsize: amount of data to write for current frame 131 + * @wbuf: current write buffer 132 + * @poll_wait: array of wait_q's for various worker threads 133 + * @poll_waddr: ???? 134 + * @pt: poll state 135 + * @rq: current read work 136 + * @wq: current write work 137 + * @wsched: ???? 138 + * 139 + */ 139 140 140 141 struct p9_conn { 141 142 spinlock_t lock; /* protect lock structure */ ··· 195 132 unsigned long wsched; 196 133 }; 197 134 198 - struct p9_mux_poll_task { 199 - struct task_struct *task; 200 - struct list_head mux_list; 201 - int muxnum; 202 - }; 135 + /** 136 + * struct p9_mux_rpc - fd mux rpc accounting structure 137 + * @m: connection this request was issued on 138 + * @err: error state 139 + * @tcall: request &p9_fcall 140 + * @rcall: response &p9_fcall 141 + * @wqueue: wait queue that client is blocked on for this rpc 142 + * 143 + * Bug: isn't this information duplicated elsewhere like &p9_req 144 + */ 203 145 204 146 struct p9_mux_rpc { 205 147 struct p9_conn *m; ··· 275 207 276 208 /** 277 209 * p9_mux_calc_poll_procs - calculates the number of polling procs 278 - * based on the number of mounted v9fs filesystems. 210 + * @muxnum: number of mounts 279 211 * 212 + * Calculation is based on the number of mounted v9fs filesystems. 280 213 * The current implementation returns sqrt of the number of mounts. 281 214 */ 215 + 282 216 static int p9_mux_calc_poll_procs(int muxnum) 283 217 { 284 218 int n; ··· 401 331 402 332 /** 403 333 * p9_conn_create - allocate and initialize the per-session mux data 404 - * Creates the polling task if this is the first session. 334 + * @trans: transport structure 405 335 * 406 - * @trans - transport structure 407 - * @msize - maximum message size 408 - * @extended - extended flag 336 + * Note: Creates the polling task if this is the first session. 409 337 */ 338 + 410 339 static struct p9_conn *p9_conn_create(struct p9_trans *trans) 411 340 { 412 341 int i, n; ··· 475 406 476 407 /** 477 408 * p9_mux_destroy - cancels all pending requests and frees mux resources 409 + * @m: mux to destroy 410 + * 478 411 */ 412 + 479 413 static void p9_conn_destroy(struct p9_conn *m) 480 414 { 481 415 P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m, ··· 501 429 } 502 430 503 431 /** 504 - * p9_pollwait - called by files poll operation to add v9fs-poll task 505 - * to files wait queue 432 + * p9_pollwait - add poll task to the wait queue 433 + * @filp: file pointer being polled 434 + * @wait_address: wait_q to block on 435 + * @p: poll state 436 + * 437 + * called by files poll operation to add v9fs-poll task to files wait queue 506 438 */ 439 + 507 440 static void 508 441 p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p) 509 442 { ··· 539 462 540 463 /** 541 464 * p9_poll_mux - polls a mux and schedules read or write works if necessary 465 + * @m: connection to poll 466 + * 542 467 */ 468 + 543 469 static void p9_poll_mux(struct p9_conn *m) 544 470 { 545 471 int n; ··· 579 499 } 580 500 581 501 /** 582 - * p9_poll_proc - polls all v9fs transports for new events and queues 583 - * the appropriate work to the work queue 502 + * p9_poll_proc - poll worker thread 503 + * @a: thread state and arguments 504 + * 505 + * polls all v9fs transports for new events and queues the appropriate 506 + * work to the work queue 507 + * 584 508 */ 509 + 585 510 static int p9_poll_proc(void *a) 586 511 { 587 512 struct p9_conn *m, *mtmp; ··· 612 527 613 528 /** 614 529 * p9_write_work - called when a transport can send some data 530 + * @work: container for work to be done 531 + * 615 532 */ 533 + 616 534 static void p9_write_work(struct work_struct *work) 617 535 { 618 536 int n, err; ··· 726 638 727 639 /** 728 640 * p9_read_work - called when there is some data to be read from a transport 641 + * @work: container of work to be done 642 + * 729 643 */ 644 + 730 645 static void p9_read_work(struct work_struct *work) 731 646 { 732 647 int n, err; ··· 884 793 * @tc: request to be sent 885 794 * @cb: callback function to call when response is received 886 795 * @cba: parameter to pass to the callback function 796 + * 887 797 */ 798 + 888 799 static struct p9_req *p9_send_request(struct p9_conn *m, 889 800 struct p9_fcall *tc, 890 801 p9_conn_req_callback cb, void *cba) ··· 1054 961 /** 1055 962 * p9_fd_rpc- sends 9P request and waits until a response is available. 1056 963 * The function can be interrupted. 1057 - * @m: mux data 964 + * @t: transport data 1058 965 * @tc: request to be sent 1059 966 * @rc: pointer where a pointer to the response is stored 967 + * 1060 968 */ 969 + 1061 970 int 1062 971 p9_fd_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) 1063 972 { ··· 1136 1041 * @m: mux data 1137 1042 * @tc: request to be sent 1138 1043 * @cb: callback function to be called when response arrives 1139 - * @cba: value to pass to the callback function 1044 + * @a: value to pass to the callback function 1045 + * 1140 1046 */ 1047 + 1141 1048 int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc, 1142 1049 p9_conn_req_callback cb, void *a) 1143 1050 { ··· 1162 1065 * p9_conn_cancel - cancel all pending requests with error 1163 1066 * @m: mux data 1164 1067 * @err: error code 1068 + * 1165 1069 */ 1070 + 1166 1071 void p9_conn_cancel(struct p9_conn *m, int err) 1167 1072 { 1168 1073 struct p9_req *req, *rtmp; ··· 1196 1097 } 1197 1098 1198 1099 /** 1199 - * v9fs_parse_options - parse mount options into session structure 1100 + * parse_options - parse mount options into session structure 1200 1101 * @options: options string passed from mount 1201 - * @v9ses: existing v9fs session information 1102 + * @opts: transport-specific structure to parse options into 1202 1103 * 1104 + * Returns 0 upon success, -ERRNO upon failure 1203 1105 */ 1204 1106 1205 - static void parse_opts(char *options, struct p9_fd_opts *opts) 1107 + static int parse_opts(char *params, struct p9_fd_opts *opts) 1206 1108 { 1207 1109 char *p; 1208 1110 substring_t args[MAX_OPT_ARGS]; 1209 1111 int option; 1112 + char *options; 1210 1113 int ret; 1211 1114 1212 1115 opts->port = P9_PORT; 1213 1116 opts->rfd = ~0; 1214 1117 opts->wfd = ~0; 1215 1118 1216 - if (!options) 1217 - return; 1119 + if (!params) 1120 + return 0; 1121 + 1122 + options = kstrdup(params, GFP_KERNEL); 1123 + if (!options) { 1124 + P9_DPRINTK(P9_DEBUG_ERROR, 1125 + "failed to allocate copy of option string\n"); 1126 + return -ENOMEM; 1127 + } 1218 1128 1219 1129 while ((p = strsep(&options, ",")) != NULL) { 1220 1130 int token; 1131 + int r; 1221 1132 if (!*p) 1222 1133 continue; 1223 1134 token = match_token(p, tokens, args); 1224 - ret = match_int(&args[0], &option); 1225 - if (ret < 0) { 1135 + r = match_int(&args[0], &option); 1136 + if (r < 0) { 1226 1137 P9_DPRINTK(P9_DEBUG_ERROR, 1227 1138 "integer field, but no integer?\n"); 1139 + ret = r; 1228 1140 continue; 1229 1141 } 1230 1142 switch (token) { ··· 1252 1142 continue; 1253 1143 } 1254 1144 } 1145 + kfree(options); 1146 + return 0; 1255 1147 } 1256 1148 1257 1149 static int p9_fd_open(struct p9_trans *trans, int rfd, int wfd) ··· 1305 1193 1306 1194 /** 1307 1195 * p9_fd_read- read from a fd 1308 - * @v9ses: session information 1196 + * @trans: transport instance state 1309 1197 * @v: buffer to receive data into 1310 1198 * @len: size of receive buffer 1311 1199 * 1312 1200 */ 1201 + 1313 1202 static int p9_fd_read(struct p9_trans *trans, void *v, int len) 1314 1203 { 1315 1204 int ret; ··· 1333 1220 1334 1221 /** 1335 1222 * p9_fd_write - write to a socket 1336 - * @v9ses: session information 1223 + * @trans: transport instance state 1337 1224 * @v: buffer to send data from 1338 1225 * @len: size of send buffer 1339 1226 * 1340 1227 */ 1228 + 1341 1229 static int p9_fd_write(struct p9_trans *trans, void *v, int len) 1342 1230 { 1343 1231 int ret; ··· 1410 1296 * @trans: private socket structure 1411 1297 * 1412 1298 */ 1299 + 1413 1300 static void p9_fd_close(struct p9_trans *trans) 1414 1301 { 1415 1302 struct p9_trans_fd *ts; ··· 1433 1318 kfree(ts); 1434 1319 } 1435 1320 1321 + /* 1322 + * stolen from NFS - maybe should be made a generic function? 1323 + */ 1324 + static inline int valid_ipaddr4(const char *buf) 1325 + { 1326 + int rc, count, in[4]; 1327 + 1328 + rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]); 1329 + if (rc != 4) 1330 + return -EINVAL; 1331 + for (count = 0; count < 4; count++) { 1332 + if (in[count] > 255) 1333 + return -EINVAL; 1334 + } 1335 + return 0; 1336 + } 1337 + 1436 1338 static struct p9_trans * 1437 1339 p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu) 1438 1340 { ··· 1460 1328 struct p9_fd_opts opts; 1461 1329 struct p9_trans_fd *p; 1462 1330 1463 - parse_opts(args, &opts); 1331 + err = parse_opts(args, &opts); 1332 + if (err < 0) 1333 + return ERR_PTR(err); 1334 + 1335 + if (valid_ipaddr4(addr) < 0) 1336 + return ERR_PTR(-EINVAL); 1464 1337 1465 1338 csocket = NULL; 1466 1339 trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); ··· 1645 1508 .create = p9_trans_create_fd, 1646 1509 }; 1647 1510 1648 - static int __init p9_trans_fd_init(void) 1511 + int p9_trans_fd_init(void) 1649 1512 { 1650 1513 int ret = p9_mux_global_init(); 1651 1514 if (ret) { ··· 1659 1522 1660 1523 return 0; 1661 1524 } 1662 - 1663 - module_init(p9_trans_fd_init); 1664 - 1665 - MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>"); 1666 - MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); 1667 - MODULE_LICENSE("GPL"); 1525 + EXPORT_SYMBOL(p9_trans_fd_init);
+155 -20
net/9p/trans_virtio.c
··· 49 49 #define VIRTQUEUE_NUM 128 50 50 51 51 /* a single mutex to manage channel initialization and attachment */ 52 - static DECLARE_MUTEX(virtio_9p_lock); 52 + static DEFINE_MUTEX(virtio_9p_lock); 53 53 /* global which tracks highest initialized channel */ 54 54 static int chan_index; 55 55 56 56 #define P9_INIT_MAXTAG 16 57 57 58 - #define REQ_STATUS_IDLE 0 59 - #define REQ_STATUS_SENT 1 60 - #define REQ_STATUS_RCVD 2 61 - #define REQ_STATUS_FLSH 3 58 + 59 + /** 60 + * enum p9_req_status_t - virtio request status 61 + * @REQ_STATUS_IDLE: request slot unused 62 + * @REQ_STATUS_SENT: request sent to server 63 + * @REQ_STATUS_RCVD: response received from server 64 + * @REQ_STATUS_FLSH: request has been flushed 65 + * 66 + * The @REQ_STATUS_IDLE state is used to mark a request slot as unused 67 + * but use is actually tracked by the idpool structure which handles tag 68 + * id allocation. 69 + * 70 + */ 71 + 72 + enum p9_req_status_t { 73 + REQ_STATUS_IDLE, 74 + REQ_STATUS_SENT, 75 + REQ_STATUS_RCVD, 76 + REQ_STATUS_FLSH, 77 + }; 78 + 79 + /** 80 + * struct p9_req_t - virtio request slots 81 + * @status: status of this request slot 82 + * @wq: wait_queue for the client to block on for this request 83 + * 84 + * The virtio transport uses an array to track outstanding requests 85 + * instead of a list. While this may incurr overhead during initial 86 + * allocation or expansion, it makes request lookup much easier as the 87 + * tag id is a index into an array. (We use tag+1 so that we can accomodate 88 + * the -1 tag for the T_VERSION request). 89 + * This also has the nice effect of only having to allocate wait_queues 90 + * once, instead of constantly allocating and freeing them. Its possible 91 + * other resources could benefit from this scheme as well. 92 + * 93 + */ 62 94 63 95 struct p9_req_t { 64 96 int status; 65 97 wait_queue_head_t *wq; 66 98 }; 67 99 68 - /* We keep all per-channel information in a structure. 100 + /** 101 + * struct virtio_chan - per-instance transport information 102 + * @initialized: whether the channel is initialized 103 + * @inuse: whether the channel is in use 104 + * @lock: protects multiple elements within this structure 105 + * @vdev: virtio dev associated with this channel 106 + * @vq: virtio queue associated with this channel 107 + * @tagpool: accounting for tag ids (and request slots) 108 + * @reqs: array of request slots 109 + * @max_tag: current number of request_slots allocated 110 + * @sg: scatter gather list which is used to pack a request (protected?) 111 + * 112 + * We keep all per-channel information in a structure. 69 113 * This structure is allocated within the devices dev->mem space. 70 114 * A pointer to the structure will get put in the transport private. 115 + * 71 116 */ 117 + 72 118 static struct virtio_chan { 73 - bool initialized; /* channel is initialized */ 74 - bool inuse; /* channel is in use */ 119 + bool initialized; 120 + bool inuse; 75 121 76 122 spinlock_t lock; 77 123 ··· 132 86 struct scatterlist sg[VIRTQUEUE_NUM]; 133 87 } channels[MAX_9P_CHAN]; 134 88 135 - /* Lookup requests by tag */ 89 + /** 90 + * p9_lookup_tag - Lookup requests by tag 91 + * @c: virtio channel to lookup tag within 92 + * @tag: numeric id for transaction 93 + * 94 + * this is a simple array lookup, but will grow the 95 + * request_slots as necessary to accomodate transaction 96 + * ids which did not previously have a slot. 97 + * 98 + * Bugs: there is currently no upper limit on request slots set 99 + * here, but that should be constrained by the id accounting. 100 + */ 101 + 136 102 static struct p9_req_t *p9_lookup_tag(struct virtio_chan *c, u16 tag) 137 103 { 138 104 /* This looks up the original request by tag so we know which ··· 188 130 return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE); 189 131 } 190 132 133 + /** 134 + * p9_virtio_close - reclaim resources of a channel 135 + * @trans: transport state 136 + * 137 + * This reclaims a channel by freeing its resources and 138 + * reseting its inuse flag. 139 + * 140 + */ 141 + 191 142 static void p9_virtio_close(struct p9_trans *trans) 192 143 { 193 144 struct virtio_chan *chan = trans->priv; 194 145 int count; 195 - unsigned int flags; 146 + unsigned long flags; 196 147 197 148 spin_lock_irqsave(&chan->lock, flags); 198 149 p9_idpool_destroy(chan->tagpool); ··· 211 144 chan->max_tag = 0; 212 145 spin_unlock_irqrestore(&chan->lock, flags); 213 146 214 - down(&virtio_9p_lock); 147 + mutex_lock(&virtio_9p_lock); 215 148 chan->inuse = false; 216 - up(&virtio_9p_lock); 149 + mutex_unlock(&virtio_9p_lock); 217 150 218 151 kfree(trans); 219 152 } 153 + 154 + /** 155 + * req_done - callback which signals activity from the server 156 + * @vq: virtio queue activity was received on 157 + * 158 + * This notifies us that the server has triggered some activity 159 + * on the virtio channel - most likely a response to request we 160 + * sent. Figure out which requests now have responses and wake up 161 + * those threads. 162 + * 163 + * Bugs: could do with some additional sanity checking, but appears to work. 164 + * 165 + */ 220 166 221 167 static void req_done(struct virtqueue *vq) 222 168 { ··· 248 168 /* In case queue is stopped waiting for more buffers. */ 249 169 spin_unlock_irqrestore(&chan->lock, flags); 250 170 } 171 + 172 + /** 173 + * pack_sg_list - pack a scatter gather list from a linear buffer 174 + * @sg: scatter/gather list to pack into 175 + * @start: which segment of the sg_list to start at 176 + * @limit: maximum segment to pack data to 177 + * @data: data to pack into scatter/gather list 178 + * @count: amount of data to pack into the scatter/gather list 179 + * 180 + * sg_lists have multiple segments of various sizes. This will pack 181 + * arbitrary data into an existing scatter gather list, segmenting the 182 + * data as necessary within constraints. 183 + * 184 + */ 251 185 252 186 static int 253 187 pack_sg_list(struct scatterlist *sg, int start, int limit, char *data, ··· 282 188 283 189 return index-start; 284 190 } 191 + 192 + /** 193 + * p9_virtio_rpc - issue a request and wait for a response 194 + * @t: transport state 195 + * @tc: &p9_fcall request to transmit 196 + * @rc: &p9_fcall to put reponse into 197 + * 198 + */ 285 199 286 200 static int 287 201 p9_virtio_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) ··· 365 263 return 0; 366 264 } 367 265 266 + /** 267 + * p9_virtio_probe - probe for existence of 9P virtio channels 268 + * @vdev: virtio device to probe 269 + * 270 + * This probes for existing virtio channels. At present only 271 + * a single channel is in use, so in the future more work may need 272 + * to be done here. 273 + * 274 + */ 275 + 368 276 static int p9_virtio_probe(struct virtio_device *vdev) 369 277 { 370 278 int err; 371 279 struct virtio_chan *chan; 372 280 int index; 373 281 374 - down(&virtio_9p_lock); 282 + mutex_lock(&virtio_9p_lock); 375 283 index = chan_index++; 376 284 chan = &channels[index]; 377 - up(&virtio_9p_lock); 285 + mutex_unlock(&virtio_9p_lock); 378 286 379 287 if (chan_index > MAX_9P_CHAN) { 380 288 printk(KERN_ERR "9p: virtio: Maximum channels exceeded\n"); ··· 413 301 out_free_vq: 414 302 vdev->config->del_vq(chan->vq); 415 303 fail: 416 - down(&virtio_9p_lock); 304 + mutex_lock(&virtio_9p_lock); 417 305 chan_index--; 418 - up(&virtio_9p_lock); 306 + mutex_unlock(&virtio_9p_lock); 419 307 return err; 420 308 } 421 309 422 - /* This sets up a transport channel for 9p communication. Right now 310 + 311 + /** 312 + * p9_virtio_create - allocate a new virtio channel 313 + * @devname: string identifying the channel to connect to (unused) 314 + * @args: args passed from sys_mount() for per-transport options (unused) 315 + * @msize: requested maximum packet size 316 + * @extended: 9p2000.u enabled flag 317 + * 318 + * This sets up a transport channel for 9p communication. Right now 423 319 * we only match the first available channel, but eventually we couldlook up 424 320 * alternate channels by matching devname versus a virtio_config entry. 425 321 * We use a simple reference count mechanism to ensure that only a single 426 - * mount has a channel open at a time. */ 322 + * mount has a channel open at a time. 323 + * 324 + * Bugs: doesn't allow identification of a specific channel 325 + * to allocate, channels are allocated sequentially. This was 326 + * a pragmatic decision to get things rolling, but ideally some 327 + * way of identifying the channel to attach to would be nice 328 + * if we are going to support multiple channels. 329 + * 330 + */ 331 + 427 332 static struct p9_trans * 428 333 p9_virtio_create(const char *devname, char *args, int msize, 429 334 unsigned char extended) ··· 449 320 struct virtio_chan *chan = channels; 450 321 int index = 0; 451 322 452 - down(&virtio_9p_lock); 323 + mutex_lock(&virtio_9p_lock); 453 324 while (index < MAX_9P_CHAN) { 454 325 if (chan->initialized && !chan->inuse) { 455 326 chan->inuse = true; ··· 459 330 chan = &channels[index]; 460 331 } 461 332 } 462 - up(&virtio_9p_lock); 333 + mutex_unlock(&virtio_9p_lock); 463 334 464 335 if (index >= MAX_9P_CHAN) { 465 336 printk(KERN_ERR "9p: no channels available\n"); ··· 488 359 489 360 return trans; 490 361 } 362 + 363 + /** 364 + * p9_virtio_remove - clean up resources associated with a virtio device 365 + * @vdev: virtio device to remove 366 + * 367 + */ 491 368 492 369 static void p9_virtio_remove(struct virtio_device *vdev) 493 370 {
+28 -8
net/9p/util.c
··· 32 32 #include <linux/idr.h> 33 33 #include <net/9p/9p.h> 34 34 35 + /** 36 + * struct p9_idpool - per-connection accounting for tag idpool 37 + * @lock: protects the pool 38 + * @pool: idr to allocate tag id from 39 + * 40 + */ 41 + 35 42 struct p9_idpool { 36 43 spinlock_t lock; 37 44 struct idr pool; 38 45 }; 46 + 47 + /** 48 + * p9_idpool_create - create a new per-connection id pool 49 + * 50 + */ 39 51 40 52 struct p9_idpool *p9_idpool_create(void) 41 53 { ··· 64 52 } 65 53 EXPORT_SYMBOL(p9_idpool_create); 66 54 55 + /** 56 + * p9_idpool_destroy - create a new per-connection id pool 57 + * @p: idpool to destory 58 + */ 59 + 67 60 void p9_idpool_destroy(struct p9_idpool *p) 68 61 { 69 62 idr_destroy(&p->pool); ··· 78 61 79 62 /** 80 63 * p9_idpool_get - allocate numeric id from pool 81 - * @p - pool to allocate from 64 + * @p: pool to allocate from 82 65 * 83 - * XXX - This seems to be an awful generic function, should it be in idr.c with 66 + * Bugs: This seems to be an awful generic function, should it be in idr.c with 84 67 * the lock included in struct idr? 85 68 */ 86 69 ··· 88 71 { 89 72 int i = 0; 90 73 int error; 91 - unsigned int flags; 74 + unsigned long flags; 92 75 93 76 retry: 94 77 if (idr_pre_get(&p->pool, GFP_KERNEL) == 0) ··· 111 94 112 95 /** 113 96 * p9_idpool_put - release numeric id from pool 114 - * @p - pool to allocate from 97 + * @id: numeric id which is being released 98 + * @p: pool to release id into 115 99 * 116 - * XXX - This seems to be an awful generic function, should it be in idr.c with 100 + * Bugs: This seems to be an awful generic function, should it be in idr.c with 117 101 * the lock included in struct idr? 118 102 */ 119 103 120 104 void p9_idpool_put(int id, struct p9_idpool *p) 121 105 { 122 - unsigned int flags; 106 + unsigned long flags; 123 107 spin_lock_irqsave(&p->lock, flags); 124 108 idr_remove(&p->pool, id); 125 109 spin_unlock_irqrestore(&p->lock, flags); ··· 129 111 130 112 /** 131 113 * p9_idpool_check - check if the specified id is available 132 - * @id - id to check 133 - * @p - pool 114 + * @id: id to check 115 + * @p: pool to check 134 116 */ 117 + 135 118 int p9_idpool_check(int id, struct p9_idpool *p) 136 119 { 137 120 return idr_find(&p->pool, id) != NULL; 138 121 } 139 122 EXPORT_SYMBOL(p9_idpool_check); 123 +