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:
9p: fix a race condition bug in umount which caused a segfault
9p: re-enable mount time debug option
9p: cache meta-data when cache=loose
net/9p: set error to EREMOTEIO if trans->write returns zero
net/9p: change net/9p module name to 9pnet
9p: Reorganization of 9p file system code

+3444 -3130
-375
fs/9p/9p.h
··· 1 - /* 2 - * linux/fs/9p/9p.h 3 - * 4 - * 9P protocol definitions. 5 - * 6 - * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net> 7 - * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 8 - * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 9 - * 10 - * This program is free software; you can redistribute it and/or modify 11 - * it under the terms of the GNU General Public License version 2 12 - * as published by the Free Software Foundation. 13 - * 14 - * This program is distributed in the hope that it will be useful, 15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 - * GNU General Public License for more details. 18 - * 19 - * You should have received a copy of the GNU General Public License 20 - * along with this program; if not, write to: 21 - * Free Software Foundation 22 - * 51 Franklin Street, Fifth Floor 23 - * Boston, MA 02111-1301 USA 24 - * 25 - */ 26 - 27 - /* Message Types */ 28 - enum { 29 - TVERSION = 100, 30 - RVERSION, 31 - TAUTH = 102, 32 - RAUTH, 33 - TATTACH = 104, 34 - RATTACH, 35 - TERROR = 106, 36 - RERROR, 37 - TFLUSH = 108, 38 - RFLUSH, 39 - TWALK = 110, 40 - RWALK, 41 - TOPEN = 112, 42 - ROPEN, 43 - TCREATE = 114, 44 - RCREATE, 45 - TREAD = 116, 46 - RREAD, 47 - TWRITE = 118, 48 - RWRITE, 49 - TCLUNK = 120, 50 - RCLUNK, 51 - TREMOVE = 122, 52 - RREMOVE, 53 - TSTAT = 124, 54 - RSTAT, 55 - TWSTAT = 126, 56 - RWSTAT, 57 - }; 58 - 59 - /* modes */ 60 - enum { 61 - V9FS_OREAD = 0x00, 62 - V9FS_OWRITE = 0x01, 63 - V9FS_ORDWR = 0x02, 64 - V9FS_OEXEC = 0x03, 65 - V9FS_OEXCL = 0x04, 66 - V9FS_OTRUNC = 0x10, 67 - V9FS_OREXEC = 0x20, 68 - V9FS_ORCLOSE = 0x40, 69 - V9FS_OAPPEND = 0x80, 70 - }; 71 - 72 - /* permissions */ 73 - enum { 74 - V9FS_DMDIR = 0x80000000, 75 - V9FS_DMAPPEND = 0x40000000, 76 - V9FS_DMEXCL = 0x20000000, 77 - V9FS_DMMOUNT = 0x10000000, 78 - V9FS_DMAUTH = 0x08000000, 79 - V9FS_DMTMP = 0x04000000, 80 - V9FS_DMSYMLINK = 0x02000000, 81 - V9FS_DMLINK = 0x01000000, 82 - /* 9P2000.u extensions */ 83 - V9FS_DMDEVICE = 0x00800000, 84 - V9FS_DMNAMEDPIPE = 0x00200000, 85 - V9FS_DMSOCKET = 0x00100000, 86 - V9FS_DMSETUID = 0x00080000, 87 - V9FS_DMSETGID = 0x00040000, 88 - }; 89 - 90 - /* qid.types */ 91 - enum { 92 - V9FS_QTDIR = 0x80, 93 - V9FS_QTAPPEND = 0x40, 94 - V9FS_QTEXCL = 0x20, 95 - V9FS_QTMOUNT = 0x10, 96 - V9FS_QTAUTH = 0x08, 97 - V9FS_QTTMP = 0x04, 98 - V9FS_QTSYMLINK = 0x02, 99 - V9FS_QTLINK = 0x01, 100 - V9FS_QTFILE = 0x00, 101 - }; 102 - 103 - #define V9FS_NOTAG (u16)(~0) 104 - #define V9FS_NOFID (u32)(~0) 105 - #define V9FS_MAXWELEM 16 106 - 107 - /* ample room for Twrite/Rread header (iounit) */ 108 - #define V9FS_IOHDRSZ 24 109 - 110 - struct v9fs_str { 111 - u16 len; 112 - char *str; 113 - }; 114 - 115 - /* qids are the unique ID for a file (like an inode */ 116 - struct v9fs_qid { 117 - u8 type; 118 - u32 version; 119 - u64 path; 120 - }; 121 - 122 - /* Plan 9 file metadata (stat) structure */ 123 - struct v9fs_stat { 124 - u16 size; 125 - u16 type; 126 - u32 dev; 127 - struct v9fs_qid qid; 128 - u32 mode; 129 - u32 atime; 130 - u32 mtime; 131 - u64 length; 132 - struct v9fs_str name; 133 - struct v9fs_str uid; 134 - struct v9fs_str gid; 135 - struct v9fs_str muid; 136 - struct v9fs_str extension; /* 9p2000.u extensions */ 137 - u32 n_uid; /* 9p2000.u extensions */ 138 - u32 n_gid; /* 9p2000.u extensions */ 139 - u32 n_muid; /* 9p2000.u extensions */ 140 - }; 141 - 142 - /* file metadata (stat) structure used to create Twstat message 143 - The is similar to v9fs_stat, but the strings don't point to 144 - the same memory block and should be freed separately 145 - */ 146 - struct v9fs_wstat { 147 - u16 size; 148 - u16 type; 149 - u32 dev; 150 - struct v9fs_qid qid; 151 - u32 mode; 152 - u32 atime; 153 - u32 mtime; 154 - u64 length; 155 - char *name; 156 - char *uid; 157 - char *gid; 158 - char *muid; 159 - char *extension; /* 9p2000.u extensions */ 160 - u32 n_uid; /* 9p2000.u extensions */ 161 - u32 n_gid; /* 9p2000.u extensions */ 162 - u32 n_muid; /* 9p2000.u extensions */ 163 - }; 164 - 165 - /* Structures for Protocol Operations */ 166 - 167 - struct Tversion { 168 - u32 msize; 169 - struct v9fs_str version; 170 - }; 171 - 172 - struct Rversion { 173 - u32 msize; 174 - struct v9fs_str version; 175 - }; 176 - 177 - struct Tauth { 178 - u32 afid; 179 - struct v9fs_str uname; 180 - struct v9fs_str aname; 181 - }; 182 - 183 - struct Rauth { 184 - struct v9fs_qid qid; 185 - }; 186 - 187 - struct Rerror { 188 - struct v9fs_str error; 189 - u32 errno; /* 9p2000.u extension */ 190 - }; 191 - 192 - struct Tflush { 193 - u16 oldtag; 194 - }; 195 - 196 - struct Rflush { 197 - }; 198 - 199 - struct Tattach { 200 - u32 fid; 201 - u32 afid; 202 - struct v9fs_str uname; 203 - struct v9fs_str aname; 204 - }; 205 - 206 - struct Rattach { 207 - struct v9fs_qid qid; 208 - }; 209 - 210 - struct Twalk { 211 - u32 fid; 212 - u32 newfid; 213 - u16 nwname; 214 - struct v9fs_str wnames[16]; 215 - }; 216 - 217 - struct Rwalk { 218 - u16 nwqid; 219 - struct v9fs_qid wqids[16]; 220 - }; 221 - 222 - struct Topen { 223 - u32 fid; 224 - u8 mode; 225 - }; 226 - 227 - struct Ropen { 228 - struct v9fs_qid qid; 229 - u32 iounit; 230 - }; 231 - 232 - struct Tcreate { 233 - u32 fid; 234 - struct v9fs_str name; 235 - u32 perm; 236 - u8 mode; 237 - struct v9fs_str extension; 238 - }; 239 - 240 - struct Rcreate { 241 - struct v9fs_qid qid; 242 - u32 iounit; 243 - }; 244 - 245 - struct Tread { 246 - u32 fid; 247 - u64 offset; 248 - u32 count; 249 - }; 250 - 251 - struct Rread { 252 - u32 count; 253 - u8 *data; 254 - }; 255 - 256 - struct Twrite { 257 - u32 fid; 258 - u64 offset; 259 - u32 count; 260 - u8 *data; 261 - }; 262 - 263 - struct Rwrite { 264 - u32 count; 265 - }; 266 - 267 - struct Tclunk { 268 - u32 fid; 269 - }; 270 - 271 - struct Rclunk { 272 - }; 273 - 274 - struct Tremove { 275 - u32 fid; 276 - }; 277 - 278 - struct Rremove { 279 - }; 280 - 281 - struct Tstat { 282 - u32 fid; 283 - }; 284 - 285 - struct Rstat { 286 - struct v9fs_stat stat; 287 - }; 288 - 289 - struct Twstat { 290 - u32 fid; 291 - struct v9fs_stat stat; 292 - }; 293 - 294 - struct Rwstat { 295 - }; 296 - 297 - /* 298 - * fcall is the primary packet structure 299 - * 300 - */ 301 - 302 - struct v9fs_fcall { 303 - u32 size; 304 - u8 id; 305 - u16 tag; 306 - void *sdata; 307 - 308 - union { 309 - struct Tversion tversion; 310 - struct Rversion rversion; 311 - struct Tauth tauth; 312 - struct Rauth rauth; 313 - struct Rerror rerror; 314 - struct Tflush tflush; 315 - struct Rflush rflush; 316 - struct Tattach tattach; 317 - struct Rattach rattach; 318 - struct Twalk twalk; 319 - struct Rwalk rwalk; 320 - struct Topen topen; 321 - struct Ropen ropen; 322 - struct Tcreate tcreate; 323 - struct Rcreate rcreate; 324 - struct Tread tread; 325 - struct Rread rread; 326 - struct Twrite twrite; 327 - struct Rwrite rwrite; 328 - struct Tclunk tclunk; 329 - struct Rclunk rclunk; 330 - struct Tremove tremove; 331 - struct Rremove rremove; 332 - struct Tstat tstat; 333 - struct Rstat rstat; 334 - struct Twstat twstat; 335 - struct Rwstat rwstat; 336 - } params; 337 - }; 338 - 339 - #define PRINT_FCALL_ERROR(s, fcall) dprintk(DEBUG_ERROR, "%s: %.*s\n", s, \ 340 - fcall?fcall->params.rerror.error.len:0, \ 341 - fcall?fcall->params.rerror.error.str:""); 342 - 343 - int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize, 344 - char *version, struct v9fs_fcall **rcall); 345 - 346 - int v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname, 347 - u32 fid, u32 afid, struct v9fs_fcall **rcall); 348 - 349 - int v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid); 350 - 351 - int v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, 352 - struct v9fs_fcall **rcall); 353 - 354 - int v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid, 355 - struct v9fs_wstat *wstat, struct v9fs_fcall **rcall); 356 - 357 - int v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid, 358 - char *name, struct v9fs_fcall **rcall); 359 - 360 - int v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode, 361 - struct v9fs_fcall **rcall); 362 - 363 - int v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid, 364 - struct v9fs_fcall **rcall); 365 - 366 - int v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, 367 - u32 perm, u8 mode, char *extension, struct v9fs_fcall **rcall); 368 - 369 - int v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, 370 - u64 offset, u32 count, struct v9fs_fcall **rcall); 371 - 372 - int v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, 373 - u32 count, const char __user * data, 374 - struct v9fs_fcall **rcall); 375 - int v9fs_printfcall(char *, int, struct v9fs_fcall *, int);
···
-6
fs/9p/Makefile
··· 1 obj-$(CONFIG_9P_FS) := 9p.o 2 3 9p-objs := \ 4 - trans_fd.o \ 5 - mux.o \ 6 - fcall.o \ 7 - conv.o \ 8 vfs_super.o \ 9 vfs_inode.o \ 10 vfs_addr.o \ 11 vfs_file.o \ 12 vfs_dir.o \ 13 vfs_dentry.o \ 14 - error.o \ 15 v9fs.o \ 16 fid.o \ 17 - fcprint.o 18
··· 1 obj-$(CONFIG_9P_FS) := 9p.o 2 3 9p-objs := \ 4 vfs_super.o \ 5 vfs_inode.o \ 6 vfs_addr.o \ 7 vfs_file.o \ 8 vfs_dir.o \ 9 vfs_dentry.o \ 10 v9fs.o \ 11 fid.o \ 12
+243 -185
fs/9p/conv.c net/9p/conv.c
··· 1 /* 2 - * linux/fs/9p/conv.c 3 * 4 * 9P protocol conversion functions 5 * ··· 29 #include <linux/fs.h> 30 #include <linux/sched.h> 31 #include <linux/idr.h> 32 - #include <asm/uaccess.h> 33 - #include "debug.h" 34 - #include "v9fs.h" 35 - #include "9p.h" 36 - #include "conv.h" 37 38 /* 39 * Buffer to help with string parsing ··· 56 { 57 if (buf->p + len > buf->ep) { 58 if (buf->p < buf->ep) { 59 - eprintk(KERN_ERR, "buffer overflow: want %d has %d\n", 60 - len, (int)(buf->ep - buf->p)); 61 dump_stack(); 62 buf->p = buf->ep + 1; 63 } ··· 181 return ret; 182 } 183 184 - static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr) 185 { 186 vstr->len = buf_get_int16(buf); 187 if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) { ··· 193 } 194 } 195 196 - static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid) 197 { 198 qid->type = buf_get_int8(bufp); 199 qid->version = buf_get_int32(bufp); ··· 201 } 202 203 /** 204 - * v9fs_size_wstat - calculate the size of a variable length stat struct 205 * @stat: metadata (stat) structure 206 - * @extended: non-zero if 9P2000.u 207 * 208 */ 209 210 - static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended) 211 { 212 int size = 0; 213 214 if (wstat == NULL) { 215 - eprintk(KERN_ERR, "v9fs_size_stat: got a NULL stat pointer\n"); 216 return 0; 217 } 218 ··· 237 if (wstat->muid) 238 size += strlen(wstat->muid); 239 240 - if (extended) { 241 size += 4 + /* n_uid[4] */ 242 4 + /* n_gid[4] */ 243 4 + /* n_muid[4] */ ··· 253 * buf_get_stat - safely decode a recieved metadata (stat) structure 254 * @bufp: buffer to deserialize 255 * @stat: metadata (stat) structure 256 - * @extended: non-zero if 9P2000.u 257 * 258 */ 259 260 static void 261 - buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended) 262 { 263 stat->size = buf_get_int16(bufp); 264 stat->type = buf_get_int16(bufp); ··· 275 buf_get_str(bufp, &stat->gid); 276 buf_get_str(bufp, &stat->muid); 277 278 - if (extended) { 279 buf_get_str(bufp, &stat->extension); 280 stat->n_uid = buf_get_int32(bufp); 281 stat->n_gid = buf_get_int32(bufp); ··· 284 } 285 286 /** 287 - * v9fs_deserialize_stat - decode a received metadata structure 288 * @buf: buffer to deserialize 289 * @buflen: length of received buffer 290 * @stat: metadata structure to decode into 291 - * @extended: non-zero if 9P2000.u 292 * 293 * Note: stat will point to the buf region. 294 */ 295 296 int 297 - v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat, 298 - int extended) 299 { 300 struct cbuf buffer; 301 struct cbuf *bufp = &buffer; ··· 303 304 buf_init(bufp, buf, buflen); 305 p = bufp->p; 306 - buf_get_stat(bufp, stat, extended); 307 308 if (buf_check_overflow(bufp)) 309 return 0; 310 else 311 return bufp->p - p; 312 } 313 314 /** 315 * deserialize_fcall - unmarshal a response ··· 318 * @buflen: length of received buffer 319 * @rcall: fcall structure to populate 320 * @rcalllen: length of fcall structure to populate 321 - * @extended: non-zero if 9P2000.u 322 * 323 */ 324 325 int 326 - v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, 327 - int extended) 328 { 329 330 struct cbuf buffer; ··· 337 rcall->id = buf_get_int8(bufp); 338 rcall->tag = buf_get_int16(bufp); 339 340 - dprintk(DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id, 341 - rcall->tag); 342 343 switch (rcall->id) { 344 default: 345 - eprintk(KERN_ERR, "unknown message type: %d\n", rcall->id); 346 return -EPROTO; 347 - case RVERSION: 348 rcall->params.rversion.msize = buf_get_int32(bufp); 349 buf_get_str(bufp, &rcall->params.rversion.version); 350 break; 351 - case RFLUSH: 352 break; 353 - case RATTACH: 354 rcall->params.rattach.qid.type = buf_get_int8(bufp); 355 rcall->params.rattach.qid.version = buf_get_int32(bufp); 356 rcall->params.rattach.qid.path = buf_get_int64(bufp); 357 break; 358 - case RWALK: 359 rcall->params.rwalk.nwqid = buf_get_int16(bufp); 360 - if (rcall->params.rwalk.nwqid > V9FS_MAXWELEM) { 361 - eprintk(KERN_ERR, "Rwalk with more than %d qids: %d\n", 362 - V9FS_MAXWELEM, rcall->params.rwalk.nwqid); 363 return -EPROTO; 364 } 365 366 for (i = 0; i < rcall->params.rwalk.nwqid; i++) 367 buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]); 368 break; 369 - case ROPEN: 370 buf_get_qid(bufp, &rcall->params.ropen.qid); 371 rcall->params.ropen.iounit = buf_get_int32(bufp); 372 break; 373 - case RCREATE: 374 buf_get_qid(bufp, &rcall->params.rcreate.qid); 375 rcall->params.rcreate.iounit = buf_get_int32(bufp); 376 break; 377 - case RREAD: 378 rcall->params.rread.count = buf_get_int32(bufp); 379 rcall->params.rread.data = bufp->p; 380 buf_check_size(bufp, rcall->params.rread.count); 381 break; 382 - case RWRITE: 383 rcall->params.rwrite.count = buf_get_int32(bufp); 384 break; 385 - case RCLUNK: 386 break; 387 - case RREMOVE: 388 break; 389 - case RSTAT: 390 buf_get_int16(bufp); 391 - buf_get_stat(bufp, &rcall->params.rstat.stat, extended); 392 break; 393 - case RWSTAT: 394 break; 395 - case RERROR: 396 buf_get_str(bufp, &rcall->params.rerror.error); 397 - if (extended) 398 rcall->params.rerror.errno = buf_get_int16(bufp); 399 break; 400 } 401 402 if (buf_check_overflow(bufp)) { 403 - dprintk(DEBUG_ERROR, "buffer overflow\n"); 404 return -EIO; 405 } 406 407 return bufp->p - bufp->sp; 408 } 409 410 - static inline void v9fs_put_int8(struct cbuf *bufp, u8 val, u8 * p) 411 { 412 *p = val; 413 buf_put_int8(bufp, val); 414 } 415 416 - static inline void v9fs_put_int16(struct cbuf *bufp, u16 val, u16 * p) 417 { 418 *p = val; 419 buf_put_int16(bufp, val); 420 } 421 422 - static inline void v9fs_put_int32(struct cbuf *bufp, u32 val, u32 * p) 423 { 424 *p = val; 425 buf_put_int32(bufp, val); 426 } 427 428 - static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p) 429 { 430 *p = val; 431 buf_put_int64(bufp, val); 432 } 433 434 static void 435 - v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str) 436 { 437 int len; 438 char *s; ··· 452 } 453 454 static int 455 - v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count, 456 unsigned char **pdata) 457 { 458 *pdata = buf_alloc(bufp, count); ··· 469 } 470 471 static void 472 - v9fs_put_wstat(struct cbuf *bufp, struct v9fs_wstat *wstat, 473 - struct v9fs_stat *stat, int statsz, int extended) 474 { 475 - v9fs_put_int16(bufp, statsz, &stat->size); 476 - v9fs_put_int16(bufp, wstat->type, &stat->type); 477 - v9fs_put_int32(bufp, wstat->dev, &stat->dev); 478 - v9fs_put_int8(bufp, wstat->qid.type, &stat->qid.type); 479 - v9fs_put_int32(bufp, wstat->qid.version, &stat->qid.version); 480 - v9fs_put_int64(bufp, wstat->qid.path, &stat->qid.path); 481 - v9fs_put_int32(bufp, wstat->mode, &stat->mode); 482 - v9fs_put_int32(bufp, wstat->atime, &stat->atime); 483 - v9fs_put_int32(bufp, wstat->mtime, &stat->mtime); 484 - v9fs_put_int64(bufp, wstat->length, &stat->length); 485 486 - v9fs_put_str(bufp, wstat->name, &stat->name); 487 - v9fs_put_str(bufp, wstat->uid, &stat->uid); 488 - v9fs_put_str(bufp, wstat->gid, &stat->gid); 489 - v9fs_put_str(bufp, wstat->muid, &stat->muid); 490 491 - if (extended) { 492 - v9fs_put_str(bufp, wstat->extension, &stat->extension); 493 - v9fs_put_int32(bufp, wstat->n_uid, &stat->n_uid); 494 - v9fs_put_int32(bufp, wstat->n_gid, &stat->n_gid); 495 - v9fs_put_int32(bufp, wstat->n_muid, &stat->n_muid); 496 } 497 } 498 499 - static struct v9fs_fcall * 500 - v9fs_create_common(struct cbuf *bufp, u32 size, u8 id) 501 { 502 - struct v9fs_fcall *fc; 503 504 size += 4 + 1 + 2; /* size[4] id[1] tag[2] */ 505 - fc = kmalloc(sizeof(struct v9fs_fcall) + size, GFP_KERNEL); 506 if (!fc) 507 return ERR_PTR(-ENOMEM); 508 509 fc->sdata = (char *)fc + sizeof(*fc); 510 511 buf_init(bufp, (char *)fc->sdata, size); 512 - v9fs_put_int32(bufp, size, &fc->size); 513 - v9fs_put_int8(bufp, id, &fc->id); 514 - v9fs_put_int16(bufp, V9FS_NOTAG, &fc->tag); 515 516 return fc; 517 } 518 519 - void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag) 520 { 521 fc->tag = tag; 522 *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag); 523 } 524 525 - struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version) 526 { 527 int size; 528 - struct v9fs_fcall *fc; 529 struct cbuf buffer; 530 struct cbuf *bufp = &buffer; 531 532 size = 4 + 2 + strlen(version); /* msize[4] version[s] */ 533 - fc = v9fs_create_common(bufp, size, TVERSION); 534 if (IS_ERR(fc)) 535 goto error; 536 537 - v9fs_put_int32(bufp, msize, &fc->params.tversion.msize); 538 - v9fs_put_str(bufp, version, &fc->params.tversion.version); 539 540 if (buf_check_overflow(bufp)) { 541 kfree(fc); 542 fc = ERR_PTR(-ENOMEM); 543 } 544 - error: 545 return fc; 546 } 547 548 - #if 0 549 - struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname) 550 { 551 int size; 552 - struct v9fs_fcall *fc; 553 struct cbuf buffer; 554 struct cbuf *bufp = &buffer; 555 556 - size = 4 + 2 + strlen(uname) + 2 + strlen(aname); /* afid[4] uname[s] aname[s] */ 557 - fc = v9fs_create_common(bufp, size, TAUTH); 558 if (IS_ERR(fc)) 559 goto error; 560 561 - v9fs_put_int32(bufp, afid, &fc->params.tauth.afid); 562 - v9fs_put_str(bufp, uname, &fc->params.tauth.uname); 563 - v9fs_put_str(bufp, aname, &fc->params.tauth.aname); 564 565 if (buf_check_overflow(bufp)) { 566 kfree(fc); 567 fc = ERR_PTR(-ENOMEM); 568 } 569 - error: 570 return fc; 571 } 572 - #endif /* 0 */ 573 574 - struct v9fs_fcall * 575 - v9fs_create_tattach(u32 fid, u32 afid, char *uname, char *aname) 576 { 577 int size; 578 - struct v9fs_fcall *fc; 579 struct cbuf buffer; 580 struct cbuf *bufp = &buffer; 581 582 - size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname); /* fid[4] afid[4] uname[s] aname[s] */ 583 - fc = v9fs_create_common(bufp, size, TATTACH); 584 if (IS_ERR(fc)) 585 goto error; 586 587 - v9fs_put_int32(bufp, fid, &fc->params.tattach.fid); 588 - v9fs_put_int32(bufp, afid, &fc->params.tattach.afid); 589 - v9fs_put_str(bufp, uname, &fc->params.tattach.uname); 590 - v9fs_put_str(bufp, aname, &fc->params.tattach.aname); 591 592 - error: 593 return fc; 594 } 595 596 - struct v9fs_fcall *v9fs_create_tflush(u16 oldtag) 597 { 598 int size; 599 - struct v9fs_fcall *fc; 600 struct cbuf buffer; 601 struct cbuf *bufp = &buffer; 602 603 size = 2; /* oldtag[2] */ 604 - fc = v9fs_create_common(bufp, size, TFLUSH); 605 if (IS_ERR(fc)) 606 goto error; 607 608 - v9fs_put_int16(bufp, oldtag, &fc->params.tflush.oldtag); 609 610 if (buf_check_overflow(bufp)) { 611 kfree(fc); 612 fc = ERR_PTR(-ENOMEM); 613 } 614 - error: 615 return fc; 616 } 617 618 - struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname, 619 char **wnames) 620 { 621 int i, size; 622 - struct v9fs_fcall *fc; 623 struct cbuf buffer; 624 struct cbuf *bufp = &buffer; 625 626 - if (nwname > V9FS_MAXWELEM) { 627 - dprintk(DEBUG_ERROR, "nwname > %d\n", V9FS_MAXWELEM); 628 return NULL; 629 } 630 ··· 638 size += 2 + strlen(wnames[i]); /* wname[s] */ 639 } 640 641 - fc = v9fs_create_common(bufp, size, TWALK); 642 if (IS_ERR(fc)) 643 goto error; 644 645 - v9fs_put_int32(bufp, fid, &fc->params.twalk.fid); 646 - v9fs_put_int32(bufp, newfid, &fc->params.twalk.newfid); 647 - v9fs_put_int16(bufp, nwname, &fc->params.twalk.nwname); 648 for (i = 0; i < nwname; i++) { 649 - v9fs_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]); 650 } 651 652 if (buf_check_overflow(bufp)) { 653 kfree(fc); 654 fc = ERR_PTR(-ENOMEM); 655 } 656 - error: 657 return fc; 658 } 659 660 - struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode) 661 { 662 int size; 663 - struct v9fs_fcall *fc; 664 struct cbuf buffer; 665 struct cbuf *bufp = &buffer; 666 667 size = 4 + 1; /* fid[4] mode[1] */ 668 - fc = v9fs_create_common(bufp, size, TOPEN); 669 if (IS_ERR(fc)) 670 goto error; 671 672 - v9fs_put_int32(bufp, fid, &fc->params.topen.fid); 673 - v9fs_put_int8(bufp, mode, &fc->params.topen.mode); 674 675 if (buf_check_overflow(bufp)) { 676 kfree(fc); 677 fc = ERR_PTR(-ENOMEM); 678 } 679 - error: 680 return fc; 681 } 682 683 - struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, 684 - char *extension, int extended) 685 { 686 int size; 687 - struct v9fs_fcall *fc; 688 struct cbuf buffer; 689 struct cbuf *bufp = &buffer; 690 691 - size = 4 + 2 + strlen(name) + 4 + 1; /* fid[4] name[s] perm[4] mode[1] */ 692 - if (extended) { 693 size += 2 + /* extension[s] */ 694 (extension == NULL ? 0 : strlen(extension)); 695 } 696 697 - fc = v9fs_create_common(bufp, size, TCREATE); 698 if (IS_ERR(fc)) 699 goto error; 700 701 - v9fs_put_int32(bufp, fid, &fc->params.tcreate.fid); 702 - v9fs_put_str(bufp, name, &fc->params.tcreate.name); 703 - v9fs_put_int32(bufp, perm, &fc->params.tcreate.perm); 704 - v9fs_put_int8(bufp, mode, &fc->params.tcreate.mode); 705 - if (extended) 706 - v9fs_put_str(bufp, extension, &fc->params.tcreate.extension); 707 708 if (buf_check_overflow(bufp)) { 709 kfree(fc); 710 fc = ERR_PTR(-ENOMEM); 711 } 712 - error: 713 return fc; 714 } 715 716 - struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count) 717 { 718 int size; 719 - struct v9fs_fcall *fc; 720 struct cbuf buffer; 721 struct cbuf *bufp = &buffer; 722 723 size = 4 + 8 + 4; /* fid[4] offset[8] count[4] */ 724 - fc = v9fs_create_common(bufp, size, TREAD); 725 if (IS_ERR(fc)) 726 goto error; 727 728 - v9fs_put_int32(bufp, fid, &fc->params.tread.fid); 729 - v9fs_put_int64(bufp, offset, &fc->params.tread.offset); 730 - v9fs_put_int32(bufp, count, &fc->params.tread.count); 731 732 if (buf_check_overflow(bufp)) { 733 kfree(fc); 734 fc = ERR_PTR(-ENOMEM); 735 } 736 - error: 737 return fc; 738 } 739 740 - struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count, 741 - const char __user * data) 742 { 743 int size, err; 744 - struct v9fs_fcall *fc; 745 struct cbuf buffer; 746 struct cbuf *bufp = &buffer; 747 748 - size = 4 + 8 + 4 + count; /* fid[4] offset[8] count[4] data[count] */ 749 - fc = v9fs_create_common(bufp, size, TWRITE); 750 if (IS_ERR(fc)) 751 goto error; 752 753 - v9fs_put_int32(bufp, fid, &fc->params.twrite.fid); 754 - v9fs_put_int64(bufp, offset, &fc->params.twrite.offset); 755 - v9fs_put_int32(bufp, count, &fc->params.twrite.count); 756 - err = v9fs_put_user_data(bufp, data, count, &fc->params.twrite.data); 757 if (err) { 758 kfree(fc); 759 fc = ERR_PTR(err); ··· 769 kfree(fc); 770 fc = ERR_PTR(-ENOMEM); 771 } 772 - error: 773 return fc; 774 } 775 776 - struct v9fs_fcall *v9fs_create_tclunk(u32 fid) 777 { 778 - int size; 779 - struct v9fs_fcall *fc; 780 struct cbuf buffer; 781 struct cbuf *bufp = &buffer; 782 783 - size = 4; /* fid[4] */ 784 - fc = v9fs_create_common(bufp, size, TCLUNK); 785 if (IS_ERR(fc)) 786 goto error; 787 788 - v9fs_put_int32(bufp, fid, &fc->params.tclunk.fid); 789 790 if (buf_check_overflow(bufp)) { 791 kfree(fc); 792 fc = ERR_PTR(-ENOMEM); 793 } 794 - error: 795 return fc; 796 } 797 798 - struct v9fs_fcall *v9fs_create_tremove(u32 fid) 799 { 800 int size; 801 - struct v9fs_fcall *fc; 802 struct cbuf buffer; 803 struct cbuf *bufp = &buffer; 804 805 size = 4; /* fid[4] */ 806 - fc = v9fs_create_common(bufp, size, TREMOVE); 807 if (IS_ERR(fc)) 808 goto error; 809 810 - v9fs_put_int32(bufp, fid, &fc->params.tremove.fid); 811 812 if (buf_check_overflow(bufp)) { 813 kfree(fc); 814 fc = ERR_PTR(-ENOMEM); 815 } 816 - error: 817 return fc; 818 } 819 820 - struct v9fs_fcall *v9fs_create_tstat(u32 fid) 821 { 822 int size; 823 - struct v9fs_fcall *fc; 824 struct cbuf buffer; 825 struct cbuf *bufp = &buffer; 826 827 size = 4; /* fid[4] */ 828 - fc = v9fs_create_common(bufp, size, TSTAT); 829 if (IS_ERR(fc)) 830 goto error; 831 832 - v9fs_put_int32(bufp, fid, &fc->params.tstat.fid); 833 834 if (buf_check_overflow(bufp)) { 835 kfree(fc); 836 fc = ERR_PTR(-ENOMEM); 837 } 838 - error: 839 return fc; 840 } 841 842 - struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat, 843 - int extended) 844 { 845 int size, statsz; 846 - struct v9fs_fcall *fc; 847 struct cbuf buffer; 848 struct cbuf *bufp = &buffer; 849 850 - statsz = v9fs_size_wstat(wstat, extended); 851 size = 4 + 2 + 2 + statsz; /* fid[4] stat[n] */ 852 - fc = v9fs_create_common(bufp, size, TWSTAT); 853 if (IS_ERR(fc)) 854 goto error; 855 856 - v9fs_put_int32(bufp, fid, &fc->params.twstat.fid); 857 buf_put_int16(bufp, statsz + 2); 858 - v9fs_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, extended); 859 860 if (buf_check_overflow(bufp)) { 861 kfree(fc); 862 fc = ERR_PTR(-ENOMEM); 863 } 864 - error: 865 return fc; 866 }
··· 1 /* 2 + * net/9p/conv.c 3 * 4 * 9P protocol conversion functions 5 * ··· 29 #include <linux/fs.h> 30 #include <linux/sched.h> 31 #include <linux/idr.h> 32 + #include <linux/uaccess.h> 33 + #include <net/9p/9p.h> 34 35 /* 36 * Buffer to help with string parsing ··· 59 { 60 if (buf->p + len > buf->ep) { 61 if (buf->p < buf->ep) { 62 + P9_EPRINTK(KERN_ERR, 63 + "buffer overflow: want %d has %d\n", len, 64 + (int)(buf->ep - buf->p)); 65 dump_stack(); 66 buf->p = buf->ep + 1; 67 } ··· 183 return ret; 184 } 185 186 + static void buf_get_str(struct cbuf *buf, struct p9_str *vstr) 187 { 188 vstr->len = buf_get_int16(buf); 189 if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) { ··· 195 } 196 } 197 198 + static void buf_get_qid(struct cbuf *bufp, struct p9_qid *qid) 199 { 200 qid->type = buf_get_int8(bufp); 201 qid->version = buf_get_int32(bufp); ··· 203 } 204 205 /** 206 + * p9_size_wstat - calculate the size of a variable length stat struct 207 * @stat: metadata (stat) structure 208 + * @dotu: non-zero if 9P2000.u 209 * 210 */ 211 212 + static int p9_size_wstat(struct p9_wstat *wstat, int dotu) 213 { 214 int size = 0; 215 216 if (wstat == NULL) { 217 + P9_EPRINTK(KERN_ERR, "p9_size_stat: got a NULL stat pointer\n"); 218 return 0; 219 } 220 ··· 239 if (wstat->muid) 240 size += strlen(wstat->muid); 241 242 + if (dotu) { 243 size += 4 + /* n_uid[4] */ 244 4 + /* n_gid[4] */ 245 4 + /* n_muid[4] */ ··· 255 * buf_get_stat - safely decode a recieved metadata (stat) structure 256 * @bufp: buffer to deserialize 257 * @stat: metadata (stat) structure 258 + * @dotu: non-zero if 9P2000.u 259 * 260 */ 261 262 static void 263 + buf_get_stat(struct cbuf *bufp, struct p9_stat *stat, int dotu) 264 { 265 stat->size = buf_get_int16(bufp); 266 stat->type = buf_get_int16(bufp); ··· 277 buf_get_str(bufp, &stat->gid); 278 buf_get_str(bufp, &stat->muid); 279 280 + if (dotu) { 281 buf_get_str(bufp, &stat->extension); 282 stat->n_uid = buf_get_int32(bufp); 283 stat->n_gid = buf_get_int32(bufp); ··· 286 } 287 288 /** 289 + * p9_deserialize_stat - decode a received metadata structure 290 * @buf: buffer to deserialize 291 * @buflen: length of received buffer 292 * @stat: metadata structure to decode into 293 + * @dotu: non-zero if 9P2000.u 294 * 295 * Note: stat will point to the buf region. 296 */ 297 298 int 299 + p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat, 300 + int dotu) 301 { 302 struct cbuf buffer; 303 struct cbuf *bufp = &buffer; ··· 305 306 buf_init(bufp, buf, buflen); 307 p = bufp->p; 308 + buf_get_stat(bufp, stat, dotu); 309 310 if (buf_check_overflow(bufp)) 311 return 0; 312 else 313 return bufp->p - p; 314 } 315 + EXPORT_SYMBOL(p9_deserialize_stat); 316 317 /** 318 * deserialize_fcall - unmarshal a response ··· 319 * @buflen: length of received buffer 320 * @rcall: fcall structure to populate 321 * @rcalllen: length of fcall structure to populate 322 + * @dotu: non-zero if 9P2000.u 323 * 324 */ 325 326 int 327 + p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *rcall, 328 + int dotu) 329 { 330 331 struct cbuf buffer; ··· 338 rcall->id = buf_get_int8(bufp); 339 rcall->tag = buf_get_int16(bufp); 340 341 + P9_DPRINTK(P9_DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, 342 + rcall->id, rcall->tag); 343 344 switch (rcall->id) { 345 default: 346 + P9_EPRINTK(KERN_ERR, "unknown message type: %d\n", rcall->id); 347 return -EPROTO; 348 + case P9_RVERSION: 349 rcall->params.rversion.msize = buf_get_int32(bufp); 350 buf_get_str(bufp, &rcall->params.rversion.version); 351 break; 352 + case P9_RFLUSH: 353 break; 354 + case P9_RATTACH: 355 rcall->params.rattach.qid.type = buf_get_int8(bufp); 356 rcall->params.rattach.qid.version = buf_get_int32(bufp); 357 rcall->params.rattach.qid.path = buf_get_int64(bufp); 358 break; 359 + case P9_RWALK: 360 rcall->params.rwalk.nwqid = buf_get_int16(bufp); 361 + if (rcall->params.rwalk.nwqid > P9_MAXWELEM) { 362 + P9_EPRINTK(KERN_ERR, 363 + "Rwalk with more than %d qids: %d\n", 364 + P9_MAXWELEM, rcall->params.rwalk.nwqid); 365 return -EPROTO; 366 } 367 368 for (i = 0; i < rcall->params.rwalk.nwqid; i++) 369 buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]); 370 break; 371 + case P9_ROPEN: 372 buf_get_qid(bufp, &rcall->params.ropen.qid); 373 rcall->params.ropen.iounit = buf_get_int32(bufp); 374 break; 375 + case P9_RCREATE: 376 buf_get_qid(bufp, &rcall->params.rcreate.qid); 377 rcall->params.rcreate.iounit = buf_get_int32(bufp); 378 break; 379 + case P9_RREAD: 380 rcall->params.rread.count = buf_get_int32(bufp); 381 rcall->params.rread.data = bufp->p; 382 buf_check_size(bufp, rcall->params.rread.count); 383 break; 384 + case P9_RWRITE: 385 rcall->params.rwrite.count = buf_get_int32(bufp); 386 break; 387 + case P9_RCLUNK: 388 break; 389 + case P9_RREMOVE: 390 break; 391 + case P9_RSTAT: 392 buf_get_int16(bufp); 393 + buf_get_stat(bufp, &rcall->params.rstat.stat, dotu); 394 break; 395 + case P9_RWSTAT: 396 break; 397 + case P9_RERROR: 398 buf_get_str(bufp, &rcall->params.rerror.error); 399 + if (dotu) 400 rcall->params.rerror.errno = buf_get_int16(bufp); 401 break; 402 } 403 404 if (buf_check_overflow(bufp)) { 405 + P9_DPRINTK(P9_DEBUG_ERROR, "buffer overflow\n"); 406 return -EIO; 407 } 408 409 return bufp->p - bufp->sp; 410 } 411 + EXPORT_SYMBOL(p9_deserialize_fcall); 412 413 + static inline void p9_put_int8(struct cbuf *bufp, u8 val, u8 * p) 414 { 415 *p = val; 416 buf_put_int8(bufp, val); 417 } 418 419 + static inline void p9_put_int16(struct cbuf *bufp, u16 val, u16 * p) 420 { 421 *p = val; 422 buf_put_int16(bufp, val); 423 } 424 425 + static inline void p9_put_int32(struct cbuf *bufp, u32 val, u32 * p) 426 { 427 *p = val; 428 buf_put_int32(bufp, val); 429 } 430 431 + static inline void p9_put_int64(struct cbuf *bufp, u64 val, u64 * p) 432 { 433 *p = val; 434 buf_put_int64(bufp, val); 435 } 436 437 static void 438 + p9_put_str(struct cbuf *bufp, char *data, struct p9_str *str) 439 { 440 int len; 441 char *s; ··· 451 } 452 453 static int 454 + p9_put_data(struct cbuf *bufp, const char *data, int count, 455 + unsigned char **pdata) 456 + { 457 + *pdata = buf_alloc(bufp, count); 458 + memmove(*pdata, data, count); 459 + return count; 460 + } 461 + 462 + static int 463 + p9_put_user_data(struct cbuf *bufp, const char __user *data, int count, 464 unsigned char **pdata) 465 { 466 *pdata = buf_alloc(bufp, count); ··· 459 } 460 461 static void 462 + p9_put_wstat(struct cbuf *bufp, struct p9_wstat *wstat, 463 + struct p9_stat *stat, int statsz, int dotu) 464 { 465 + p9_put_int16(bufp, statsz, &stat->size); 466 + p9_put_int16(bufp, wstat->type, &stat->type); 467 + p9_put_int32(bufp, wstat->dev, &stat->dev); 468 + p9_put_int8(bufp, wstat->qid.type, &stat->qid.type); 469 + p9_put_int32(bufp, wstat->qid.version, &stat->qid.version); 470 + p9_put_int64(bufp, wstat->qid.path, &stat->qid.path); 471 + p9_put_int32(bufp, wstat->mode, &stat->mode); 472 + p9_put_int32(bufp, wstat->atime, &stat->atime); 473 + p9_put_int32(bufp, wstat->mtime, &stat->mtime); 474 + p9_put_int64(bufp, wstat->length, &stat->length); 475 476 + p9_put_str(bufp, wstat->name, &stat->name); 477 + p9_put_str(bufp, wstat->uid, &stat->uid); 478 + p9_put_str(bufp, wstat->gid, &stat->gid); 479 + p9_put_str(bufp, wstat->muid, &stat->muid); 480 481 + if (dotu) { 482 + p9_put_str(bufp, wstat->extension, &stat->extension); 483 + p9_put_int32(bufp, wstat->n_uid, &stat->n_uid); 484 + p9_put_int32(bufp, wstat->n_gid, &stat->n_gid); 485 + p9_put_int32(bufp, wstat->n_muid, &stat->n_muid); 486 } 487 } 488 489 + static struct p9_fcall * 490 + p9_create_common(struct cbuf *bufp, u32 size, u8 id) 491 { 492 + struct p9_fcall *fc; 493 494 size += 4 + 1 + 2; /* size[4] id[1] tag[2] */ 495 + fc = kmalloc(sizeof(struct p9_fcall) + size, GFP_KERNEL); 496 if (!fc) 497 return ERR_PTR(-ENOMEM); 498 499 fc->sdata = (char *)fc + sizeof(*fc); 500 501 buf_init(bufp, (char *)fc->sdata, size); 502 + p9_put_int32(bufp, size, &fc->size); 503 + p9_put_int8(bufp, id, &fc->id); 504 + p9_put_int16(bufp, P9_NOTAG, &fc->tag); 505 506 return fc; 507 } 508 509 + void p9_set_tag(struct p9_fcall *fc, u16 tag) 510 { 511 fc->tag = tag; 512 *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag); 513 } 514 + EXPORT_SYMBOL(p9_set_tag); 515 516 + struct p9_fcall *p9_create_tversion(u32 msize, char *version) 517 { 518 int size; 519 + struct p9_fcall *fc; 520 struct cbuf buffer; 521 struct cbuf *bufp = &buffer; 522 523 size = 4 + 2 + strlen(version); /* msize[4] version[s] */ 524 + fc = p9_create_common(bufp, size, P9_TVERSION); 525 if (IS_ERR(fc)) 526 goto error; 527 528 + p9_put_int32(bufp, msize, &fc->params.tversion.msize); 529 + p9_put_str(bufp, version, &fc->params.tversion.version); 530 531 if (buf_check_overflow(bufp)) { 532 kfree(fc); 533 fc = ERR_PTR(-ENOMEM); 534 } 535 + error: 536 return fc; 537 } 538 + EXPORT_SYMBOL(p9_create_tversion); 539 540 + struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname) 541 { 542 int size; 543 + struct p9_fcall *fc; 544 struct cbuf buffer; 545 struct cbuf *bufp = &buffer; 546 547 + /* afid[4] uname[s] aname[s] */ 548 + size = 4 + 2 + strlen(uname) + 2 + strlen(aname); 549 + fc = p9_create_common(bufp, size, P9_TAUTH); 550 if (IS_ERR(fc)) 551 goto error; 552 553 + p9_put_int32(bufp, afid, &fc->params.tauth.afid); 554 + p9_put_str(bufp, uname, &fc->params.tauth.uname); 555 + p9_put_str(bufp, aname, &fc->params.tauth.aname); 556 557 if (buf_check_overflow(bufp)) { 558 kfree(fc); 559 fc = ERR_PTR(-ENOMEM); 560 } 561 + error: 562 return fc; 563 } 564 + EXPORT_SYMBOL(p9_create_tauth); 565 566 + struct p9_fcall * 567 + p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname) 568 { 569 int size; 570 + struct p9_fcall *fc; 571 struct cbuf buffer; 572 struct cbuf *bufp = &buffer; 573 574 + /* fid[4] afid[4] uname[s] aname[s] */ 575 + size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname); 576 + fc = p9_create_common(bufp, size, P9_TATTACH); 577 if (IS_ERR(fc)) 578 goto error; 579 580 + p9_put_int32(bufp, fid, &fc->params.tattach.fid); 581 + p9_put_int32(bufp, afid, &fc->params.tattach.afid); 582 + p9_put_str(bufp, uname, &fc->params.tattach.uname); 583 + p9_put_str(bufp, aname, &fc->params.tattach.aname); 584 585 + error: 586 return fc; 587 } 588 + EXPORT_SYMBOL(p9_create_tattach); 589 590 + struct p9_fcall *p9_create_tflush(u16 oldtag) 591 { 592 int size; 593 + struct p9_fcall *fc; 594 struct cbuf buffer; 595 struct cbuf *bufp = &buffer; 596 597 size = 2; /* oldtag[2] */ 598 + fc = p9_create_common(bufp, size, P9_TFLUSH); 599 if (IS_ERR(fc)) 600 goto error; 601 602 + p9_put_int16(bufp, oldtag, &fc->params.tflush.oldtag); 603 604 if (buf_check_overflow(bufp)) { 605 kfree(fc); 606 fc = ERR_PTR(-ENOMEM); 607 } 608 + error: 609 return fc; 610 } 611 + EXPORT_SYMBOL(p9_create_tflush); 612 613 + struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname, 614 char **wnames) 615 { 616 int i, size; 617 + struct p9_fcall *fc; 618 struct cbuf buffer; 619 struct cbuf *bufp = &buffer; 620 621 + if (nwname > P9_MAXWELEM) { 622 + P9_DPRINTK(P9_DEBUG_ERROR, "nwname > %d\n", P9_MAXWELEM); 623 return NULL; 624 } 625 ··· 623 size += 2 + strlen(wnames[i]); /* wname[s] */ 624 } 625 626 + fc = p9_create_common(bufp, size, P9_TWALK); 627 if (IS_ERR(fc)) 628 goto error; 629 630 + p9_put_int32(bufp, fid, &fc->params.twalk.fid); 631 + p9_put_int32(bufp, newfid, &fc->params.twalk.newfid); 632 + p9_put_int16(bufp, nwname, &fc->params.twalk.nwname); 633 for (i = 0; i < nwname; i++) { 634 + p9_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]); 635 } 636 637 if (buf_check_overflow(bufp)) { 638 kfree(fc); 639 fc = ERR_PTR(-ENOMEM); 640 } 641 + error: 642 return fc; 643 } 644 + EXPORT_SYMBOL(p9_create_twalk); 645 646 + struct p9_fcall *p9_create_topen(u32 fid, u8 mode) 647 { 648 int size; 649 + struct p9_fcall *fc; 650 struct cbuf buffer; 651 struct cbuf *bufp = &buffer; 652 653 size = 4 + 1; /* fid[4] mode[1] */ 654 + fc = p9_create_common(bufp, size, P9_TOPEN); 655 if (IS_ERR(fc)) 656 goto error; 657 658 + p9_put_int32(bufp, fid, &fc->params.topen.fid); 659 + p9_put_int8(bufp, mode, &fc->params.topen.mode); 660 661 if (buf_check_overflow(bufp)) { 662 kfree(fc); 663 fc = ERR_PTR(-ENOMEM); 664 } 665 + error: 666 return fc; 667 } 668 + EXPORT_SYMBOL(p9_create_topen); 669 670 + struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, 671 + char *extension, int dotu) 672 { 673 int size; 674 + struct p9_fcall *fc; 675 struct cbuf buffer; 676 struct cbuf *bufp = &buffer; 677 678 + /* fid[4] name[s] perm[4] mode[1] */ 679 + size = 4 + 2 + strlen(name) + 4 + 1; 680 + if (dotu) { 681 size += 2 + /* extension[s] */ 682 (extension == NULL ? 0 : strlen(extension)); 683 } 684 685 + fc = p9_create_common(bufp, size, P9_TCREATE); 686 if (IS_ERR(fc)) 687 goto error; 688 689 + p9_put_int32(bufp, fid, &fc->params.tcreate.fid); 690 + p9_put_str(bufp, name, &fc->params.tcreate.name); 691 + p9_put_int32(bufp, perm, &fc->params.tcreate.perm); 692 + p9_put_int8(bufp, mode, &fc->params.tcreate.mode); 693 + if (dotu) 694 + p9_put_str(bufp, extension, &fc->params.tcreate.extension); 695 696 if (buf_check_overflow(bufp)) { 697 kfree(fc); 698 fc = ERR_PTR(-ENOMEM); 699 } 700 + error: 701 return fc; 702 } 703 + EXPORT_SYMBOL(p9_create_tcreate); 704 705 + struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count) 706 { 707 int size; 708 + struct p9_fcall *fc; 709 struct cbuf buffer; 710 struct cbuf *bufp = &buffer; 711 712 size = 4 + 8 + 4; /* fid[4] offset[8] count[4] */ 713 + fc = p9_create_common(bufp, size, P9_TREAD); 714 if (IS_ERR(fc)) 715 goto error; 716 717 + p9_put_int32(bufp, fid, &fc->params.tread.fid); 718 + p9_put_int64(bufp, offset, &fc->params.tread.offset); 719 + p9_put_int32(bufp, count, &fc->params.tread.count); 720 721 if (buf_check_overflow(bufp)) { 722 kfree(fc); 723 fc = ERR_PTR(-ENOMEM); 724 } 725 + error: 726 return fc; 727 } 728 + EXPORT_SYMBOL(p9_create_tread); 729 730 + struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count, 731 + const char *data) 732 { 733 int size, err; 734 + struct p9_fcall *fc; 735 struct cbuf buffer; 736 struct cbuf *bufp = &buffer; 737 738 + /* fid[4] offset[8] count[4] data[count] */ 739 + size = 4 + 8 + 4 + count; 740 + fc = p9_create_common(bufp, size, P9_TWRITE); 741 if (IS_ERR(fc)) 742 goto error; 743 744 + p9_put_int32(bufp, fid, &fc->params.twrite.fid); 745 + p9_put_int64(bufp, offset, &fc->params.twrite.offset); 746 + p9_put_int32(bufp, count, &fc->params.twrite.count); 747 + err = p9_put_data(bufp, data, count, &fc->params.twrite.data); 748 if (err) { 749 kfree(fc); 750 fc = ERR_PTR(err); ··· 748 kfree(fc); 749 fc = ERR_PTR(-ENOMEM); 750 } 751 + error: 752 return fc; 753 } 754 + EXPORT_SYMBOL(p9_create_twrite); 755 756 + struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count, 757 + const char __user *data) 758 { 759 + int size, err; 760 + struct p9_fcall *fc; 761 struct cbuf buffer; 762 struct cbuf *bufp = &buffer; 763 764 + /* fid[4] offset[8] count[4] data[count] */ 765 + size = 4 + 8 + 4 + count; 766 + fc = p9_create_common(bufp, size, P9_TWRITE); 767 if (IS_ERR(fc)) 768 goto error; 769 770 + p9_put_int32(bufp, fid, &fc->params.twrite.fid); 771 + p9_put_int64(bufp, offset, &fc->params.twrite.offset); 772 + p9_put_int32(bufp, count, &fc->params.twrite.count); 773 + err = p9_put_user_data(bufp, data, count, &fc->params.twrite.data); 774 + if (err) { 775 + kfree(fc); 776 + fc = ERR_PTR(err); 777 + } 778 779 if (buf_check_overflow(bufp)) { 780 kfree(fc); 781 fc = ERR_PTR(-ENOMEM); 782 } 783 + error: 784 return fc; 785 } 786 + EXPORT_SYMBOL(p9_create_twrite_u); 787 788 + struct p9_fcall *p9_create_tclunk(u32 fid) 789 { 790 int size; 791 + struct p9_fcall *fc; 792 struct cbuf buffer; 793 struct cbuf *bufp = &buffer; 794 795 size = 4; /* fid[4] */ 796 + fc = p9_create_common(bufp, size, P9_TCLUNK); 797 if (IS_ERR(fc)) 798 goto error; 799 800 + p9_put_int32(bufp, fid, &fc->params.tclunk.fid); 801 802 if (buf_check_overflow(bufp)) { 803 kfree(fc); 804 fc = ERR_PTR(-ENOMEM); 805 } 806 + error: 807 return fc; 808 } 809 + EXPORT_SYMBOL(p9_create_tclunk); 810 811 + struct p9_fcall *p9_create_tremove(u32 fid) 812 { 813 int size; 814 + struct p9_fcall *fc; 815 struct cbuf buffer; 816 struct cbuf *bufp = &buffer; 817 818 size = 4; /* fid[4] */ 819 + fc = p9_create_common(bufp, size, P9_TREMOVE); 820 if (IS_ERR(fc)) 821 goto error; 822 823 + p9_put_int32(bufp, fid, &fc->params.tremove.fid); 824 825 if (buf_check_overflow(bufp)) { 826 kfree(fc); 827 fc = ERR_PTR(-ENOMEM); 828 } 829 + error: 830 return fc; 831 } 832 + EXPORT_SYMBOL(p9_create_tremove); 833 834 + struct p9_fcall *p9_create_tstat(u32 fid) 835 + { 836 + int size; 837 + struct p9_fcall *fc; 838 + struct cbuf buffer; 839 + struct cbuf *bufp = &buffer; 840 + 841 + size = 4; /* fid[4] */ 842 + fc = p9_create_common(bufp, size, P9_TSTAT); 843 + if (IS_ERR(fc)) 844 + goto error; 845 + 846 + p9_put_int32(bufp, fid, &fc->params.tstat.fid); 847 + 848 + if (buf_check_overflow(bufp)) { 849 + kfree(fc); 850 + fc = ERR_PTR(-ENOMEM); 851 + } 852 + error: 853 + return fc; 854 + } 855 + EXPORT_SYMBOL(p9_create_tstat); 856 + 857 + struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat, 858 + int dotu) 859 { 860 int size, statsz; 861 + struct p9_fcall *fc; 862 struct cbuf buffer; 863 struct cbuf *bufp = &buffer; 864 865 + statsz = p9_size_wstat(wstat, dotu); 866 size = 4 + 2 + 2 + statsz; /* fid[4] stat[n] */ 867 + fc = p9_create_common(bufp, size, P9_TWSTAT); 868 if (IS_ERR(fc)) 869 goto error; 870 871 + p9_put_int32(bufp, fid, &fc->params.twstat.fid); 872 buf_put_int16(bufp, statsz + 2); 873 + p9_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, dotu); 874 875 if (buf_check_overflow(bufp)) { 876 kfree(fc); 877 fc = ERR_PTR(-ENOMEM); 878 } 879 + error: 880 return fc; 881 } 882 + EXPORT_SYMBOL(p9_create_twstat);
-50
fs/9p/conv.h
··· 1 - /* 2 - * linux/fs/9p/conv.h 3 - * 4 - * 9P protocol conversion definitions. 5 - * 6 - * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net> 7 - * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 8 - * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 9 - * 10 - * This program is free software; you can redistribute it and/or modify 11 - * it under the terms of the GNU General Public License version 2 12 - * as published by the Free Software Foundation. 13 - * 14 - * This program is distributed in the hope that it will be useful, 15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 - * GNU General Public License for more details. 18 - * 19 - * You should have received a copy of the GNU General Public License 20 - * along with this program; if not, write to: 21 - * Free Software Foundation 22 - * 51 Franklin Street, Fifth Floor 23 - * Boston, MA 02111-1301 USA 24 - * 25 - */ 26 - 27 - int v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat, 28 - int extended); 29 - int v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, 30 - int extended); 31 - 32 - void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag); 33 - 34 - struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version); 35 - struct v9fs_fcall *v9fs_create_tattach(u32 fid, u32 afid, char *uname, 36 - char *aname); 37 - struct v9fs_fcall *v9fs_create_tflush(u16 oldtag); 38 - struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname, 39 - char **wnames); 40 - struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode); 41 - struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, 42 - char *extension, int extended); 43 - struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count); 44 - struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count, 45 - const char __user *data); 46 - struct v9fs_fcall *v9fs_create_tclunk(u32 fid); 47 - struct v9fs_fcall *v9fs_create_tremove(u32 fid); 48 - struct v9fs_fcall *v9fs_create_tstat(u32 fid); 49 - struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat, 50 - int extended);
···
-77
fs/9p/debug.h
··· 1 - /* 2 - * linux/fs/9p/debug.h - V9FS Debug Definitions 3 - * 4 - * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 5 - * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 6 - * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License version 2 9 - * as published by the Free Software Foundation. 10 - * 11 - * This program is distributed in the hope that it will be useful, 12 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 - * GNU General Public License for more details. 15 - * 16 - * You should have received a copy of the GNU General Public License 17 - * along with this program; if not, write to: 18 - * Free Software Foundation 19 - * 51 Franklin Street, Fifth Floor 20 - * Boston, MA 02111-1301 USA 21 - * 22 - */ 23 - 24 - #define DEBUG_ERROR (1<<0) 25 - #define DEBUG_CURRENT (1<<1) 26 - #define DEBUG_9P (1<<2) 27 - #define DEBUG_VFS (1<<3) 28 - #define DEBUG_CONV (1<<4) 29 - #define DEBUG_MUX (1<<5) 30 - #define DEBUG_TRANS (1<<6) 31 - #define DEBUG_SLABS (1<<7) 32 - #define DEBUG_FCALL (1<<8) 33 - 34 - #define DEBUG_DUMP_PKT 0 35 - 36 - extern int v9fs_debug_level; 37 - 38 - #define dprintk(level, format, arg...) \ 39 - do { \ 40 - if((v9fs_debug_level & level)==level) \ 41 - printk(KERN_NOTICE "-- %s (%d): " \ 42 - format , __FUNCTION__, current->pid , ## arg); \ 43 - } while(0) 44 - 45 - #define eprintk(level, format, arg...) \ 46 - do { \ 47 - printk(level "v9fs: %s (%d): " \ 48 - format , __FUNCTION__, current->pid , ## arg); \ 49 - } while(0) 50 - 51 - #if DEBUG_DUMP_PKT 52 - static inline void dump_data(const unsigned char *data, unsigned int datalen) 53 - { 54 - int i, n; 55 - char buf[5*8]; 56 - 57 - n = 0; 58 - i = 0; 59 - while (i < datalen) { 60 - n += snprintf(buf+n, sizeof(buf)-n, "%02x", data[i++]); 61 - if (i%4 == 0) 62 - n += snprintf(buf+n, sizeof(buf)-n, " "); 63 - 64 - if (i%16 == 0) { 65 - dprintk(DEBUG_ERROR, "%s\n", buf); 66 - n = 0; 67 - } 68 - } 69 - 70 - dprintk(DEBUG_ERROR, "%s\n", buf); 71 - } 72 - #else /* DEBUG_DUMP_PKT */ 73 - static inline void dump_data(const unsigned char *data, unsigned int datalen) 74 - { 75 - 76 - } 77 - #endif /* DEBUG_DUMP_PKT */
···
-93
fs/9p/error.c
··· 1 - /* 2 - * linux/fs/9p/error.c 3 - * 4 - * Error string handling 5 - * 6 - * Plan 9 uses error strings, Unix uses error numbers. These functions 7 - * try to help manage that and provide for dynamically adding error 8 - * mappings. 9 - * 10 - * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 11 - * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 12 - * 13 - * This program is free software; you can redistribute it and/or modify 14 - * it under the terms of the GNU General Public License version 2 15 - * as published by the Free Software Foundation. 16 - * 17 - * This program is distributed in the hope that it will be useful, 18 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 - * GNU General Public License for more details. 21 - * 22 - * You should have received a copy of the GNU General Public License 23 - * along with this program; if not, write to: 24 - * Free Software Foundation 25 - * 51 Franklin Street, Fifth Floor 26 - * Boston, MA 02111-1301 USA 27 - * 28 - */ 29 - 30 - #include <linux/module.h> 31 - 32 - #include <linux/list.h> 33 - #include <linux/jhash.h> 34 - 35 - #include "debug.h" 36 - #include "error.h" 37 - 38 - /** 39 - * v9fs_error_init - preload 40 - * @errstr: error string 41 - * 42 - */ 43 - 44 - int v9fs_error_init(void) 45 - { 46 - struct errormap *c; 47 - int bucket; 48 - 49 - /* initialize hash table */ 50 - for (bucket = 0; bucket < ERRHASHSZ; bucket++) 51 - INIT_HLIST_HEAD(&hash_errmap[bucket]); 52 - 53 - /* load initial error map into hash table */ 54 - for (c = errmap; c->name != NULL; c++) { 55 - c->namelen = strlen(c->name); 56 - bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ; 57 - INIT_HLIST_NODE(&c->list); 58 - hlist_add_head(&c->list, &hash_errmap[bucket]); 59 - } 60 - 61 - return 1; 62 - } 63 - 64 - /** 65 - * errstr2errno - convert error string to error number 66 - * @errstr: error string 67 - * 68 - */ 69 - 70 - int v9fs_errstr2errno(char *errstr, int len) 71 - { 72 - int errno = 0; 73 - struct hlist_node *p = NULL; 74 - struct errormap *c = NULL; 75 - int bucket = jhash(errstr, len, 0) % ERRHASHSZ; 76 - 77 - hlist_for_each_entry(c, p, &hash_errmap[bucket], list) { 78 - if (c->namelen==len && !memcmp(c->name, errstr, len)) { 79 - errno = c->val; 80 - break; 81 - } 82 - } 83 - 84 - if (errno == 0) { 85 - /* TODO: if error isn't found, add it dynamically */ 86 - errstr[len] = 0; 87 - printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__, 88 - errstr); 89 - errno = 1; 90 - } 91 - 92 - return -errno; 93 - }
···
+71 -8
fs/9p/error.h net/9p/error.c
··· 1 /* 2 - * linux/fs/9p/error.h 3 * 4 - * Huge Nasty Error Table 5 * 6 - * Plan 9 uses error strings, Unix uses error numbers. This table tries to 7 - * match UNIX strings and Plan 9 strings to unix error numbers. It is used 8 - * to preload the dynamic error table which can also track user-specific error 9 - * strings. 10 * 11 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 12 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> ··· 27 * 28 */ 29 30 #include <linux/errno.h> 31 - #include <asm/errno.h> 32 33 struct errormap { 34 char *name; ··· 176 {NULL, -1} 177 }; 178 179 - extern int v9fs_error_init(void);
··· 1 /* 2 + * linux/fs/9p/error.c 3 * 4 + * Error string handling 5 * 6 + * Plan 9 uses error strings, Unix uses error numbers. These functions 7 + * try to help manage that and provide for dynamically adding error 8 + * mappings. 9 * 10 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 11 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> ··· 28 * 29 */ 30 31 + #include <linux/module.h> 32 + #include <linux/list.h> 33 + #include <linux/jhash.h> 34 #include <linux/errno.h> 35 + #include <net/9p/9p.h> 36 37 struct errormap { 38 char *name; ··· 174 {NULL, -1} 175 }; 176 177 + /** 178 + * p9_error_init - preload 179 + * @errstr: error string 180 + * 181 + */ 182 + 183 + int p9_error_init(void) 184 + { 185 + struct errormap *c; 186 + int bucket; 187 + 188 + /* initialize hash table */ 189 + for (bucket = 0; bucket < ERRHASHSZ; bucket++) 190 + INIT_HLIST_HEAD(&hash_errmap[bucket]); 191 + 192 + /* load initial error map into hash table */ 193 + for (c = errmap; c->name != NULL; c++) { 194 + c->namelen = strlen(c->name); 195 + bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ; 196 + INIT_HLIST_NODE(&c->list); 197 + hlist_add_head(&c->list, &hash_errmap[bucket]); 198 + } 199 + 200 + return 1; 201 + } 202 + EXPORT_SYMBOL(p9_error_init); 203 + 204 + /** 205 + * errstr2errno - convert error string to error number 206 + * @errstr: error string 207 + * 208 + */ 209 + 210 + int p9_errstr2errno(char *errstr, int len) 211 + { 212 + int errno; 213 + struct hlist_node *p; 214 + struct errormap *c; 215 + int bucket; 216 + 217 + errno = 0; 218 + p = NULL; 219 + c = NULL; 220 + bucket = jhash(errstr, len, 0) % ERRHASHSZ; 221 + hlist_for_each_entry(c, p, &hash_errmap[bucket], list) { 222 + if (c->namelen == len && !memcmp(c->name, errstr, len)) { 223 + errno = c->val; 224 + break; 225 + } 226 + } 227 + 228 + if (errno == 0) { 229 + /* TODO: if error isn't found, add it dynamically */ 230 + errstr[len] = 0; 231 + printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__, 232 + errstr); 233 + errno = 1; 234 + } 235 + 236 + return -errno; 237 + } 238 + EXPORT_SYMBOL(p9_errstr2errno);
-427
fs/9p/fcall.c
··· 1 - /* 2 - * linux/fs/9p/fcall.c 3 - * 4 - * This file contains functions to perform synchronous 9P calls 5 - * 6 - * Copyright (C) 2004 by Latchesar Ionkov <lucho@ionkov.net> 7 - * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 8 - * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 9 - * 10 - * This program is free software; you can redistribute it and/or modify 11 - * it under the terms of the GNU General Public License version 2 12 - * as published by the Free Software Foundation. 13 - * 14 - * This program is distributed in the hope that it will be useful, 15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 - * GNU General Public License for more details. 18 - * 19 - * You should have received a copy of the GNU General Public License 20 - * along with this program; if not, write to: 21 - * Free Software Foundation 22 - * 51 Franklin Street, Fifth Floor 23 - * Boston, MA 02111-1301 USA 24 - * 25 - */ 26 - 27 - #include <linux/module.h> 28 - #include <linux/errno.h> 29 - #include <linux/fs.h> 30 - #include <linux/sched.h> 31 - #include <linux/idr.h> 32 - 33 - #include "debug.h" 34 - #include "v9fs.h" 35 - #include "9p.h" 36 - #include "conv.h" 37 - #include "mux.h" 38 - 39 - /** 40 - * v9fs_t_version - negotiate protocol parameters with sever 41 - * @v9ses: 9P2000 session information 42 - * @msize: requested max size packet 43 - * @version: requested version.extension string 44 - * @fcall: pointer to response fcall pointer 45 - * 46 - */ 47 - 48 - int 49 - v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize, 50 - char *version, struct v9fs_fcall **rcp) 51 - { 52 - int ret; 53 - struct v9fs_fcall *tc; 54 - 55 - dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version); 56 - tc = v9fs_create_tversion(msize, version); 57 - 58 - if (!IS_ERR(tc)) { 59 - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); 60 - kfree(tc); 61 - } else 62 - ret = PTR_ERR(tc); 63 - 64 - return ret; 65 - } 66 - 67 - /** 68 - * v9fs_t_attach - mount the server 69 - * @v9ses: 9P2000 session information 70 - * @uname: user name doing the attach 71 - * @aname: remote name being attached to 72 - * @fid: mount fid to attatch to root node 73 - * @afid: authentication fid (in this case result key) 74 - * @fcall: pointer to response fcall pointer 75 - * 76 - */ 77 - 78 - int 79 - v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname, 80 - u32 fid, u32 afid, struct v9fs_fcall **rcp) 81 - { 82 - int ret; 83 - struct v9fs_fcall* tc; 84 - 85 - dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname, 86 - aname, fid, afid); 87 - 88 - tc = v9fs_create_tattach(fid, afid, uname, aname); 89 - if (!IS_ERR(tc)) { 90 - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); 91 - kfree(tc); 92 - } else 93 - ret = PTR_ERR(tc); 94 - 95 - return ret; 96 - } 97 - 98 - static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc, 99 - struct v9fs_fcall *rc, int err) 100 - { 101 - int fid, id; 102 - struct v9fs_session_info *v9ses; 103 - 104 - id = 0; 105 - fid = tc->params.tclunk.fid; 106 - if (rc) 107 - id = rc->id; 108 - 109 - kfree(tc); 110 - kfree(rc); 111 - if (id == RCLUNK) { 112 - v9ses = a; 113 - v9fs_put_idpool(fid, &v9ses->fidpool); 114 - } 115 - } 116 - 117 - /** 118 - * v9fs_t_clunk - release a fid (finish a transaction) 119 - * @v9ses: 9P2000 session information 120 - * @fid: fid to release 121 - * @fcall: pointer to response fcall pointer 122 - * 123 - */ 124 - 125 - int 126 - v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid) 127 - { 128 - int ret; 129 - struct v9fs_fcall *tc, *rc; 130 - 131 - dprintk(DEBUG_9P, "fid %d\n", fid); 132 - 133 - rc = NULL; 134 - tc = v9fs_create_tclunk(fid); 135 - if (!IS_ERR(tc)) 136 - ret = v9fs_mux_rpc(v9ses->mux, tc, &rc); 137 - else 138 - ret = PTR_ERR(tc); 139 - 140 - if (ret) 141 - dprintk(DEBUG_ERROR, "failed fid %d err %d\n", fid, ret); 142 - 143 - v9fs_t_clunk_cb(v9ses, tc, rc, ret); 144 - return ret; 145 - } 146 - 147 - #if 0 148 - /** 149 - * v9fs_v9fs_t_flush - flush a pending transaction 150 - * @v9ses: 9P2000 session information 151 - * @tag: tag to release 152 - * 153 - */ 154 - int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag) 155 - { 156 - int ret; 157 - struct v9fs_fcall *tc; 158 - 159 - dprintk(DEBUG_9P, "oldtag %d\n", oldtag); 160 - 161 - tc = v9fs_create_tflush(oldtag); 162 - if (!IS_ERR(tc)) { 163 - ret = v9fs_mux_rpc(v9ses->mux, tc, NULL); 164 - kfree(tc); 165 - } else 166 - ret = PTR_ERR(tc); 167 - 168 - return ret; 169 - } 170 - #endif 171 - 172 - /** 173 - * v9fs_t_stat - read a file's meta-data 174 - * @v9ses: 9P2000 session information 175 - * @fid: fid pointing to file or directory to get info about 176 - * @fcall: pointer to response fcall 177 - * 178 - */ 179 - 180 - int 181 - v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **rcp) 182 - { 183 - int ret; 184 - struct v9fs_fcall *tc; 185 - 186 - dprintk(DEBUG_9P, "fid %d\n", fid); 187 - 188 - ret = -ENOMEM; 189 - tc = v9fs_create_tstat(fid); 190 - if (!IS_ERR(tc)) { 191 - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); 192 - kfree(tc); 193 - } else 194 - ret = PTR_ERR(tc); 195 - 196 - return ret; 197 - } 198 - 199 - /** 200 - * v9fs_t_wstat - write a file's meta-data 201 - * @v9ses: 9P2000 session information 202 - * @fid: fid pointing to file or directory to write info about 203 - * @stat: metadata 204 - * @fcall: pointer to response fcall 205 - * 206 - */ 207 - 208 - int 209 - v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid, 210 - struct v9fs_wstat *wstat, struct v9fs_fcall **rcp) 211 - { 212 - int ret; 213 - struct v9fs_fcall *tc; 214 - 215 - dprintk(DEBUG_9P, "fid %d\n", fid); 216 - 217 - tc = v9fs_create_twstat(fid, wstat, v9ses->extended); 218 - if (!IS_ERR(tc)) { 219 - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); 220 - kfree(tc); 221 - } else 222 - ret = PTR_ERR(tc); 223 - 224 - return ret; 225 - } 226 - 227 - /** 228 - * v9fs_t_walk - walk a fid to a new file or directory 229 - * @v9ses: 9P2000 session information 230 - * @fid: fid to walk 231 - * @newfid: new fid (for clone operations) 232 - * @name: path to walk fid to 233 - * @fcall: pointer to response fcall 234 - * 235 - */ 236 - 237 - /* TODO: support multiple walk */ 238 - 239 - int 240 - v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid, 241 - char *name, struct v9fs_fcall **rcp) 242 - { 243 - int ret; 244 - struct v9fs_fcall *tc; 245 - int nwname; 246 - 247 - dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name); 248 - 249 - if (name) 250 - nwname = 1; 251 - else 252 - nwname = 0; 253 - 254 - tc = v9fs_create_twalk(fid, newfid, nwname, &name); 255 - if (!IS_ERR(tc)) { 256 - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); 257 - kfree(tc); 258 - } else 259 - ret = PTR_ERR(tc); 260 - 261 - return ret; 262 - } 263 - 264 - /** 265 - * v9fs_t_open - open a file 266 - * 267 - * @v9ses - 9P2000 session information 268 - * @fid - fid to open 269 - * @mode - mode to open file (R, RW, etc) 270 - * @fcall - pointer to response fcall 271 - * 272 - */ 273 - 274 - int 275 - v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode, 276 - struct v9fs_fcall **rcp) 277 - { 278 - int ret; 279 - struct v9fs_fcall *tc; 280 - 281 - dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode); 282 - 283 - tc = v9fs_create_topen(fid, mode); 284 - if (!IS_ERR(tc)) { 285 - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); 286 - kfree(tc); 287 - } else 288 - ret = PTR_ERR(tc); 289 - 290 - return ret; 291 - } 292 - 293 - /** 294 - * v9fs_t_remove - remove a file or directory 295 - * @v9ses: 9P2000 session information 296 - * @fid: fid to remove 297 - * @fcall: pointer to response fcall 298 - * 299 - */ 300 - 301 - int 302 - v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid, 303 - struct v9fs_fcall **rcp) 304 - { 305 - int ret; 306 - struct v9fs_fcall *tc; 307 - 308 - dprintk(DEBUG_9P, "fid %d\n", fid); 309 - 310 - tc = v9fs_create_tremove(fid); 311 - if (!IS_ERR(tc)) { 312 - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); 313 - kfree(tc); 314 - } else 315 - ret = PTR_ERR(tc); 316 - 317 - return ret; 318 - } 319 - 320 - /** 321 - * v9fs_t_create - create a file or directory 322 - * @v9ses: 9P2000 session information 323 - * @fid: fid to create 324 - * @name: name of the file or directory to create 325 - * @perm: permissions to create with 326 - * @mode: mode to open file (R, RW, etc) 327 - * @fcall: pointer to response fcall 328 - * 329 - */ 330 - 331 - int 332 - v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, u32 perm, 333 - u8 mode, char *extension, struct v9fs_fcall **rcp) 334 - { 335 - int ret; 336 - struct v9fs_fcall *tc; 337 - 338 - dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n", 339 - fid, name, perm, mode); 340 - 341 - tc = v9fs_create_tcreate(fid, name, perm, mode, extension, 342 - v9ses->extended); 343 - 344 - if (!IS_ERR(tc)) { 345 - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); 346 - kfree(tc); 347 - } else 348 - ret = PTR_ERR(tc); 349 - 350 - return ret; 351 - } 352 - 353 - /** 354 - * v9fs_t_read - read data 355 - * @v9ses: 9P2000 session information 356 - * @fid: fid to read from 357 - * @offset: offset to start read at 358 - * @count: how many bytes to read 359 - * @fcall: pointer to response fcall (with data) 360 - * 361 - */ 362 - 363 - int 364 - v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset, 365 - u32 count, struct v9fs_fcall **rcp) 366 - { 367 - int ret; 368 - struct v9fs_fcall *tc, *rc; 369 - 370 - dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid, 371 - (long long unsigned) offset, count); 372 - 373 - tc = v9fs_create_tread(fid, offset, count); 374 - if (!IS_ERR(tc)) { 375 - ret = v9fs_mux_rpc(v9ses->mux, tc, &rc); 376 - if (!ret) 377 - ret = rc->params.rread.count; 378 - if (rcp) 379 - *rcp = rc; 380 - else 381 - kfree(rc); 382 - 383 - kfree(tc); 384 - } else 385 - ret = PTR_ERR(tc); 386 - 387 - return ret; 388 - } 389 - 390 - /** 391 - * v9fs_t_write - write data 392 - * @v9ses: 9P2000 session information 393 - * @fid: fid to write to 394 - * @offset: offset to start write at 395 - * @count: how many bytes to write 396 - * @fcall: pointer to response fcall 397 - * 398 - */ 399 - 400 - int 401 - v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, u32 count, 402 - const char __user *data, struct v9fs_fcall **rcp) 403 - { 404 - int ret; 405 - struct v9fs_fcall *tc, *rc; 406 - 407 - dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid, 408 - (long long unsigned) offset, count); 409 - 410 - tc = v9fs_create_twrite(fid, offset, count, data); 411 - if (!IS_ERR(tc)) { 412 - ret = v9fs_mux_rpc(v9ses->mux, tc, &rc); 413 - 414 - if (!ret) 415 - ret = rc->params.rwrite.count; 416 - if (rcp) 417 - *rcp = rc; 418 - else 419 - kfree(rc); 420 - 421 - kfree(tc); 422 - } else 423 - ret = PTR_ERR(tc); 424 - 425 - return ret; 426 - } 427 -
···
+100 -87
fs/9p/fcprint.c net/9p/fcprint.c
··· 1 /* 2 - * linux/fs/9p/fcprint.c 3 * 4 * Print 9P call. 5 * ··· 25 #include <linux/errno.h> 26 #include <linux/fs.h> 27 #include <linux/idr.h> 28 29 - #include "debug.h" 30 - #include "v9fs.h" 31 - #include "9p.h" 32 - #include "mux.h" 33 34 static int 35 - v9fs_printqid(char *buf, int buflen, struct v9fs_qid *q) 36 { 37 int n; 38 char b[10]; 39 40 n = 0; 41 - if (q->type & V9FS_QTDIR) 42 b[n++] = 'd'; 43 - if (q->type & V9FS_QTAPPEND) 44 b[n++] = 'a'; 45 - if (q->type & V9FS_QTAUTH) 46 b[n++] = 'A'; 47 - if (q->type & V9FS_QTEXCL) 48 b[n++] = 'l'; 49 - if (q->type & V9FS_QTTMP) 50 b[n++] = 't'; 51 - if (q->type & V9FS_QTSYMLINK) 52 b[n++] = 'L'; 53 b[n] = '\0'; 54 55 - return scnprintf(buf, buflen, "(%.16llx %x %s)", (long long int) q->path, 56 - q->version, b); 57 } 58 59 static int 60 - v9fs_printperm(char *buf, int buflen, int perm) 61 { 62 int n; 63 char b[15]; 64 65 n = 0; 66 - if (perm & V9FS_DMDIR) 67 b[n++] = 'd'; 68 - if (perm & V9FS_DMAPPEND) 69 b[n++] = 'a'; 70 - if (perm & V9FS_DMAUTH) 71 b[n++] = 'A'; 72 - if (perm & V9FS_DMEXCL) 73 b[n++] = 'l'; 74 - if (perm & V9FS_DMTMP) 75 b[n++] = 't'; 76 - if (perm & V9FS_DMDEVICE) 77 b[n++] = 'D'; 78 - if (perm & V9FS_DMSOCKET) 79 b[n++] = 'S'; 80 - if (perm & V9FS_DMNAMEDPIPE) 81 b[n++] = 'P'; 82 - if (perm & V9FS_DMSYMLINK) 83 b[n++] = 'L'; 84 b[n] = '\0'; 85 ··· 85 } 86 87 static int 88 - v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended) 89 { 90 int n; 91 ··· 103 n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid); 104 105 n += scnprintf(buf+n, buflen-n, " q "); 106 - n += v9fs_printqid(buf+n, buflen-n, &st->qid); 107 n += scnprintf(buf+n, buflen-n, " m "); 108 - n += v9fs_printperm(buf+n, buflen-n, st->mode); 109 n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld", 110 st->atime, st->mtime, (long long int) st->length); 111 ··· 117 } 118 119 static int 120 - v9fs_dumpdata(char *buf, int buflen, u8 *data, int datalen) 121 { 122 int i, n; 123 ··· 137 } 138 139 static int 140 - v9fs_printdata(char *buf, int buflen, u8 *data, int datalen) 141 { 142 - return v9fs_dumpdata(buf, buflen, data, datalen<16?datalen:16); 143 } 144 145 int 146 - v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended) 147 { 148 int i, ret, type, tag; 149 ··· 155 156 ret = 0; 157 switch (type) { 158 - case TVERSION: 159 ret += scnprintf(buf+ret, buflen-ret, 160 - "Tversion tag %u msize %u version '%.*s'", tag, 161 - fc->params.tversion.msize, fc->params.tversion.version.len, 162 - fc->params.tversion.version.str); 163 break; 164 165 - case RVERSION: 166 ret += scnprintf(buf+ret, buflen-ret, 167 - "Rversion tag %u msize %u version '%.*s'", tag, 168 - fc->params.rversion.msize, fc->params.rversion.version.len, 169 - fc->params.rversion.version.str); 170 break; 171 172 - case TAUTH: 173 ret += scnprintf(buf+ret, buflen-ret, 174 "Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag, 175 fc->params.tauth.afid, fc->params.tauth.uname.len, ··· 179 fc->params.tauth.aname.str); 180 break; 181 182 - case RAUTH: 183 ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag); 184 - v9fs_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid); 185 break; 186 187 - case TATTACH: 188 ret += scnprintf(buf+ret, buflen-ret, 189 - "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'", 190 - tag, fc->params.tattach.fid, fc->params.tattach.afid, 191 - fc->params.tattach.uname.len, fc->params.tattach.uname.str, 192 - fc->params.tattach.aname.len, fc->params.tattach.aname.str); 193 break; 194 195 - case RATTACH: 196 - ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ", tag); 197 - v9fs_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid); 198 break; 199 200 - case RERROR: 201 - ret += scnprintf(buf+ret, buflen-ret, "Rerror tag %u ename '%.*s'", 202 - tag, fc->params.rerror.error.len, 203 - fc->params.rerror.error.str); 204 if (extended) 205 ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n", 206 fc->params.rerror.errno); 207 break; 208 209 - case TFLUSH: 210 ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u", 211 tag, fc->params.tflush.oldtag); 212 break; 213 214 - case RFLUSH: 215 ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag); 216 break; 217 218 - case TWALK: 219 ret += scnprintf(buf+ret, buflen-ret, 220 "Twalk tag %u fid %d newfid %d nwname %d", tag, 221 fc->params.twalk.fid, fc->params.twalk.newfid, 222 fc->params.twalk.nwname); 223 - for(i = 0; i < fc->params.twalk.nwname; i++) 224 - ret += scnprintf(buf+ret, buflen-ret," '%.*s'", 225 fc->params.twalk.wnames[i].len, 226 fc->params.twalk.wnames[i].str); 227 break; 228 229 - case RWALK: 230 ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d", 231 tag, fc->params.rwalk.nwqid); 232 - for(i = 0; i < fc->params.rwalk.nwqid; i++) 233 - ret += v9fs_printqid(buf+ret, buflen-ret, 234 &fc->params.rwalk.wqids[i]); 235 break; 236 237 - case TOPEN: 238 ret += scnprintf(buf+ret, buflen-ret, 239 "Topen tag %u fid %d mode %d", tag, 240 fc->params.topen.fid, fc->params.topen.mode); 241 break; 242 243 - case ROPEN: 244 ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag); 245 - ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid); 246 - ret += scnprintf(buf+ret, buflen-ret," iounit %d", 247 fc->params.ropen.iounit); 248 break; 249 250 - case TCREATE: 251 ret += scnprintf(buf+ret, buflen-ret, 252 "Tcreate tag %u fid %d name '%.*s' perm ", tag, 253 fc->params.tcreate.fid, fc->params.tcreate.name.len, 254 fc->params.tcreate.name.str); 255 256 - ret += v9fs_printperm(buf+ret, buflen-ret, fc->params.tcreate.perm); 257 ret += scnprintf(buf+ret, buflen-ret, " mode %d", 258 fc->params.tcreate.mode); 259 break; 260 261 - case RCREATE: 262 ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag); 263 - ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.rcreate.qid); 264 ret += scnprintf(buf+ret, buflen-ret, " iounit %d", 265 fc->params.rcreate.iounit); 266 break; 267 268 - case TREAD: 269 ret += scnprintf(buf+ret, buflen-ret, 270 "Tread tag %u fid %d offset %lld count %u", tag, 271 fc->params.tread.fid, ··· 277 fc->params.tread.count); 278 break; 279 280 - case RREAD: 281 ret += scnprintf(buf+ret, buflen-ret, 282 "Rread tag %u count %u data ", tag, 283 fc->params.rread.count); 284 - ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.rread.data, 285 fc->params.rread.count); 286 break; 287 288 - case TWRITE: 289 ret += scnprintf(buf+ret, buflen-ret, 290 "Twrite tag %u fid %d offset %lld count %u data ", 291 tag, fc->params.twrite.fid, 292 (long long int) fc->params.twrite.offset, 293 fc->params.twrite.count); 294 - ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.twrite.data, 295 fc->params.twrite.count); 296 break; 297 298 - case RWRITE: 299 ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u", 300 tag, fc->params.rwrite.count); 301 break; 302 303 - case TCLUNK: 304 ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d", 305 tag, fc->params.tclunk.fid); 306 break; 307 308 - case RCLUNK: 309 ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag); 310 break; 311 312 - case TREMOVE: 313 ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d", 314 tag, fc->params.tremove.fid); 315 break; 316 317 - case RREMOVE: 318 ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag); 319 break; 320 321 - case TSTAT: 322 ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d", 323 tag, fc->params.tstat.fid); 324 break; 325 326 - case RSTAT: 327 ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag); 328 - ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat, 329 extended); 330 break; 331 332 - case TWSTAT: 333 ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ", 334 tag, fc->params.twstat.fid); 335 - ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.twstat.stat, 336 - extended); 337 break; 338 339 - case RWSTAT: 340 ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag); 341 break; 342 ··· 347 348 return ret; 349 }
··· 1 /* 2 + * net/9p/fcprint.c 3 * 4 * Print 9P call. 5 * ··· 25 #include <linux/errno.h> 26 #include <linux/fs.h> 27 #include <linux/idr.h> 28 + #include <net/9p/9p.h> 29 30 + #ifdef CONFIG_NET_9P_DEBUG 31 32 static int 33 + p9_printqid(char *buf, int buflen, struct p9_qid *q) 34 { 35 int n; 36 char b[10]; 37 38 n = 0; 39 + if (q->type & P9_QTDIR) 40 b[n++] = 'd'; 41 + if (q->type & P9_QTAPPEND) 42 b[n++] = 'a'; 43 + if (q->type & P9_QTAUTH) 44 b[n++] = 'A'; 45 + if (q->type & P9_QTEXCL) 46 b[n++] = 'l'; 47 + if (q->type & P9_QTTMP) 48 b[n++] = 't'; 49 + if (q->type & P9_QTSYMLINK) 50 b[n++] = 'L'; 51 b[n] = '\0'; 52 53 + return scnprintf(buf, buflen, "(%.16llx %x %s)", 54 + (long long int) q->path, q->version, b); 55 } 56 57 static int 58 + p9_printperm(char *buf, int buflen, int perm) 59 { 60 int n; 61 char b[15]; 62 63 n = 0; 64 + if (perm & P9_DMDIR) 65 b[n++] = 'd'; 66 + if (perm & P9_DMAPPEND) 67 b[n++] = 'a'; 68 + if (perm & P9_DMAUTH) 69 b[n++] = 'A'; 70 + if (perm & P9_DMEXCL) 71 b[n++] = 'l'; 72 + if (perm & P9_DMTMP) 73 b[n++] = 't'; 74 + if (perm & P9_DMDEVICE) 75 b[n++] = 'D'; 76 + if (perm & P9_DMSOCKET) 77 b[n++] = 'S'; 78 + if (perm & P9_DMNAMEDPIPE) 79 b[n++] = 'P'; 80 + if (perm & P9_DMSYMLINK) 81 b[n++] = 'L'; 82 b[n] = '\0'; 83 ··· 87 } 88 89 static int 90 + p9_printstat(char *buf, int buflen, struct p9_stat *st, int extended) 91 { 92 int n; 93 ··· 105 n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid); 106 107 n += scnprintf(buf+n, buflen-n, " q "); 108 + n += p9_printqid(buf+n, buflen-n, &st->qid); 109 n += scnprintf(buf+n, buflen-n, " m "); 110 + n += p9_printperm(buf+n, buflen-n, st->mode); 111 n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld", 112 st->atime, st->mtime, (long long int) st->length); 113 ··· 119 } 120 121 static int 122 + p9_dumpdata(char *buf, int buflen, u8 *data, int datalen) 123 { 124 int i, n; 125 ··· 139 } 140 141 static int 142 + p9_printdata(char *buf, int buflen, u8 *data, int datalen) 143 { 144 + return p9_dumpdata(buf, buflen, data, datalen < 16?datalen:16); 145 } 146 147 int 148 + p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended) 149 { 150 int i, ret, type, tag; 151 ··· 157 158 ret = 0; 159 switch (type) { 160 + case P9_TVERSION: 161 ret += scnprintf(buf+ret, buflen-ret, 162 + "Tversion tag %u msize %u version '%.*s'", tag, 163 + fc->params.tversion.msize, 164 + fc->params.tversion.version.len, 165 + fc->params.tversion.version.str); 166 break; 167 168 + case P9_RVERSION: 169 ret += scnprintf(buf+ret, buflen-ret, 170 + "Rversion tag %u msize %u version '%.*s'", tag, 171 + fc->params.rversion.msize, 172 + fc->params.rversion.version.len, 173 + fc->params.rversion.version.str); 174 break; 175 176 + case P9_TAUTH: 177 ret += scnprintf(buf+ret, buflen-ret, 178 "Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag, 179 fc->params.tauth.afid, fc->params.tauth.uname.len, ··· 179 fc->params.tauth.aname.str); 180 break; 181 182 + case P9_RAUTH: 183 ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag); 184 + p9_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid); 185 break; 186 187 + case P9_TATTACH: 188 ret += scnprintf(buf+ret, buflen-ret, 189 + "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'", tag, 190 + fc->params.tattach.fid, fc->params.tattach.afid, 191 + fc->params.tattach.uname.len, fc->params.tattach.uname.str, 192 + fc->params.tattach.aname.len, fc->params.tattach.aname.str); 193 break; 194 195 + case P9_RATTACH: 196 + ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ", 197 + tag); 198 + p9_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid); 199 break; 200 201 + case P9_RERROR: 202 + ret += scnprintf(buf+ret, buflen-ret, 203 + "Rerror tag %u ename '%.*s'", tag, 204 + fc->params.rerror.error.len, 205 + fc->params.rerror.error.str); 206 if (extended) 207 ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n", 208 fc->params.rerror.errno); 209 break; 210 211 + case P9_TFLUSH: 212 ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u", 213 tag, fc->params.tflush.oldtag); 214 break; 215 216 + case P9_RFLUSH: 217 ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag); 218 break; 219 220 + case P9_TWALK: 221 ret += scnprintf(buf+ret, buflen-ret, 222 "Twalk tag %u fid %d newfid %d nwname %d", tag, 223 fc->params.twalk.fid, fc->params.twalk.newfid, 224 fc->params.twalk.nwname); 225 + for (i = 0; i < fc->params.twalk.nwname; i++) 226 + ret += scnprintf(buf+ret, buflen-ret, " '%.*s'", 227 fc->params.twalk.wnames[i].len, 228 fc->params.twalk.wnames[i].str); 229 break; 230 231 + case P9_RWALK: 232 ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d", 233 tag, fc->params.rwalk.nwqid); 234 + for (i = 0; i < fc->params.rwalk.nwqid; i++) 235 + ret += p9_printqid(buf+ret, buflen-ret, 236 &fc->params.rwalk.wqids[i]); 237 break; 238 239 + case P9_TOPEN: 240 ret += scnprintf(buf+ret, buflen-ret, 241 "Topen tag %u fid %d mode %d", tag, 242 fc->params.topen.fid, fc->params.topen.mode); 243 break; 244 245 + case P9_ROPEN: 246 ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag); 247 + ret += p9_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid); 248 + ret += scnprintf(buf+ret, buflen-ret, " iounit %d", 249 fc->params.ropen.iounit); 250 break; 251 252 + case P9_TCREATE: 253 ret += scnprintf(buf+ret, buflen-ret, 254 "Tcreate tag %u fid %d name '%.*s' perm ", tag, 255 fc->params.tcreate.fid, fc->params.tcreate.name.len, 256 fc->params.tcreate.name.str); 257 258 + ret += p9_printperm(buf+ret, buflen-ret, 259 + fc->params.tcreate.perm); 260 ret += scnprintf(buf+ret, buflen-ret, " mode %d", 261 fc->params.tcreate.mode); 262 break; 263 264 + case P9_RCREATE: 265 ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag); 266 + ret += p9_printqid(buf+ret, buflen-ret, 267 + &fc->params.rcreate.qid); 268 ret += scnprintf(buf+ret, buflen-ret, " iounit %d", 269 fc->params.rcreate.iounit); 270 break; 271 272 + case P9_TREAD: 273 ret += scnprintf(buf+ret, buflen-ret, 274 "Tread tag %u fid %d offset %lld count %u", tag, 275 fc->params.tread.fid, ··· 273 fc->params.tread.count); 274 break; 275 276 + case P9_RREAD: 277 ret += scnprintf(buf+ret, buflen-ret, 278 "Rread tag %u count %u data ", tag, 279 fc->params.rread.count); 280 + ret += p9_printdata(buf+ret, buflen-ret, fc->params.rread.data, 281 fc->params.rread.count); 282 break; 283 284 + case P9_TWRITE: 285 ret += scnprintf(buf+ret, buflen-ret, 286 "Twrite tag %u fid %d offset %lld count %u data ", 287 tag, fc->params.twrite.fid, 288 (long long int) fc->params.twrite.offset, 289 fc->params.twrite.count); 290 + ret += p9_printdata(buf+ret, buflen-ret, fc->params.twrite.data, 291 fc->params.twrite.count); 292 break; 293 294 + case P9_RWRITE: 295 ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u", 296 tag, fc->params.rwrite.count); 297 break; 298 299 + case P9_TCLUNK: 300 ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d", 301 tag, fc->params.tclunk.fid); 302 break; 303 304 + case P9_RCLUNK: 305 ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag); 306 break; 307 308 + case P9_TREMOVE: 309 ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d", 310 tag, fc->params.tremove.fid); 311 break; 312 313 + case P9_RREMOVE: 314 ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag); 315 break; 316 317 + case P9_TSTAT: 318 ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d", 319 tag, fc->params.tstat.fid); 320 break; 321 322 + case P9_RSTAT: 323 ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag); 324 + ret += p9_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat, 325 extended); 326 break; 327 328 + case P9_TWSTAT: 329 ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ", 330 tag, fc->params.twstat.fid); 331 + ret += p9_printstat(buf+ret, buflen-ret, 332 + &fc->params.twstat.stat, extended); 333 break; 334 335 + case P9_RWSTAT: 336 ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag); 337 break; 338 ··· 343 344 return ret; 345 } 346 + 347 + #else 348 + int 349 + p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended) 350 + { 351 + return 0; 352 + } 353 + EXPORT_SYMBOL(p9_printfcall); 354 + #endif /* CONFIG_NET_9P_DEBUG */
+54 -114
fs/9p/fid.c
··· 26 #include <linux/sched.h> 27 #include <linux/idr.h> 28 #include <asm/semaphore.h> 29 30 - #include "debug.h" 31 #include "v9fs.h" 32 - #include "9p.h" 33 #include "v9fs_vfs.h" 34 #include "fid.h" 35 ··· 40 * 41 */ 42 43 - int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) 44 { 45 - struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; 46 - dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid, 47 - dentry->d_iname, dentry); 48 - if (dentry->d_fsdata == NULL) { 49 - dentry->d_fsdata = 50 - kmalloc(sizeof(struct list_head), GFP_KERNEL); 51 - if (dentry->d_fsdata == NULL) { 52 - dprintk(DEBUG_ERROR, "Out of memory\n"); 53 return -ENOMEM; 54 - } 55 - fid_list = (struct list_head *)dentry->d_fsdata; 56 - INIT_LIST_HEAD(fid_list); /* Initialize list head */ 57 } 58 59 - fid->uid = current->uid; 60 - list_add(&fid->list, fid_list); 61 return 0; 62 - } 63 - 64 - /** 65 - * v9fs_fid_create - allocate a FID structure 66 - * @dentry - dentry to link newly created fid to 67 - * 68 - */ 69 - 70 - struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid) 71 - { 72 - struct v9fs_fid *new; 73 - 74 - dprintk(DEBUG_9P, "fid create fid %d\n", fid); 75 - new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); 76 - if (new == NULL) { 77 - dprintk(DEBUG_ERROR, "Out of Memory\n"); 78 - return ERR_PTR(-ENOMEM); 79 - } 80 - 81 - new->fid = fid; 82 - new->v9ses = v9ses; 83 - new->fidopen = 0; 84 - new->fidclunked = 0; 85 - new->iounit = 0; 86 - new->rdir_pos = 0; 87 - new->rdir_fcall = NULL; 88 - init_MUTEX(&new->lock); 89 - INIT_LIST_HEAD(&new->list); 90 - 91 - return new; 92 - } 93 - 94 - /** 95 - * v9fs_fid_destroy - deallocate a FID structure 96 - * @fid: fid to destroy 97 - * 98 - */ 99 - 100 - void v9fs_fid_destroy(struct v9fs_fid *fid) 101 - { 102 - list_del(&fid->list); 103 - kfree(fid); 104 } 105 106 /** ··· 76 * 77 */ 78 79 - struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) 80 { 81 - struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; 82 - struct v9fs_fid *return_fid = NULL; 83 84 - dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); 85 86 - if (fid_list) 87 - return_fid = list_entry(fid_list->next, struct v9fs_fid, list); 88 89 - if (!return_fid) { 90 - dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n"); 91 - return_fid = ERR_PTR(-EBADF); 92 } 93 94 - if(down_interruptible(&return_fid->lock)) 95 - return ERR_PTR(-EINTR); 96 - 97 - return return_fid; 98 } 99 100 /** 101 * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and 102 - * release it 103 * @dentry: dentry to look for fid in 104 * 105 * find a fid in the dentry and then clone to a new private fid ··· 120 * 121 */ 122 123 - struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry) 124 { 125 - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); 126 - struct v9fs_fid *base_fid, *new_fid = ERR_PTR(-EBADF); 127 - struct v9fs_fcall *fcall = NULL; 128 - int fid, err; 129 130 - base_fid = v9fs_fid_lookup(dentry); 131 132 - if(IS_ERR(base_fid)) 133 - return base_fid; 134 - 135 - if(base_fid) { /* clone fid */ 136 - fid = v9fs_get_idpool(&v9ses->fidpool); 137 - if (fid < 0) { 138 - eprintk(KERN_WARNING, "newfid fails!\n"); 139 - new_fid = ERR_PTR(-ENOSPC); 140 - goto Release_Fid; 141 - } 142 - 143 - err = v9fs_t_walk(v9ses, base_fid->fid, fid, NULL, &fcall); 144 - if (err < 0) { 145 - dprintk(DEBUG_ERROR, "clone walk didn't work\n"); 146 - v9fs_put_idpool(fid, &v9ses->fidpool); 147 - new_fid = ERR_PTR(err); 148 - goto Free_Fcall; 149 - } 150 - new_fid = v9fs_fid_create(v9ses, fid); 151 - if (new_fid == NULL) { 152 - dprintk(DEBUG_ERROR, "out of memory\n"); 153 - new_fid = ERR_PTR(-ENOMEM); 154 - } 155 - Free_Fcall: 156 - kfree(fcall); 157 - } 158 - 159 - Release_Fid: 160 - up(&base_fid->lock); 161 - return new_fid; 162 - } 163 - 164 - void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid) 165 - { 166 - v9fs_t_clunk(v9ses, fid->fid); 167 - v9fs_fid_destroy(fid); 168 }
··· 26 #include <linux/sched.h> 27 #include <linux/idr.h> 28 #include <asm/semaphore.h> 29 + #include <net/9p/9p.h> 30 + #include <net/9p/client.h> 31 32 #include "v9fs.h" 33 #include "v9fs_vfs.h" 34 #include "fid.h" 35 ··· 40 * 41 */ 42 43 + int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid) 44 { 45 + struct v9fs_dentry *dent; 46 + 47 + P9_DPRINTK(P9_DEBUG_VFS, "fid %d dentry %s\n", 48 + fid->fid, dentry->d_iname); 49 + 50 + dent = dentry->d_fsdata; 51 + if (!dent) { 52 + dent = kmalloc(sizeof(struct v9fs_dentry), GFP_KERNEL); 53 + if (!dent) 54 return -ENOMEM; 55 + 56 + spin_lock_init(&dent->lock); 57 + INIT_LIST_HEAD(&dent->fidlist); 58 + dentry->d_fsdata = dent; 59 } 60 61 + spin_lock(&dent->lock); 62 + list_add(&fid->dlist, &dent->fidlist); 63 + spin_unlock(&dent->lock); 64 + 65 return 0; 66 } 67 68 /** ··· 114 * 115 */ 116 117 + struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) 118 { 119 + struct v9fs_dentry *dent; 120 + struct p9_fid *fid; 121 122 + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 123 + dent = dentry->d_fsdata; 124 + if (dent) 125 + fid = list_entry(dent->fidlist.next, struct p9_fid, dlist); 126 + else 127 + fid = ERR_PTR(-EBADF); 128 129 + P9_DPRINTK(P9_DEBUG_VFS, " fid: %p\n", fid); 130 + return fid; 131 + } 132 133 + struct p9_fid *v9fs_fid_lookup_remove(struct dentry *dentry) 134 + { 135 + struct p9_fid *fid; 136 + struct v9fs_dentry *dent; 137 + 138 + dent = dentry->d_fsdata; 139 + fid = v9fs_fid_lookup(dentry); 140 + if (!IS_ERR(fid)) { 141 + spin_lock(&dent->lock); 142 + list_del(&fid->dlist); 143 + spin_unlock(&dent->lock); 144 } 145 146 + return fid; 147 } 148 + 149 150 /** 151 * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and 152 + * release it 153 * @dentry: dentry to look for fid in 154 * 155 * find a fid in the dentry and then clone to a new private fid ··· 146 * 147 */ 148 149 + struct p9_fid *v9fs_fid_clone(struct dentry *dentry) 150 { 151 + struct p9_fid *ofid, *fid; 152 153 + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 154 + ofid = v9fs_fid_lookup(dentry); 155 + if (IS_ERR(ofid)) 156 + return ofid; 157 158 + fid = p9_client_walk(ofid, 0, NULL, 1); 159 + return fid; 160 }
+7 -36
fs/9p/fid.h
··· 22 23 #include <linux/list.h> 24 25 - #define FID_OP 0 26 - #define FID_WALK 1 27 - #define FID_CREATE 2 28 - 29 - struct v9fs_fid { 30 - struct list_head list; /* list of fids associated with a dentry */ 31 - struct list_head active; /* XXX - debug */ 32 - 33 - struct semaphore lock; 34 - 35 - u32 fid; 36 - unsigned char fidopen; /* set when fid is opened */ 37 - unsigned char fidclunked; /* set when fid has already been clunked */ 38 - 39 - struct v9fs_qid qid; 40 - u32 iounit; 41 - 42 - /* readdir stuff */ 43 - int rdir_fpos; 44 - loff_t rdir_pos; 45 - struct v9fs_fcall *rdir_fcall; 46 - 47 - /* management stuff */ 48 - uid_t uid; /* user associated with this fid */ 49 - 50 - /* private data */ 51 - struct file *filp; /* backpointer to File struct for open files */ 52 - struct v9fs_session_info *v9ses; /* session info for this FID */ 53 }; 54 55 - struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry); 56 - struct v9fs_fid *v9fs_fid_get_created(struct dentry *); 57 - void v9fs_fid_destroy(struct v9fs_fid *fid); 58 - struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid); 59 - int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry); 60 - struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry); 61 - void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid); 62 -
··· 22 23 #include <linux/list.h> 24 25 + struct v9fs_dentry { 26 + spinlock_t lock; /* protect fidlist */ 27 + struct list_head fidlist; 28 }; 29 30 + struct p9_fid *v9fs_fid_lookup(struct dentry *dentry); 31 + struct p9_fid *v9fs_fid_lookup_remove(struct dentry *dentry); 32 + struct p9_fid *v9fs_fid_clone(struct dentry *dentry); 33 + int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid);
+268 -247
fs/9p/mux.c net/9p/mux.c
··· 1 /* 2 - * linux/fs/9p/mux.c 3 * 4 * Protocol Multiplexer 5 * ··· 30 #include <linux/kthread.h> 31 #include <linux/idr.h> 32 #include <linux/mutex.h> 33 - 34 - #include "debug.h" 35 - #include "v9fs.h" 36 - #include "9p.h" 37 - #include "conv.h" 38 - #include "transport.h" 39 - #include "mux.h" 40 41 #define ERREQFLUSH 1 42 #define SCHED_TIMEOUT 10 ··· 51 Flushed, 52 }; 53 54 - struct v9fs_mux_poll_task; 55 56 - struct v9fs_req { 57 - spinlock_t lock; 58 int tag; 59 - struct v9fs_fcall *tcall; 60 - struct v9fs_fcall *rcall; 61 int err; 62 - v9fs_mux_req_callback cb; 63 void *cba; 64 int flush; 65 struct list_head req_list; 66 }; 67 68 - struct v9fs_mux_data { 69 - spinlock_t lock; 70 struct list_head mux_list; 71 - struct v9fs_mux_poll_task *poll_task; 72 int msize; 73 unsigned char *extended; 74 - struct v9fs_transport *trans; 75 - struct v9fs_idpool tagpool; 76 int err; 77 wait_queue_head_t equeue; 78 struct list_head req_list; 79 struct list_head unsent_req_list; 80 - struct v9fs_fcall *rcall; 81 int rpos; 82 char *rbuf; 83 int wpos; ··· 91 unsigned long wsched; 92 }; 93 94 - struct v9fs_mux_poll_task { 95 struct task_struct *task; 96 struct list_head mux_list; 97 int muxnum; 98 }; 99 100 - struct v9fs_mux_rpc { 101 - struct v9fs_mux_data *m; 102 int err; 103 - struct v9fs_fcall *tcall; 104 - struct v9fs_fcall *rcall; 105 wait_queue_head_t wqueue; 106 }; 107 108 - static int v9fs_poll_proc(void *); 109 - static void v9fs_read_work(struct work_struct *work); 110 - static void v9fs_write_work(struct work_struct *work); 111 - static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address, 112 poll_table * p); 113 - static u16 v9fs_mux_get_tag(struct v9fs_mux_data *); 114 - static void v9fs_mux_put_tag(struct v9fs_mux_data *, u16); 115 116 - static DEFINE_MUTEX(v9fs_mux_task_lock); 117 - static struct workqueue_struct *v9fs_mux_wq; 118 119 - static int v9fs_mux_num; 120 - static int v9fs_mux_poll_task_num; 121 - static struct v9fs_mux_poll_task v9fs_mux_poll_tasks[100]; 122 123 - int v9fs_mux_global_init(void) 124 { 125 int i; 126 127 - for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) 128 - v9fs_mux_poll_tasks[i].task = NULL; 129 130 - v9fs_mux_wq = create_workqueue("v9fs"); 131 - if (!v9fs_mux_wq) { 132 printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); 133 return -ENOMEM; 134 } ··· 136 return 0; 137 } 138 139 - void v9fs_mux_global_exit(void) 140 { 141 - destroy_workqueue(v9fs_mux_wq); 142 } 143 144 /** 145 - * v9fs_mux_calc_poll_procs - calculates the number of polling procs 146 * based on the number of mounted v9fs filesystems. 147 * 148 * The current implementation returns sqrt of the number of mounts. 149 */ 150 - static int v9fs_mux_calc_poll_procs(int muxnum) 151 { 152 int n; 153 154 - if (v9fs_mux_poll_task_num) 155 - n = muxnum / v9fs_mux_poll_task_num + 156 - (muxnum % v9fs_mux_poll_task_num ? 1 : 0); 157 else 158 n = 1; 159 160 - if (n > ARRAY_SIZE(v9fs_mux_poll_tasks)) 161 - n = ARRAY_SIZE(v9fs_mux_poll_tasks); 162 163 return n; 164 } 165 166 - static int v9fs_mux_poll_start(struct v9fs_mux_data *m) 167 { 168 int i, n; 169 - struct v9fs_mux_poll_task *vpt, *vptlast; 170 struct task_struct *pproc; 171 172 - dprintk(DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, v9fs_mux_num, 173 - v9fs_mux_poll_task_num); 174 - mutex_lock(&v9fs_mux_task_lock); 175 176 - n = v9fs_mux_calc_poll_procs(v9fs_mux_num + 1); 177 - if (n > v9fs_mux_poll_task_num) { 178 - for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) { 179 - if (v9fs_mux_poll_tasks[i].task == NULL) { 180 - vpt = &v9fs_mux_poll_tasks[i]; 181 - dprintk(DEBUG_MUX, "create proc %p\n", vpt); 182 - pproc = kthread_create(v9fs_poll_proc, vpt, 183 - "v9fs-poll"); 184 185 if (!IS_ERR(pproc)) { 186 vpt->task = pproc; 187 INIT_LIST_HEAD(&vpt->mux_list); 188 vpt->muxnum = 0; 189 - v9fs_mux_poll_task_num++; 190 wake_up_process(vpt->task); 191 } 192 break; 193 } 194 } 195 196 - if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks)) 197 - dprintk(DEBUG_ERROR, "warning: no free poll slots\n"); 198 } 199 200 - n = (v9fs_mux_num + 1) / v9fs_mux_poll_task_num + 201 - ((v9fs_mux_num + 1) % v9fs_mux_poll_task_num ? 1 : 0); 202 203 vptlast = NULL; 204 - for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) { 205 - vpt = &v9fs_mux_poll_tasks[i]; 206 if (vpt->task != NULL) { 207 vptlast = vpt; 208 if (vpt->muxnum < n) { 209 - dprintk(DEBUG_MUX, "put in proc %d\n", i); 210 list_add(&m->mux_list, &vpt->mux_list); 211 vpt->muxnum++; 212 m->poll_task = vpt; 213 - memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); 214 - init_poll_funcptr(&m->pt, v9fs_pollwait); 215 break; 216 } 217 } 218 } 219 220 - if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks)) { 221 if (vptlast == NULL) 222 return -ENOMEM; 223 224 - dprintk(DEBUG_MUX, "put in proc %d\n", i); 225 list_add(&m->mux_list, &vptlast->mux_list); 226 vptlast->muxnum++; 227 m->poll_task = vptlast; 228 memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); 229 - init_poll_funcptr(&m->pt, v9fs_pollwait); 230 } 231 232 - v9fs_mux_num++; 233 - mutex_unlock(&v9fs_mux_task_lock); 234 235 return 0; 236 } 237 238 - static void v9fs_mux_poll_stop(struct v9fs_mux_data *m) 239 { 240 int i; 241 - struct v9fs_mux_poll_task *vpt; 242 243 - mutex_lock(&v9fs_mux_task_lock); 244 vpt = m->poll_task; 245 list_del(&m->mux_list); 246 - for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { 247 if (m->poll_waddr[i] != NULL) { 248 remove_wait_queue(m->poll_waddr[i], &m->poll_wait[i]); 249 m->poll_waddr[i] = NULL; ··· 254 } 255 vpt->muxnum--; 256 if (!vpt->muxnum) { 257 - dprintk(DEBUG_MUX, "destroy proc %p\n", vpt); 258 kthread_stop(vpt->task); 259 vpt->task = NULL; 260 - v9fs_mux_poll_task_num--; 261 } 262 - v9fs_mux_num--; 263 - mutex_unlock(&v9fs_mux_task_lock); 264 } 265 266 /** 267 - * v9fs_mux_init - allocate and initialize the per-session mux data 268 * Creates the polling task if this is the first session. 269 * 270 * @trans - transport structure 271 * @msize - maximum message size 272 * @extended - pointer to the extended flag 273 */ 274 - struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize, 275 unsigned char *extended) 276 { 277 int i, n; 278 - struct v9fs_mux_data *m, *mtmp; 279 280 - dprintk(DEBUG_MUX, "transport %p msize %d\n", trans, msize); 281 - m = kmalloc(sizeof(struct v9fs_mux_data), GFP_KERNEL); 282 if (!m) 283 return ERR_PTR(-ENOMEM); 284 ··· 287 m->msize = msize; 288 m->extended = extended; 289 m->trans = trans; 290 - idr_init(&m->tagpool.pool); 291 - init_MUTEX(&m->tagpool.lock); 292 m->err = 0; 293 init_waitqueue_head(&m->equeue); 294 INIT_LIST_HEAD(&m->req_list); ··· 302 m->rbuf = NULL; 303 m->wpos = m->wsize = 0; 304 m->wbuf = NULL; 305 - INIT_WORK(&m->rq, v9fs_read_work); 306 - INIT_WORK(&m->wq, v9fs_write_work); 307 m->wsched = 0; 308 memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); 309 m->poll_task = NULL; 310 - n = v9fs_mux_poll_start(m); 311 if (n) 312 return ERR_PTR(n); 313 314 n = trans->poll(trans, &m->pt); 315 if (n & POLLIN) { 316 - dprintk(DEBUG_MUX, "mux %p can read\n", m); 317 set_bit(Rpending, &m->wsched); 318 } 319 320 if (n & POLLOUT) { 321 - dprintk(DEBUG_MUX, "mux %p can write\n", m); 322 set_bit(Wpending, &m->wsched); 323 } 324 325 - for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { 326 if (IS_ERR(m->poll_waddr[i])) { 327 - v9fs_mux_poll_stop(m); 328 mtmp = (void *)m->poll_waddr; /* the error code */ 329 kfree(m); 330 m = mtmp; ··· 334 335 return m; 336 } 337 338 /** 339 - * v9fs_mux_destroy - cancels all pending requests and frees mux resources 340 */ 341 - void v9fs_mux_destroy(struct v9fs_mux_data *m) 342 { 343 - dprintk(DEBUG_MUX, "mux %p prev %p next %p\n", m, 344 m->mux_list.prev, m->mux_list.next); 345 - v9fs_mux_cancel(m, -ECONNRESET); 346 347 if (!list_empty(&m->req_list)) { 348 /* wait until all processes waiting on this session exit */ 349 - dprintk(DEBUG_MUX, "mux %p waiting for empty request queue\n", 350 - m); 351 wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000); 352 - dprintk(DEBUG_MUX, "mux %p request queue empty: %d\n", m, 353 list_empty(&m->req_list)); 354 } 355 356 - v9fs_mux_poll_stop(m); 357 m->trans = NULL; 358 - 359 kfree(m); 360 } 361 362 /** 363 - * v9fs_pollwait - called by files poll operation to add v9fs-poll task 364 * to files wait queue 365 */ 366 static void 367 - v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address, 368 poll_table * p) 369 { 370 int i; 371 - struct v9fs_mux_data *m; 372 373 - m = container_of(p, struct v9fs_mux_data, pt); 374 - for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) 375 if (m->poll_waddr[i] == NULL) 376 break; 377 378 if (i >= ARRAY_SIZE(m->poll_waddr)) { 379 - dprintk(DEBUG_ERROR, "not enough wait_address slots\n"); 380 return; 381 } 382 383 m->poll_waddr[i] = wait_address; 384 385 if (!wait_address) { 386 - dprintk(DEBUG_ERROR, "no wait_address\n"); 387 m->poll_waddr[i] = ERR_PTR(-EIO); 388 return; 389 } ··· 395 } 396 397 /** 398 - * v9fs_poll_mux - polls a mux and schedules read or write works if necessary 399 */ 400 - static void v9fs_poll_mux(struct v9fs_mux_data *m) 401 { 402 int n; 403 ··· 406 407 n = m->trans->poll(m->trans, NULL); 408 if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) { 409 - dprintk(DEBUG_MUX, "error mux %p err %d\n", m, n); 410 if (n >= 0) 411 n = -ECONNRESET; 412 - v9fs_mux_cancel(m, n); 413 } 414 415 if (n & POLLIN) { 416 set_bit(Rpending, &m->wsched); 417 - dprintk(DEBUG_MUX, "mux %p can read\n", m); 418 if (!test_and_set_bit(Rworksched, &m->wsched)) { 419 - dprintk(DEBUG_MUX, "schedule read work mux %p\n", m); 420 - queue_work(v9fs_mux_wq, &m->rq); 421 } 422 } 423 424 if (n & POLLOUT) { 425 set_bit(Wpending, &m->wsched); 426 - dprintk(DEBUG_MUX, "mux %p can write\n", m); 427 if ((m->wsize || !list_empty(&m->unsent_req_list)) 428 && !test_and_set_bit(Wworksched, &m->wsched)) { 429 - dprintk(DEBUG_MUX, "schedule write work mux %p\n", m); 430 - queue_work(v9fs_mux_wq, &m->wq); 431 } 432 } 433 } 434 435 /** 436 - * v9fs_poll_proc - polls all v9fs transports for new events and queues 437 * the appropriate work to the work queue 438 */ 439 - static int v9fs_poll_proc(void *a) 440 { 441 - struct v9fs_mux_data *m, *mtmp; 442 - struct v9fs_mux_poll_task *vpt; 443 444 vpt = a; 445 - dprintk(DEBUG_MUX, "start %p %p\n", current, vpt); 446 while (!kthread_should_stop()) { 447 set_current_state(TASK_INTERRUPTIBLE); 448 449 list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) { 450 - v9fs_poll_mux(m); 451 } 452 453 - dprintk(DEBUG_MUX, "sleeping...\n"); 454 schedule_timeout(SCHED_TIMEOUT * HZ); 455 } 456 457 __set_current_state(TASK_RUNNING); 458 - dprintk(DEBUG_MUX, "finish\n"); 459 return 0; 460 } 461 462 /** 463 - * v9fs_write_work - called when a transport can send some data 464 */ 465 - static void v9fs_write_work(struct work_struct *work) 466 { 467 int n, err; 468 - struct v9fs_mux_data *m; 469 - struct v9fs_req *req; 470 471 - m = container_of(work, struct v9fs_mux_data, wq); 472 473 if (m->err < 0) { 474 clear_bit(Wworksched, &m->wsched); ··· 483 484 spin_lock(&m->lock); 485 again: 486 - req = list_entry(m->unsent_req_list.next, struct v9fs_req, 487 req_list); 488 list_move_tail(&req->req_list, &m->req_list); 489 if (req->err == ERREQFLUSH) ··· 492 m->wbuf = req->tcall->sdata; 493 m->wsize = req->tcall->size; 494 m->wpos = 0; 495 - dump_data(m->wbuf, m->wsize); 496 spin_unlock(&m->lock); 497 } 498 499 - dprintk(DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, m->wsize); 500 clear_bit(Wpending, &m->wsched); 501 err = m->trans->write(m->trans, m->wbuf + m->wpos, m->wsize - m->wpos); 502 - dprintk(DEBUG_MUX, "mux %p sent %d bytes\n", m, err); 503 if (err == -EAGAIN) { 504 clear_bit(Wworksched, &m->wsched); 505 return; 506 } 507 508 - if (err <= 0) 509 goto error; 510 511 m->wpos += err; 512 if (m->wpos == m->wsize) ··· 523 n = m->trans->poll(m->trans, NULL); 524 525 if (n & POLLOUT) { 526 - dprintk(DEBUG_MUX, "schedule write work mux %p\n", m); 527 - queue_work(v9fs_mux_wq, &m->wq); 528 } else 529 clear_bit(Wworksched, &m->wsched); 530 } else ··· 532 533 return; 534 535 - error: 536 - v9fs_mux_cancel(m, err); 537 clear_bit(Wworksched, &m->wsched); 538 } 539 540 - static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) 541 { 542 int ecode; 543 - struct v9fs_str *ename; 544 545 - if (!req->err && req->rcall->id == RERROR) { 546 ecode = req->rcall->params.rerror.errno; 547 ename = &req->rcall->params.rerror.error; 548 549 - dprintk(DEBUG_MUX, "Rerror %.*s\n", ename->len, ename->str); 550 551 if (*m->extended) 552 req->err = -ecode; 553 554 if (!req->err) { 555 - req->err = v9fs_errstr2errno(ename->str, ename->len); 556 557 if (!req->err) { /* string match failed */ 558 PRINT_FCALL_ERROR("unknown error", req->rcall); ··· 563 req->err = -ESERVERFAULT; 564 } 565 } else if (req->tcall && req->rcall->id != req->tcall->id + 1) { 566 - dprintk(DEBUG_ERROR, "fcall mismatch: expected %d, got %d\n", 567 - req->tcall->id + 1, req->rcall->id); 568 if (!req->err) 569 req->err = -EIO; 570 } 571 } 572 573 /** 574 - * v9fs_read_work - called when there is some data to be read from a transport 575 */ 576 - static void v9fs_read_work(struct work_struct *work) 577 { 578 int n, err; 579 - struct v9fs_mux_data *m; 580 - struct v9fs_req *req, *rptr, *rreq; 581 - struct v9fs_fcall *rcall; 582 char *rbuf; 583 584 - m = container_of(work, struct v9fs_mux_data, rq); 585 586 if (m->err < 0) 587 return; 588 589 rcall = NULL; 590 - dprintk(DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos); 591 592 if (!m->rcall) { 593 m->rcall = 594 - kmalloc(sizeof(struct v9fs_fcall) + m->msize, GFP_KERNEL); 595 if (!m->rcall) { 596 err = -ENOMEM; 597 goto error; 598 } 599 600 - m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall); 601 m->rpos = 0; 602 } 603 604 clear_bit(Rpending, &m->wsched); 605 err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos); 606 - dprintk(DEBUG_MUX, "mux %p got %d bytes\n", m, err); 607 if (err == -EAGAIN) { 608 clear_bit(Rworksched, &m->wsched); 609 return; ··· 617 while (m->rpos > 4) { 618 n = le32_to_cpu(*(__le32 *) m->rbuf); 619 if (n >= m->msize) { 620 - dprintk(DEBUG_ERROR, 621 "requested packet size too big: %d\n", n); 622 err = -EIO; 623 goto error; ··· 626 if (m->rpos < n) 627 break; 628 629 - dump_data(m->rbuf, n); 630 err = 631 - v9fs_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended); 632 if (err < 0) { 633 goto error; 634 } 635 636 - if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) { 637 char buf[150]; 638 639 - v9fs_printfcall(buf, sizeof(buf), m->rcall, 640 *m->extended); 641 printk(KERN_NOTICE ">>> %p %s\n", m, buf); 642 } 643 644 rcall = m->rcall; 645 rbuf = m->rbuf; 646 if (m->rpos > n) { 647 - m->rcall = kmalloc(sizeof(struct v9fs_fcall) + m->msize, 648 GFP_KERNEL); 649 if (!m->rcall) { 650 err = -ENOMEM; 651 goto error; 652 } 653 654 - m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall); 655 memmove(m->rbuf, rbuf + n, m->rpos - n); 656 m->rpos -= n; 657 } else { ··· 661 m->rpos = 0; 662 } 663 664 - dprintk(DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, rcall->id, 665 - rcall->tag); 666 667 req = NULL; 668 spin_lock(&m->lock); ··· 689 wake_up(&m->equeue); 690 } 691 } else { 692 - if (err >= 0 && rcall->id != RFLUSH) 693 - dprintk(DEBUG_ERROR, 694 - "unexpected response mux %p id %d tag %d\n", 695 - m, rcall->id, rcall->tag); 696 kfree(rcall); 697 } 698 } ··· 704 n = m->trans->poll(m->trans, NULL); 705 706 if (n & POLLIN) { 707 - dprintk(DEBUG_MUX, "schedule read work mux %p\n", m); 708 - queue_work(v9fs_mux_wq, &m->rq); 709 } else 710 clear_bit(Rworksched, &m->wsched); 711 } else ··· 713 714 return; 715 716 - error: 717 - v9fs_mux_cancel(m, err); 718 clear_bit(Rworksched, &m->wsched); 719 } 720 721 /** 722 - * v9fs_send_request - send 9P request 723 * The function can sleep until the request is scheduled for sending. 724 * The function can be interrupted. Return from the function is not 725 * a guarantee that the request is sent successfully. Can return errors ··· 730 * @cb: callback function to call when response is received 731 * @cba: parameter to pass to the callback function 732 */ 733 - static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m, 734 - struct v9fs_fcall *tc, 735 - v9fs_mux_req_callback cb, void *cba) 736 { 737 int n; 738 - struct v9fs_req *req; 739 740 - dprintk(DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current, 741 tc, tc->id); 742 if (m->err < 0) 743 return ERR_PTR(m->err); 744 745 - req = kmalloc(sizeof(struct v9fs_req), GFP_KERNEL); 746 if (!req) 747 return ERR_PTR(-ENOMEM); 748 749 - if (tc->id == TVERSION) 750 - n = V9FS_NOTAG; 751 else 752 - n = v9fs_mux_get_tag(m); 753 754 if (n < 0) 755 return ERR_PTR(-ENOMEM); 756 757 - v9fs_set_tag(tc, n); 758 - if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) { 759 char buf[150]; 760 761 - v9fs_printfcall(buf, sizeof(buf), tc, *m->extended); 762 printk(KERN_NOTICE "<<< %p %s\n", m, buf); 763 } 764 765 spin_lock_init(&req->lock); 766 req->tag = n; ··· 784 n = m->trans->poll(m->trans, NULL); 785 786 if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched)) 787 - queue_work(v9fs_mux_wq, &m->wq); 788 789 return req; 790 } 791 792 - static void v9fs_mux_free_request(struct v9fs_mux_data *m, struct v9fs_req *req) 793 { 794 - v9fs_mux_put_tag(m, req->tag); 795 kfree(req); 796 } 797 798 - static void v9fs_mux_flush_cb(struct v9fs_req *freq, void *a) 799 { 800 - v9fs_mux_req_callback cb; 801 int tag; 802 - struct v9fs_mux_data *m; 803 - struct v9fs_req *req, *rreq, *rptr; 804 805 m = a; 806 - dprintk(DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, 807 freq->tcall, freq->rcall, freq->err, 808 freq->tcall->params.tflush.oldtag); 809 ··· 835 836 kfree(freq->tcall); 837 kfree(freq->rcall); 838 - v9fs_mux_free_request(m, freq); 839 } 840 841 static int 842 - v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req) 843 { 844 - struct v9fs_fcall *fc; 845 - struct v9fs_req *rreq, *rptr; 846 847 - dprintk(DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); 848 849 /* if a response was received for a request, do nothing */ 850 spin_lock(&req->lock); 851 if (req->rcall || req->err) { 852 spin_unlock(&req->lock); 853 - dprintk(DEBUG_MUX, "mux %p req %p response already received\n", m, req); 854 return 0; 855 } 856 ··· 862 /* if the request is not sent yet, just remove it from the list */ 863 list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) { 864 if (rreq->tag == req->tag) { 865 - dprintk(DEBUG_MUX, "mux %p req %p request is not sent yet\n", m, req); 866 list_del(&rreq->req_list); 867 req->flush = Flushed; 868 spin_unlock(&m->lock); ··· 875 spin_unlock(&m->lock); 876 877 clear_thread_flag(TIF_SIGPENDING); 878 - fc = v9fs_create_tflush(req->tag); 879 - v9fs_send_request(m, fc, v9fs_mux_flush_cb, m); 880 return 1; 881 } 882 883 static void 884 - v9fs_mux_rpc_cb(struct v9fs_req *req, void *a) 885 { 886 - struct v9fs_mux_rpc *r; 887 888 - dprintk(DEBUG_MUX, "req %p r %p\n", req, a); 889 r = a; 890 r->rcall = req->rcall; 891 r->err = req->err; 892 893 - if (req->flush!=None && !req->err) 894 r->err = -ERESTARTSYS; 895 896 wake_up(&r->wqueue); 897 } 898 899 /** 900 - * v9fs_mux_rpc - sends 9P request and waits until a response is available. 901 * The function can be interrupted. 902 * @m: mux data 903 * @tc: request to be sent 904 * @rc: pointer where a pointer to the response is stored 905 */ 906 int 907 - v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc, 908 - struct v9fs_fcall **rc) 909 { 910 int err, sigpending; 911 unsigned long flags; 912 - struct v9fs_req *req; 913 - struct v9fs_mux_rpc r; 914 915 r.err = 0; 916 r.tcall = tc; ··· 927 clear_thread_flag(TIF_SIGPENDING); 928 } 929 930 - req = v9fs_send_request(m, tc, v9fs_mux_rpc_cb, &r); 931 if (IS_ERR(req)) { 932 err = PTR_ERR(req); 933 - dprintk(DEBUG_MUX, "error %d\n", err); 934 return err; 935 } 936 ··· 938 if (r.err < 0) 939 err = r.err; 940 941 - if (err == -ERESTARTSYS && m->trans->status == Connected && m->err == 0) { 942 - if (v9fs_mux_flush_request(m, req)) { 943 /* wait until we get response of the flush message */ 944 do { 945 clear_thread_flag(TIF_SIGPENDING); 946 err = wait_event_interruptible(r.wqueue, 947 r.rcall || r.err); 948 - } while (!r.rcall && !r.err && err==-ERESTARTSYS && 949 - m->trans->status==Connected && !m->err); 950 951 err = -ERESTARTSYS; 952 } ··· 965 else 966 kfree(r.rcall); 967 968 - v9fs_mux_free_request(m, req); 969 if (err > 0) 970 err = -EIO; 971 972 return err; 973 } 974 975 - #if 0 976 /** 977 - * v9fs_mux_rpcnb - sends 9P request without waiting for response. 978 * @m: mux data 979 * @tc: request to be sent 980 * @cb: callback function to be called when response arrives 981 * @cba: value to pass to the callback function 982 */ 983 - int v9fs_mux_rpcnb(struct v9fs_mux_data *m, struct v9fs_fcall *tc, 984 - v9fs_mux_req_callback cb, void *a) 985 { 986 int err; 987 - struct v9fs_req *req; 988 989 - req = v9fs_send_request(m, tc, cb, a); 990 if (IS_ERR(req)) { 991 err = PTR_ERR(req); 992 - dprintk(DEBUG_MUX, "error %d\n", err); 993 return PTR_ERR(req); 994 } 995 996 - dprintk(DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag); 997 return 0; 998 } 999 - #endif /* 0 */ 1000 1001 /** 1002 - * v9fs_mux_cancel - cancel all pending requests with error 1003 * @m: mux data 1004 * @err: error code 1005 */ 1006 - void v9fs_mux_cancel(struct v9fs_mux_data *m, int err) 1007 { 1008 - struct v9fs_req *req, *rtmp; 1009 LIST_HEAD(cancel_list); 1010 1011 - dprintk(DEBUG_ERROR, "mux %p err %d\n", m, err); 1012 m->err = err; 1013 spin_lock(&m->lock); 1014 list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { ··· 1034 1035 wake_up(&m->equeue); 1036 } 1037 1038 - static u16 v9fs_mux_get_tag(struct v9fs_mux_data *m) 1039 { 1040 int tag; 1041 1042 - tag = v9fs_get_idpool(&m->tagpool); 1043 if (tag < 0) 1044 - return V9FS_NOTAG; 1045 else 1046 return (u16) tag; 1047 } 1048 1049 - static void v9fs_mux_put_tag(struct v9fs_mux_data *m, u16 tag) 1050 { 1051 - if (tag != V9FS_NOTAG && v9fs_check_idpool(tag, &m->tagpool)) 1052 - v9fs_put_idpool(tag, &m->tagpool); 1053 }
··· 1 /* 2 + * net/9p/mux.c 3 * 4 * Protocol Multiplexer 5 * ··· 30 #include <linux/kthread.h> 31 #include <linux/idr.h> 32 #include <linux/mutex.h> 33 + #include <net/9p/9p.h> 34 + #include <net/9p/transport.h> 35 + #include <net/9p/conn.h> 36 37 #define ERREQFLUSH 1 38 #define SCHED_TIMEOUT 10 ··· 55 Flushed, 56 }; 57 58 + struct p9_mux_poll_task; 59 60 + struct p9_req { 61 + spinlock_t lock; /* protect request structure */ 62 int tag; 63 + struct p9_fcall *tcall; 64 + struct p9_fcall *rcall; 65 int err; 66 + p9_conn_req_callback cb; 67 void *cba; 68 int flush; 69 struct list_head req_list; 70 }; 71 72 + struct p9_conn { 73 + spinlock_t lock; /* protect lock structure */ 74 struct list_head mux_list; 75 + struct p9_mux_poll_task *poll_task; 76 int msize; 77 unsigned char *extended; 78 + struct p9_transport *trans; 79 + struct p9_idpool *tagpool; 80 int err; 81 wait_queue_head_t equeue; 82 struct list_head req_list; 83 struct list_head unsent_req_list; 84 + struct p9_fcall *rcall; 85 int rpos; 86 char *rbuf; 87 int wpos; ··· 95 unsigned long wsched; 96 }; 97 98 + struct p9_mux_poll_task { 99 struct task_struct *task; 100 struct list_head mux_list; 101 int muxnum; 102 }; 103 104 + struct p9_mux_rpc { 105 + struct p9_conn *m; 106 int err; 107 + struct p9_fcall *tcall; 108 + struct p9_fcall *rcall; 109 wait_queue_head_t wqueue; 110 }; 111 112 + static int p9_poll_proc(void *); 113 + static void p9_read_work(struct work_struct *work); 114 + static void p9_write_work(struct work_struct *work); 115 + static void p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, 116 poll_table * p); 117 + static u16 p9_mux_get_tag(struct p9_conn *); 118 + static void p9_mux_put_tag(struct p9_conn *, u16); 119 120 + static DEFINE_MUTEX(p9_mux_task_lock); 121 + static struct workqueue_struct *p9_mux_wq; 122 123 + static int p9_mux_num; 124 + static int p9_mux_poll_task_num; 125 + static struct p9_mux_poll_task p9_mux_poll_tasks[100]; 126 127 + int p9_mux_global_init(void) 128 { 129 int i; 130 131 + for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) 132 + p9_mux_poll_tasks[i].task = NULL; 133 134 + p9_mux_wq = create_workqueue("v9fs"); 135 + if (!p9_mux_wq) { 136 printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); 137 return -ENOMEM; 138 } ··· 140 return 0; 141 } 142 143 + void p9_mux_global_exit(void) 144 { 145 + destroy_workqueue(p9_mux_wq); 146 } 147 148 /** 149 + * p9_mux_calc_poll_procs - calculates the number of polling procs 150 * based on the number of mounted v9fs filesystems. 151 * 152 * The current implementation returns sqrt of the number of mounts. 153 */ 154 + static int p9_mux_calc_poll_procs(int muxnum) 155 { 156 int n; 157 158 + if (p9_mux_poll_task_num) 159 + n = muxnum / p9_mux_poll_task_num + 160 + (muxnum % p9_mux_poll_task_num ? 1 : 0); 161 else 162 n = 1; 163 164 + if (n > ARRAY_SIZE(p9_mux_poll_tasks)) 165 + n = ARRAY_SIZE(p9_mux_poll_tasks); 166 167 return n; 168 } 169 170 + static int p9_mux_poll_start(struct p9_conn *m) 171 { 172 int i, n; 173 + struct p9_mux_poll_task *vpt, *vptlast; 174 struct task_struct *pproc; 175 176 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, p9_mux_num, 177 + p9_mux_poll_task_num); 178 + mutex_lock(&p9_mux_task_lock); 179 180 + n = p9_mux_calc_poll_procs(p9_mux_num + 1); 181 + if (n > p9_mux_poll_task_num) { 182 + for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) { 183 + if (p9_mux_poll_tasks[i].task == NULL) { 184 + vpt = &p9_mux_poll_tasks[i]; 185 + P9_DPRINTK(P9_DEBUG_MUX, "create proc %p\n", 186 + vpt); 187 + pproc = kthread_create(p9_poll_proc, vpt, 188 + "v9fs-poll"); 189 190 if (!IS_ERR(pproc)) { 191 vpt->task = pproc; 192 INIT_LIST_HEAD(&vpt->mux_list); 193 vpt->muxnum = 0; 194 + p9_mux_poll_task_num++; 195 wake_up_process(vpt->task); 196 } 197 break; 198 } 199 } 200 201 + if (i >= ARRAY_SIZE(p9_mux_poll_tasks)) 202 + P9_DPRINTK(P9_DEBUG_ERROR, 203 + "warning: no free poll slots\n"); 204 } 205 206 + n = (p9_mux_num + 1) / p9_mux_poll_task_num + 207 + ((p9_mux_num + 1) % p9_mux_poll_task_num ? 1 : 0); 208 209 vptlast = NULL; 210 + for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) { 211 + vpt = &p9_mux_poll_tasks[i]; 212 if (vpt->task != NULL) { 213 vptlast = vpt; 214 if (vpt->muxnum < n) { 215 + P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i); 216 list_add(&m->mux_list, &vpt->mux_list); 217 vpt->muxnum++; 218 m->poll_task = vpt; 219 + memset(&m->poll_waddr, 0, 220 + sizeof(m->poll_waddr)); 221 + init_poll_funcptr(&m->pt, p9_pollwait); 222 break; 223 } 224 } 225 } 226 227 + if (i >= ARRAY_SIZE(p9_mux_poll_tasks)) { 228 if (vptlast == NULL) 229 return -ENOMEM; 230 231 + P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i); 232 list_add(&m->mux_list, &vptlast->mux_list); 233 vptlast->muxnum++; 234 m->poll_task = vptlast; 235 memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); 236 + init_poll_funcptr(&m->pt, p9_pollwait); 237 } 238 239 + p9_mux_num++; 240 + mutex_unlock(&p9_mux_task_lock); 241 242 return 0; 243 } 244 245 + static void p9_mux_poll_stop(struct p9_conn *m) 246 { 247 int i; 248 + struct p9_mux_poll_task *vpt; 249 250 + mutex_lock(&p9_mux_task_lock); 251 vpt = m->poll_task; 252 list_del(&m->mux_list); 253 + for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { 254 if (m->poll_waddr[i] != NULL) { 255 remove_wait_queue(m->poll_waddr[i], &m->poll_wait[i]); 256 m->poll_waddr[i] = NULL; ··· 255 } 256 vpt->muxnum--; 257 if (!vpt->muxnum) { 258 + P9_DPRINTK(P9_DEBUG_MUX, "destroy proc %p\n", vpt); 259 kthread_stop(vpt->task); 260 vpt->task = NULL; 261 + p9_mux_poll_task_num--; 262 } 263 + p9_mux_num--; 264 + mutex_unlock(&p9_mux_task_lock); 265 } 266 267 /** 268 + * p9_conn_create - allocate and initialize the per-session mux data 269 * Creates the polling task if this is the first session. 270 * 271 * @trans - transport structure 272 * @msize - maximum message size 273 * @extended - pointer to the extended flag 274 */ 275 + struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize, 276 unsigned char *extended) 277 { 278 int i, n; 279 + struct p9_conn *m, *mtmp; 280 281 + P9_DPRINTK(P9_DEBUG_MUX, "transport %p msize %d\n", trans, msize); 282 + m = kmalloc(sizeof(struct p9_conn), GFP_KERNEL); 283 if (!m) 284 return ERR_PTR(-ENOMEM); 285 ··· 288 m->msize = msize; 289 m->extended = extended; 290 m->trans = trans; 291 + m->tagpool = p9_idpool_create(); 292 + if (!m->tagpool) { 293 + kfree(m); 294 + return ERR_PTR(PTR_ERR(m->tagpool)); 295 + } 296 + 297 m->err = 0; 298 init_waitqueue_head(&m->equeue); 299 INIT_LIST_HEAD(&m->req_list); ··· 299 m->rbuf = NULL; 300 m->wpos = m->wsize = 0; 301 m->wbuf = NULL; 302 + INIT_WORK(&m->rq, p9_read_work); 303 + INIT_WORK(&m->wq, p9_write_work); 304 m->wsched = 0; 305 memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); 306 m->poll_task = NULL; 307 + n = p9_mux_poll_start(m); 308 if (n) 309 return ERR_PTR(n); 310 311 n = trans->poll(trans, &m->pt); 312 if (n & POLLIN) { 313 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m); 314 set_bit(Rpending, &m->wsched); 315 } 316 317 if (n & POLLOUT) { 318 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m); 319 set_bit(Wpending, &m->wsched); 320 } 321 322 + for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { 323 if (IS_ERR(m->poll_waddr[i])) { 324 + p9_mux_poll_stop(m); 325 mtmp = (void *)m->poll_waddr; /* the error code */ 326 kfree(m); 327 m = mtmp; ··· 331 332 return m; 333 } 334 + EXPORT_SYMBOL(p9_conn_create); 335 336 /** 337 + * p9_mux_destroy - cancels all pending requests and frees mux resources 338 */ 339 + void p9_conn_destroy(struct p9_conn *m) 340 { 341 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m, 342 m->mux_list.prev, m->mux_list.next); 343 + p9_conn_cancel(m, -ECONNRESET); 344 345 if (!list_empty(&m->req_list)) { 346 /* wait until all processes waiting on this session exit */ 347 + P9_DPRINTK(P9_DEBUG_MUX, 348 + "mux %p waiting for empty request queue\n", m); 349 wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000); 350 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p request queue empty: %d\n", m, 351 list_empty(&m->req_list)); 352 } 353 354 + p9_mux_poll_stop(m); 355 m->trans = NULL; 356 + p9_idpool_destroy(m->tagpool); 357 kfree(m); 358 } 359 + EXPORT_SYMBOL(p9_conn_destroy); 360 361 /** 362 + * p9_pollwait - called by files poll operation to add v9fs-poll task 363 * to files wait queue 364 */ 365 static void 366 + p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, 367 poll_table * p) 368 { 369 int i; 370 + struct p9_conn *m; 371 372 + m = container_of(p, struct p9_conn, pt); 373 + for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) 374 if (m->poll_waddr[i] == NULL) 375 break; 376 377 if (i >= ARRAY_SIZE(m->poll_waddr)) { 378 + P9_DPRINTK(P9_DEBUG_ERROR, "not enough wait_address slots\n"); 379 return; 380 } 381 382 m->poll_waddr[i] = wait_address; 383 384 if (!wait_address) { 385 + P9_DPRINTK(P9_DEBUG_ERROR, "no wait_address\n"); 386 m->poll_waddr[i] = ERR_PTR(-EIO); 387 return; 388 } ··· 390 } 391 392 /** 393 + * p9_poll_mux - polls a mux and schedules read or write works if necessary 394 */ 395 + static void p9_poll_mux(struct p9_conn *m) 396 { 397 int n; 398 ··· 401 402 n = m->trans->poll(m->trans, NULL); 403 if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) { 404 + P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n); 405 if (n >= 0) 406 n = -ECONNRESET; 407 + p9_conn_cancel(m, n); 408 } 409 410 if (n & POLLIN) { 411 set_bit(Rpending, &m->wsched); 412 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m); 413 if (!test_and_set_bit(Rworksched, &m->wsched)) { 414 + P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m); 415 + queue_work(p9_mux_wq, &m->rq); 416 } 417 } 418 419 if (n & POLLOUT) { 420 set_bit(Wpending, &m->wsched); 421 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m); 422 if ((m->wsize || !list_empty(&m->unsent_req_list)) 423 && !test_and_set_bit(Wworksched, &m->wsched)) { 424 + P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m); 425 + queue_work(p9_mux_wq, &m->wq); 426 } 427 } 428 } 429 430 /** 431 + * p9_poll_proc - polls all v9fs transports for new events and queues 432 * the appropriate work to the work queue 433 */ 434 + static int p9_poll_proc(void *a) 435 { 436 + struct p9_conn *m, *mtmp; 437 + struct p9_mux_poll_task *vpt; 438 439 vpt = a; 440 + P9_DPRINTK(P9_DEBUG_MUX, "start %p %p\n", current, vpt); 441 while (!kthread_should_stop()) { 442 set_current_state(TASK_INTERRUPTIBLE); 443 444 list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) { 445 + p9_poll_mux(m); 446 } 447 448 + P9_DPRINTK(P9_DEBUG_MUX, "sleeping...\n"); 449 schedule_timeout(SCHED_TIMEOUT * HZ); 450 } 451 452 __set_current_state(TASK_RUNNING); 453 + P9_DPRINTK(P9_DEBUG_MUX, "finish\n"); 454 return 0; 455 } 456 457 /** 458 + * p9_write_work - called when a transport can send some data 459 */ 460 + static void p9_write_work(struct work_struct *work) 461 { 462 int n, err; 463 + struct p9_conn *m; 464 + struct p9_req *req; 465 466 + m = container_of(work, struct p9_conn, wq); 467 468 if (m->err < 0) { 469 clear_bit(Wworksched, &m->wsched); ··· 478 479 spin_lock(&m->lock); 480 again: 481 + req = list_entry(m->unsent_req_list.next, struct p9_req, 482 req_list); 483 list_move_tail(&req->req_list, &m->req_list); 484 if (req->err == ERREQFLUSH) ··· 487 m->wbuf = req->tcall->sdata; 488 m->wsize = req->tcall->size; 489 m->wpos = 0; 490 spin_unlock(&m->lock); 491 } 492 493 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, 494 + m->wsize); 495 clear_bit(Wpending, &m->wsched); 496 err = m->trans->write(m->trans, m->wbuf + m->wpos, m->wsize - m->wpos); 497 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err); 498 if (err == -EAGAIN) { 499 clear_bit(Wworksched, &m->wsched); 500 return; 501 } 502 503 + if (err < 0) 504 goto error; 505 + else if (err == 0) { 506 + err = -EREMOTEIO; 507 + goto error; 508 + } 509 510 m->wpos += err; 511 if (m->wpos == m->wsize) ··· 514 n = m->trans->poll(m->trans, NULL); 515 516 if (n & POLLOUT) { 517 + P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m); 518 + queue_work(p9_mux_wq, &m->wq); 519 } else 520 clear_bit(Wworksched, &m->wsched); 521 } else ··· 523 524 return; 525 526 + error: 527 + p9_conn_cancel(m, err); 528 clear_bit(Wworksched, &m->wsched); 529 } 530 531 + static void process_request(struct p9_conn *m, struct p9_req *req) 532 { 533 int ecode; 534 + struct p9_str *ename; 535 536 + if (!req->err && req->rcall->id == P9_RERROR) { 537 ecode = req->rcall->params.rerror.errno; 538 ename = &req->rcall->params.rerror.error; 539 540 + P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len, 541 + ename->str); 542 543 if (*m->extended) 544 req->err = -ecode; 545 546 if (!req->err) { 547 + req->err = p9_errstr2errno(ename->str, ename->len); 548 549 if (!req->err) { /* string match failed */ 550 PRINT_FCALL_ERROR("unknown error", req->rcall); ··· 553 req->err = -ESERVERFAULT; 554 } 555 } else if (req->tcall && req->rcall->id != req->tcall->id + 1) { 556 + P9_DPRINTK(P9_DEBUG_ERROR, 557 + "fcall mismatch: expected %d, got %d\n", 558 + req->tcall->id + 1, req->rcall->id); 559 if (!req->err) 560 req->err = -EIO; 561 } 562 } 563 564 /** 565 + * p9_read_work - called when there is some data to be read from a transport 566 */ 567 + static void p9_read_work(struct work_struct *work) 568 { 569 int n, err; 570 + struct p9_conn *m; 571 + struct p9_req *req, *rptr, *rreq; 572 + struct p9_fcall *rcall; 573 char *rbuf; 574 575 + m = container_of(work, struct p9_conn, rq); 576 577 if (m->err < 0) 578 return; 579 580 rcall = NULL; 581 + P9_DPRINTK(P9_DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos); 582 583 if (!m->rcall) { 584 m->rcall = 585 + kmalloc(sizeof(struct p9_fcall) + m->msize, GFP_KERNEL); 586 if (!m->rcall) { 587 err = -ENOMEM; 588 goto error; 589 } 590 591 + m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall); 592 m->rpos = 0; 593 } 594 595 clear_bit(Rpending, &m->wsched); 596 err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos); 597 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err); 598 if (err == -EAGAIN) { 599 clear_bit(Rworksched, &m->wsched); 600 return; ··· 606 while (m->rpos > 4) { 607 n = le32_to_cpu(*(__le32 *) m->rbuf); 608 if (n >= m->msize) { 609 + P9_DPRINTK(P9_DEBUG_ERROR, 610 "requested packet size too big: %d\n", n); 611 err = -EIO; 612 goto error; ··· 615 if (m->rpos < n) 616 break; 617 618 err = 619 + p9_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended); 620 if (err < 0) { 621 goto error; 622 } 623 624 + #ifdef CONFIG_NET_9P_DEBUG 625 + if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { 626 char buf[150]; 627 628 + p9_printfcall(buf, sizeof(buf), m->rcall, 629 *m->extended); 630 printk(KERN_NOTICE ">>> %p %s\n", m, buf); 631 } 632 + #endif 633 634 rcall = m->rcall; 635 rbuf = m->rbuf; 636 if (m->rpos > n) { 637 + m->rcall = kmalloc(sizeof(struct p9_fcall) + m->msize, 638 GFP_KERNEL); 639 if (!m->rcall) { 640 err = -ENOMEM; 641 goto error; 642 } 643 644 + m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall); 645 memmove(m->rbuf, rbuf + n, m->rpos - n); 646 m->rpos -= n; 647 } else { ··· 649 m->rpos = 0; 650 } 651 652 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, 653 + rcall->id, rcall->tag); 654 655 req = NULL; 656 spin_lock(&m->lock); ··· 677 wake_up(&m->equeue); 678 } 679 } else { 680 + if (err >= 0 && rcall->id != P9_RFLUSH) 681 + P9_DPRINTK(P9_DEBUG_ERROR, 682 + "unexpected response mux %p id %d tag %d\n", 683 + m, rcall->id, rcall->tag); 684 kfree(rcall); 685 } 686 } ··· 692 n = m->trans->poll(m->trans, NULL); 693 694 if (n & POLLIN) { 695 + P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m); 696 + queue_work(p9_mux_wq, &m->rq); 697 } else 698 clear_bit(Rworksched, &m->wsched); 699 } else ··· 701 702 return; 703 704 + error: 705 + p9_conn_cancel(m, err); 706 clear_bit(Rworksched, &m->wsched); 707 } 708 709 /** 710 + * p9_send_request - send 9P request 711 * The function can sleep until the request is scheduled for sending. 712 * The function can be interrupted. Return from the function is not 713 * a guarantee that the request is sent successfully. Can return errors ··· 718 * @cb: callback function to call when response is received 719 * @cba: parameter to pass to the callback function 720 */ 721 + static struct p9_req *p9_send_request(struct p9_conn *m, 722 + struct p9_fcall *tc, 723 + p9_conn_req_callback cb, void *cba) 724 { 725 int n; 726 + struct p9_req *req; 727 728 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current, 729 tc, tc->id); 730 if (m->err < 0) 731 return ERR_PTR(m->err); 732 733 + req = kmalloc(sizeof(struct p9_req), GFP_KERNEL); 734 if (!req) 735 return ERR_PTR(-ENOMEM); 736 737 + if (tc->id == P9_TVERSION) 738 + n = P9_NOTAG; 739 else 740 + n = p9_mux_get_tag(m); 741 742 if (n < 0) 743 return ERR_PTR(-ENOMEM); 744 745 + p9_set_tag(tc, n); 746 + 747 + #ifdef CONFIG_NET_9P_DEBUG 748 + if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { 749 char buf[150]; 750 751 + p9_printfcall(buf, sizeof(buf), tc, *m->extended); 752 printk(KERN_NOTICE "<<< %p %s\n", m, buf); 753 } 754 + #endif 755 756 spin_lock_init(&req->lock); 757 req->tag = n; ··· 769 n = m->trans->poll(m->trans, NULL); 770 771 if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched)) 772 + queue_work(p9_mux_wq, &m->wq); 773 774 return req; 775 } 776 777 + static void p9_mux_free_request(struct p9_conn *m, struct p9_req *req) 778 { 779 + p9_mux_put_tag(m, req->tag); 780 kfree(req); 781 } 782 783 + static void p9_mux_flush_cb(struct p9_req *freq, void *a) 784 { 785 + p9_conn_req_callback cb; 786 int tag; 787 + struct p9_conn *m; 788 + struct p9_req *req, *rreq, *rptr; 789 790 m = a; 791 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, 792 freq->tcall, freq->rcall, freq->err, 793 freq->tcall->params.tflush.oldtag); 794 ··· 820 821 kfree(freq->tcall); 822 kfree(freq->rcall); 823 + p9_mux_free_request(m, freq); 824 } 825 826 static int 827 + p9_mux_flush_request(struct p9_conn *m, struct p9_req *req) 828 { 829 + struct p9_fcall *fc; 830 + struct p9_req *rreq, *rptr; 831 832 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); 833 834 /* if a response was received for a request, do nothing */ 835 spin_lock(&req->lock); 836 if (req->rcall || req->err) { 837 spin_unlock(&req->lock); 838 + P9_DPRINTK(P9_DEBUG_MUX, 839 + "mux %p req %p response already received\n", m, req); 840 return 0; 841 } 842 ··· 846 /* if the request is not sent yet, just remove it from the list */ 847 list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) { 848 if (rreq->tag == req->tag) { 849 + P9_DPRINTK(P9_DEBUG_MUX, 850 + "mux %p req %p request is not sent yet\n", m, req); 851 list_del(&rreq->req_list); 852 req->flush = Flushed; 853 spin_unlock(&m->lock); ··· 858 spin_unlock(&m->lock); 859 860 clear_thread_flag(TIF_SIGPENDING); 861 + fc = p9_create_tflush(req->tag); 862 + p9_send_request(m, fc, p9_mux_flush_cb, m); 863 return 1; 864 } 865 866 static void 867 + p9_conn_rpc_cb(struct p9_req *req, void *a) 868 { 869 + struct p9_mux_rpc *r; 870 871 + P9_DPRINTK(P9_DEBUG_MUX, "req %p r %p\n", req, a); 872 r = a; 873 r->rcall = req->rcall; 874 r->err = req->err; 875 876 + if (req->flush != None && !req->err) 877 r->err = -ERESTARTSYS; 878 879 wake_up(&r->wqueue); 880 } 881 882 /** 883 + * p9_mux_rpc - sends 9P request and waits until a response is available. 884 * The function can be interrupted. 885 * @m: mux data 886 * @tc: request to be sent 887 * @rc: pointer where a pointer to the response is stored 888 */ 889 int 890 + p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc, 891 + struct p9_fcall **rc) 892 { 893 int err, sigpending; 894 unsigned long flags; 895 + struct p9_req *req; 896 + struct p9_mux_rpc r; 897 898 r.err = 0; 899 r.tcall = tc; ··· 910 clear_thread_flag(TIF_SIGPENDING); 911 } 912 913 + req = p9_send_request(m, tc, p9_conn_rpc_cb, &r); 914 if (IS_ERR(req)) { 915 err = PTR_ERR(req); 916 + P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err); 917 return err; 918 } 919 ··· 921 if (r.err < 0) 922 err = r.err; 923 924 + if (err == -ERESTARTSYS && m->trans->status == Connected 925 + && m->err == 0) { 926 + if (p9_mux_flush_request(m, req)) { 927 /* wait until we get response of the flush message */ 928 do { 929 clear_thread_flag(TIF_SIGPENDING); 930 err = wait_event_interruptible(r.wqueue, 931 r.rcall || r.err); 932 + } while (!r.rcall && !r.err && err == -ERESTARTSYS && 933 + m->trans->status == Connected && !m->err); 934 935 err = -ERESTARTSYS; 936 } ··· 947 else 948 kfree(r.rcall); 949 950 + p9_mux_free_request(m, req); 951 if (err > 0) 952 err = -EIO; 953 954 return err; 955 } 956 + EXPORT_SYMBOL(p9_conn_rpc); 957 958 + #ifdef P9_NONBLOCK 959 /** 960 + * p9_conn_rpcnb - sends 9P request without waiting for response. 961 * @m: mux data 962 * @tc: request to be sent 963 * @cb: callback function to be called when response arrives 964 * @cba: value to pass to the callback function 965 */ 966 + int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc, 967 + p9_conn_req_callback cb, void *a) 968 { 969 int err; 970 + struct p9_req *req; 971 972 + req = p9_send_request(m, tc, cb, a); 973 if (IS_ERR(req)) { 974 err = PTR_ERR(req); 975 + P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err); 976 return PTR_ERR(req); 977 } 978 979 + P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag); 980 return 0; 981 } 982 + EXPORT_SYMBOL(p9_conn_rpcnb); 983 + #endif /* P9_NONBLOCK */ 984 985 /** 986 + * p9_conn_cancel - cancel all pending requests with error 987 * @m: mux data 988 * @err: error code 989 */ 990 + void p9_conn_cancel(struct p9_conn *m, int err) 991 { 992 + struct p9_req *req, *rtmp; 993 LIST_HEAD(cancel_list); 994 995 + P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err); 996 m->err = err; 997 spin_lock(&m->lock); 998 list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { ··· 1014 1015 wake_up(&m->equeue); 1016 } 1017 + EXPORT_SYMBOL(p9_conn_cancel); 1018 1019 + static u16 p9_mux_get_tag(struct p9_conn *m) 1020 { 1021 int tag; 1022 1023 + tag = p9_idpool_get(m->tagpool); 1024 if (tag < 0) 1025 + return P9_NOTAG; 1026 else 1027 return (u16) tag; 1028 } 1029 1030 + static void p9_mux_put_tag(struct p9_conn *m, u16 tag) 1031 { 1032 + if (tag != P9_NOTAG && p9_idpool_check(tag, m->tagpool)) 1033 + p9_idpool_put(tag, m->tagpool); 1034 }
+22 -20
fs/9p/mux.h include/net/9p/conn.h
··· 1 /* 2 - * linux/fs/9p/mux.h 3 * 4 - * Multiplexer Definitions 5 * 6 * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net> 7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> ··· 23 * 24 */ 25 26 - struct v9fs_mux_data; 27 - struct v9fs_req; 28 29 /** 30 - * v9fs_mux_req_callback - callback function that is called when the 31 * response of a request is received. The callback is called from 32 * a workqueue and shouldn't block. 33 * 34 * @a - the pointer that was specified when the request was send to be 35 * passed to the callback 36 - * @tc - request call 37 - * @rc - response call 38 - * @err - error code (non-zero if error occured) 39 */ 40 - typedef void (*v9fs_mux_req_callback)(struct v9fs_req *req, void *a); 41 42 - int v9fs_mux_global_init(void); 43 - void v9fs_mux_global_exit(void); 44 45 - struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize, 46 - unsigned char *extended); 47 - void v9fs_mux_destroy(struct v9fs_mux_data *); 48 49 - int v9fs_mux_send(struct v9fs_mux_data *m, struct v9fs_fcall *tc); 50 - struct v9fs_fcall *v9fs_mux_recv(struct v9fs_mux_data *m); 51 - int v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc, struct v9fs_fcall **rc); 52 53 - void v9fs_mux_flush(struct v9fs_mux_data *m, int sendflush); 54 - void v9fs_mux_cancel(struct v9fs_mux_data *m, int err); 55 - int v9fs_errstr2errno(char *errstr, int len);
··· 1 /* 2 + * include/net/9p/conn.h 3 * 4 + * Connection Definitions 5 * 6 * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net> 7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> ··· 23 * 24 */ 25 26 + #ifndef NET_9P_CONN_H 27 + #define NET_9P_CONN_H 28 + 29 + #undef P9_NONBLOCK 30 + 31 + struct p9_conn; 32 + struct p9_req; 33 34 /** 35 + * p9_mux_req_callback - callback function that is called when the 36 * response of a request is received. The callback is called from 37 * a workqueue and shouldn't block. 38 * 39 + * @req - request 40 * @a - the pointer that was specified when the request was send to be 41 * passed to the callback 42 */ 43 + typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a); 44 45 + struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize, 46 + unsigned char *dotu); 47 + void p9_conn_destroy(struct p9_conn *); 48 + int p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc, struct p9_fcall **rc); 49 50 + #ifdef P9_NONBLOCK 51 + int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc, 52 + p9_conn_req_callback cb, void *a); 53 + #endif /* P9_NONBLOCK */ 54 55 + void p9_conn_cancel(struct p9_conn *m, int err); 56 57 + #endif /* NET_9P_CONN_H */
-308
fs/9p/trans_fd.c
··· 1 - /* 2 - * linux/fs/9p/trans_fd.c 3 - * 4 - * Fd transport layer. Includes deprecated socket layer. 5 - * 6 - * Copyright (C) 2006 by Russ Cox <rsc@swtch.com> 7 - * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net> 8 - * Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com> 9 - * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com> 10 - * 11 - * This program is free software; you can redistribute it and/or modify 12 - * it under the terms of the GNU General Public License version 2 13 - * as published by the Free Software Foundation. 14 - * 15 - * This program is distributed in the hope that it will be useful, 16 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 - * GNU General Public License for more details. 19 - * 20 - * You should have received a copy of the GNU General Public License 21 - * along with this program; if not, write to: 22 - * Free Software Foundation 23 - * 51 Franklin Street, Fifth Floor 24 - * Boston, MA 02111-1301 USA 25 - * 26 - */ 27 - 28 - #include <linux/in.h> 29 - #include <linux/module.h> 30 - #include <linux/net.h> 31 - #include <linux/ipv6.h> 32 - #include <linux/errno.h> 33 - #include <linux/kernel.h> 34 - #include <linux/un.h> 35 - #include <asm/uaccess.h> 36 - #include <linux/inet.h> 37 - #include <linux/idr.h> 38 - #include <linux/file.h> 39 - 40 - #include "debug.h" 41 - #include "v9fs.h" 42 - #include "transport.h" 43 - 44 - #define V9FS_PORT 564 45 - 46 - struct v9fs_trans_fd { 47 - struct file *rd; 48 - struct file *wr; 49 - }; 50 - 51 - /** 52 - * v9fs_fd_read- read from a fd 53 - * @v9ses: session information 54 - * @v: buffer to receive data into 55 - * @len: size of receive buffer 56 - * 57 - */ 58 - static int v9fs_fd_read(struct v9fs_transport *trans, void *v, int len) 59 - { 60 - int ret; 61 - struct v9fs_trans_fd *ts; 62 - 63 - if (!trans || trans->status == Disconnected || !(ts = trans->priv)) 64 - return -EREMOTEIO; 65 - 66 - if (!(ts->rd->f_flags & O_NONBLOCK)) 67 - dprintk(DEBUG_ERROR, "blocking read ...\n"); 68 - 69 - ret = kernel_read(ts->rd, ts->rd->f_pos, v, len); 70 - if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) 71 - trans->status = Disconnected; 72 - return ret; 73 - } 74 - 75 - /** 76 - * v9fs_fd_write - write to a socket 77 - * @v9ses: session information 78 - * @v: buffer to send data from 79 - * @len: size of send buffer 80 - * 81 - */ 82 - static int v9fs_fd_write(struct v9fs_transport *trans, void *v, int len) 83 - { 84 - int ret; 85 - mm_segment_t oldfs; 86 - struct v9fs_trans_fd *ts; 87 - 88 - if (!trans || trans->status == Disconnected || !(ts = trans->priv)) 89 - return -EREMOTEIO; 90 - 91 - if (!(ts->wr->f_flags & O_NONBLOCK)) 92 - dprintk(DEBUG_ERROR, "blocking write ...\n"); 93 - 94 - oldfs = get_fs(); 95 - set_fs(get_ds()); 96 - /* The cast to a user pointer is valid due to the set_fs() */ 97 - ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos); 98 - set_fs(oldfs); 99 - 100 - if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) 101 - trans->status = Disconnected; 102 - return ret; 103 - } 104 - 105 - static unsigned int 106 - v9fs_fd_poll(struct v9fs_transport *trans, struct poll_table_struct *pt) 107 - { 108 - int ret, n; 109 - struct v9fs_trans_fd *ts; 110 - mm_segment_t oldfs; 111 - 112 - if (!trans || trans->status != Connected || !(ts = trans->priv)) 113 - return -EREMOTEIO; 114 - 115 - if (!ts->rd->f_op || !ts->rd->f_op->poll) 116 - return -EIO; 117 - 118 - if (!ts->wr->f_op || !ts->wr->f_op->poll) 119 - return -EIO; 120 - 121 - oldfs = get_fs(); 122 - set_fs(get_ds()); 123 - 124 - ret = ts->rd->f_op->poll(ts->rd, pt); 125 - if (ret < 0) 126 - goto end; 127 - 128 - if (ts->rd != ts->wr) { 129 - n = ts->wr->f_op->poll(ts->wr, pt); 130 - if (n < 0) { 131 - ret = n; 132 - goto end; 133 - } 134 - ret = (ret & ~POLLOUT) | (n & ~POLLIN); 135 - } 136 - 137 - end: 138 - set_fs(oldfs); 139 - return ret; 140 - } 141 - 142 - static int v9fs_fd_open(struct v9fs_session_info *v9ses, int rfd, int wfd) 143 - { 144 - struct v9fs_transport *trans = v9ses->transport; 145 - struct v9fs_trans_fd *ts = kmalloc(sizeof(struct v9fs_trans_fd), 146 - GFP_KERNEL); 147 - if (!ts) 148 - return -ENOMEM; 149 - 150 - ts->rd = fget(rfd); 151 - ts->wr = fget(wfd); 152 - if (!ts->rd || !ts->wr) { 153 - if (ts->rd) 154 - fput(ts->rd); 155 - if (ts->wr) 156 - fput(ts->wr); 157 - kfree(ts); 158 - return -EIO; 159 - } 160 - 161 - trans->priv = ts; 162 - trans->status = Connected; 163 - 164 - return 0; 165 - } 166 - 167 - static int v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr, 168 - char *data) 169 - { 170 - if (v9ses->rfdno == ~0 || v9ses->wfdno == ~0) { 171 - printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n"); 172 - return -ENOPROTOOPT; 173 - } 174 - 175 - return v9fs_fd_open(v9ses, v9ses->rfdno, v9ses->wfdno); 176 - } 177 - 178 - static int v9fs_socket_open(struct v9fs_session_info *v9ses, 179 - struct socket *csocket) 180 - { 181 - int fd, ret; 182 - 183 - csocket->sk->sk_allocation = GFP_NOIO; 184 - if ((fd = sock_map_fd(csocket)) < 0) { 185 - eprintk(KERN_ERR, "v9fs_socket_open: failed to map fd\n"); 186 - ret = fd; 187 - release_csocket: 188 - sock_release(csocket); 189 - return ret; 190 - } 191 - 192 - if ((ret = v9fs_fd_open(v9ses, fd, fd)) < 0) { 193 - sockfd_put(csocket); 194 - eprintk(KERN_ERR, "v9fs_socket_open: failed to open fd\n"); 195 - goto release_csocket; 196 - } 197 - 198 - ((struct v9fs_trans_fd *)v9ses->transport->priv)->rd->f_flags |= 199 - O_NONBLOCK; 200 - return 0; 201 - } 202 - 203 - static int v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr, 204 - char *data) 205 - { 206 - int ret; 207 - struct socket *csocket = NULL; 208 - struct sockaddr_in sin_server; 209 - 210 - sin_server.sin_family = AF_INET; 211 - sin_server.sin_addr.s_addr = in_aton(addr); 212 - sin_server.sin_port = htons(v9ses->port); 213 - sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); 214 - 215 - if (!csocket) { 216 - eprintk(KERN_ERR, "v9fs_trans_tcp: problem creating socket\n"); 217 - return -1; 218 - } 219 - 220 - ret = csocket->ops->connect(csocket, 221 - (struct sockaddr *)&sin_server, 222 - sizeof(struct sockaddr_in), 0); 223 - if (ret < 0) { 224 - eprintk(KERN_ERR, 225 - "v9fs_trans_tcp: problem connecting socket to %s\n", 226 - addr); 227 - return ret; 228 - } 229 - 230 - return v9fs_socket_open(v9ses, csocket); 231 - } 232 - 233 - static int 234 - v9fs_unix_init(struct v9fs_session_info *v9ses, const char *addr, char *data) 235 - { 236 - int ret; 237 - struct socket *csocket; 238 - struct sockaddr_un sun_server; 239 - 240 - if (strlen(addr) > UNIX_PATH_MAX) { 241 - eprintk(KERN_ERR, "v9fs_trans_unix: address too long: %s\n", 242 - addr); 243 - return -ENAMETOOLONG; 244 - } 245 - 246 - sun_server.sun_family = PF_UNIX; 247 - strcpy(sun_server.sun_path, addr); 248 - sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); 249 - ret = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, 250 - sizeof(struct sockaddr_un) - 1, 0); 251 - if (ret < 0) { 252 - eprintk(KERN_ERR, 253 - "v9fs_trans_unix: problem connecting socket: %s: %d\n", 254 - addr, ret); 255 - return ret; 256 - } 257 - 258 - return v9fs_socket_open(v9ses, csocket); 259 - } 260 - 261 - /** 262 - * v9fs_sock_close - shutdown socket 263 - * @trans: private socket structure 264 - * 265 - */ 266 - static void v9fs_fd_close(struct v9fs_transport *trans) 267 - { 268 - struct v9fs_trans_fd *ts; 269 - 270 - if (!trans) 271 - return; 272 - 273 - ts = xchg(&trans->priv, NULL); 274 - 275 - if (!ts) 276 - return; 277 - 278 - trans->status = Disconnected; 279 - if (ts->rd) 280 - fput(ts->rd); 281 - if (ts->wr) 282 - fput(ts->wr); 283 - kfree(ts); 284 - } 285 - 286 - struct v9fs_transport v9fs_trans_fd = { 287 - .init = v9fs_fd_init, 288 - .write = v9fs_fd_write, 289 - .read = v9fs_fd_read, 290 - .close = v9fs_fd_close, 291 - .poll = v9fs_fd_poll, 292 - }; 293 - 294 - struct v9fs_transport v9fs_trans_tcp = { 295 - .init = v9fs_tcp_init, 296 - .write = v9fs_fd_write, 297 - .read = v9fs_fd_read, 298 - .close = v9fs_fd_close, 299 - .poll = v9fs_fd_poll, 300 - }; 301 - 302 - struct v9fs_transport v9fs_trans_unix = { 303 - .init = v9fs_unix_init, 304 - .write = v9fs_fd_write, 305 - .read = v9fs_fd_read, 306 - .close = v9fs_fd_close, 307 - .poll = v9fs_fd_poll, 308 - };
···
+16 -12
fs/9p/transport.h include/net/9p/transport.h
··· 1 /* 2 - * linux/fs/9p/transport.h 3 * 4 * Transport Definition 5 * ··· 23 * 24 */ 25 26 - enum v9fs_transport_status { 27 Connected, 28 Disconnected, 29 Hung, 30 }; 31 32 - struct v9fs_transport { 33 - enum v9fs_transport_status status; 34 void *priv; 35 36 - int (*init) (struct v9fs_session_info *, const char *, char *); 37 - int (*write) (struct v9fs_transport *, void *, int); 38 - int (*read) (struct v9fs_transport *, void *, int); 39 - void (*close) (struct v9fs_transport *); 40 - unsigned int (*poll)(struct v9fs_transport *, struct poll_table_struct *); 41 }; 42 43 - extern struct v9fs_transport v9fs_trans_tcp; 44 - extern struct v9fs_transport v9fs_trans_unix; 45 - extern struct v9fs_transport v9fs_trans_fd;
··· 1 /* 2 + * include/net/9p/transport.h 3 * 4 * Transport Definition 5 * ··· 23 * 24 */ 25 26 + #ifndef NET_9P_TRANSPORT_H 27 + #define NET_9P_TRANSPORT_H 28 + 29 + enum p9_transport_status { 30 Connected, 31 Disconnected, 32 Hung, 33 }; 34 35 + struct p9_transport { 36 + enum p9_transport_status status; 37 void *priv; 38 39 + int (*write) (struct p9_transport *, void *, int); 40 + int (*read) (struct p9_transport *, void *, int); 41 + void (*close) (struct p9_transport *); 42 + unsigned int (*poll)(struct p9_transport *, struct poll_table_struct *); 43 }; 44 45 + struct p9_transport *p9_trans_create_tcp(const char *addr, int port); 46 + struct p9_transport *p9_trans_create_unix(const char *addr); 47 + struct p9_transport *p9_trans_create_fd(int rfd, int wfd); 48 + 49 + #endif /* NET_9P_TRANSPORT_H */
+63 -230
fs/9p/v9fs.c
··· 29 #include <linux/sched.h> 30 #include <linux/parser.h> 31 #include <linux/idr.h> 32 - 33 - #include "debug.h" 34 #include "v9fs.h" 35 - #include "9p.h" 36 #include "v9fs_vfs.h" 37 - #include "transport.h" 38 - #include "mux.h" 39 - 40 - /* TODO: sysfs or debugfs interface */ 41 - int v9fs_debug_level = 0; /* feature-rific global debug level */ 42 43 /* 44 * Option Parsing (code inspired by NFS code) ··· 43 44 enum { 45 /* Options that take integer arguments */ 46 - Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, Opt_debug, 47 Opt_rfdno, Opt_wfdno, 48 /* String options */ 49 Opt_uname, Opt_remotename, 50 /* Options that take no arguments */ 51 - Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, 52 /* Cache options */ 53 Opt_cache_loose, 54 /* Error token */ ··· 56 }; 57 58 static match_table_t tokens = { 59 {Opt_port, "port=%u"}, 60 {Opt_msize, "msize=%u"}, 61 {Opt_uid, "uid=%u"}, ··· 64 {Opt_afid, "afid=%u"}, 65 {Opt_rfdno, "rfdno=%u"}, 66 {Opt_wfdno, "wfdno=%u"}, 67 - {Opt_debug, "debug=%x"}, 68 {Opt_uname, "uname=%s"}, 69 {Opt_remotename, "aname=%s"}, 70 {Opt_unix, "proto=unix"}, 71 {Opt_tcp, "proto=tcp"}, 72 {Opt_fd, "proto=fd"}, 73 {Opt_tcp, "tcp"}, 74 {Opt_unix, "unix"}, 75 {Opt_fd, "fd"}, ··· 81 {Opt_cache_loose, "loose"}, 82 {Opt_err, NULL} 83 }; 84 85 /* 86 * Parse option string. ··· 123 token = match_token(p, tokens, args); 124 if (token < Opt_uname) { 125 if ((ret = match_int(&args[0], &option)) < 0) { 126 - dprintk(DEBUG_ERROR, 127 "integer field, but no integer?\n"); 128 continue; 129 } 130 } 131 switch (token) { 132 case Opt_port: 133 v9ses->port = option; 134 break; ··· 154 case Opt_wfdno: 155 v9ses->wfdno = option; 156 break; 157 - case Opt_debug: 158 - v9ses->debug = option; 159 - break; 160 case Opt_tcp: 161 v9ses->proto = PROTO_TCP; 162 break; 163 case Opt_unix: 164 v9ses->proto = PROTO_UNIX; 165 break; 166 case Opt_fd: 167 v9ses->proto = PROTO_FD; ··· 188 } 189 190 /** 191 - * v9fs_inode2v9ses - safely extract v9fs session info from super block 192 - * @inode: inode to extract information from 193 - * 194 - * Paranoid function to extract v9ses information from superblock, 195 - * if anything is missing it will report an error. 196 - * 197 - */ 198 - 199 - struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) 200 - { 201 - return (inode->i_sb->s_fs_info); 202 - } 203 - 204 - /** 205 - * v9fs_get_idpool - allocate numeric id from pool 206 - * @p - pool to allocate from 207 - * 208 - * XXX - This seems to be an awful generic function, should it be in idr.c with 209 - * the lock included in struct idr? 210 - */ 211 - 212 - int v9fs_get_idpool(struct v9fs_idpool *p) 213 - { 214 - int i = 0; 215 - int error; 216 - 217 - retry: 218 - if (idr_pre_get(&p->pool, GFP_KERNEL) == 0) 219 - return 0; 220 - 221 - if (down_interruptible(&p->lock) == -EINTR) { 222 - eprintk(KERN_WARNING, "Interrupted while locking\n"); 223 - return -1; 224 - } 225 - 226 - /* no need to store exactly p, we just need something non-null */ 227 - error = idr_get_new(&p->pool, p, &i); 228 - up(&p->lock); 229 - 230 - if (error == -EAGAIN) 231 - goto retry; 232 - else if (error) 233 - return -1; 234 - 235 - return i; 236 - } 237 - 238 - /** 239 - * v9fs_put_idpool - release numeric id from pool 240 - * @p - pool to allocate from 241 - * 242 - * XXX - This seems to be an awful generic function, should it be in idr.c with 243 - * the lock included in struct idr? 244 - */ 245 - 246 - void v9fs_put_idpool(int id, struct v9fs_idpool *p) 247 - { 248 - if (down_interruptible(&p->lock) == -EINTR) { 249 - eprintk(KERN_WARNING, "Interrupted while locking\n"); 250 - return; 251 - } 252 - idr_remove(&p->pool, id); 253 - up(&p->lock); 254 - } 255 - 256 - /** 257 - * v9fs_check_idpool - check if the specified id is available 258 - * @id - id to check 259 - * @p - pool 260 - */ 261 - int v9fs_check_idpool(int id, struct v9fs_idpool *p) 262 - { 263 - return idr_find(&p->pool, id) != NULL; 264 - } 265 - 266 - /** 267 * v9fs_session_init - initialize session 268 * @v9ses: session information structure 269 * @dev_name: device being mounted ··· 195 * 196 */ 197 198 - int 199 - v9fs_session_init(struct v9fs_session_info *v9ses, 200 const char *dev_name, char *data) 201 { 202 - struct v9fs_fcall *fcall = NULL; 203 - struct v9fs_transport *trans_proto; 204 - int n = 0; 205 - int newfid = -1; 206 int retval = -EINVAL; 207 - struct v9fs_str *version; 208 209 v9ses->name = __getname(); 210 if (!v9ses->name) 211 - return -ENOMEM; 212 213 v9ses->remotename = __getname(); 214 if (!v9ses->remotename) { 215 __putname(v9ses->name); 216 - return -ENOMEM; 217 } 218 219 strcpy(v9ses->name, V9FS_DEFUSER); ··· 217 218 v9fs_parse_options(data, v9ses); 219 220 - /* set global debug level */ 221 - v9fs_debug_level = v9ses->debug; 222 - 223 - /* id pools that are session-dependent: fids and tags */ 224 - idr_init(&v9ses->fidpool.pool); 225 - init_MUTEX(&v9ses->fidpool.lock); 226 - 227 switch (v9ses->proto) { 228 case PROTO_TCP: 229 - trans_proto = &v9fs_trans_tcp; 230 break; 231 case PROTO_UNIX: 232 - trans_proto = &v9fs_trans_unix; 233 *v9ses->remotename = 0; 234 break; 235 case PROTO_FD: 236 - trans_proto = &v9fs_trans_fd; 237 *v9ses->remotename = 0; 238 break; 239 default: 240 printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto); 241 retval = -ENOPROTOOPT; 242 - goto SessCleanUp; 243 }; 244 245 - v9ses->transport = kmalloc(sizeof(*v9ses->transport), GFP_KERNEL); 246 - if (!v9ses->transport) { 247 - retval = -ENOMEM; 248 - goto SessCleanUp; 249 } 250 251 - memmove(v9ses->transport, trans_proto, sizeof(*v9ses->transport)); 252 253 - if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) { 254 - eprintk(KERN_ERR, "problem initializing transport\n"); 255 - goto SessCleanUp; 256 } 257 258 - v9ses->inprogress = 0; 259 - v9ses->shutdown = 0; 260 - v9ses->session_hung = 0; 261 - 262 - v9ses->mux = v9fs_mux_init(v9ses->transport, v9ses->maxdata + V9FS_IOHDRSZ, 263 - &v9ses->extended); 264 - 265 - if (IS_ERR(v9ses->mux)) { 266 - retval = PTR_ERR(v9ses->mux); 267 - v9ses->mux = NULL; 268 - dprintk(DEBUG_ERROR, "problem initializing mux\n"); 269 - goto SessCleanUp; 270 } 271 272 - if (v9ses->afid == ~0) { 273 - if (v9ses->extended) 274 - retval = 275 - v9fs_t_version(v9ses, v9ses->maxdata, "9P2000.u", 276 - &fcall); 277 - else 278 - retval = v9fs_t_version(v9ses, v9ses->maxdata, "9P2000", 279 - &fcall); 280 281 - if (retval < 0) { 282 - dprintk(DEBUG_ERROR, "v9fs_t_version failed\n"); 283 - goto FreeFcall; 284 - } 285 - 286 - version = &fcall->params.rversion.version; 287 - if (version->len==8 && !memcmp(version->str, "9P2000.u", 8)) { 288 - dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n"); 289 - v9ses->extended = 1; 290 - } else if (version->len==6 && !memcmp(version->str, "9P2000", 6)) { 291 - dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n"); 292 - v9ses->extended = 0; 293 - } else { 294 - retval = -EREMOTEIO; 295 - goto FreeFcall; 296 - } 297 - 298 - n = fcall->params.rversion.msize; 299 - kfree(fcall); 300 - 301 - if (n < v9ses->maxdata) 302 - v9ses->maxdata = n; 303 - } 304 - 305 - newfid = v9fs_get_idpool(&v9ses->fidpool); 306 - if (newfid < 0) { 307 - eprintk(KERN_WARNING, "couldn't allocate FID\n"); 308 - retval = -ENOMEM; 309 - goto SessCleanUp; 310 - } 311 - /* it is a little bit ugly, but we have to prevent newfid */ 312 - /* being the same as afid, so if it is, get a new fid */ 313 - if (v9ses->afid != ~0 && newfid == v9ses->afid) { 314 - newfid = v9fs_get_idpool(&v9ses->fidpool); 315 - if (newfid < 0) { 316 - eprintk(KERN_WARNING, "couldn't allocate FID\n"); 317 - retval = -ENOMEM; 318 - goto SessCleanUp; 319 - } 320 - } 321 - 322 - if ((retval = 323 - v9fs_t_attach(v9ses, v9ses->name, v9ses->remotename, newfid, 324 - v9ses->afid, NULL)) 325 - < 0) { 326 - dprintk(DEBUG_ERROR, "cannot attach\n"); 327 - goto SessCleanUp; 328 - } 329 - 330 - if (v9ses->afid != ~0) { 331 - dprintk(DEBUG_ERROR, "afid not equal to ~0\n"); 332 - if (v9fs_t_clunk(v9ses, v9ses->afid)) 333 - dprintk(DEBUG_ERROR, "clunk failed\n"); 334 - } 335 - 336 - return newfid; 337 - 338 - FreeFcall: 339 - kfree(fcall); 340 - 341 - SessCleanUp: 342 v9fs_session_close(v9ses); 343 - return retval; 344 } 345 346 /** ··· 281 282 void v9fs_session_close(struct v9fs_session_info *v9ses) 283 { 284 - if (v9ses->mux) { 285 - v9fs_mux_destroy(v9ses->mux); 286 - v9ses->mux = NULL; 287 - } 288 - 289 - if (v9ses->transport) { 290 - v9ses->transport->close(v9ses->transport); 291 - kfree(v9ses->transport); 292 - v9ses->transport = NULL; 293 } 294 295 __putname(v9ses->name); ··· 295 * and cancel all pending requests. 296 */ 297 void v9fs_session_cancel(struct v9fs_session_info *v9ses) { 298 - dprintk(DEBUG_ERROR, "cancel session %p\n", v9ses); 299 - v9ses->transport->status = Disconnected; 300 - v9fs_mux_cancel(v9ses->mux, -EIO); 301 } 302 303 extern int v9fs_error_init(void); ··· 308 309 static int __init init_v9fs(void) 310 { 311 - int ret; 312 - 313 - v9fs_error_init(); 314 - 315 printk(KERN_INFO "Installing v9fs 9p2000 file system support\n"); 316 317 - ret = v9fs_mux_global_init(); 318 - if (ret) { 319 - printk(KERN_WARNING "v9fs: starting mux failed\n"); 320 - return ret; 321 - } 322 - ret = register_filesystem(&v9fs_fs_type); 323 - if (ret) { 324 - printk(KERN_WARNING "v9fs: registering file system failed\n"); 325 - v9fs_mux_global_exit(); 326 - } 327 - 328 - return ret; 329 } 330 331 /** ··· 320 321 static void __exit exit_v9fs(void) 322 { 323 - v9fs_mux_global_exit(); 324 unregister_filesystem(&v9fs_fs_type); 325 } 326 327 module_init(init_v9fs) 328 module_exit(exit_v9fs) 329 330 MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); 331 MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>"); 332 MODULE_LICENSE("GPL");
··· 29 #include <linux/sched.h> 30 #include <linux/parser.h> 31 #include <linux/idr.h> 32 + #include <net/9p/9p.h> 33 + #include <net/9p/transport.h> 34 + #include <net/9p/conn.h> 35 + #include <net/9p/client.h> 36 #include "v9fs.h" 37 #include "v9fs_vfs.h" 38 39 /* 40 * Option Parsing (code inspired by NFS code) ··· 47 48 enum { 49 /* Options that take integer arguments */ 50 + Opt_debug, Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, 51 Opt_rfdno, Opt_wfdno, 52 /* String options */ 53 Opt_uname, Opt_remotename, 54 /* Options that take no arguments */ 55 + Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, Opt_pci, 56 /* Cache options */ 57 Opt_cache_loose, 58 /* Error token */ ··· 60 }; 61 62 static match_table_t tokens = { 63 + {Opt_debug, "debug=%x"}, 64 {Opt_port, "port=%u"}, 65 {Opt_msize, "msize=%u"}, 66 {Opt_uid, "uid=%u"}, ··· 67 {Opt_afid, "afid=%u"}, 68 {Opt_rfdno, "rfdno=%u"}, 69 {Opt_wfdno, "wfdno=%u"}, 70 {Opt_uname, "uname=%s"}, 71 {Opt_remotename, "aname=%s"}, 72 {Opt_unix, "proto=unix"}, 73 {Opt_tcp, "proto=tcp"}, 74 {Opt_fd, "proto=fd"}, 75 + #ifdef CONFIG_PCI_9P 76 + {Opt_pci, "proto=pci"}, 77 + #endif 78 {Opt_tcp, "tcp"}, 79 {Opt_unix, "unix"}, 80 {Opt_fd, "fd"}, ··· 82 {Opt_cache_loose, "loose"}, 83 {Opt_err, NULL} 84 }; 85 + 86 + extern struct p9_transport *p9pci_trans_create(void); 87 88 /* 89 * Parse option string. ··· 122 token = match_token(p, tokens, args); 123 if (token < Opt_uname) { 124 if ((ret = match_int(&args[0], &option)) < 0) { 125 + P9_DPRINTK(P9_DEBUG_ERROR, 126 "integer field, but no integer?\n"); 127 continue; 128 } 129 } 130 switch (token) { 131 + case Opt_debug: 132 + v9ses->debug = option; 133 + p9_debug_level = option; 134 + break; 135 case Opt_port: 136 v9ses->port = option; 137 break; ··· 149 case Opt_wfdno: 150 v9ses->wfdno = option; 151 break; 152 case Opt_tcp: 153 v9ses->proto = PROTO_TCP; 154 break; 155 case Opt_unix: 156 v9ses->proto = PROTO_UNIX; 157 + break; 158 + case Opt_pci: 159 + v9ses->proto = PROTO_PCI; 160 break; 161 case Opt_fd: 162 v9ses->proto = PROTO_FD; ··· 183 } 184 185 /** 186 * v9fs_session_init - initialize session 187 * @v9ses: session information structure 188 * @dev_name: device being mounted ··· 266 * 267 */ 268 269 + struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, 270 const char *dev_name, char *data) 271 { 272 int retval = -EINVAL; 273 + struct p9_transport *trans; 274 + struct p9_fid *fid; 275 276 v9ses->name = __getname(); 277 if (!v9ses->name) 278 + return ERR_PTR(-ENOMEM); 279 280 v9ses->remotename = __getname(); 281 if (!v9ses->remotename) { 282 __putname(v9ses->name); 283 + return ERR_PTR(-ENOMEM); 284 } 285 286 strcpy(v9ses->name, V9FS_DEFUSER); ··· 292 293 v9fs_parse_options(data, v9ses); 294 295 switch (v9ses->proto) { 296 case PROTO_TCP: 297 + trans = p9_trans_create_tcp(dev_name, v9ses->port); 298 break; 299 case PROTO_UNIX: 300 + trans = p9_trans_create_unix(dev_name); 301 *v9ses->remotename = 0; 302 break; 303 case PROTO_FD: 304 + trans = p9_trans_create_fd(v9ses->rfdno, v9ses->wfdno); 305 *v9ses->remotename = 0; 306 break; 307 + #ifdef CONFIG_PCI_9P 308 + case PROTO_PCI: 309 + trans = p9pci_trans_create(); 310 + *v9ses->remotename = 0; 311 + break; 312 + #endif 313 default: 314 printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto); 315 retval = -ENOPROTOOPT; 316 + goto error; 317 }; 318 319 + if (IS_ERR(trans)) { 320 + retval = PTR_ERR(trans); 321 + trans = NULL; 322 + goto error; 323 } 324 325 + v9ses->clnt = p9_client_create(trans, v9ses->maxdata + P9_IOHDRSZ, 326 + v9ses->extended); 327 328 + if (IS_ERR(v9ses->clnt)) { 329 + retval = PTR_ERR(v9ses->clnt); 330 + v9ses->clnt = NULL; 331 + P9_DPRINTK(P9_DEBUG_ERROR, "problem initializing 9p client\n"); 332 + goto error; 333 } 334 335 + fid = p9_client_attach(v9ses->clnt, NULL, v9ses->name, 336 + v9ses->remotename); 337 + if (IS_ERR(fid)) { 338 + retval = PTR_ERR(fid); 339 + fid = NULL; 340 + P9_DPRINTK(P9_DEBUG_ERROR, "cannot attach\n"); 341 + goto error; 342 } 343 344 + return fid; 345 346 + error: 347 v9fs_session_close(v9ses); 348 + return ERR_PTR(retval); 349 } 350 351 /** ··· 426 427 void v9fs_session_close(struct v9fs_session_info *v9ses) 428 { 429 + if (v9ses->clnt) { 430 + p9_client_destroy(v9ses->clnt); 431 + v9ses->clnt = NULL; 432 } 433 434 __putname(v9ses->name); ··· 446 * and cancel all pending requests. 447 */ 448 void v9fs_session_cancel(struct v9fs_session_info *v9ses) { 449 + P9_DPRINTK(P9_DEBUG_ERROR, "cancel session %p\n", v9ses); 450 + p9_client_disconnect(v9ses->clnt); 451 } 452 453 extern int v9fs_error_init(void); ··· 460 461 static int __init init_v9fs(void) 462 { 463 printk(KERN_INFO "Installing v9fs 9p2000 file system support\n"); 464 465 + return register_filesystem(&v9fs_fs_type); 466 } 467 468 /** ··· 487 488 static void __exit exit_v9fs(void) 489 { 490 unregister_filesystem(&v9fs_fs_type); 491 } 492 493 module_init(init_v9fs) 494 module_exit(exit_v9fs) 495 496 + MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>"); 497 MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); 498 MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>"); 499 MODULE_LICENSE("GPL");
+8 -24
fs/9p/v9fs.h
··· 22 */ 23 24 /* 25 - * Idpool structure provides lock and id management 26 - * 27 - */ 28 - 29 - struct v9fs_idpool { 30 - struct semaphore lock; 31 - struct idr pool; 32 - }; 33 - 34 - /* 35 * Session structure provides information for an opened session 36 * 37 */ ··· 44 unsigned int uid; /* default uid/muid for legacy support */ 45 unsigned int gid; /* default gid for legacy support */ 46 47 - /* book keeping */ 48 - struct v9fs_idpool fidpool; /* The FID pool for file descriptors */ 49 - 50 - struct v9fs_transport *transport; 51 - struct v9fs_mux_data *mux; 52 - 53 - int inprogress; /* session in progress => true */ 54 - int shutdown; /* session shutting down. no more attaches. */ 55 - unsigned char session_hung; 56 struct dentry *debugfs_dir; 57 }; 58 ··· 53 PROTO_TCP, 54 PROTO_UNIX, 55 PROTO_FD, 56 }; 57 58 /* possible values of ->cache */ ··· 65 66 extern struct dentry *v9fs_debugfs_root; 67 68 - int v9fs_session_init(struct v9fs_session_info *, const char *, char *); 69 - struct v9fs_session_info *v9fs_inode2v9ses(struct inode *); 70 void v9fs_session_close(struct v9fs_session_info *v9ses); 71 - int v9fs_get_idpool(struct v9fs_idpool *p); 72 - void v9fs_put_idpool(int id, struct v9fs_idpool *p); 73 - int v9fs_check_idpool(int id, struct v9fs_idpool *p); 74 void v9fs_session_cancel(struct v9fs_session_info *v9ses); 75 76 #define V9FS_MAGIC 0x01021997 ··· 77 #define V9FS_DEFUSER "nobody" 78 #define V9FS_DEFANAME "" 79
··· 22 */ 23 24 /* 25 * Session structure provides information for an opened session 26 * 27 */ ··· 54 unsigned int uid; /* default uid/muid for legacy support */ 55 unsigned int gid; /* default gid for legacy support */ 56 57 + struct p9_client *clnt; /* 9p client */ 58 struct dentry *debugfs_dir; 59 }; 60 ··· 71 PROTO_TCP, 72 PROTO_UNIX, 73 PROTO_FD, 74 + PROTO_PCI, 75 }; 76 77 /* possible values of ->cache */ ··· 82 83 extern struct dentry *v9fs_debugfs_root; 84 85 + struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, 86 + char *); 87 void v9fs_session_close(struct v9fs_session_info *v9ses); 88 void v9fs_session_cancel(struct v9fs_session_info *v9ses); 89 90 #define V9FS_MAGIC 0x01021997 ··· 97 #define V9FS_DEFUSER "nobody" 98 #define V9FS_DEFANAME "" 99 100 + static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) 101 + { 102 + return (inode->i_sb->s_fs_info); 103 + }
+3 -3
fs/9p/v9fs_vfs.h
··· 45 extern struct dentry_operations v9fs_cached_dentry_operations; 46 47 struct inode *v9fs_get_inode(struct super_block *sb, int mode); 48 - ino_t v9fs_qid2ino(struct v9fs_qid *qid); 49 - void v9fs_stat2inode(struct v9fs_stat *, struct inode *, struct super_block *); 50 int v9fs_dir_release(struct inode *inode, struct file *filp); 51 int v9fs_file_open(struct inode *inode, struct file *file); 52 - void v9fs_inode2stat(struct inode *inode, struct v9fs_stat *stat); 53 void v9fs_dentry_release(struct dentry *); 54 int v9fs_uflags2omode(int uflags);
··· 45 extern struct dentry_operations v9fs_cached_dentry_operations; 46 47 struct inode *v9fs_get_inode(struct super_block *sb, int mode); 48 + ino_t v9fs_qid2ino(struct p9_qid *qid); 49 + void v9fs_stat2inode(struct p9_stat *, struct inode *, struct super_block *); 50 int v9fs_dir_release(struct inode *inode, struct file *filp); 51 int v9fs_file_open(struct inode *inode, struct file *file); 52 + void v9fs_inode2stat(struct inode *inode, struct p9_stat *stat); 53 void v9fs_dentry_release(struct dentry *); 54 int v9fs_uflags2omode(int uflags);
+14 -43
fs/9p/vfs_addr.c
··· 33 #include <linux/pagemap.h> 34 #include <linux/idr.h> 35 #include <linux/sched.h> 36 37 - #include "debug.h" 38 #include "v9fs.h" 39 - #include "9p.h" 40 #include "v9fs_vfs.h" 41 #include "fid.h" 42 ··· 50 51 static int v9fs_vfs_readpage(struct file *filp, struct page *page) 52 { 53 - char *buffer = NULL; 54 - int retval = -EIO; 55 - loff_t offset = page_offset(page); 56 - int count = PAGE_CACHE_SIZE; 57 - struct inode *inode = filp->f_path.dentry->d_inode; 58 - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 59 - int rsize = v9ses->maxdata - V9FS_IOHDRSZ; 60 - struct v9fs_fid *v9f = filp->private_data; 61 - struct v9fs_fcall *fcall = NULL; 62 - int fid = v9f->fid; 63 - int total = 0; 64 - int result = 0; 65 66 - dprintk(DEBUG_VFS, "\n"); 67 - 68 buffer = kmap(page); 69 - do { 70 - if (count < rsize) 71 - rsize = count; 72 73 - result = v9fs_t_read(v9ses, fid, offset, rsize, &fcall); 74 75 - if (result < 0) { 76 - printk(KERN_ERR "v9fs_t_read returned %d\n", 77 - result); 78 - 79 - kfree(fcall); 80 - goto UnmapAndUnlock; 81 - } else 82 - offset += result; 83 - 84 - memcpy(buffer, fcall->params.rread.data, result); 85 - 86 - count -= result; 87 - buffer += result; 88 - total += result; 89 - 90 - kfree(fcall); 91 - 92 - if (result < rsize) 93 - break; 94 - } while (count); 95 - 96 - memset(buffer, 0, count); 97 flush_dcache_page(page); 98 SetPageUptodate(page); 99 retval = 0; 100 101 - UnmapAndUnlock: 102 kunmap(page); 103 unlock_page(page); 104 return retval;
··· 33 #include <linux/pagemap.h> 34 #include <linux/idr.h> 35 #include <linux/sched.h> 36 + #include <net/9p/9p.h> 37 + #include <net/9p/client.h> 38 39 #include "v9fs.h" 40 #include "v9fs_vfs.h" 41 #include "fid.h" 42 ··· 50 51 static int v9fs_vfs_readpage(struct file *filp, struct page *page) 52 { 53 + int retval; 54 + loff_t offset; 55 + char *buffer; 56 + struct p9_fid *fid; 57 58 + P9_DPRINTK(P9_DEBUG_VFS, "\n"); 59 + fid = filp->private_data; 60 buffer = kmap(page); 61 + offset = page_offset(page); 62 63 + retval = p9_client_readn(fid, buffer, offset, PAGE_CACHE_SIZE); 64 + if (retval < 0) 65 + goto done; 66 67 + memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); 68 flush_dcache_page(page); 69 SetPageUptodate(page); 70 retval = 0; 71 72 + done: 73 kunmap(page); 74 unlock_page(page); 75 return retval;
+14 -21
fs/9p/vfs_dentry.c
··· 34 #include <linux/namei.h> 35 #include <linux/idr.h> 36 #include <linux/sched.h> 37 38 - #include "debug.h" 39 #include "v9fs.h" 40 - #include "9p.h" 41 #include "v9fs_vfs.h" 42 #include "fid.h" 43 ··· 52 53 static int v9fs_dentry_delete(struct dentry *dentry) 54 { 55 - dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 56 57 return 1; 58 } ··· 69 static int v9fs_cached_dentry_delete(struct dentry *dentry) 70 { 71 struct inode *inode = dentry->d_inode; 72 - dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 73 74 if(!inode) 75 return 1; ··· 85 86 void v9fs_dentry_release(struct dentry *dentry) 87 { 88 - int err; 89 90 - dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 91 - 92 - if (dentry->d_fsdata != NULL) { 93 - struct list_head *fid_list = dentry->d_fsdata; 94 - struct v9fs_fid *temp = NULL; 95 - struct v9fs_fid *current_fid = NULL; 96 - 97 - list_for_each_entry_safe(current_fid, temp, fid_list, list) { 98 - err = v9fs_t_clunk(current_fid->v9ses, current_fid->fid); 99 - 100 - if (err < 0) 101 - dprintk(DEBUG_ERROR, "clunk failed: %d name %s\n", 102 - err, dentry->d_iname); 103 - 104 - v9fs_fid_destroy(current_fid); 105 } 106 107 - kfree(dentry->d_fsdata); /* free the list_head */ 108 } 109 } 110
··· 34 #include <linux/namei.h> 35 #include <linux/idr.h> 36 #include <linux/sched.h> 37 + #include <net/9p/9p.h> 38 + #include <net/9p/client.h> 39 40 #include "v9fs.h" 41 #include "v9fs_vfs.h" 42 #include "fid.h" 43 ··· 52 53 static int v9fs_dentry_delete(struct dentry *dentry) 54 { 55 + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 56 57 return 1; 58 } ··· 69 static int v9fs_cached_dentry_delete(struct dentry *dentry) 70 { 71 struct inode *inode = dentry->d_inode; 72 + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 73 74 if(!inode) 75 return 1; ··· 85 86 void v9fs_dentry_release(struct dentry *dentry) 87 { 88 + struct v9fs_dentry *dent; 89 + struct p9_fid *temp, *current_fid; 90 91 + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 92 + dent = dentry->d_fsdata; 93 + if (dent) { 94 + list_for_each_entry_safe(current_fid, temp, &dent->fidlist, 95 + dlist) { 96 + p9_client_clunk(current_fid); 97 } 98 99 + kfree(dent); 100 + dentry->d_fsdata = NULL; 101 } 102 } 103
+31 -118
fs/9p/vfs_dir.c
··· 32 #include <linux/sched.h> 33 #include <linux/inet.h> 34 #include <linux/idr.h> 35 36 - #include "debug.h" 37 #include "v9fs.h" 38 - #include "9p.h" 39 - #include "conv.h" 40 #include "v9fs_vfs.h" 41 #include "fid.h" 42 ··· 45 * 46 */ 47 48 - static inline int dt_type(struct v9fs_stat *mistat) 49 { 50 unsigned long perm = mistat->mode; 51 int rettype = DT_REG; 52 53 - if (perm & V9FS_DMDIR) 54 rettype = DT_DIR; 55 - if (perm & V9FS_DMSYMLINK) 56 rettype = DT_LNK; 57 58 return rettype; ··· 68 69 static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) 70 { 71 - struct v9fs_fcall *fcall = NULL; 72 - struct inode *inode = filp->f_path.dentry->d_inode; 73 - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 74 - struct v9fs_fid *file = filp->private_data; 75 - unsigned int i, n, s; 76 - int fid = -1; 77 - int ret = 0; 78 - struct v9fs_stat stat; 79 - int over = 0; 80 81 - dprintk(DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); 82 83 - fid = file->fid; 84 85 - if (file->rdir_fcall && (filp->f_pos != file->rdir_pos)) { 86 - kfree(file->rdir_fcall); 87 - file->rdir_fcall = NULL; 88 - } 89 - 90 - if (file->rdir_fcall) { 91 - n = file->rdir_fcall->params.rread.count; 92 - i = file->rdir_fpos; 93 - while (i < n) { 94 - s = v9fs_deserialize_stat( 95 - file->rdir_fcall->params.rread.data + i, 96 - n - i, &stat, v9ses->extended); 97 - 98 - if (s == 0) { 99 - dprintk(DEBUG_ERROR, 100 - "error while deserializing stat\n"); 101 - ret = -EIO; 102 - goto FreeStructs; 103 - } 104 - 105 - over = filldir(dirent, stat.name.str, stat.name.len, 106 - filp->f_pos, v9fs_qid2ino(&stat.qid), 107 - dt_type(&stat)); 108 - 109 - if (over) { 110 - file->rdir_fpos = i; 111 - file->rdir_pos = filp->f_pos; 112 - break; 113 - } 114 - 115 - i += s; 116 - filp->f_pos += s; 117 - } 118 - 119 - if (!over) { 120 - kfree(file->rdir_fcall); 121 - file->rdir_fcall = NULL; 122 - } 123 - } 124 - 125 - while (!over) { 126 - ret = v9fs_t_read(v9ses, fid, filp->f_pos, 127 - v9ses->maxdata-V9FS_IOHDRSZ, &fcall); 128 - if (ret < 0) { 129 - dprintk(DEBUG_ERROR, "error while reading: %d: %p\n", 130 - ret, fcall); 131 - goto FreeStructs; 132 - } else if (ret == 0) 133 break; 134 135 - n = ret; 136 - i = 0; 137 - while (i < n) { 138 - s = v9fs_deserialize_stat(fcall->params.rread.data + i, 139 - n - i, &stat, v9ses->extended); 140 - 141 - if (s == 0) { 142 - dprintk(DEBUG_ERROR, 143 - "error while deserializing stat\n"); 144 - return -EIO; 145 - } 146 - 147 - over = filldir(dirent, stat.name.str, stat.name.len, 148 - filp->f_pos, v9fs_qid2ino(&stat.qid), 149 - dt_type(&stat)); 150 - 151 - if (over) { 152 - file->rdir_fcall = fcall; 153 - file->rdir_fpos = i; 154 - file->rdir_pos = filp->f_pos; 155 - fcall = NULL; 156 - break; 157 - } 158 - 159 - i += s; 160 - filp->f_pos += s; 161 - } 162 - 163 - kfree(fcall); 164 } 165 166 - FreeStructs: 167 - kfree(fcall); 168 - return ret; 169 } 170 171 /** 172 * v9fs_dir_release - close a directory ··· 107 108 int v9fs_dir_release(struct inode *inode, struct file *filp) 109 { 110 - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 111 - struct v9fs_fid *fid = filp->private_data; 112 - int fidnum = -1; 113 114 - dprintk(DEBUG_VFS, "inode: %p filp: %p fid: %d\n", inode, filp, 115 - fid->fid); 116 - fidnum = fid->fid; 117 - 118 filemap_write_and_wait(inode->i_mapping); 119 - 120 - if (fidnum >= 0) { 121 - dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen, 122 - fid->fid); 123 - 124 - if (v9fs_t_clunk(v9ses, fidnum)) 125 - dprintk(DEBUG_ERROR, "clunk failed\n"); 126 - 127 - kfree(fid->rdir_fcall); 128 - kfree(fid); 129 - 130 - filp->private_data = NULL; 131 - } 132 - 133 return 0; 134 } 135
··· 32 #include <linux/sched.h> 33 #include <linux/inet.h> 34 #include <linux/idr.h> 35 + #include <net/9p/9p.h> 36 + #include <net/9p/client.h> 37 38 #include "v9fs.h" 39 #include "v9fs_vfs.h" 40 #include "fid.h" 41 ··· 46 * 47 */ 48 49 + static inline int dt_type(struct p9_stat *mistat) 50 { 51 unsigned long perm = mistat->mode; 52 int rettype = DT_REG; 53 54 + if (perm & P9_DMDIR) 55 rettype = DT_DIR; 56 + if (perm & P9_DMSYMLINK) 57 rettype = DT_LNK; 58 59 return rettype; ··· 69 70 static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) 71 { 72 + int over; 73 + struct p9_fid *fid; 74 + struct v9fs_session_info *v9ses; 75 + struct inode *inode; 76 + struct p9_stat *st; 77 78 + P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); 79 + inode = filp->f_path.dentry->d_inode; 80 + v9ses = v9fs_inode2v9ses(inode); 81 + fid = filp->private_data; 82 + while ((st = p9_client_dirread(fid, filp->f_pos)) != NULL) { 83 + if (IS_ERR(st)) 84 + return PTR_ERR(st); 85 86 + over = filldir(dirent, st->name.str, st->name.len, filp->f_pos, 87 + v9fs_qid2ino(&st->qid), dt_type(st)); 88 89 + if (over) 90 break; 91 92 + filp->f_pos += st->size; 93 + kfree(st); 94 + st = NULL; 95 } 96 97 + kfree(st); 98 + return 0; 99 } 100 + 101 102 /** 103 * v9fs_dir_release - close a directory ··· 178 179 int v9fs_dir_release(struct inode *inode, struct file *filp) 180 { 181 + struct p9_fid *fid; 182 183 + fid = filp->private_data; 184 + P9_DPRINTK(P9_DEBUG_VFS, 185 + "inode: %p filp: %p fid: %d\n", inode, filp, fid->fid); 186 filemap_write_and_wait(inode->i_mapping); 187 + p9_client_clunk(fid); 188 return 0; 189 } 190
+47 -119
fs/9p/vfs_file.c
··· 34 #include <linux/list.h> 35 #include <asm/uaccess.h> 36 #include <linux/idr.h> 37 38 - #include "debug.h" 39 #include "v9fs.h" 40 - #include "9p.h" 41 #include "v9fs_vfs.h" 42 #include "fid.h" 43 ··· 52 53 int v9fs_file_open(struct inode *inode, struct file *file) 54 { 55 - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 56 - struct v9fs_fid *vfid; 57 - struct v9fs_fcall *fcall = NULL; 58 - int omode; 59 int err; 60 61 - dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); 62 - 63 - vfid = v9fs_fid_clone(file->f_path.dentry); 64 - if (IS_ERR(vfid)) 65 - return PTR_ERR(vfid); 66 - 67 omode = v9fs_uflags2omode(file->f_flags); 68 - err = v9fs_t_open(v9ses, vfid->fid, omode, &fcall); 69 - if (err < 0) { 70 - PRINT_FCALL_ERROR("open failed", fcall); 71 - goto Clunk_Fid; 72 } 73 74 - file->private_data = vfid; 75 - vfid->fidopen = 1; 76 - vfid->fidclunked = 0; 77 - vfid->iounit = fcall->params.ropen.iounit; 78 - vfid->rdir_pos = 0; 79 - vfid->rdir_fcall = NULL; 80 - vfid->filp = file; 81 - kfree(fcall); 82 - 83 - if((vfid->qid.version) && (v9ses->cache)) { 84 - dprintk(DEBUG_VFS, "cached"); 85 /* enable cached file options */ 86 if(file->f_op == &v9fs_file_operations) 87 file->f_op = &v9fs_cached_file_operations; 88 } 89 90 return 0; 91 - 92 - Clunk_Fid: 93 - v9fs_fid_clunk(v9ses, vfid); 94 - kfree(fcall); 95 - 96 - return err; 97 } 98 99 /** ··· 102 int res = 0; 103 struct inode *inode = filp->f_path.dentry->d_inode; 104 105 - dprintk(DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); 106 107 /* No mandatory locks */ 108 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) ··· 128 v9fs_file_read(struct file *filp, char __user * data, size_t count, 129 loff_t * offset) 130 { 131 - struct inode *inode = filp->f_path.dentry->d_inode; 132 - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 133 - struct v9fs_fid *v9f = filp->private_data; 134 - struct v9fs_fcall *fcall = NULL; 135 - int fid = v9f->fid; 136 - int rsize = 0; 137 - int result = 0; 138 - int total = 0; 139 - int n; 140 141 - dprintk(DEBUG_VFS, "\n"); 142 143 - rsize = v9ses->maxdata - V9FS_IOHDRSZ; 144 - if (v9f->iounit != 0 && rsize > v9f->iounit) 145 - rsize = v9f->iounit; 146 - 147 - do { 148 - if (count < rsize) 149 - rsize = count; 150 - 151 - result = v9fs_t_read(v9ses, fid, *offset, rsize, &fcall); 152 - 153 - if (result < 0) { 154 - printk(KERN_ERR "9P2000: v9fs_t_read returned %d\n", 155 - result); 156 - 157 - kfree(fcall); 158 - return total; 159 - } else 160 - *offset += result; 161 - 162 - n = copy_to_user(data, fcall->params.rread.data, result); 163 - if (n) { 164 - dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n); 165 - kfree(fcall); 166 - return -EFAULT; 167 - } 168 - 169 - count -= result; 170 - data += result; 171 - total += result; 172 - 173 - kfree(fcall); 174 - 175 - if (result < rsize) 176 - break; 177 - } while (count); 178 - 179 - return total; 180 } 181 182 /** ··· 153 v9fs_file_write(struct file *filp, const char __user * data, 154 size_t count, loff_t * offset) 155 { 156 struct inode *inode = filp->f_path.dentry->d_inode; 157 - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 158 - struct v9fs_fid *v9fid = filp->private_data; 159 - struct v9fs_fcall *fcall; 160 - int fid = v9fid->fid; 161 - int result = -EIO; 162 - int rsize = 0; 163 - int total = 0; 164 165 - dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, 166 - (int)*offset); 167 - rsize = v9ses->maxdata - V9FS_IOHDRSZ; 168 - if (v9fid->iounit != 0 && rsize > v9fid->iounit) 169 - rsize = v9fid->iounit; 170 171 - do { 172 - if (count < rsize) 173 - rsize = count; 174 175 - result = v9fs_t_write(v9ses, fid, *offset, rsize, data, &fcall); 176 - if (result < 0) { 177 - PRINT_FCALL_ERROR("error while writing", fcall); 178 - kfree(fcall); 179 - return result; 180 - } else 181 - *offset += result; 182 - 183 - kfree(fcall); 184 - fcall = NULL; 185 - 186 - if (result != rsize) { 187 - eprintk(KERN_ERR, 188 - "short write: v9fs_t_write returned %d\n", 189 - result); 190 - break; 191 - } 192 - 193 - count -= result; 194 - data += result; 195 - total += result; 196 - } while (count); 197 198 invalidate_inode_pages2(inode->i_mapping); 199 - return total; 200 } 201 202 static const struct file_operations v9fs_cached_file_operations = {
··· 34 #include <linux/list.h> 35 #include <asm/uaccess.h> 36 #include <linux/idr.h> 37 + #include <net/9p/9p.h> 38 + #include <net/9p/client.h> 39 40 #include "v9fs.h" 41 #include "v9fs_vfs.h" 42 #include "fid.h" 43 ··· 52 53 int v9fs_file_open(struct inode *inode, struct file *file) 54 { 55 int err; 56 + struct v9fs_session_info *v9ses; 57 + struct p9_fid *fid; 58 + int omode; 59 60 + P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p \n", inode, file); 61 + v9ses = v9fs_inode2v9ses(inode); 62 omode = v9fs_uflags2omode(file->f_flags); 63 + fid = file->private_data; 64 + if (!fid) { 65 + fid = v9fs_fid_clone(file->f_path.dentry); 66 + if (IS_ERR(fid)) 67 + return PTR_ERR(fid); 68 + 69 + err = p9_client_open(fid, omode); 70 + if (err < 0) { 71 + p9_client_clunk(fid); 72 + return err; 73 + } 74 + if (omode & P9_OTRUNC) { 75 + inode->i_size = 0; 76 + inode->i_blocks = 0; 77 + } 78 } 79 80 + file->private_data = fid; 81 + if ((fid->qid.version) && (v9ses->cache)) { 82 + P9_DPRINTK(P9_DEBUG_VFS, "cached"); 83 /* enable cached file options */ 84 if(file->f_op == &v9fs_file_operations) 85 file->f_op = &v9fs_cached_file_operations; 86 } 87 88 return 0; 89 } 90 91 /** ··· 110 int res = 0; 111 struct inode *inode = filp->f_path.dentry->d_inode; 112 113 + P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); 114 115 /* No mandatory locks */ 116 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) ··· 136 v9fs_file_read(struct file *filp, char __user * data, size_t count, 137 loff_t * offset) 138 { 139 + int ret; 140 + struct p9_fid *fid; 141 142 + P9_DPRINTK(P9_DEBUG_VFS, "\n"); 143 + fid = filp->private_data; 144 + ret = p9_client_uread(fid, data, *offset, count); 145 + if (ret > 0) 146 + *offset += ret; 147 148 + return ret; 149 } 150 151 /** ··· 200 v9fs_file_write(struct file *filp, const char __user * data, 201 size_t count, loff_t * offset) 202 { 203 + int ret; 204 + struct p9_fid *fid; 205 struct inode *inode = filp->f_path.dentry->d_inode; 206 207 + P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data, 208 + (int)count, (int)*offset); 209 210 + fid = filp->private_data; 211 + ret = p9_client_uwrite(fid, data, *offset, count); 212 + if (ret > 0) 213 + *offset += ret; 214 215 + if (*offset > inode->i_size) { 216 + inode->i_size = *offset; 217 + inode->i_blocks = (inode->i_size + 512 - 1) >> 9; 218 + } 219 220 invalidate_inode_pages2(inode->i_mapping); 221 + return ret; 222 } 223 224 static const struct file_operations v9fs_cached_file_operations = {
+285 -469
fs/9p/vfs_inode.c
··· 34 #include <linux/namei.h> 35 #include <linux/idr.h> 36 #include <linux/sched.h> 37 38 - #include "debug.h" 39 #include "v9fs.h" 40 - #include "9p.h" 41 #include "v9fs_vfs.h" 42 #include "fid.h" 43 ··· 58 int res; 59 res = mode & 0777; 60 if (S_ISDIR(mode)) 61 - res |= V9FS_DMDIR; 62 if (v9ses->extended) { 63 if (S_ISLNK(mode)) 64 - res |= V9FS_DMSYMLINK; 65 if (v9ses->nodev == 0) { 66 if (S_ISSOCK(mode)) 67 - res |= V9FS_DMSOCKET; 68 if (S_ISFIFO(mode)) 69 - res |= V9FS_DMNAMEDPIPE; 70 if (S_ISBLK(mode)) 71 - res |= V9FS_DMDEVICE; 72 if (S_ISCHR(mode)) 73 - res |= V9FS_DMDEVICE; 74 } 75 76 if ((mode & S_ISUID) == S_ISUID) 77 - res |= V9FS_DMSETUID; 78 if ((mode & S_ISGID) == S_ISGID) 79 - res |= V9FS_DMSETGID; 80 - if ((mode & V9FS_DMLINK)) 81 - res |= V9FS_DMLINK; 82 } 83 84 return res; ··· 97 98 res = mode & 0777; 99 100 - if ((mode & V9FS_DMDIR) == V9FS_DMDIR) 101 res |= S_IFDIR; 102 - else if ((mode & V9FS_DMSYMLINK) && (v9ses->extended)) 103 res |= S_IFLNK; 104 - else if ((mode & V9FS_DMSOCKET) && (v9ses->extended) 105 && (v9ses->nodev == 0)) 106 res |= S_IFSOCK; 107 - else if ((mode & V9FS_DMNAMEDPIPE) && (v9ses->extended) 108 && (v9ses->nodev == 0)) 109 res |= S_IFIFO; 110 - else if ((mode & V9FS_DMDEVICE) && (v9ses->extended) 111 && (v9ses->nodev == 0)) 112 res |= S_IFBLK; 113 else 114 res |= S_IFREG; 115 116 if (v9ses->extended) { 117 - if ((mode & V9FS_DMSETUID) == V9FS_DMSETUID) 118 res |= S_ISUID; 119 120 - if ((mode & V9FS_DMSETGID) == V9FS_DMSETGID) 121 res |= S_ISGID; 122 } 123 ··· 132 switch (uflags&3) { 133 default: 134 case O_RDONLY: 135 - ret = V9FS_OREAD; 136 break; 137 138 case O_WRONLY: 139 - ret = V9FS_OWRITE; 140 break; 141 142 case O_RDWR: 143 - ret = V9FS_ORDWR; 144 break; 145 } 146 147 if (uflags & O_EXCL) 148 - ret |= V9FS_OEXCL; 149 150 if (uflags & O_TRUNC) 151 - ret |= V9FS_OTRUNC; 152 153 if (uflags & O_APPEND) 154 - ret |= V9FS_OAPPEND; 155 156 return ret; 157 } ··· 164 */ 165 166 static void 167 - v9fs_blank_wstat(struct v9fs_wstat *wstat) 168 { 169 wstat->type = ~0; 170 wstat->dev = ~0; ··· 197 struct inode *inode; 198 struct v9fs_session_info *v9ses = sb->s_fs_info; 199 200 - dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); 201 202 inode = new_inode(sb); 203 if (inode) { ··· 215 case S_IFCHR: 216 case S_IFSOCK: 217 if(!v9ses->extended) { 218 - dprintk(DEBUG_ERROR, "special files without extended mode\n"); 219 return ERR_PTR(-EINVAL); 220 } 221 init_special_inode(inode, inode->i_mode, ··· 228 break; 229 case S_IFLNK: 230 if(!v9ses->extended) { 231 - dprintk(DEBUG_ERROR, "extended modes used w/o 9P2000.u\n"); 232 return ERR_PTR(-EINVAL); 233 } 234 inode->i_op = &v9fs_symlink_inode_operations; ··· 243 inode->i_fop = &v9fs_dir_operations; 244 break; 245 default: 246 - dprintk(DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n", 247 mode, mode & S_IFMT); 248 return ERR_PTR(-EINVAL); 249 } 250 } else { 251 - eprintk(KERN_WARNING, "Problem allocating inode\n"); 252 return ERR_PTR(-ENOMEM); 253 } 254 return inode; 255 } 256 257 - static int 258 - v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm, 259 - u8 mode, char *extension, u32 *fidp, struct v9fs_qid *qid, u32 *iounit) 260 - { 261 - int fid; 262 - int err; 263 - struct v9fs_fcall *fcall; 264 - 265 - fid = v9fs_get_idpool(&v9ses->fidpool); 266 - if (fid < 0) { 267 - eprintk(KERN_WARNING, "no free fids available\n"); 268 - return -ENOSPC; 269 - } 270 - 271 - err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall); 272 - if (err < 0) { 273 - PRINT_FCALL_ERROR("clone error", fcall); 274 - if (fcall && fcall->id == RWALK) 275 - goto clunk_fid; 276 - else 277 - goto put_fid; 278 - } 279 - kfree(fcall); 280 - 281 - err = v9fs_t_create(v9ses, fid, name, perm, mode, extension, &fcall); 282 - if (err < 0) { 283 - PRINT_FCALL_ERROR("create fails", fcall); 284 - goto clunk_fid; 285 - } 286 - 287 - if (iounit) 288 - *iounit = fcall->params.rcreate.iounit; 289 - 290 - if (qid) 291 - *qid = fcall->params.rcreate.qid; 292 - 293 - if (fidp) 294 - *fidp = fid; 295 - 296 - kfree(fcall); 297 - return 0; 298 - 299 - clunk_fid: 300 - v9fs_t_clunk(v9ses, fid); 301 - fid = V9FS_NOFID; 302 - 303 - put_fid: 304 - if (fid != V9FS_NOFID) 305 - v9fs_put_idpool(fid, &v9ses->fidpool); 306 - 307 - kfree(fcall); 308 - return err; 309 - } 310 - 311 static struct v9fs_fid* 312 v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) 313 { ··· 305 kfree(fcall); 306 return ERR_PTR(err); 307 } 308 309 static struct inode * 310 - v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid, 311 struct super_block *sb) 312 { 313 int err, umode; 314 struct inode *ret; 315 - struct v9fs_fcall *fcall; 316 317 ret = NULL; 318 - err = v9fs_t_stat(v9ses, fid, &fcall); 319 - if (err) { 320 - PRINT_FCALL_ERROR("stat error", fcall); 321 goto error; 322 } 323 324 - umode = p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode); 325 ret = v9fs_get_inode(sb, umode); 326 if (IS_ERR(ret)) { 327 err = PTR_ERR(ret); ··· 331 goto error; 332 } 333 334 - v9fs_stat2inode(&fcall->params.rstat.stat, ret, sb); 335 - kfree(fcall); 336 return ret; 337 338 error: 339 - kfree(fcall); 340 if (ret) 341 iput(ret); 342 ··· 354 355 static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) 356 { 357 - struct v9fs_fcall *fcall = NULL; 358 - struct super_block *sb = NULL; 359 - struct v9fs_session_info *v9ses = NULL; 360 - struct v9fs_fid *v9fid = NULL; 361 - struct inode *file_inode = NULL; 362 - int fid = -1; 363 - int result = 0; 364 365 - dprintk(DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, 366 rmdir); 367 368 file_inode = file->d_inode; 369 - sb = file_inode->i_sb; 370 v9ses = v9fs_inode2v9ses(file_inode); 371 v9fid = v9fs_fid_clone(file); 372 if(IS_ERR(v9fid)) 373 return PTR_ERR(v9fid); 374 375 - fid = v9fid->fid; 376 - if (fid < 0) { 377 - dprintk(DEBUG_ERROR, "inode #%lu, no fid!\n", 378 - file_inode->i_ino); 379 - return -EBADF; 380 - } 381 - 382 - result = v9fs_t_remove(v9ses, fid, &fcall); 383 - if (result < 0) { 384 - PRINT_FCALL_ERROR("remove fails", fcall); 385 - goto Error; 386 - } 387 - 388 - v9fs_put_idpool(fid, &v9ses->fidpool); 389 - v9fs_fid_destroy(v9fid); 390 - 391 - Error: 392 - kfree(fcall); 393 - return result; 394 } 395 396 static int ··· 376 return 0; 377 } 378 379 /** 380 * v9fs_vfs_create - VFS hook to create files 381 - * @inode: directory inode that is being deleted 382 * @dentry: dentry that is being deleted 383 * @mode: create permissions 384 * @nd: path information ··· 468 struct nameidata *nd) 469 { 470 int err; 471 - u32 fid, perm, iounit; 472 int flags; 473 struct v9fs_session_info *v9ses; 474 - struct v9fs_fid *dfid, *vfid, *ffid; 475 - struct inode *inode; 476 - struct v9fs_qid qid; 477 struct file *filp; 478 479 - inode = NULL; 480 - vfid = NULL; 481 v9ses = v9fs_inode2v9ses(dir); 482 - dfid = v9fs_fid_clone(dentry->d_parent); 483 - if(IS_ERR(dfid)) { 484 - err = PTR_ERR(dfid); 485 - goto error; 486 - } 487 - 488 perm = unixmode2p9mode(v9ses, mode); 489 if (nd && nd->flags & LOOKUP_OPEN) 490 flags = nd->intent.open.flags - 1; 491 else 492 flags = O_RDWR; 493 494 - err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, 495 - perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit); 496 - 497 - if (err) 498 - goto clunk_dfid; 499 - 500 - vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); 501 - v9fs_fid_clunk(v9ses, dfid); 502 - if (IS_ERR(vfid)) { 503 - err = PTR_ERR(vfid); 504 - vfid = NULL; 505 goto error; 506 } 507 508 - inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); 509 - if (IS_ERR(inode)) { 510 - err = PTR_ERR(inode); 511 - inode = NULL; 512 - goto error; 513 - } 514 - 515 - if(v9ses->cache) 516 - dentry->d_op = &v9fs_cached_dentry_operations; 517 - else 518 - dentry->d_op = &v9fs_dentry_operations; 519 - d_instantiate(dentry, inode); 520 - 521 if (nd && nd->flags & LOOKUP_OPEN) { 522 - ffid = v9fs_fid_create(v9ses, fid); 523 - if (!ffid) 524 - return -ENOMEM; 525 - 526 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); 527 if (IS_ERR(filp)) { 528 - v9fs_fid_destroy(ffid); 529 - return PTR_ERR(filp); 530 } 531 532 - ffid->rdir_pos = 0; 533 - ffid->rdir_fcall = NULL; 534 - ffid->fidopen = 1; 535 - ffid->iounit = iounit; 536 - ffid->filp = filp; 537 - filp->private_data = ffid; 538 - } 539 540 return 0; 541 542 - clunk_dfid: 543 - v9fs_fid_clunk(v9ses, dfid); 544 - 545 error: 546 - if (vfid) 547 - v9fs_fid_destroy(vfid); 548 549 return err; 550 } ··· 523 static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 524 { 525 int err; 526 - u32 fid, perm; 527 struct v9fs_session_info *v9ses; 528 - struct v9fs_fid *dfid, *vfid; 529 - struct inode *inode; 530 531 - inode = NULL; 532 - vfid = NULL; 533 v9ses = v9fs_inode2v9ses(dir); 534 - dfid = v9fs_fid_clone(dentry->d_parent); 535 - if(IS_ERR(dfid)) { 536 - err = PTR_ERR(dfid); 537 - goto error; 538 - } 539 - 540 perm = unixmode2p9mode(v9ses, mode | S_IFDIR); 541 - 542 - err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, 543 - perm, V9FS_OREAD, NULL, &fid, NULL, NULL); 544 - 545 - if (err) { 546 - dprintk(DEBUG_ERROR, "create error %d\n", err); 547 - goto clean_up_dfid; 548 } 549 550 - vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); 551 - if (IS_ERR(vfid)) { 552 - err = PTR_ERR(vfid); 553 - vfid = NULL; 554 - goto clean_up_dfid; 555 - } 556 557 - v9fs_fid_clunk(v9ses, dfid); 558 - inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); 559 - if (IS_ERR(inode)) { 560 - err = PTR_ERR(inode); 561 - inode = NULL; 562 - v9fs_fid_destroy(vfid); 563 - goto error; 564 - } 565 - 566 - if(v9ses->cache) 567 - dentry->d_op = &v9fs_cached_dentry_operations; 568 - else 569 - dentry->d_op = &v9fs_dentry_operations; 570 - d_instantiate(dentry, inode); 571 - return 0; 572 - 573 - clean_up_dfid: 574 - v9fs_fid_clunk(v9ses, dfid); 575 - 576 - error: 577 return err; 578 } 579 ··· 556 { 557 struct super_block *sb; 558 struct v9fs_session_info *v9ses; 559 - struct v9fs_fid *dirfid; 560 - struct v9fs_fid *fid; 561 struct inode *inode; 562 - struct v9fs_fcall *fcall = NULL; 563 - int dirfidnum = -1; 564 - int newfid = -1; 565 int result = 0; 566 567 - dprintk(DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", 568 dir, dentry->d_name.name, dentry, nameidata); 569 570 sb = dir->i_sb; 571 v9ses = v9fs_inode2v9ses(dir); 572 - dirfid = v9fs_fid_lookup(dentry->d_parent); 573 574 - if(IS_ERR(dirfid)) 575 - return ERR_PTR(PTR_ERR(dirfid)); 576 - 577 - dirfidnum = dirfid->fid; 578 - 579 - newfid = v9fs_get_idpool(&v9ses->fidpool); 580 - if (newfid < 0) { 581 - eprintk(KERN_WARNING, "newfid fails!\n"); 582 - result = -ENOSPC; 583 - goto Release_Dirfid; 584 - } 585 - 586 - result = v9fs_t_walk(v9ses, dirfidnum, newfid, 587 - (char *)dentry->d_name.name, &fcall); 588 - 589 - up(&dirfid->lock); 590 - 591 - if (result < 0) { 592 - if (fcall && fcall->id == RWALK) 593 - v9fs_t_clunk(v9ses, newfid); 594 - else 595 - v9fs_put_idpool(newfid, &v9ses->fidpool); 596 - 597 if (result == -ENOENT) { 598 d_add(dentry, NULL); 599 - dprintk(DEBUG_VFS, 600 - "Return negative dentry %p count %d\n", 601 - dentry, atomic_read(&dentry->d_count)); 602 - kfree(fcall); 603 return NULL; 604 } 605 - dprintk(DEBUG_ERROR, "walk error:%d\n", result); 606 - goto FreeFcall; 607 - } 608 - kfree(fcall); 609 610 - result = v9fs_t_stat(v9ses, newfid, &fcall); 611 - if (result < 0) { 612 - dprintk(DEBUG_ERROR, "stat error\n"); 613 - goto FreeFcall; 614 } 615 616 - inode = v9fs_get_inode(sb, p9mode2unixmode(v9ses, 617 - fcall->params.rstat.stat.mode)); 618 - 619 - if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) { 620 - eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n", 621 - PTR_ERR(inode)); 622 - 623 - result = -ENOSPC; 624 - goto FreeFcall; 625 } 626 627 - inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); 628 - 629 - fid = v9fs_fid_create(v9ses, newfid); 630 - if (fid == NULL) { 631 - dprintk(DEBUG_ERROR, "couldn't insert\n"); 632 - result = -ENOMEM; 633 - goto FreeFcall; 634 - } 635 - 636 - result = v9fs_fid_insert(fid, dentry); 637 if (result < 0) 638 - goto FreeFcall; 639 640 - fid->qid = fcall->params.rstat.stat.qid; 641 - v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb); 642 if((fid->qid.version)&&(v9ses->cache)) 643 dentry->d_op = &v9fs_cached_dentry_operations; 644 else 645 dentry->d_op = &v9fs_dentry_operations; 646 647 d_add(dentry, inode); 648 - kfree(fcall); 649 - 650 return NULL; 651 652 - Release_Dirfid: 653 - up(&dirfid->lock); 654 - 655 - FreeFcall: 656 - kfree(fcall); 657 658 return ERR_PTR(result); 659 } ··· 645 v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, 646 struct inode *new_dir, struct dentry *new_dentry) 647 { 648 - struct inode *old_inode = old_dentry->d_inode; 649 - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); 650 - struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); 651 - struct v9fs_fid *olddirfid; 652 - struct v9fs_fid *newdirfid; 653 - struct v9fs_wstat wstat; 654 - struct v9fs_fcall *fcall = NULL; 655 - int fid = -1; 656 - int olddirfidnum = -1; 657 - int newdirfidnum = -1; 658 - int retval = 0; 659 660 - dprintk(DEBUG_VFS, "\n"); 661 - 662 if(IS_ERR(oldfid)) 663 return PTR_ERR(oldfid); 664 665 olddirfid = v9fs_fid_clone(old_dentry->d_parent); 666 if(IS_ERR(olddirfid)) { 667 retval = PTR_ERR(olddirfid); 668 - goto Release_lock; 669 } 670 671 newdirfid = v9fs_fid_clone(new_dentry->d_parent); 672 if(IS_ERR(newdirfid)) { 673 retval = PTR_ERR(newdirfid); 674 - goto Clunk_olddir; 675 } 676 677 /* 9P can only handle file rename in the same directory */ 678 if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { 679 - dprintk(DEBUG_ERROR, "old dir and new dir are different\n"); 680 retval = -EXDEV; 681 - goto Clunk_newdir; 682 - } 683 - 684 - fid = oldfid->fid; 685 - olddirfidnum = olddirfid->fid; 686 - newdirfidnum = newdirfid->fid; 687 - 688 - if (fid < 0) { 689 - dprintk(DEBUG_ERROR, "no fid for old file #%lu\n", 690 - old_inode->i_ino); 691 - retval = -EBADF; 692 - goto Clunk_newdir; 693 } 694 695 v9fs_blank_wstat(&wstat); 696 wstat.muid = v9ses->name; 697 wstat.name = (char *) new_dentry->d_name.name; 698 699 - retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall); 700 701 - if (retval < 0) 702 - PRINT_FCALL_ERROR("wstat error", fcall); 703 704 - kfree(fcall); 705 - 706 - Clunk_newdir: 707 - v9fs_fid_clunk(v9ses, newdirfid); 708 - 709 - Clunk_olddir: 710 - v9fs_fid_clunk(v9ses, olddirfid); 711 - 712 - Release_lock: 713 - up(&oldfid->lock); 714 - 715 return retval; 716 } 717 ··· 708 v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 709 struct kstat *stat) 710 { 711 - struct v9fs_fcall *fcall = NULL; 712 - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); 713 - struct v9fs_fid *fid = v9fs_fid_clone(dentry); 714 - int err = -EPERM; 715 716 - dprintk(DEBUG_VFS, "dentry: %p\n", dentry); 717 - if(IS_ERR(fid)) 718 return PTR_ERR(fid); 719 720 - err = v9fs_t_stat(v9ses, fid->fid, &fcall); 721 722 - if (err < 0) 723 - dprintk(DEBUG_ERROR, "stat error\n"); 724 - else { 725 - v9fs_stat2inode(&fcall->params.rstat.stat, dentry->d_inode, 726 - dentry->d_inode->i_sb); 727 generic_fillattr(dentry->d_inode, stat); 728 - } 729 730 - kfree(fcall); 731 - v9fs_fid_clunk(v9ses, fid); 732 - return err; 733 } 734 735 /** ··· 743 744 static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) 745 { 746 - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); 747 - struct v9fs_fid *fid = v9fs_fid_clone(dentry); 748 - struct v9fs_fcall *fcall = NULL; 749 - struct v9fs_wstat wstat; 750 - int res = -EPERM; 751 752 - dprintk(DEBUG_VFS, "\n"); 753 if(IS_ERR(fid)) 754 return PTR_ERR(fid); 755 ··· 776 wstat.n_gid = iattr->ia_gid; 777 } 778 779 - res = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall); 780 781 - if (res < 0) 782 - PRINT_FCALL_ERROR("wstat error", fcall); 783 - 784 - kfree(fcall); 785 - if (res >= 0) 786 - res = inode_setattr(dentry->d_inode, iattr); 787 - 788 - v9fs_fid_clunk(v9ses, fid); 789 - return res; 790 } 791 792 /** ··· 792 */ 793 794 void 795 - v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode, 796 struct super_block *sb) 797 { 798 int n; ··· 833 case 'b': 834 break; 835 default: 836 - dprintk(DEBUG_ERROR, "Unknown special type %c (%.*s)\n", 837 - type, stat->extension.len, stat->extension.str); 838 }; 839 inode->i_rdev = MKDEV(major, minor); 840 } else ··· 843 844 inode->i_size = stat->length; 845 846 - inode->i_blocks = 847 - (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; 848 } 849 850 /** ··· 854 * BUG: potential for inode number collisions? 855 */ 856 857 - ino_t v9fs_qid2ino(struct v9fs_qid *qid) 858 { 859 u64 path = qid->path + 2; 860 ino_t i = 0; ··· 877 878 static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) 879 { 880 - int retval = -EPERM; 881 882 - struct v9fs_fcall *fcall = NULL; 883 - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); 884 - struct v9fs_fid *fid = v9fs_fid_clone(dentry); 885 886 if(IS_ERR(fid)) 887 return PTR_ERR(fid); 888 889 - if (!v9ses->extended) { 890 - retval = -EBADF; 891 - dprintk(DEBUG_ERROR, "not extended\n"); 892 - goto ClunkFid; 893 - } 894 895 - dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name); 896 - retval = v9fs_t_stat(v9ses, fid->fid, &fcall); 897 898 - if (retval < 0) { 899 - dprintk(DEBUG_ERROR, "stat error\n"); 900 - goto FreeFcall; 901 - } 902 - 903 - if (!fcall) { 904 - retval = -EIO; 905 - goto ClunkFid; 906 - } 907 - 908 - if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) { 909 retval = -EINVAL; 910 - goto FreeFcall; 911 } 912 913 /* copy extension buffer into buffer */ 914 - if (fcall->params.rstat.stat.extension.len < buflen) 915 - buflen = fcall->params.rstat.stat.extension.len + 1; 916 917 - memmove(buffer, fcall->params.rstat.stat.extension.str, buflen - 1); 918 buffer[buflen-1] = 0; 919 920 - dprintk(DEBUG_ERROR, "%s -> %.*s (%s)\n", dentry->d_name.name, fcall->params.rstat.stat.extension.len, 921 - fcall->params.rstat.stat.extension.str, buffer); 922 retval = buflen; 923 924 - FreeFcall: 925 - kfree(fcall); 926 - 927 - ClunkFid: 928 - v9fs_fid_clunk(v9ses, fid); 929 - 930 return retval; 931 } 932 ··· 941 if (buflen > PATH_MAX) 942 buflen = PATH_MAX; 943 944 - dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 945 946 retval = v9fs_readlink(dentry, link, buflen); 947 948 if (retval > 0) { 949 if ((ret = copy_to_user(buffer, link, retval)) != 0) { 950 - dprintk(DEBUG_ERROR, "problem copying to user: %d\n", 951 - ret); 952 retval = ret; 953 } 954 } ··· 969 int len = 0; 970 char *link = __getname(); 971 972 - dprintk(DEBUG_VFS, "%s n", dentry->d_name.name); 973 974 if (!link) 975 link = ERR_PTR(-ENOMEM); ··· 998 { 999 char *s = nd_get_link(nd); 1000 1001 - dprintk(DEBUG_VFS, " %s %s\n", dentry->d_name.name, s); 1002 if (!IS_ERR(s)) 1003 __putname(s); 1004 } ··· 1006 static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, 1007 int mode, const char *extension) 1008 { 1009 - int err; 1010 - u32 fid, perm; 1011 struct v9fs_session_info *v9ses; 1012 - struct v9fs_fid *dfid, *vfid = NULL; 1013 - struct inode *inode = NULL; 1014 1015 v9ses = v9fs_inode2v9ses(dir); 1016 if (!v9ses->extended) { 1017 - dprintk(DEBUG_ERROR, "not extended\n"); 1018 return -EPERM; 1019 } 1020 1021 - dfid = v9fs_fid_clone(dentry->d_parent); 1022 - if(IS_ERR(dfid)) { 1023 - err = PTR_ERR(dfid); 1024 - goto error; 1025 - } 1026 - 1027 perm = unixmode2p9mode(v9ses, mode); 1028 1029 - err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, 1030 - perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL); 1031 - 1032 - if (err) 1033 - goto clunk_dfid; 1034 - 1035 - err = v9fs_t_clunk(v9ses, fid); 1036 - if (err) 1037 - goto clunk_dfid; 1038 - 1039 - vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); 1040 - if (IS_ERR(vfid)) { 1041 - err = PTR_ERR(vfid); 1042 - vfid = NULL; 1043 - goto clunk_dfid; 1044 - } 1045 - 1046 - inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); 1047 - if (IS_ERR(inode)) { 1048 - err = PTR_ERR(inode); 1049 - inode = NULL; 1050 - goto free_vfid; 1051 - } 1052 - 1053 - if(v9ses->cache) 1054 - dentry->d_op = &v9fs_cached_dentry_operations; 1055 - else 1056 - dentry->d_op = &v9fs_dentry_operations; 1057 - d_instantiate(dentry, inode); 1058 return 0; 1059 - 1060 - free_vfid: 1061 - v9fs_fid_destroy(vfid); 1062 - 1063 - clunk_dfid: 1064 - v9fs_fid_clunk(v9ses, dfid); 1065 - 1066 - error: 1067 - return err; 1068 - 1069 } 1070 1071 /** ··· 1039 static int 1040 v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 1041 { 1042 - dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, 1043 - symname); 1044 1045 return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname); 1046 } ··· 1062 struct dentry *dentry) 1063 { 1064 int retval; 1065 - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); 1066 - struct v9fs_fid *oldfid; 1067 char *name; 1068 1069 - dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, 1070 old_dentry->d_name.name); 1071 1072 oldfid = v9fs_fid_clone(old_dentry); ··· 1080 } 1081 1082 sprintf(name, "%d\n", oldfid->fid); 1083 - retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name); 1084 __putname(name); 1085 1086 clunk_fid: 1087 - v9fs_fid_clunk(v9ses, oldfid); 1088 return retval; 1089 } 1090 ··· 1103 int retval; 1104 char *name; 1105 1106 - dprintk(DEBUG_VFS, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, 1107 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); 1108 1109 if (!new_valid_dev(rdev))
··· 34 #include <linux/namei.h> 35 #include <linux/idr.h> 36 #include <linux/sched.h> 37 + #include <net/9p/9p.h> 38 + #include <net/9p/client.h> 39 40 #include "v9fs.h" 41 #include "v9fs_vfs.h" 42 #include "fid.h" 43 ··· 58 int res; 59 res = mode & 0777; 60 if (S_ISDIR(mode)) 61 + res |= P9_DMDIR; 62 if (v9ses->extended) { 63 if (S_ISLNK(mode)) 64 + res |= P9_DMSYMLINK; 65 if (v9ses->nodev == 0) { 66 if (S_ISSOCK(mode)) 67 + res |= P9_DMSOCKET; 68 if (S_ISFIFO(mode)) 69 + res |= P9_DMNAMEDPIPE; 70 if (S_ISBLK(mode)) 71 + res |= P9_DMDEVICE; 72 if (S_ISCHR(mode)) 73 + res |= P9_DMDEVICE; 74 } 75 76 if ((mode & S_ISUID) == S_ISUID) 77 + res |= P9_DMSETUID; 78 if ((mode & S_ISGID) == S_ISGID) 79 + res |= P9_DMSETGID; 80 + if ((mode & P9_DMLINK)) 81 + res |= P9_DMLINK; 82 } 83 84 return res; ··· 97 98 res = mode & 0777; 99 100 + if ((mode & P9_DMDIR) == P9_DMDIR) 101 res |= S_IFDIR; 102 + else if ((mode & P9_DMSYMLINK) && (v9ses->extended)) 103 res |= S_IFLNK; 104 + else if ((mode & P9_DMSOCKET) && (v9ses->extended) 105 && (v9ses->nodev == 0)) 106 res |= S_IFSOCK; 107 + else if ((mode & P9_DMNAMEDPIPE) && (v9ses->extended) 108 && (v9ses->nodev == 0)) 109 res |= S_IFIFO; 110 + else if ((mode & P9_DMDEVICE) && (v9ses->extended) 111 && (v9ses->nodev == 0)) 112 res |= S_IFBLK; 113 else 114 res |= S_IFREG; 115 116 if (v9ses->extended) { 117 + if ((mode & P9_DMSETUID) == P9_DMSETUID) 118 res |= S_ISUID; 119 120 + if ((mode & P9_DMSETGID) == P9_DMSETGID) 121 res |= S_ISGID; 122 } 123 ··· 132 switch (uflags&3) { 133 default: 134 case O_RDONLY: 135 + ret = P9_OREAD; 136 break; 137 138 case O_WRONLY: 139 + ret = P9_OWRITE; 140 break; 141 142 case O_RDWR: 143 + ret = P9_ORDWR; 144 break; 145 } 146 147 if (uflags & O_EXCL) 148 + ret |= P9_OEXCL; 149 150 if (uflags & O_TRUNC) 151 + ret |= P9_OTRUNC; 152 153 if (uflags & O_APPEND) 154 + ret |= P9_OAPPEND; 155 156 return ret; 157 } ··· 164 */ 165 166 static void 167 + v9fs_blank_wstat(struct p9_wstat *wstat) 168 { 169 wstat->type = ~0; 170 wstat->dev = ~0; ··· 197 struct inode *inode; 198 struct v9fs_session_info *v9ses = sb->s_fs_info; 199 200 + P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); 201 202 inode = new_inode(sb); 203 if (inode) { ··· 215 case S_IFCHR: 216 case S_IFSOCK: 217 if(!v9ses->extended) { 218 + P9_DPRINTK(P9_DEBUG_ERROR, 219 + "special files without extended mode\n"); 220 return ERR_PTR(-EINVAL); 221 } 222 init_special_inode(inode, inode->i_mode, ··· 227 break; 228 case S_IFLNK: 229 if(!v9ses->extended) { 230 + P9_DPRINTK(P9_DEBUG_ERROR, 231 + "extended modes used w/o 9P2000.u\n"); 232 return ERR_PTR(-EINVAL); 233 } 234 inode->i_op = &v9fs_symlink_inode_operations; ··· 241 inode->i_fop = &v9fs_dir_operations; 242 break; 243 default: 244 + P9_DPRINTK(P9_DEBUG_ERROR, 245 + "BAD mode 0x%x S_IFMT 0x%x\n", 246 mode, mode & S_IFMT); 247 return ERR_PTR(-EINVAL); 248 } 249 } else { 250 + P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n"); 251 return ERR_PTR(-ENOMEM); 252 } 253 return inode; 254 } 255 256 + /* 257 static struct v9fs_fid* 258 v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) 259 { ··· 355 kfree(fcall); 356 return ERR_PTR(err); 357 } 358 + */ 359 360 static struct inode * 361 + v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, 362 struct super_block *sb) 363 { 364 int err, umode; 365 struct inode *ret; 366 + struct p9_stat *st; 367 368 ret = NULL; 369 + st = p9_client_stat(fid); 370 + if (IS_ERR(st)) { 371 + err = PTR_ERR(st); 372 + st = NULL; 373 goto error; 374 } 375 376 + umode = p9mode2unixmode(v9ses, st->mode); 377 ret = v9fs_get_inode(sb, umode); 378 if (IS_ERR(ret)) { 379 err = PTR_ERR(ret); ··· 379 goto error; 380 } 381 382 + v9fs_stat2inode(st, ret, sb); 383 + ret->i_ino = v9fs_qid2ino(&st->qid); 384 + kfree(st); 385 return ret; 386 387 error: 388 + kfree(st); 389 if (ret) 390 iput(ret); 391 ··· 401 402 static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) 403 { 404 + struct inode *file_inode; 405 + struct v9fs_session_info *v9ses; 406 + struct p9_fid *v9fid; 407 408 + P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, 409 rmdir); 410 411 file_inode = file->d_inode; 412 v9ses = v9fs_inode2v9ses(file_inode); 413 v9fid = v9fs_fid_clone(file); 414 if(IS_ERR(v9fid)) 415 return PTR_ERR(v9fid); 416 417 + return p9_client_remove(v9fid); 418 } 419 420 static int ··· 446 return 0; 447 } 448 449 + 450 + /** 451 + * v9fs_create - Create a file 452 + * @dentry: dentry that is being created 453 + * @perm: create permissions 454 + * @mode: open mode 455 + * 456 + */ 457 + static struct p9_fid * 458 + v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, 459 + struct dentry *dentry, char *extension, u32 perm, u8 mode) 460 + { 461 + int err; 462 + char *name; 463 + struct p9_fid *dfid, *ofid, *fid; 464 + struct inode *inode; 465 + 466 + err = 0; 467 + ofid = NULL; 468 + fid = NULL; 469 + name = (char *) dentry->d_name.name; 470 + dfid = v9fs_fid_clone(dentry->d_parent); 471 + if(IS_ERR(dfid)) { 472 + err = PTR_ERR(dfid); 473 + dfid = NULL; 474 + goto error; 475 + } 476 + 477 + /* clone a fid to use for creation */ 478 + ofid = p9_client_walk(dfid, 0, NULL, 1); 479 + if (IS_ERR(ofid)) { 480 + err = PTR_ERR(ofid); 481 + ofid = NULL; 482 + goto error; 483 + } 484 + 485 + err = p9_client_fcreate(ofid, name, perm, mode, extension); 486 + if (err < 0) 487 + goto error; 488 + 489 + /* now walk from the parent so we can get unopened fid */ 490 + fid = p9_client_walk(dfid, 1, &name, 0); 491 + if (IS_ERR(fid)) { 492 + err = PTR_ERR(fid); 493 + fid = NULL; 494 + goto error; 495 + } else 496 + dfid = NULL; 497 + 498 + /* instantiate inode and assign the unopened fid to the dentry */ 499 + inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 500 + if (IS_ERR(inode)) { 501 + err = PTR_ERR(inode); 502 + goto error; 503 + } 504 + 505 + if(v9ses->cache) 506 + dentry->d_op = &v9fs_cached_dentry_operations; 507 + else 508 + dentry->d_op = &v9fs_dentry_operations; 509 + 510 + d_instantiate(dentry, inode); 511 + v9fs_fid_add(dentry, fid); 512 + return ofid; 513 + 514 + error: 515 + if (dfid) 516 + p9_client_clunk(dfid); 517 + 518 + if (ofid) 519 + p9_client_clunk(ofid); 520 + 521 + if (fid) 522 + p9_client_clunk(fid); 523 + 524 + return ERR_PTR(err); 525 + } 526 + 527 /** 528 * v9fs_vfs_create - VFS hook to create files 529 + * @inode: directory inode that is being created 530 * @dentry: dentry that is being deleted 531 * @mode: create permissions 532 * @nd: path information ··· 460 struct nameidata *nd) 461 { 462 int err; 463 + u32 perm; 464 int flags; 465 struct v9fs_session_info *v9ses; 466 + struct p9_fid *fid; 467 struct file *filp; 468 469 + err = 0; 470 + fid = NULL; 471 v9ses = v9fs_inode2v9ses(dir); 472 perm = unixmode2p9mode(v9ses, mode); 473 if (nd && nd->flags & LOOKUP_OPEN) 474 flags = nd->intent.open.flags - 1; 475 else 476 flags = O_RDWR; 477 478 + fid = v9fs_create(v9ses, dir, dentry, NULL, perm, 479 + v9fs_uflags2omode(flags)); 480 + if (IS_ERR(fid)) { 481 + err = PTR_ERR(fid); 482 + fid = NULL; 483 goto error; 484 } 485 486 + /* if we are opening a file, assign the open fid to the file */ 487 if (nd && nd->flags & LOOKUP_OPEN) { 488 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); 489 if (IS_ERR(filp)) { 490 + err = PTR_ERR(filp); 491 + goto error; 492 } 493 494 + filp->private_data = fid; 495 + } else 496 + p9_client_clunk(fid); 497 498 return 0; 499 500 error: 501 + if (fid) 502 + p9_client_clunk(fid); 503 504 return err; 505 } ··· 552 static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 553 { 554 int err; 555 + u32 perm; 556 struct v9fs_session_info *v9ses; 557 + struct p9_fid *fid; 558 559 + P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); 560 + err = 0; 561 v9ses = v9fs_inode2v9ses(dir); 562 perm = unixmode2p9mode(v9ses, mode | S_IFDIR); 563 + fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD); 564 + if (IS_ERR(fid)) { 565 + err = PTR_ERR(fid); 566 + fid = NULL; 567 } 568 569 + if (fid) 570 + p9_client_clunk(fid); 571 572 return err; 573 } 574 ··· 619 { 620 struct super_block *sb; 621 struct v9fs_session_info *v9ses; 622 + struct p9_fid *dfid, *fid; 623 struct inode *inode; 624 + char *name; 625 int result = 0; 626 627 + P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", 628 dir, dentry->d_name.name, dentry, nameidata); 629 630 sb = dir->i_sb; 631 v9ses = v9fs_inode2v9ses(dir); 632 + dfid = v9fs_fid_lookup(dentry->d_parent); 633 + if (IS_ERR(dfid)) 634 + return ERR_PTR(PTR_ERR(dfid)); 635 636 + name = (char *) dentry->d_name.name; 637 + fid = p9_client_walk(dfid, 1, &name, 1); 638 + if (IS_ERR(fid)) { 639 + result = PTR_ERR(fid); 640 if (result == -ENOENT) { 641 d_add(dentry, NULL); 642 return NULL; 643 } 644 645 + return ERR_PTR(result); 646 } 647 648 + inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 649 + if (IS_ERR(inode)) { 650 + result = PTR_ERR(inode); 651 + inode = NULL; 652 + goto error; 653 } 654 655 + result = v9fs_fid_add(dentry, fid); 656 if (result < 0) 657 + goto error; 658 659 if((fid->qid.version)&&(v9ses->cache)) 660 dentry->d_op = &v9fs_cached_dentry_operations; 661 else 662 dentry->d_op = &v9fs_dentry_operations; 663 664 d_add(dentry, inode); 665 return NULL; 666 667 + error: 668 + if (fid) 669 + p9_client_clunk(fid); 670 671 return ERR_PTR(result); 672 } ··· 758 v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, 759 struct inode *new_dir, struct dentry *new_dentry) 760 { 761 + struct inode *old_inode; 762 + struct v9fs_session_info *v9ses; 763 + struct p9_fid *oldfid; 764 + struct p9_fid *olddirfid; 765 + struct p9_fid *newdirfid; 766 + struct p9_wstat wstat; 767 + int retval; 768 769 + P9_DPRINTK(P9_DEBUG_VFS, "\n"); 770 + retval = 0; 771 + old_inode = old_dentry->d_inode; 772 + v9ses = v9fs_inode2v9ses(old_inode); 773 + oldfid = v9fs_fid_lookup(old_dentry); 774 if(IS_ERR(oldfid)) 775 return PTR_ERR(oldfid); 776 777 olddirfid = v9fs_fid_clone(old_dentry->d_parent); 778 if(IS_ERR(olddirfid)) { 779 retval = PTR_ERR(olddirfid); 780 + goto done; 781 } 782 783 newdirfid = v9fs_fid_clone(new_dentry->d_parent); 784 if(IS_ERR(newdirfid)) { 785 retval = PTR_ERR(newdirfid); 786 + goto clunk_olddir; 787 } 788 789 /* 9P can only handle file rename in the same directory */ 790 if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { 791 + P9_DPRINTK(P9_DEBUG_ERROR, 792 + "old dir and new dir are different\n"); 793 retval = -EXDEV; 794 + goto clunk_newdir; 795 } 796 797 v9fs_blank_wstat(&wstat); 798 wstat.muid = v9ses->name; 799 wstat.name = (char *) new_dentry->d_name.name; 800 + retval = p9_client_wstat(oldfid, &wstat); 801 802 + clunk_newdir: 803 + p9_client_clunk(olddirfid); 804 805 + clunk_olddir: 806 + p9_client_clunk(newdirfid); 807 808 + done: 809 return retval; 810 } 811 ··· 840 v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 841 struct kstat *stat) 842 { 843 + int err; 844 + struct v9fs_session_info *v9ses; 845 + struct p9_fid *fid; 846 + struct p9_stat *st; 847 848 + P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); 849 + err = -EPERM; 850 + v9ses = v9fs_inode2v9ses(dentry->d_inode); 851 + if (v9ses->cache == CACHE_LOOSE) 852 + return simple_getattr(mnt, dentry, stat); 853 + 854 + fid = v9fs_fid_lookup(dentry); 855 + if (IS_ERR(fid)) 856 return PTR_ERR(fid); 857 858 + st = p9_client_stat(fid); 859 + if (IS_ERR(st)) 860 + return PTR_ERR(st); 861 862 + v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); 863 generic_fillattr(dentry->d_inode, stat); 864 865 + kfree(st); 866 + return 0; 867 } 868 869 /** ··· 873 874 static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) 875 { 876 + int retval; 877 + struct v9fs_session_info *v9ses; 878 + struct p9_fid *fid; 879 + struct p9_wstat wstat; 880 881 + P9_DPRINTK(P9_DEBUG_VFS, "\n"); 882 + retval = -EPERM; 883 + v9ses = v9fs_inode2v9ses(dentry->d_inode); 884 + fid = v9fs_fid_lookup(dentry); 885 if(IS_ERR(fid)) 886 return PTR_ERR(fid); 887 ··· 904 wstat.n_gid = iattr->ia_gid; 905 } 906 907 + retval = p9_client_wstat(fid, &wstat); 908 + if (retval >= 0) 909 + retval = inode_setattr(dentry->d_inode, iattr); 910 911 + return retval; 912 } 913 914 /** ··· 926 */ 927 928 void 929 + v9fs_stat2inode(struct p9_stat *stat, struct inode *inode, 930 struct super_block *sb) 931 { 932 int n; ··· 967 case 'b': 968 break; 969 default: 970 + P9_DPRINTK(P9_DEBUG_ERROR, 971 + "Unknown special type %c (%.*s)\n", type, 972 + stat->extension.len, stat->extension.str); 973 }; 974 inode->i_rdev = MKDEV(major, minor); 975 } else ··· 976 977 inode->i_size = stat->length; 978 979 + /* not real number of blocks, but 512 byte ones ... */ 980 + inode->i_blocks = (inode->i_size + 512 - 1) >> 9; 981 } 982 983 /** ··· 987 * BUG: potential for inode number collisions? 988 */ 989 990 + ino_t v9fs_qid2ino(struct p9_qid *qid) 991 { 992 u64 path = qid->path + 2; 993 ino_t i = 0; ··· 1010 1011 static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) 1012 { 1013 + int retval; 1014 1015 + struct v9fs_session_info *v9ses; 1016 + struct p9_fid *fid; 1017 + struct p9_stat *st; 1018 1019 + P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); 1020 + retval = -EPERM; 1021 + v9ses = v9fs_inode2v9ses(dentry->d_inode); 1022 + fid = v9fs_fid_lookup(dentry); 1023 if(IS_ERR(fid)) 1024 return PTR_ERR(fid); 1025 1026 + if (!v9ses->extended) 1027 + return -EBADF; 1028 1029 + st = p9_client_stat(fid); 1030 + if (IS_ERR(st)) 1031 + return PTR_ERR(st); 1032 1033 + if (!(st->mode & P9_DMSYMLINK)) { 1034 retval = -EINVAL; 1035 + goto done; 1036 } 1037 1038 /* copy extension buffer into buffer */ 1039 + if (st->extension.len < buflen) 1040 + buflen = st->extension.len + 1; 1041 1042 + memmove(buffer, st->extension.str, buflen - 1); 1043 buffer[buflen-1] = 0; 1044 1045 + P9_DPRINTK(P9_DEBUG_VFS, 1046 + "%s -> %.*s (%s)\n", dentry->d_name.name, st->extension.len, 1047 + st->extension.str, buffer); 1048 + 1049 retval = buflen; 1050 1051 + done: 1052 + kfree(st); 1053 return retval; 1054 } 1055 ··· 1084 if (buflen > PATH_MAX) 1085 buflen = PATH_MAX; 1086 1087 + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 1088 1089 retval = v9fs_readlink(dentry, link, buflen); 1090 1091 if (retval > 0) { 1092 if ((ret = copy_to_user(buffer, link, retval)) != 0) { 1093 + P9_DPRINTK(P9_DEBUG_ERROR, 1094 + "problem copying to user: %d\n", ret); 1095 retval = ret; 1096 } 1097 } ··· 1112 int len = 0; 1113 char *link = __getname(); 1114 1115 + P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name); 1116 1117 if (!link) 1118 link = ERR_PTR(-ENOMEM); ··· 1141 { 1142 char *s = nd_get_link(nd); 1143 1144 + P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name, s); 1145 if (!IS_ERR(s)) 1146 __putname(s); 1147 } ··· 1149 static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, 1150 int mode, const char *extension) 1151 { 1152 + u32 perm; 1153 struct v9fs_session_info *v9ses; 1154 + struct p9_fid *fid; 1155 1156 v9ses = v9fs_inode2v9ses(dir); 1157 if (!v9ses->extended) { 1158 + P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n"); 1159 return -EPERM; 1160 } 1161 1162 perm = unixmode2p9mode(v9ses, mode); 1163 + fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm, 1164 + P9_OREAD); 1165 + if (IS_ERR(fid)) 1166 + return PTR_ERR(fid); 1167 1168 + p9_client_clunk(fid); 1169 return 0; 1170 } 1171 1172 /** ··· 1224 static int 1225 v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 1226 { 1227 + P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, 1228 + dentry->d_name.name, symname); 1229 1230 return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname); 1231 } ··· 1247 struct dentry *dentry) 1248 { 1249 int retval; 1250 + struct p9_fid *oldfid; 1251 char *name; 1252 1253 + P9_DPRINTK(P9_DEBUG_VFS, 1254 + " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, 1255 old_dentry->d_name.name); 1256 1257 oldfid = v9fs_fid_clone(old_dentry); ··· 1265 } 1266 1267 sprintf(name, "%d\n", oldfid->fid); 1268 + retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name); 1269 __putname(name); 1270 1271 clunk_fid: 1272 + p9_client_clunk(oldfid); 1273 return retval; 1274 } 1275 ··· 1288 int retval; 1289 char *name; 1290 1291 + P9_DPRINTK(P9_DEBUG_VFS, 1292 + " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, 1293 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); 1294 1295 if (!new_valid_dev(rdev))
+40 -57
fs/9p/vfs_super.c
··· 37 #include <linux/mount.h> 38 #include <linux/idr.h> 39 #include <linux/sched.h> 40 41 - #include "debug.h" 42 #include "v9fs.h" 43 - #include "9p.h" 44 #include "v9fs_vfs.h" 45 #include "fid.h" 46 ··· 107 struct vfsmount *mnt) 108 { 109 struct super_block *sb = NULL; 110 - struct v9fs_fcall *fcall = NULL; 111 struct inode *inode = NULL; 112 struct dentry *root = NULL; 113 struct v9fs_session_info *v9ses = NULL; 114 - struct v9fs_fid *root_fid = NULL; 115 int mode = S_IRWXUGO | S_ISVTX; 116 uid_t uid = current->fsuid; 117 gid_t gid = current->fsgid; 118 - int stat_result = 0; 119 - int newfid = 0; 120 int retval = 0; 121 122 - dprintk(DEBUG_VFS, " \n"); 123 124 v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); 125 if (!v9ses) 126 return -ENOMEM; 127 128 - if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { 129 - dprintk(DEBUG_ERROR, "problem initiating session\n"); 130 - retval = newfid; 131 - goto out_free_session; 132 } 133 134 sb = sget(fs_type, NULL, v9fs_set_super, v9ses); 135 if (IS_ERR(sb)) { 136 retval = PTR_ERR(sb); 137 - goto out_close_session; 138 } 139 v9fs_fill_super(sb, v9ses, flags); 140 141 inode = v9fs_get_inode(sb, S_IFDIR | mode); 142 if (IS_ERR(inode)) { 143 retval = PTR_ERR(inode); 144 - goto put_back_sb; 145 } 146 147 inode->i_uid = uid; ··· 157 root = d_alloc_root(inode); 158 if (!root) { 159 retval = -ENOMEM; 160 - goto put_back_sb; 161 } 162 163 sb->s_root = root; 164 - 165 - stat_result = v9fs_t_stat(v9ses, newfid, &fcall); 166 - if (stat_result < 0) { 167 - dprintk(DEBUG_ERROR, "stat error\n"); 168 - v9fs_t_clunk(v9ses, newfid); 169 - } else { 170 - /* Setup the Root Inode */ 171 - root_fid = v9fs_fid_create(v9ses, newfid); 172 - if (root_fid == NULL) { 173 - retval = -ENOMEM; 174 - goto put_back_sb; 175 - } 176 - 177 - retval = v9fs_fid_insert(root_fid, root); 178 - if (retval < 0) { 179 - kfree(fcall); 180 - goto put_back_sb; 181 - } 182 - 183 - root_fid->qid = fcall->params.rstat.stat.qid; 184 - root->d_inode->i_ino = 185 - v9fs_qid2ino(&fcall->params.rstat.stat.qid); 186 - v9fs_stat2inode(&fcall->params.rstat.stat, root->d_inode, sb); 187 - } 188 - 189 - kfree(fcall); 190 - 191 - if (stat_result < 0) { 192 - retval = stat_result; 193 - goto put_back_sb; 194 - } 195 196 return simple_set_mnt(mnt, sb); 197 198 - out_close_session: 199 - v9fs_session_close(v9ses); 200 - out_free_session: 201 - kfree(v9ses); 202 - return retval; 203 204 - put_back_sb: 205 - /* deactivate_super calls v9fs_kill_super which will frees the rest */ 206 - up_write(&sb->s_umount); 207 - deactivate_super(sb); 208 return retval; 209 } 210 ··· 194 { 195 struct v9fs_session_info *v9ses = s->s_fs_info; 196 197 - dprintk(DEBUG_VFS, " %p\n", s); 198 199 v9fs_dentry_release(s->s_root); /* clunk root */ 200 ··· 202 203 v9fs_session_close(v9ses); 204 kfree(v9ses); 205 - dprintk(DEBUG_VFS, "exiting kill_super\n"); 206 } 207 208 /** ··· 217 struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info; 218 219 if (v9ses->debug != 0) 220 - seq_printf(m, ",debug=%u", v9ses->debug); 221 if (v9ses->port != V9FS_PORT) 222 seq_printf(m, ",port=%u", v9ses->port); 223 if (v9ses->maxdata != 9000)
··· 37 #include <linux/mount.h> 38 #include <linux/idr.h> 39 #include <linux/sched.h> 40 + #include <net/9p/9p.h> 41 + #include <net/9p/client.h> 42 43 #include "v9fs.h" 44 #include "v9fs_vfs.h" 45 #include "fid.h" 46 ··· 107 struct vfsmount *mnt) 108 { 109 struct super_block *sb = NULL; 110 struct inode *inode = NULL; 111 struct dentry *root = NULL; 112 struct v9fs_session_info *v9ses = NULL; 113 + struct p9_stat *st = NULL; 114 int mode = S_IRWXUGO | S_ISVTX; 115 uid_t uid = current->fsuid; 116 gid_t gid = current->fsgid; 117 + struct p9_fid *fid; 118 int retval = 0; 119 120 + P9_DPRINTK(P9_DEBUG_VFS, " \n"); 121 122 v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); 123 if (!v9ses) 124 return -ENOMEM; 125 126 + fid = v9fs_session_init(v9ses, dev_name, data); 127 + if (IS_ERR(fid)) { 128 + retval = PTR_ERR(fid); 129 + fid = NULL; 130 + kfree(v9ses); 131 + v9ses = NULL; 132 + goto error; 133 + } 134 + 135 + st = p9_client_stat(fid); 136 + if (IS_ERR(st)) { 137 + retval = PTR_ERR(st); 138 + goto error; 139 } 140 141 sb = sget(fs_type, NULL, v9fs_set_super, v9ses); 142 if (IS_ERR(sb)) { 143 retval = PTR_ERR(sb); 144 + goto error; 145 } 146 v9fs_fill_super(sb, v9ses, flags); 147 148 inode = v9fs_get_inode(sb, S_IFDIR | mode); 149 if (IS_ERR(inode)) { 150 retval = PTR_ERR(inode); 151 + goto error; 152 } 153 154 inode->i_uid = uid; ··· 150 root = d_alloc_root(inode); 151 if (!root) { 152 retval = -ENOMEM; 153 + goto error; 154 } 155 156 sb->s_root = root; 157 + root->d_inode->i_ino = v9fs_qid2ino(&st->qid); 158 + v9fs_stat2inode(st, root->d_inode, sb); 159 + v9fs_fid_add(root, fid); 160 161 return simple_set_mnt(mnt, sb); 162 163 + error: 164 + if (fid) 165 + p9_client_clunk(fid); 166 167 + if (v9ses) { 168 + v9fs_session_close(v9ses); 169 + kfree(v9ses); 170 + } 171 + 172 + if (sb) { 173 + up_write(&sb->s_umount); 174 + deactivate_super(sb); 175 + } 176 + 177 return retval; 178 } 179 ··· 211 { 212 struct v9fs_session_info *v9ses = s->s_fs_info; 213 214 + P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s); 215 216 v9fs_dentry_release(s->s_root); /* clunk root */ 217 ··· 219 220 v9fs_session_close(v9ses); 221 kfree(v9ses); 222 + P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n"); 223 } 224 225 /** ··· 234 struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info; 235 236 if (v9ses->debug != 0) 237 + seq_printf(m, ",debug=%x", v9ses->debug); 238 if (v9ses->port != V9FS_PORT) 239 seq_printf(m, ",port=%u", v9ses->port); 240 if (v9ses->maxdata != 9000)
+1 -1
fs/Kconfig
··· 2048 2049 config 9P_FS 2050 tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)" 2051 - depends on INET && EXPERIMENTAL 2052 help 2053 If you say Y here, you will get experimental support for 2054 Plan 9 resource sharing via the 9P2000 protocol.
··· 2048 2049 config 9P_FS 2050 tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)" 2051 + depends on INET && NET_9P && EXPERIMENTAL 2052 help 2053 If you say Y here, you will get experimental support for 2054 Plan 9 resource sharing via the 9P2000 protocol.
+417
include/net/9p/9p.h
···
··· 1 + /* 2 + * include/net/9p/9p.h 3 + * 4 + * 9P protocol definitions. 5 + * 6 + * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net> 7 + * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 8 + * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 12 + * as published by the Free Software Foundation. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this program; if not, write to: 21 + * Free Software Foundation 22 + * 51 Franklin Street, Fifth Floor 23 + * Boston, MA 02111-1301 USA 24 + * 25 + */ 26 + 27 + #ifndef NET_9P_H 28 + #define NET_9P_H 29 + 30 + #ifdef CONFIG_NET_9P_DEBUG 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) 40 + 41 + extern unsigned int p9_debug_level; 42 + 43 + #define P9_DPRINTK(level, format, arg...) \ 44 + do { \ 45 + if ((p9_debug_level & level) == level) \ 46 + printk(KERN_NOTICE "-- %s (%d): " \ 47 + format , __FUNCTION__, current->pid , ## arg); \ 48 + } while (0) 49 + 50 + #define PRINT_FCALL_ERROR(s, fcall) P9_DPRINTK(P9_DEBUG_ERROR, \ 51 + "%s: %.*s\n", s, fcall?fcall->params.rerror.error.len:0, \ 52 + fcall?fcall->params.rerror.error.str:""); 53 + 54 + #else 55 + #define P9_DPRINTK(level, format, arg...) do { } while (0) 56 + #define PRINT_FCALL_ERROR(s, fcall) do { } while (0) 57 + #endif 58 + 59 + #define P9_EPRINTK(level, format, arg...) \ 60 + do { \ 61 + printk(level "9p: %s (%d): " \ 62 + format , __FUNCTION__, current->pid , ## arg); \ 63 + } while (0) 64 + 65 + 66 + /* Message Types */ 67 + enum { 68 + P9_TVERSION = 100, 69 + P9_RVERSION, 70 + P9_TAUTH = 102, 71 + P9_RAUTH, 72 + P9_TATTACH = 104, 73 + P9_RATTACH, 74 + P9_TERROR = 106, 75 + P9_RERROR, 76 + P9_TFLUSH = 108, 77 + P9_RFLUSH, 78 + P9_TWALK = 110, 79 + P9_RWALK, 80 + P9_TOPEN = 112, 81 + P9_ROPEN, 82 + P9_TCREATE = 114, 83 + P9_RCREATE, 84 + P9_TREAD = 116, 85 + P9_RREAD, 86 + P9_TWRITE = 118, 87 + P9_RWRITE, 88 + P9_TCLUNK = 120, 89 + P9_RCLUNK, 90 + P9_TREMOVE = 122, 91 + P9_RREMOVE, 92 + P9_TSTAT = 124, 93 + P9_RSTAT, 94 + P9_TWSTAT = 126, 95 + P9_RWSTAT, 96 + }; 97 + 98 + /* open modes */ 99 + enum { 100 + P9_OREAD = 0x00, 101 + P9_OWRITE = 0x01, 102 + P9_ORDWR = 0x02, 103 + P9_OEXEC = 0x03, 104 + P9_OEXCL = 0x04, 105 + P9_OTRUNC = 0x10, 106 + P9_OREXEC = 0x20, 107 + P9_ORCLOSE = 0x40, 108 + P9_OAPPEND = 0x80, 109 + }; 110 + 111 + /* permissions */ 112 + enum { 113 + P9_DMDIR = 0x80000000, 114 + P9_DMAPPEND = 0x40000000, 115 + P9_DMEXCL = 0x20000000, 116 + P9_DMMOUNT = 0x10000000, 117 + P9_DMAUTH = 0x08000000, 118 + P9_DMTMP = 0x04000000, 119 + P9_DMSYMLINK = 0x02000000, 120 + P9_DMLINK = 0x01000000, 121 + /* 9P2000.u extensions */ 122 + P9_DMDEVICE = 0x00800000, 123 + P9_DMNAMEDPIPE = 0x00200000, 124 + P9_DMSOCKET = 0x00100000, 125 + P9_DMSETUID = 0x00080000, 126 + P9_DMSETGID = 0x00040000, 127 + }; 128 + 129 + /* qid.types */ 130 + enum { 131 + P9_QTDIR = 0x80, 132 + P9_QTAPPEND = 0x40, 133 + P9_QTEXCL = 0x20, 134 + P9_QTMOUNT = 0x10, 135 + P9_QTAUTH = 0x08, 136 + P9_QTTMP = 0x04, 137 + P9_QTSYMLINK = 0x02, 138 + P9_QTLINK = 0x01, 139 + P9_QTFILE = 0x00, 140 + }; 141 + 142 + #define P9_NOTAG (u16)(~0) 143 + #define P9_NOFID (u32)(~0) 144 + #define P9_MAXWELEM 16 145 + 146 + /* ample room for Twrite/Rread header */ 147 + #define P9_IOHDRSZ 24 148 + 149 + struct p9_str { 150 + u16 len; 151 + char *str; 152 + }; 153 + 154 + /* qids are the unique ID for a file (like an inode */ 155 + struct p9_qid { 156 + u8 type; 157 + u32 version; 158 + u64 path; 159 + }; 160 + 161 + /* Plan 9 file metadata (stat) structure */ 162 + struct p9_stat { 163 + u16 size; 164 + u16 type; 165 + u32 dev; 166 + struct p9_qid qid; 167 + u32 mode; 168 + u32 atime; 169 + u32 mtime; 170 + u64 length; 171 + struct p9_str name; 172 + struct p9_str uid; 173 + struct p9_str gid; 174 + struct p9_str muid; 175 + struct p9_str extension; /* 9p2000.u extensions */ 176 + u32 n_uid; /* 9p2000.u extensions */ 177 + u32 n_gid; /* 9p2000.u extensions */ 178 + u32 n_muid; /* 9p2000.u extensions */ 179 + }; 180 + 181 + /* file metadata (stat) structure used to create Twstat message 182 + The is similar to p9_stat, but the strings don't point to 183 + the same memory block and should be freed separately 184 + */ 185 + struct p9_wstat { 186 + u16 size; 187 + u16 type; 188 + u32 dev; 189 + struct p9_qid qid; 190 + u32 mode; 191 + u32 atime; 192 + u32 mtime; 193 + u64 length; 194 + char *name; 195 + char *uid; 196 + char *gid; 197 + char *muid; 198 + char *extension; /* 9p2000.u extensions */ 199 + u32 n_uid; /* 9p2000.u extensions */ 200 + u32 n_gid; /* 9p2000.u extensions */ 201 + u32 n_muid; /* 9p2000.u extensions */ 202 + }; 203 + 204 + /* Structures for Protocol Operations */ 205 + struct p9_tversion { 206 + u32 msize; 207 + struct p9_str version; 208 + }; 209 + 210 + struct p9_rversion { 211 + u32 msize; 212 + struct p9_str version; 213 + }; 214 + 215 + struct p9_tauth { 216 + u32 afid; 217 + struct p9_str uname; 218 + struct p9_str aname; 219 + }; 220 + 221 + struct p9_rauth { 222 + struct p9_qid qid; 223 + }; 224 + 225 + struct p9_rerror { 226 + struct p9_str error; 227 + u32 errno; /* 9p2000.u extension */ 228 + }; 229 + 230 + struct p9_tflush { 231 + u16 oldtag; 232 + }; 233 + 234 + struct p9_rflush { 235 + }; 236 + 237 + struct p9_tattach { 238 + u32 fid; 239 + u32 afid; 240 + struct p9_str uname; 241 + struct p9_str aname; 242 + }; 243 + 244 + struct p9_rattach { 245 + struct p9_qid qid; 246 + }; 247 + 248 + struct p9_twalk { 249 + u32 fid; 250 + u32 newfid; 251 + u16 nwname; 252 + struct p9_str wnames[16]; 253 + }; 254 + 255 + struct p9_rwalk { 256 + u16 nwqid; 257 + struct p9_qid wqids[16]; 258 + }; 259 + 260 + struct p9_topen { 261 + u32 fid; 262 + u8 mode; 263 + }; 264 + 265 + struct p9_ropen { 266 + struct p9_qid qid; 267 + u32 iounit; 268 + }; 269 + 270 + struct p9_tcreate { 271 + u32 fid; 272 + struct p9_str name; 273 + u32 perm; 274 + u8 mode; 275 + struct p9_str extension; 276 + }; 277 + 278 + struct p9_rcreate { 279 + struct p9_qid qid; 280 + u32 iounit; 281 + }; 282 + 283 + struct p9_tread { 284 + u32 fid; 285 + u64 offset; 286 + u32 count; 287 + }; 288 + 289 + struct p9_rread { 290 + u32 count; 291 + u8 *data; 292 + }; 293 + 294 + struct p9_twrite { 295 + u32 fid; 296 + u64 offset; 297 + u32 count; 298 + u8 *data; 299 + }; 300 + 301 + struct p9_rwrite { 302 + u32 count; 303 + }; 304 + 305 + struct p9_tclunk { 306 + u32 fid; 307 + }; 308 + 309 + struct p9_rclunk { 310 + }; 311 + 312 + struct p9_tremove { 313 + u32 fid; 314 + }; 315 + 316 + struct p9_rremove { 317 + }; 318 + 319 + struct p9_tstat { 320 + u32 fid; 321 + }; 322 + 323 + struct p9_rstat { 324 + struct p9_stat stat; 325 + }; 326 + 327 + struct p9_twstat { 328 + u32 fid; 329 + struct p9_stat stat; 330 + }; 331 + 332 + struct p9_rwstat { 333 + }; 334 + 335 + /* 336 + * fcall is the primary packet structure 337 + * 338 + */ 339 + 340 + struct p9_fcall { 341 + u32 size; 342 + u8 id; 343 + u16 tag; 344 + void *sdata; 345 + 346 + union { 347 + struct p9_tversion tversion; 348 + struct p9_rversion rversion; 349 + struct p9_tauth tauth; 350 + struct p9_rauth rauth; 351 + struct p9_rerror rerror; 352 + struct p9_tflush tflush; 353 + struct p9_rflush rflush; 354 + struct p9_tattach tattach; 355 + struct p9_rattach rattach; 356 + struct p9_twalk twalk; 357 + struct p9_rwalk rwalk; 358 + struct p9_topen topen; 359 + struct p9_ropen ropen; 360 + struct p9_tcreate tcreate; 361 + struct p9_rcreate rcreate; 362 + struct p9_tread tread; 363 + struct p9_rread rread; 364 + struct p9_twrite twrite; 365 + struct p9_rwrite rwrite; 366 + struct p9_tclunk tclunk; 367 + struct p9_rclunk rclunk; 368 + struct p9_tremove tremove; 369 + struct p9_rremove rremove; 370 + struct p9_tstat tstat; 371 + struct p9_rstat rstat; 372 + struct p9_twstat twstat; 373 + struct p9_rwstat rwstat; 374 + } params; 375 + }; 376 + 377 + struct p9_idpool; 378 + 379 + int p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat, 380 + int dotu); 381 + int p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *fc, int dotu); 382 + void p9_set_tag(struct p9_fcall *fc, u16 tag); 383 + struct p9_fcall *p9_create_tversion(u32 msize, char *version); 384 + struct p9_fcall *p9_create_tattach(u32 fid, u32 afid, char *uname, 385 + char *aname); 386 + struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname); 387 + struct p9_fcall *p9_create_tflush(u16 oldtag); 388 + struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname, 389 + char **wnames); 390 + struct p9_fcall *p9_create_topen(u32 fid, u8 mode); 391 + struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, 392 + char *extension, int dotu); 393 + struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count); 394 + struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count, 395 + const char *data); 396 + struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count, 397 + const char __user *data); 398 + struct p9_fcall *p9_create_tclunk(u32 fid); 399 + struct p9_fcall *p9_create_tremove(u32 fid); 400 + struct p9_fcall *p9_create_tstat(u32 fid); 401 + struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat, 402 + int dotu); 403 + 404 + int p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int dotu); 405 + int p9_errstr2errno(char *errstr, int len); 406 + 407 + struct p9_idpool *p9_idpool_create(void); 408 + void p9_idpool_destroy(struct p9_idpool *); 409 + int p9_idpool_get(struct p9_idpool *p); 410 + void p9_idpool_put(int id, struct p9_idpool *p); 411 + int p9_idpool_check(int id, struct p9_idpool *p); 412 + 413 + int p9_error_init(void); 414 + int p9_errstr2errno(char *, int); 415 + int __init p9_sysctl_register(void); 416 + void __exit p9_sysctl_unregister(void); 417 + #endif /* NET_9P_H */
+80
include/net/9p/client.h
···
··· 1 + /* 2 + * include/net/9p/client.h 3 + * 4 + * 9P Client Definitions 5 + * 6 + * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 10 + * as published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program; if not, write to: 19 + * Free Software Foundation 20 + * 51 Franklin Street, Fifth Floor 21 + * Boston, MA 02111-1301 USA 22 + * 23 + */ 24 + 25 + #ifndef NET_9P_CLIENT_H 26 + #define NET_9P_CLIENT_H 27 + 28 + struct p9_client { 29 + spinlock_t lock; /* protect client structure */ 30 + int msize; 31 + unsigned char dotu; 32 + struct p9_transport *trans; 33 + struct p9_conn *conn; 34 + 35 + struct p9_idpool *fidpool; 36 + struct list_head fidlist; 37 + }; 38 + 39 + struct p9_fid { 40 + struct p9_client *clnt; 41 + u32 fid; 42 + int mode; 43 + struct p9_qid qid; 44 + u32 iounit; 45 + uid_t uid; 46 + void *aux; 47 + 48 + int rdir_fpos; 49 + int rdir_pos; 50 + struct p9_fcall *rdir_fcall; 51 + struct list_head flist; 52 + struct list_head dlist; /* list of all fids attached to a dentry */ 53 + }; 54 + 55 + struct p9_client *p9_client_create(struct p9_transport *trans, int msize, 56 + int dotu); 57 + void p9_client_destroy(struct p9_client *clnt); 58 + void p9_client_disconnect(struct p9_client *clnt); 59 + struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, 60 + char *uname, char *aname); 61 + struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname); 62 + struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, 63 + int clone); 64 + int p9_client_open(struct p9_fid *fid, int mode); 65 + int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, 66 + char *extension); 67 + int p9_client_clunk(struct p9_fid *fid); 68 + int p9_client_remove(struct p9_fid *fid); 69 + int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count); 70 + int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count); 71 + int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count); 72 + int p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, 73 + u32 count); 74 + int p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset, 75 + u32 count); 76 + struct p9_stat *p9_client_stat(struct p9_fid *fid); 77 + int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst); 78 + struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset); 79 + 80 + #endif /* NET_9P_CLIENT_H */
+21
net/9p/Kconfig
···
··· 1 + # 2 + # 9P protocol configuration 3 + # 4 + 5 + menuconfig NET_9P 6 + depends on NET && EXPERIMENTAL 7 + tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)" 8 + help 9 + If you say Y here, you will get experimental support for 10 + Plan 9 resource sharing via the 9P2000 protocol. 11 + 12 + See <http://v9fs.sf.net> for more information. 13 + 14 + If unsure, say N. 15 + 16 + config NET_9P_DEBUG 17 + bool "Debug information" 18 + depends on NET_9P 19 + help 20 + Say Y if you want the 9P subsistem to log debug information. 21 +
+13
net/9p/Makefile
···
··· 1 + obj-$(CONFIG_NET_9P) := 9pnet.o 2 + 3 + 9pnet-objs := \ 4 + mod.o \ 5 + trans_fd.o \ 6 + mux.o \ 7 + client.o \ 8 + conv.o \ 9 + error.o \ 10 + fcprint.o \ 11 + util.o \ 12 + 13 + 9pnet-$(CONFIG_SYSCTL) += sysctl.o
+965
net/9p/client.c
···
··· 1 + /* 2 + * net/9p/clnt.c 3 + * 4 + * 9P Client 5 + * 6 + * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 10 + * as published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program; if not, write to: 19 + * Free Software Foundation 20 + * 51 Franklin Street, Fifth Floor 21 + * Boston, MA 02111-1301 USA 22 + * 23 + */ 24 + 25 + #include <linux/module.h> 26 + #include <linux/errno.h> 27 + #include <linux/fs.h> 28 + #include <linux/idr.h> 29 + #include <linux/mutex.h> 30 + #include <linux/sched.h> 31 + #include <linux/uaccess.h> 32 + #include <net/9p/9p.h> 33 + #include <net/9p/transport.h> 34 + #include <net/9p/conn.h> 35 + #include <net/9p/client.h> 36 + 37 + static struct p9_fid *p9_fid_create(struct p9_client *clnt); 38 + static void p9_fid_destroy(struct p9_fid *fid); 39 + static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu); 40 + 41 + struct p9_client *p9_client_create(struct p9_transport *trans, int msize, 42 + int dotu) 43 + { 44 + int err, n; 45 + struct p9_client *clnt; 46 + struct p9_fcall *tc, *rc; 47 + struct p9_str *version; 48 + 49 + err = 0; 50 + tc = NULL; 51 + rc = NULL; 52 + clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL); 53 + if (!clnt) 54 + return ERR_PTR(-ENOMEM); 55 + 56 + P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n", 57 + clnt, trans, msize, dotu); 58 + spin_lock_init(&clnt->lock); 59 + clnt->trans = trans; 60 + clnt->msize = msize; 61 + clnt->dotu = dotu; 62 + INIT_LIST_HEAD(&clnt->fidlist); 63 + clnt->fidpool = p9_idpool_create(); 64 + if (!clnt->fidpool) { 65 + err = PTR_ERR(clnt->fidpool); 66 + clnt->fidpool = NULL; 67 + goto error; 68 + } 69 + 70 + clnt->conn = p9_conn_create(clnt->trans, clnt->msize, &clnt->dotu); 71 + if (IS_ERR(clnt->conn)) { 72 + err = PTR_ERR(clnt->conn); 73 + clnt->conn = NULL; 74 + goto error; 75 + } 76 + 77 + tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000"); 78 + if (IS_ERR(tc)) { 79 + err = PTR_ERR(tc); 80 + tc = NULL; 81 + goto error; 82 + } 83 + 84 + err = p9_conn_rpc(clnt->conn, tc, &rc); 85 + if (err) 86 + goto error; 87 + 88 + version = &rc->params.rversion.version; 89 + if (version->len == 8 && !memcmp(version->str, "9P2000.u", 8)) 90 + clnt->dotu = 1; 91 + else if (version->len == 6 && !memcmp(version->str, "9P2000", 6)) 92 + clnt->dotu = 0; 93 + else { 94 + err = -EREMOTEIO; 95 + goto error; 96 + } 97 + 98 + n = rc->params.rversion.msize; 99 + if (n < clnt->msize) 100 + clnt->msize = n; 101 + 102 + kfree(tc); 103 + kfree(rc); 104 + return clnt; 105 + 106 + error: 107 + kfree(tc); 108 + kfree(rc); 109 + p9_client_destroy(clnt); 110 + return ERR_PTR(err); 111 + } 112 + EXPORT_SYMBOL(p9_client_create); 113 + 114 + void p9_client_destroy(struct p9_client *clnt) 115 + { 116 + struct p9_fid *fid, *fidptr; 117 + 118 + P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); 119 + if (clnt->conn) { 120 + p9_conn_destroy(clnt->conn); 121 + clnt->conn = NULL; 122 + } 123 + 124 + if (clnt->trans) { 125 + clnt->trans->close(clnt->trans); 126 + kfree(clnt->trans); 127 + clnt->trans = NULL; 128 + } 129 + 130 + list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) 131 + p9_fid_destroy(fid); 132 + 133 + if (clnt->fidpool) 134 + p9_idpool_destroy(clnt->fidpool); 135 + 136 + kfree(clnt); 137 + } 138 + EXPORT_SYMBOL(p9_client_destroy); 139 + 140 + void p9_client_disconnect(struct p9_client *clnt) 141 + { 142 + P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); 143 + clnt->trans->status = Disconnected; 144 + p9_conn_cancel(clnt->conn, -EIO); 145 + } 146 + EXPORT_SYMBOL(p9_client_disconnect); 147 + 148 + struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, 149 + char *uname, char *aname) 150 + { 151 + int err; 152 + struct p9_fcall *tc, *rc; 153 + struct p9_fid *fid; 154 + 155 + P9_DPRINTK(P9_DEBUG_9P, "clnt %p afid %d uname %s aname %s\n", 156 + clnt, afid?afid->fid:-1, uname, aname); 157 + err = 0; 158 + tc = NULL; 159 + rc = NULL; 160 + 161 + fid = p9_fid_create(clnt); 162 + if (IS_ERR(fid)) { 163 + err = PTR_ERR(fid); 164 + fid = NULL; 165 + goto error; 166 + } 167 + 168 + tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname); 169 + if (IS_ERR(tc)) { 170 + err = PTR_ERR(tc); 171 + tc = NULL; 172 + goto error; 173 + } 174 + 175 + err = p9_conn_rpc(clnt->conn, tc, &rc); 176 + if (err) 177 + goto error; 178 + 179 + memmove(&fid->qid, &rc->params.rattach.qid, sizeof(struct p9_qid)); 180 + kfree(tc); 181 + kfree(rc); 182 + return fid; 183 + 184 + error: 185 + kfree(tc); 186 + kfree(rc); 187 + if (fid) 188 + p9_fid_destroy(fid); 189 + return ERR_PTR(err); 190 + } 191 + EXPORT_SYMBOL(p9_client_attach); 192 + 193 + struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname) 194 + { 195 + int err; 196 + struct p9_fcall *tc, *rc; 197 + struct p9_fid *fid; 198 + 199 + P9_DPRINTK(P9_DEBUG_9P, "clnt %p uname %s aname %s\n", clnt, uname, 200 + aname); 201 + err = 0; 202 + tc = NULL; 203 + rc = NULL; 204 + 205 + fid = p9_fid_create(clnt); 206 + if (IS_ERR(fid)) { 207 + err = PTR_ERR(fid); 208 + fid = NULL; 209 + goto error; 210 + } 211 + 212 + tc = p9_create_tauth(fid->fid, uname, aname); 213 + if (IS_ERR(tc)) { 214 + err = PTR_ERR(tc); 215 + tc = NULL; 216 + goto error; 217 + } 218 + 219 + err = p9_conn_rpc(clnt->conn, tc, &rc); 220 + if (err) 221 + goto error; 222 + 223 + memmove(&fid->qid, &rc->params.rauth.qid, sizeof(struct p9_qid)); 224 + kfree(tc); 225 + kfree(rc); 226 + return fid; 227 + 228 + error: 229 + kfree(tc); 230 + kfree(rc); 231 + if (fid) 232 + p9_fid_destroy(fid); 233 + return ERR_PTR(err); 234 + } 235 + EXPORT_SYMBOL(p9_client_auth); 236 + 237 + struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, 238 + int clone) 239 + { 240 + int err; 241 + struct p9_fcall *tc, *rc; 242 + struct p9_client *clnt; 243 + struct p9_fid *fid; 244 + 245 + P9_DPRINTK(P9_DEBUG_9P, "fid %d nwname %d wname[0] %s\n", 246 + oldfid->fid, nwname, wnames?wnames[0]:NULL); 247 + err = 0; 248 + tc = NULL; 249 + rc = NULL; 250 + clnt = oldfid->clnt; 251 + if (clone) { 252 + fid = p9_fid_create(clnt); 253 + if (IS_ERR(fid)) { 254 + err = PTR_ERR(fid); 255 + fid = NULL; 256 + goto error; 257 + } 258 + 259 + fid->uid = oldfid->uid; 260 + } else 261 + fid = oldfid; 262 + 263 + tc = p9_create_twalk(oldfid->fid, fid->fid, nwname, wnames); 264 + if (IS_ERR(tc)) { 265 + err = PTR_ERR(tc); 266 + tc = NULL; 267 + goto error; 268 + } 269 + 270 + err = p9_conn_rpc(clnt->conn, tc, &rc); 271 + if (err) { 272 + if (rc && rc->id == P9_RWALK) 273 + goto clunk_fid; 274 + else 275 + goto error; 276 + } 277 + 278 + if (rc->params.rwalk.nwqid != nwname) { 279 + err = -ENOENT; 280 + goto clunk_fid; 281 + } 282 + 283 + if (nwname) 284 + memmove(&fid->qid, 285 + &rc->params.rwalk.wqids[rc->params.rwalk.nwqid - 1], 286 + sizeof(struct p9_qid)); 287 + else 288 + fid->qid = oldfid->qid; 289 + 290 + kfree(tc); 291 + kfree(rc); 292 + return fid; 293 + 294 + clunk_fid: 295 + kfree(tc); 296 + kfree(rc); 297 + rc = NULL; 298 + tc = p9_create_tclunk(fid->fid); 299 + if (IS_ERR(tc)) { 300 + err = PTR_ERR(tc); 301 + tc = NULL; 302 + goto error; 303 + } 304 + 305 + p9_conn_rpc(clnt->conn, tc, &rc); 306 + 307 + error: 308 + kfree(tc); 309 + kfree(rc); 310 + if (fid && (fid != oldfid)) 311 + p9_fid_destroy(fid); 312 + 313 + return ERR_PTR(err); 314 + } 315 + EXPORT_SYMBOL(p9_client_walk); 316 + 317 + int p9_client_open(struct p9_fid *fid, int mode) 318 + { 319 + int err; 320 + struct p9_fcall *tc, *rc; 321 + struct p9_client *clnt; 322 + 323 + P9_DPRINTK(P9_DEBUG_9P, "fid %d mode %d\n", fid->fid, mode); 324 + err = 0; 325 + tc = NULL; 326 + rc = NULL; 327 + clnt = fid->clnt; 328 + 329 + if (fid->mode != -1) 330 + return -EINVAL; 331 + 332 + tc = p9_create_topen(fid->fid, mode); 333 + if (IS_ERR(tc)) { 334 + err = PTR_ERR(tc); 335 + tc = NULL; 336 + goto done; 337 + } 338 + 339 + err = p9_conn_rpc(clnt->conn, tc, &rc); 340 + if (err) 341 + goto done; 342 + 343 + fid->mode = mode; 344 + fid->iounit = rc->params.ropen.iounit; 345 + 346 + done: 347 + kfree(tc); 348 + kfree(rc); 349 + return err; 350 + } 351 + EXPORT_SYMBOL(p9_client_open); 352 + 353 + int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, 354 + char *extension) 355 + { 356 + int err; 357 + struct p9_fcall *tc, *rc; 358 + struct p9_client *clnt; 359 + 360 + P9_DPRINTK(P9_DEBUG_9P, "fid %d name %s perm %d mode %d\n", fid->fid, 361 + name, perm, mode); 362 + err = 0; 363 + tc = NULL; 364 + rc = NULL; 365 + clnt = fid->clnt; 366 + 367 + if (fid->mode != -1) 368 + return -EINVAL; 369 + 370 + tc = p9_create_tcreate(fid->fid, name, perm, mode, extension, 371 + clnt->dotu); 372 + if (IS_ERR(tc)) { 373 + err = PTR_ERR(tc); 374 + tc = NULL; 375 + goto done; 376 + } 377 + 378 + err = p9_conn_rpc(clnt->conn, tc, &rc); 379 + if (err) 380 + goto done; 381 + 382 + fid->mode = mode; 383 + fid->iounit = rc->params.ropen.iounit; 384 + 385 + done: 386 + kfree(tc); 387 + kfree(rc); 388 + return err; 389 + } 390 + EXPORT_SYMBOL(p9_client_fcreate); 391 + 392 + int p9_client_clunk(struct p9_fid *fid) 393 + { 394 + int err; 395 + struct p9_fcall *tc, *rc; 396 + struct p9_client *clnt; 397 + 398 + P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 399 + err = 0; 400 + tc = NULL; 401 + rc = NULL; 402 + clnt = fid->clnt; 403 + 404 + tc = p9_create_tclunk(fid->fid); 405 + if (IS_ERR(tc)) { 406 + err = PTR_ERR(tc); 407 + tc = NULL; 408 + goto done; 409 + } 410 + 411 + err = p9_conn_rpc(clnt->conn, tc, &rc); 412 + if (err) 413 + goto done; 414 + 415 + p9_fid_destroy(fid); 416 + 417 + done: 418 + kfree(tc); 419 + kfree(rc); 420 + return err; 421 + } 422 + EXPORT_SYMBOL(p9_client_clunk); 423 + 424 + int p9_client_remove(struct p9_fid *fid) 425 + { 426 + int err; 427 + struct p9_fcall *tc, *rc; 428 + struct p9_client *clnt; 429 + 430 + P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 431 + err = 0; 432 + tc = NULL; 433 + rc = NULL; 434 + clnt = fid->clnt; 435 + 436 + tc = p9_create_tremove(fid->fid); 437 + if (IS_ERR(tc)) { 438 + err = PTR_ERR(tc); 439 + tc = NULL; 440 + goto done; 441 + } 442 + 443 + err = p9_conn_rpc(clnt->conn, tc, &rc); 444 + if (err) 445 + goto done; 446 + 447 + p9_fid_destroy(fid); 448 + 449 + done: 450 + kfree(tc); 451 + kfree(rc); 452 + return err; 453 + } 454 + EXPORT_SYMBOL(p9_client_remove); 455 + 456 + int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count) 457 + { 458 + int err, n, rsize, total; 459 + struct p9_fcall *tc, *rc; 460 + struct p9_client *clnt; 461 + 462 + P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu %d\n", fid->fid, 463 + (long long unsigned) offset, count); 464 + err = 0; 465 + tc = NULL; 466 + rc = NULL; 467 + clnt = fid->clnt; 468 + total = 0; 469 + 470 + rsize = fid->iounit; 471 + if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 472 + rsize = clnt->msize - P9_IOHDRSZ; 473 + 474 + do { 475 + if (count < rsize) 476 + rsize = count; 477 + 478 + tc = p9_create_tread(fid->fid, offset, rsize); 479 + if (IS_ERR(tc)) { 480 + err = PTR_ERR(tc); 481 + tc = NULL; 482 + goto error; 483 + } 484 + 485 + err = p9_conn_rpc(clnt->conn, tc, &rc); 486 + if (err) 487 + goto error; 488 + 489 + n = rc->params.rread.count; 490 + if (n > count) 491 + n = count; 492 + 493 + memmove(data, rc->params.rread.data, n); 494 + count -= n; 495 + data += n; 496 + offset += n; 497 + total += n; 498 + kfree(tc); 499 + tc = NULL; 500 + kfree(rc); 501 + rc = NULL; 502 + } while (count > 0 && n == rsize); 503 + 504 + return total; 505 + 506 + error: 507 + kfree(tc); 508 + kfree(rc); 509 + return err; 510 + } 511 + EXPORT_SYMBOL(p9_client_read); 512 + 513 + int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count) 514 + { 515 + int err, n, rsize, total; 516 + struct p9_fcall *tc, *rc; 517 + struct p9_client *clnt; 518 + 519 + P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, 520 + (long long unsigned) offset, count); 521 + err = 0; 522 + tc = NULL; 523 + rc = NULL; 524 + clnt = fid->clnt; 525 + total = 0; 526 + 527 + rsize = fid->iounit; 528 + if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 529 + rsize = clnt->msize - P9_IOHDRSZ; 530 + 531 + do { 532 + if (count < rsize) 533 + rsize = count; 534 + 535 + tc = p9_create_twrite(fid->fid, offset, rsize, data); 536 + if (IS_ERR(tc)) { 537 + err = PTR_ERR(tc); 538 + tc = NULL; 539 + goto error; 540 + } 541 + 542 + err = p9_conn_rpc(clnt->conn, tc, &rc); 543 + if (err) 544 + goto error; 545 + 546 + n = rc->params.rread.count; 547 + count -= n; 548 + data += n; 549 + offset += n; 550 + total += n; 551 + kfree(tc); 552 + tc = NULL; 553 + kfree(rc); 554 + rc = NULL; 555 + } while (count > 0); 556 + 557 + return total; 558 + 559 + error: 560 + kfree(tc); 561 + kfree(rc); 562 + return err; 563 + } 564 + EXPORT_SYMBOL(p9_client_write); 565 + 566 + int 567 + p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, u32 count) 568 + { 569 + int err, n, rsize, total; 570 + struct p9_fcall *tc, *rc; 571 + struct p9_client *clnt; 572 + 573 + P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, 574 + (long long unsigned) offset, count); 575 + err = 0; 576 + tc = NULL; 577 + rc = NULL; 578 + clnt = fid->clnt; 579 + total = 0; 580 + 581 + rsize = fid->iounit; 582 + if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 583 + rsize = clnt->msize - P9_IOHDRSZ; 584 + 585 + do { 586 + if (count < rsize) 587 + rsize = count; 588 + 589 + tc = p9_create_tread(fid->fid, offset, rsize); 590 + if (IS_ERR(tc)) { 591 + err = PTR_ERR(tc); 592 + tc = NULL; 593 + goto error; 594 + } 595 + 596 + err = p9_conn_rpc(clnt->conn, tc, &rc); 597 + if (err) 598 + goto error; 599 + 600 + n = rc->params.rread.count; 601 + if (n > count) 602 + n = count; 603 + 604 + err = copy_to_user(data, rc->params.rread.data, n); 605 + if (err) { 606 + err = -EFAULT; 607 + goto error; 608 + } 609 + 610 + count -= n; 611 + data += n; 612 + offset += n; 613 + total += n; 614 + kfree(tc); 615 + tc = NULL; 616 + kfree(rc); 617 + rc = NULL; 618 + } while (count > 0 && n == rsize); 619 + 620 + return total; 621 + 622 + error: 623 + kfree(tc); 624 + kfree(rc); 625 + return err; 626 + } 627 + EXPORT_SYMBOL(p9_client_uread); 628 + 629 + int 630 + p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset, 631 + u32 count) 632 + { 633 + int err, n, rsize, total; 634 + struct p9_fcall *tc, *rc; 635 + struct p9_client *clnt; 636 + 637 + P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, 638 + (long long unsigned) offset, count); 639 + err = 0; 640 + tc = NULL; 641 + rc = NULL; 642 + clnt = fid->clnt; 643 + total = 0; 644 + 645 + rsize = fid->iounit; 646 + if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 647 + rsize = clnt->msize - P9_IOHDRSZ; 648 + 649 + do { 650 + if (count < rsize) 651 + rsize = count; 652 + 653 + tc = p9_create_twrite_u(fid->fid, offset, rsize, data); 654 + if (IS_ERR(tc)) { 655 + err = PTR_ERR(tc); 656 + tc = NULL; 657 + goto error; 658 + } 659 + 660 + err = p9_conn_rpc(clnt->conn, tc, &rc); 661 + if (err) 662 + goto error; 663 + 664 + n = rc->params.rread.count; 665 + count -= n; 666 + data += n; 667 + offset += n; 668 + total += n; 669 + kfree(tc); 670 + tc = NULL; 671 + kfree(rc); 672 + rc = NULL; 673 + } while (count > 0); 674 + 675 + return total; 676 + 677 + error: 678 + kfree(tc); 679 + kfree(rc); 680 + return err; 681 + } 682 + EXPORT_SYMBOL(p9_client_uwrite); 683 + 684 + int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count) 685 + { 686 + int n, total; 687 + 688 + P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, 689 + (long long unsigned) offset, count); 690 + n = 0; 691 + total = 0; 692 + while (count) { 693 + n = p9_client_read(fid, data, offset, count); 694 + if (n <= 0) 695 + break; 696 + 697 + data += n; 698 + offset += n; 699 + count -= n; 700 + total += n; 701 + } 702 + 703 + if (n < 0) 704 + total = n; 705 + 706 + return total; 707 + } 708 + EXPORT_SYMBOL(p9_client_readn); 709 + 710 + struct p9_stat *p9_client_stat(struct p9_fid *fid) 711 + { 712 + int err; 713 + struct p9_fcall *tc, *rc; 714 + struct p9_client *clnt; 715 + struct p9_stat *ret; 716 + 717 + P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 718 + err = 0; 719 + tc = NULL; 720 + rc = NULL; 721 + ret = NULL; 722 + clnt = fid->clnt; 723 + 724 + tc = p9_create_tstat(fid->fid); 725 + if (IS_ERR(tc)) { 726 + err = PTR_ERR(tc); 727 + tc = NULL; 728 + goto error; 729 + } 730 + 731 + err = p9_conn_rpc(clnt->conn, tc, &rc); 732 + if (err) 733 + goto error; 734 + 735 + ret = p9_clone_stat(&rc->params.rstat.stat, clnt->dotu); 736 + if (IS_ERR(ret)) { 737 + err = PTR_ERR(ret); 738 + ret = NULL; 739 + goto error; 740 + } 741 + 742 + kfree(tc); 743 + kfree(rc); 744 + return ret; 745 + 746 + error: 747 + kfree(tc); 748 + kfree(rc); 749 + kfree(ret); 750 + return ERR_PTR(err); 751 + } 752 + EXPORT_SYMBOL(p9_client_stat); 753 + 754 + int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) 755 + { 756 + int err; 757 + struct p9_fcall *tc, *rc; 758 + struct p9_client *clnt; 759 + 760 + P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 761 + err = 0; 762 + tc = NULL; 763 + rc = NULL; 764 + clnt = fid->clnt; 765 + 766 + tc = p9_create_twstat(fid->fid, wst, clnt->dotu); 767 + if (IS_ERR(tc)) { 768 + err = PTR_ERR(tc); 769 + tc = NULL; 770 + goto done; 771 + } 772 + 773 + err = p9_conn_rpc(clnt->conn, tc, &rc); 774 + 775 + done: 776 + kfree(tc); 777 + kfree(rc); 778 + return err; 779 + } 780 + EXPORT_SYMBOL(p9_client_wstat); 781 + 782 + struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset) 783 + { 784 + int err, n, m; 785 + struct p9_fcall *tc, *rc; 786 + struct p9_client *clnt; 787 + struct p9_stat st, *ret; 788 + 789 + P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu\n", fid->fid, 790 + (long long unsigned) offset); 791 + err = 0; 792 + tc = NULL; 793 + rc = NULL; 794 + ret = NULL; 795 + clnt = fid->clnt; 796 + 797 + /* if the offset is below or above the current response, free it */ 798 + if (offset < fid->rdir_fpos || (fid->rdir_fcall && 799 + offset >= fid->rdir_fpos+fid->rdir_fcall->params.rread.count)) { 800 + fid->rdir_pos = 0; 801 + if (fid->rdir_fcall) 802 + fid->rdir_fpos += fid->rdir_fcall->params.rread.count; 803 + 804 + kfree(fid->rdir_fcall); 805 + fid->rdir_fcall = NULL; 806 + if (offset < fid->rdir_fpos) 807 + fid->rdir_fpos = 0; 808 + } 809 + 810 + if (!fid->rdir_fcall) { 811 + n = fid->iounit; 812 + if (!n || n > clnt->msize-P9_IOHDRSZ) 813 + n = clnt->msize - P9_IOHDRSZ; 814 + 815 + while (1) { 816 + if (fid->rdir_fcall) { 817 + fid->rdir_fpos += 818 + fid->rdir_fcall->params.rread.count; 819 + kfree(fid->rdir_fcall); 820 + fid->rdir_fcall = NULL; 821 + } 822 + 823 + tc = p9_create_tread(fid->fid, fid->rdir_fpos, n); 824 + if (IS_ERR(tc)) { 825 + err = PTR_ERR(tc); 826 + tc = NULL; 827 + goto error; 828 + } 829 + 830 + err = p9_conn_rpc(clnt->conn, tc, &rc); 831 + if (err) 832 + goto error; 833 + 834 + n = rc->params.rread.count; 835 + if (n == 0) 836 + goto done; 837 + 838 + fid->rdir_fcall = rc; 839 + rc = NULL; 840 + if (offset >= fid->rdir_fpos && 841 + offset < fid->rdir_fpos+n) 842 + break; 843 + } 844 + 845 + fid->rdir_pos = 0; 846 + } 847 + 848 + m = offset - fid->rdir_fpos; 849 + if (m < 0) 850 + goto done; 851 + 852 + n = p9_deserialize_stat(fid->rdir_fcall->params.rread.data + m, 853 + fid->rdir_fcall->params.rread.count - m, &st, clnt->dotu); 854 + 855 + if (!n) { 856 + err = -EIO; 857 + goto error; 858 + } 859 + 860 + fid->rdir_pos += n; 861 + st.size = n; 862 + ret = p9_clone_stat(&st, clnt->dotu); 863 + if (IS_ERR(ret)) { 864 + err = PTR_ERR(ret); 865 + ret = NULL; 866 + goto error; 867 + } 868 + 869 + done: 870 + kfree(tc); 871 + kfree(rc); 872 + return ret; 873 + 874 + error: 875 + kfree(tc); 876 + kfree(rc); 877 + kfree(ret); 878 + return ERR_PTR(err); 879 + } 880 + EXPORT_SYMBOL(p9_client_dirread); 881 + 882 + static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu) 883 + { 884 + int n; 885 + char *p; 886 + struct p9_stat *ret; 887 + 888 + n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len + 889 + st->muid.len; 890 + 891 + if (dotu) 892 + n += st->extension.len; 893 + 894 + ret = kmalloc(n, GFP_KERNEL); 895 + if (!ret) 896 + return ERR_PTR(-ENOMEM); 897 + 898 + memmove(ret, st, sizeof(struct p9_stat)); 899 + p = ((char *) ret) + sizeof(struct p9_stat); 900 + memmove(p, st->name.str, st->name.len); 901 + p += st->name.len; 902 + memmove(p, st->uid.str, st->uid.len); 903 + p += st->uid.len; 904 + memmove(p, st->gid.str, st->gid.len); 905 + p += st->gid.len; 906 + memmove(p, st->muid.str, st->muid.len); 907 + p += st->muid.len; 908 + 909 + if (dotu) { 910 + memmove(p, st->extension.str, st->extension.len); 911 + p += st->extension.len; 912 + } 913 + 914 + return ret; 915 + } 916 + 917 + static struct p9_fid *p9_fid_create(struct p9_client *clnt) 918 + { 919 + int err; 920 + struct p9_fid *fid; 921 + 922 + P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); 923 + fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); 924 + if (!fid) 925 + return ERR_PTR(-ENOMEM); 926 + 927 + fid->fid = p9_idpool_get(clnt->fidpool); 928 + if (fid->fid < 0) { 929 + err = -ENOSPC; 930 + goto error; 931 + } 932 + 933 + memset(&fid->qid, 0, sizeof(struct p9_qid)); 934 + fid->mode = -1; 935 + fid->rdir_fpos = 0; 936 + fid->rdir_pos = 0; 937 + fid->rdir_fcall = NULL; 938 + fid->uid = current->fsuid; 939 + fid->clnt = clnt; 940 + fid->aux = NULL; 941 + 942 + spin_lock(&clnt->lock); 943 + list_add(&fid->flist, &clnt->fidlist); 944 + spin_unlock(&clnt->lock); 945 + 946 + return fid; 947 + 948 + error: 949 + kfree(fid); 950 + return ERR_PTR(err); 951 + } 952 + 953 + static void p9_fid_destroy(struct p9_fid *fid) 954 + { 955 + struct p9_client *clnt; 956 + 957 + P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 958 + clnt = fid->clnt; 959 + p9_idpool_put(fid->fid, clnt->fidpool); 960 + spin_lock(&clnt->lock); 961 + list_del(&fid->flist); 962 + spin_unlock(&clnt->lock); 963 + kfree(fid->rdir_fcall); 964 + kfree(fid); 965 + }
+85
net/9p/mod.c
···
··· 1 + /* 2 + * net/9p/9p.c 3 + * 4 + * 9P entry point 5 + * 6 + * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> 7 + * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 8 + * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 12 + * as published by the Free Software Foundation. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this program; if not, write to: 21 + * Free Software Foundation 22 + * 51 Franklin Street, Fifth Floor 23 + * Boston, MA 02111-1301 USA 24 + * 25 + */ 26 + 27 + #include <linux/module.h> 28 + #include <linux/moduleparam.h> 29 + #include <net/9p/9p.h> 30 + 31 + #ifdef CONFIG_NET_9P_DEBUG 32 + unsigned int p9_debug_level = 0; /* feature-rific global debug level */ 33 + EXPORT_SYMBOL(p9_debug_level); 34 + module_param_named(debug, p9_debug_level, uint, 0); 35 + MODULE_PARM_DESC(debug, "9P debugging level"); 36 + #endif 37 + 38 + extern int p9_mux_global_init(void); 39 + extern void p9_mux_global_exit(void); 40 + extern int p9_sysctl_register(void); 41 + extern void p9_sysctl_unregister(void); 42 + 43 + /** 44 + * v9fs_init - Initialize module 45 + * 46 + */ 47 + static int __init init_p9(void) 48 + { 49 + int ret; 50 + 51 + p9_error_init(); 52 + printk(KERN_INFO "Installing 9P2000 support\n"); 53 + ret = p9_mux_global_init(); 54 + if (ret) { 55 + printk(KERN_WARNING "9p: starting mux failed\n"); 56 + return ret; 57 + } 58 + 59 + ret = p9_sysctl_register(); 60 + if (ret) { 61 + printk(KERN_WARNING "9p: registering sysctl failed\n"); 62 + return ret; 63 + } 64 + 65 + return ret; 66 + } 67 + 68 + /** 69 + * v9fs_init - shutdown module 70 + * 71 + */ 72 + 73 + static void __exit exit_p9(void) 74 + { 75 + p9_sysctl_unregister(); 76 + p9_mux_global_exit(); 77 + } 78 + 79 + module_init(init_p9) 80 + module_exit(exit_p9) 81 + 82 + MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>"); 83 + MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); 84 + MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>"); 85 + MODULE_LICENSE("GPL");
+86
net/9p/sysctl.c
···
··· 1 + /* 2 + * net/9p/sysctl.c 3 + * 4 + * 9P sysctl interface 5 + * 6 + * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 10 + * as published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program; if not, write to: 19 + * Free Software Foundation 20 + * 51 Franklin Street, Fifth Floor 21 + * Boston, MA 02111-1301 USA 22 + * 23 + */ 24 + 25 + #include <linux/kernel.h> 26 + #include <linux/mm.h> 27 + #include <linux/sysctl.h> 28 + #include <linux/init.h> 29 + #include <net/9p/9p.h> 30 + 31 + enum { 32 + P9_SYSCTL_NET = 487, 33 + P9_SYSCTL_DEBUG = 1, 34 + }; 35 + 36 + static ctl_table p9_table[] = { 37 + #ifdef CONFIG_NET_9P_DEBUG 38 + { 39 + .ctl_name = P9_SYSCTL_DEBUG, 40 + .procname = "debug", 41 + .data = &p9_debug_level, 42 + .maxlen = sizeof(int), 43 + .mode = 0644, 44 + .proc_handler = &proc_dointvec 45 + }, 46 + #endif 47 + { .ctl_name = 0 }, 48 + }; 49 + 50 + static ctl_table p9_net_table[] = { 51 + { 52 + .ctl_name = P9_SYSCTL_NET, 53 + .procname = "9p", 54 + .maxlen = 0, 55 + .mode = 0555, 56 + .child = p9_table, 57 + }, 58 + { .ctl_name = 0 }, 59 + }; 60 + 61 + static ctl_table p9_ctl_table[] = { 62 + { 63 + .ctl_name = CTL_NET, 64 + .procname = "net", 65 + .maxlen = 0, 66 + .mode = 0555, 67 + .child = p9_net_table, 68 + }, 69 + { .ctl_name = 0 }, 70 + }; 71 + 72 + static struct ctl_table_header *p9_table_header; 73 + 74 + int __init p9_sysctl_register(void) 75 + { 76 + p9_table_header = register_sysctl_table(p9_ctl_table); 77 + if (!p9_table_header) 78 + return -ENOMEM; 79 + 80 + return 0; 81 + } 82 + 83 + void __exit p9_sysctl_unregister(void) 84 + { 85 + unregister_sysctl_table(p9_table_header); 86 + }
+363
net/9p/trans_fd.c
···
··· 1 + /* 2 + * linux/fs/9p/trans_fd.c 3 + * 4 + * Fd transport layer. Includes deprecated socket layer. 5 + * 6 + * Copyright (C) 2006 by Russ Cox <rsc@swtch.com> 7 + * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net> 8 + * Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com> 9 + * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com> 10 + * 11 + * This program is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License version 2 13 + * as published by the Free Software Foundation. 14 + * 15 + * This program is distributed in the hope that it will be useful, 16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 + * GNU General Public License for more details. 19 + * 20 + * You should have received a copy of the GNU General Public License 21 + * along with this program; if not, write to: 22 + * Free Software Foundation 23 + * 51 Franklin Street, Fifth Floor 24 + * Boston, MA 02111-1301 USA 25 + * 26 + */ 27 + 28 + #include <linux/in.h> 29 + #include <linux/module.h> 30 + #include <linux/net.h> 31 + #include <linux/ipv6.h> 32 + #include <linux/errno.h> 33 + #include <linux/kernel.h> 34 + #include <linux/un.h> 35 + #include <linux/uaccess.h> 36 + #include <linux/inet.h> 37 + #include <linux/idr.h> 38 + #include <linux/file.h> 39 + #include <net/9p/9p.h> 40 + #include <net/9p/transport.h> 41 + 42 + #define P9_PORT 564 43 + 44 + struct p9_trans_fd { 45 + struct file *rd; 46 + struct file *wr; 47 + }; 48 + 49 + static int p9_socket_open(struct p9_transport *trans, struct socket *csocket); 50 + static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd); 51 + static int p9_fd_read(struct p9_transport *trans, void *v, int len); 52 + static int p9_fd_write(struct p9_transport *trans, void *v, int len); 53 + static unsigned int p9_fd_poll(struct p9_transport *trans, 54 + struct poll_table_struct *pt); 55 + static void p9_fd_close(struct p9_transport *trans); 56 + 57 + struct p9_transport *p9_trans_create_tcp(const char *addr, int port) 58 + { 59 + int err; 60 + struct p9_transport *trans; 61 + struct socket *csocket; 62 + struct sockaddr_in sin_server; 63 + 64 + csocket = NULL; 65 + trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); 66 + if (!trans) 67 + return ERR_PTR(-ENOMEM); 68 + 69 + trans->write = p9_fd_write; 70 + trans->read = p9_fd_read; 71 + trans->close = p9_fd_close; 72 + trans->poll = p9_fd_poll; 73 + 74 + sin_server.sin_family = AF_INET; 75 + sin_server.sin_addr.s_addr = in_aton(addr); 76 + sin_server.sin_port = htons(port); 77 + sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); 78 + 79 + if (!csocket) { 80 + P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n"); 81 + err = -EIO; 82 + goto error; 83 + } 84 + 85 + err = csocket->ops->connect(csocket, 86 + (struct sockaddr *)&sin_server, 87 + sizeof(struct sockaddr_in), 0); 88 + if (err < 0) { 89 + P9_EPRINTK(KERN_ERR, 90 + "p9_trans_tcp: problem connecting socket to %s\n", 91 + addr); 92 + goto error; 93 + } 94 + 95 + err = p9_socket_open(trans, csocket); 96 + if (err < 0) 97 + goto error; 98 + 99 + return trans; 100 + 101 + error: 102 + if (csocket) 103 + sock_release(csocket); 104 + 105 + kfree(trans); 106 + return ERR_PTR(err); 107 + } 108 + EXPORT_SYMBOL(p9_trans_create_tcp); 109 + 110 + struct p9_transport *p9_trans_create_unix(const char *addr) 111 + { 112 + int err; 113 + struct socket *csocket; 114 + struct sockaddr_un sun_server; 115 + struct p9_transport *trans; 116 + 117 + csocket = NULL; 118 + trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); 119 + if (!trans) 120 + return ERR_PTR(-ENOMEM); 121 + 122 + trans->write = p9_fd_write; 123 + trans->read = p9_fd_read; 124 + trans->close = p9_fd_close; 125 + trans->poll = p9_fd_poll; 126 + 127 + if (strlen(addr) > UNIX_PATH_MAX) { 128 + P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n", 129 + addr); 130 + err = -ENAMETOOLONG; 131 + goto error; 132 + } 133 + 134 + sun_server.sun_family = PF_UNIX; 135 + strcpy(sun_server.sun_path, addr); 136 + sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); 137 + err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, 138 + sizeof(struct sockaddr_un) - 1, 0); 139 + if (err < 0) { 140 + P9_EPRINTK(KERN_ERR, 141 + "p9_trans_unix: problem connecting socket: %s: %d\n", 142 + addr, err); 143 + goto error; 144 + } 145 + 146 + err = p9_socket_open(trans, csocket); 147 + if (err < 0) 148 + goto error; 149 + 150 + return trans; 151 + 152 + error: 153 + if (csocket) 154 + sock_release(csocket); 155 + 156 + kfree(trans); 157 + return ERR_PTR(err); 158 + } 159 + EXPORT_SYMBOL(p9_trans_create_unix); 160 + 161 + struct p9_transport *p9_trans_create_fd(int rfd, int wfd) 162 + { 163 + int err; 164 + struct p9_transport *trans; 165 + 166 + if (rfd == ~0 || wfd == ~0) { 167 + printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n"); 168 + return ERR_PTR(-ENOPROTOOPT); 169 + } 170 + 171 + trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); 172 + if (!trans) 173 + return ERR_PTR(-ENOMEM); 174 + 175 + trans->write = p9_fd_write; 176 + trans->read = p9_fd_read; 177 + trans->close = p9_fd_close; 178 + trans->poll = p9_fd_poll; 179 + 180 + err = p9_fd_open(trans, rfd, wfd); 181 + if (err < 0) 182 + goto error; 183 + 184 + return trans; 185 + 186 + error: 187 + kfree(trans); 188 + return ERR_PTR(err); 189 + } 190 + EXPORT_SYMBOL(p9_trans_create_fd); 191 + 192 + static int p9_socket_open(struct p9_transport *trans, struct socket *csocket) 193 + { 194 + int fd, ret; 195 + 196 + csocket->sk->sk_allocation = GFP_NOIO; 197 + fd = sock_map_fd(csocket); 198 + if (fd < 0) { 199 + P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n"); 200 + return fd; 201 + } 202 + 203 + ret = p9_fd_open(trans, fd, fd); 204 + if (ret < 0) { 205 + P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n"); 206 + sockfd_put(csocket); 207 + return ret; 208 + } 209 + 210 + ((struct p9_trans_fd *)trans->priv)->rd->f_flags |= O_NONBLOCK; 211 + 212 + return 0; 213 + } 214 + 215 + static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd) 216 + { 217 + struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd), 218 + GFP_KERNEL); 219 + if (!ts) 220 + return -ENOMEM; 221 + 222 + ts->rd = fget(rfd); 223 + ts->wr = fget(wfd); 224 + if (!ts->rd || !ts->wr) { 225 + if (ts->rd) 226 + fput(ts->rd); 227 + if (ts->wr) 228 + fput(ts->wr); 229 + kfree(ts); 230 + return -EIO; 231 + } 232 + 233 + trans->priv = ts; 234 + trans->status = Connected; 235 + 236 + return 0; 237 + } 238 + 239 + /** 240 + * p9_fd_read- read from a fd 241 + * @v9ses: session information 242 + * @v: buffer to receive data into 243 + * @len: size of receive buffer 244 + * 245 + */ 246 + static int p9_fd_read(struct p9_transport *trans, void *v, int len) 247 + { 248 + int ret; 249 + struct p9_trans_fd *ts = NULL; 250 + 251 + if (trans && trans->status != Disconnected) 252 + ts = trans->priv; 253 + 254 + if (!ts) 255 + return -EREMOTEIO; 256 + 257 + if (!(ts->rd->f_flags & O_NONBLOCK)) 258 + P9_DPRINTK(P9_DEBUG_ERROR, "blocking read ...\n"); 259 + 260 + ret = kernel_read(ts->rd, ts->rd->f_pos, v, len); 261 + if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) 262 + trans->status = Disconnected; 263 + return ret; 264 + } 265 + 266 + /** 267 + * p9_fd_write - write to a socket 268 + * @v9ses: session information 269 + * @v: buffer to send data from 270 + * @len: size of send buffer 271 + * 272 + */ 273 + static int p9_fd_write(struct p9_transport *trans, void *v, int len) 274 + { 275 + int ret; 276 + mm_segment_t oldfs; 277 + struct p9_trans_fd *ts = NULL; 278 + 279 + if (trans && trans->status != Disconnected) 280 + ts = trans->priv; 281 + 282 + if (!ts) 283 + return -EREMOTEIO; 284 + 285 + if (!(ts->wr->f_flags & O_NONBLOCK)) 286 + P9_DPRINTK(P9_DEBUG_ERROR, "blocking write ...\n"); 287 + 288 + oldfs = get_fs(); 289 + set_fs(get_ds()); 290 + /* The cast to a user pointer is valid due to the set_fs() */ 291 + ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos); 292 + set_fs(oldfs); 293 + 294 + if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) 295 + trans->status = Disconnected; 296 + return ret; 297 + } 298 + 299 + static unsigned int 300 + p9_fd_poll(struct p9_transport *trans, struct poll_table_struct *pt) 301 + { 302 + int ret, n; 303 + struct p9_trans_fd *ts = NULL; 304 + mm_segment_t oldfs; 305 + 306 + if (trans && trans->status == Connected) 307 + ts = trans->priv; 308 + 309 + if (!ts) 310 + return -EREMOTEIO; 311 + 312 + if (!ts->rd->f_op || !ts->rd->f_op->poll) 313 + return -EIO; 314 + 315 + if (!ts->wr->f_op || !ts->wr->f_op->poll) 316 + return -EIO; 317 + 318 + oldfs = get_fs(); 319 + set_fs(get_ds()); 320 + 321 + ret = ts->rd->f_op->poll(ts->rd, pt); 322 + if (ret < 0) 323 + goto end; 324 + 325 + if (ts->rd != ts->wr) { 326 + n = ts->wr->f_op->poll(ts->wr, pt); 327 + if (n < 0) { 328 + ret = n; 329 + goto end; 330 + } 331 + ret = (ret & ~POLLOUT) | (n & ~POLLIN); 332 + } 333 + 334 + end: 335 + set_fs(oldfs); 336 + return ret; 337 + } 338 + 339 + /** 340 + * p9_sock_close - shutdown socket 341 + * @trans: private socket structure 342 + * 343 + */ 344 + static void p9_fd_close(struct p9_transport *trans) 345 + { 346 + struct p9_trans_fd *ts; 347 + 348 + if (!trans) 349 + return; 350 + 351 + ts = xchg(&trans->priv, NULL); 352 + 353 + if (!ts) 354 + return; 355 + 356 + trans->status = Disconnected; 357 + if (ts->rd) 358 + fput(ts->rd); 359 + if (ts->wr) 360 + fput(ts->wr); 361 + kfree(ts); 362 + } 363 +
+125
net/9p/util.c
···
··· 1 + /* 2 + * net/9p/util.c 3 + * 4 + * This file contains some helper functions 5 + * 6 + * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> 7 + * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 8 + * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 12 + * as published by the Free Software Foundation. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this program; if not, write to: 21 + * Free Software Foundation 22 + * 51 Franklin Street, Fifth Floor 23 + * Boston, MA 02111-1301 USA 24 + * 25 + */ 26 + 27 + #include <linux/module.h> 28 + #include <linux/errno.h> 29 + #include <linux/fs.h> 30 + #include <linux/sched.h> 31 + #include <linux/parser.h> 32 + #include <linux/idr.h> 33 + #include <net/9p/9p.h> 34 + 35 + struct p9_idpool { 36 + struct semaphore lock; 37 + struct idr pool; 38 + }; 39 + 40 + struct p9_idpool *p9_idpool_create(void) 41 + { 42 + struct p9_idpool *p; 43 + 44 + p = kmalloc(sizeof(struct p9_idpool), GFP_KERNEL); 45 + if (!p) 46 + return ERR_PTR(-ENOMEM); 47 + 48 + init_MUTEX(&p->lock); 49 + idr_init(&p->pool); 50 + 51 + return p; 52 + } 53 + EXPORT_SYMBOL(p9_idpool_create); 54 + 55 + void p9_idpool_destroy(struct p9_idpool *p) 56 + { 57 + idr_destroy(&p->pool); 58 + kfree(p); 59 + } 60 + EXPORT_SYMBOL(p9_idpool_destroy); 61 + 62 + /** 63 + * p9_idpool_get - allocate numeric id from pool 64 + * @p - pool to allocate from 65 + * 66 + * XXX - This seems to be an awful generic function, should it be in idr.c with 67 + * the lock included in struct idr? 68 + */ 69 + 70 + int p9_idpool_get(struct p9_idpool *p) 71 + { 72 + int i = 0; 73 + int error; 74 + 75 + retry: 76 + if (idr_pre_get(&p->pool, GFP_KERNEL) == 0) 77 + return 0; 78 + 79 + if (down_interruptible(&p->lock) == -EINTR) { 80 + P9_EPRINTK(KERN_WARNING, "Interrupted while locking\n"); 81 + return -1; 82 + } 83 + 84 + /* no need to store exactly p, we just need something non-null */ 85 + error = idr_get_new(&p->pool, p, &i); 86 + up(&p->lock); 87 + 88 + if (error == -EAGAIN) 89 + goto retry; 90 + else if (error) 91 + return -1; 92 + 93 + return i; 94 + } 95 + EXPORT_SYMBOL(p9_idpool_get); 96 + 97 + /** 98 + * p9_idpool_put - release numeric id from pool 99 + * @p - pool to allocate from 100 + * 101 + * XXX - This seems to be an awful generic function, should it be in idr.c with 102 + * the lock included in struct idr? 103 + */ 104 + 105 + void p9_idpool_put(int id, struct p9_idpool *p) 106 + { 107 + if (down_interruptible(&p->lock) == -EINTR) { 108 + P9_EPRINTK(KERN_WARNING, "Interrupted while locking\n"); 109 + return; 110 + } 111 + idr_remove(&p->pool, id); 112 + up(&p->lock); 113 + } 114 + EXPORT_SYMBOL(p9_idpool_put); 115 + 116 + /** 117 + * p9_idpool_check - check if the specified id is available 118 + * @id - id to check 119 + * @p - pool 120 + */ 121 + int p9_idpool_check(int id, struct p9_idpool *p) 122 + { 123 + return idr_find(&p->pool, id) != NULL; 124 + } 125 + EXPORT_SYMBOL(p9_idpool_check);
+1
net/Kconfig
··· 227 endmenu 228 229 source "net/rfkill/Kconfig" 230 231 endif # if NET 232 endmenu # Networking
··· 227 endmenu 228 229 source "net/rfkill/Kconfig" 230 + source "net/9p/Kconfig" 231 232 endif # if NET 233 endmenu # Networking
+1
net/Makefile
··· 51 obj-$(CONFIG_NETLABEL) += netlabel/ 52 obj-$(CONFIG_IUCV) += iucv/ 53 obj-$(CONFIG_RFKILL) += rfkill/ 54 55 ifeq ($(CONFIG_NET),y) 56 obj-$(CONFIG_SYSCTL) += sysctl_net.o
··· 51 obj-$(CONFIG_NETLABEL) += netlabel/ 52 obj-$(CONFIG_IUCV) += iucv/ 53 obj-$(CONFIG_RFKILL) += rfkill/ 54 + obj-$(CONFIG_NET_9P) += 9p/ 55 56 ifeq ($(CONFIG_NET),y) 57 obj-$(CONFIG_SYSCTL) += sysctl_net.o