19e82cf6aSEric Van Hensbergen /* 29e82cf6aSEric Van Hensbergen * linux/fs/9p/v9fs.c 39e82cf6aSEric Van Hensbergen * 49e82cf6aSEric Van Hensbergen * This file contains functions assisting in mapping VFS to 9P2000 59e82cf6aSEric Van Hensbergen * 69e82cf6aSEric Van Hensbergen * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 79e82cf6aSEric Van Hensbergen * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 89e82cf6aSEric Van Hensbergen * 99e82cf6aSEric Van Hensbergen * This program is free software; you can redistribute it and/or modify 1042e8c509SEric Van Hensbergen * it under the terms of the GNU General Public License version 2 1142e8c509SEric Van Hensbergen * as published by the Free Software Foundation. 129e82cf6aSEric Van Hensbergen * 139e82cf6aSEric Van Hensbergen * This program is distributed in the hope that it will be useful, 149e82cf6aSEric Van Hensbergen * but WITHOUT ANY WARRANTY; without even the implied warranty of 159e82cf6aSEric Van Hensbergen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 169e82cf6aSEric Van Hensbergen * GNU General Public License for more details. 179e82cf6aSEric Van Hensbergen * 189e82cf6aSEric Van Hensbergen * You should have received a copy of the GNU General Public License 199e82cf6aSEric Van Hensbergen * along with this program; if not, write to: 209e82cf6aSEric Van Hensbergen * Free Software Foundation 219e82cf6aSEric Van Hensbergen * 51 Franklin Street, Fifth Floor 229e82cf6aSEric Van Hensbergen * Boston, MA 02111-1301 USA 239e82cf6aSEric Van Hensbergen * 249e82cf6aSEric Van Hensbergen */ 259e82cf6aSEric Van Hensbergen 269e82cf6aSEric Van Hensbergen #include <linux/module.h> 279e82cf6aSEric Van Hensbergen #include <linux/errno.h> 289e82cf6aSEric Van Hensbergen #include <linux/fs.h> 29914e2637SAl Viro #include <linux/sched.h> 309e82cf6aSEric Van Hensbergen #include <linux/parser.h> 319e82cf6aSEric Van Hensbergen #include <linux/idr.h> 329e82cf6aSEric Van Hensbergen 339e82cf6aSEric Van Hensbergen #include "debug.h" 349e82cf6aSEric Van Hensbergen #include "v9fs.h" 359e82cf6aSEric Van Hensbergen #include "9p.h" 369e82cf6aSEric Van Hensbergen #include "v9fs_vfs.h" 379e82cf6aSEric Van Hensbergen #include "transport.h" 389e82cf6aSEric Van Hensbergen #include "mux.h" 399e82cf6aSEric Van Hensbergen 409e82cf6aSEric Van Hensbergen /* TODO: sysfs or debugfs interface */ 419e82cf6aSEric Van Hensbergen int v9fs_debug_level = 0; /* feature-rific global debug level */ 429e82cf6aSEric Van Hensbergen 439e82cf6aSEric Van Hensbergen /* 449e82cf6aSEric Van Hensbergen * Option Parsing (code inspired by NFS code) 459e82cf6aSEric Van Hensbergen * 469e82cf6aSEric Van Hensbergen */ 479e82cf6aSEric Van Hensbergen 489e82cf6aSEric Van Hensbergen enum { 499e82cf6aSEric Van Hensbergen /* Options that take integer arguments */ 509e82cf6aSEric Van Hensbergen Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, Opt_debug, 519e82cf6aSEric Van Hensbergen Opt_rfdno, Opt_wfdno, 529e82cf6aSEric Van Hensbergen /* String options */ 5367543e50SEric Van Hensbergen Opt_uname, Opt_remotename, 549e82cf6aSEric Van Hensbergen /* Options that take no arguments */ 559e82cf6aSEric Van Hensbergen Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, 569e82cf6aSEric Van Hensbergen /* Error token */ 579e82cf6aSEric Van Hensbergen Opt_err 589e82cf6aSEric Van Hensbergen }; 599e82cf6aSEric Van Hensbergen 609e82cf6aSEric Van Hensbergen static match_table_t tokens = { 619e82cf6aSEric Van Hensbergen {Opt_port, "port=%u"}, 629e82cf6aSEric Van Hensbergen {Opt_msize, "msize=%u"}, 639e82cf6aSEric Van Hensbergen {Opt_uid, "uid=%u"}, 649e82cf6aSEric Van Hensbergen {Opt_gid, "gid=%u"}, 659e82cf6aSEric Van Hensbergen {Opt_afid, "afid=%u"}, 669e82cf6aSEric Van Hensbergen {Opt_rfdno, "rfdno=%u"}, 679e82cf6aSEric Van Hensbergen {Opt_wfdno, "wfdno=%u"}, 68e1c92117SEric Van Hensbergen {Opt_debug, "debug=%x"}, 6967543e50SEric Van Hensbergen {Opt_uname, "uname=%s"}, 709e82cf6aSEric Van Hensbergen {Opt_remotename, "aname=%s"}, 719e82cf6aSEric Van Hensbergen {Opt_unix, "proto=unix"}, 729e82cf6aSEric Van Hensbergen {Opt_tcp, "proto=tcp"}, 739e82cf6aSEric Van Hensbergen {Opt_fd, "proto=fd"}, 749e82cf6aSEric Van Hensbergen {Opt_tcp, "tcp"}, 759e82cf6aSEric Van Hensbergen {Opt_unix, "unix"}, 769e82cf6aSEric Van Hensbergen {Opt_fd, "fd"}, 779e82cf6aSEric Van Hensbergen {Opt_legacy, "noextend"}, 789e82cf6aSEric Van Hensbergen {Opt_nodevmap, "nodevmap"}, 799e82cf6aSEric Van Hensbergen {Opt_err, NULL} 809e82cf6aSEric Van Hensbergen }; 819e82cf6aSEric Van Hensbergen 829e82cf6aSEric Van Hensbergen /* 839e82cf6aSEric Van Hensbergen * Parse option string. 849e82cf6aSEric Van Hensbergen */ 859e82cf6aSEric Van Hensbergen 869e82cf6aSEric Van Hensbergen /** 879e82cf6aSEric Van Hensbergen * v9fs_parse_options - parse mount options into session structure 889e82cf6aSEric Van Hensbergen * @options: options string passed from mount 899e82cf6aSEric Van Hensbergen * @v9ses: existing v9fs session information 909e82cf6aSEric Van Hensbergen * 919e82cf6aSEric Van Hensbergen */ 929e82cf6aSEric Van Hensbergen 939e82cf6aSEric Van Hensbergen static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) 949e82cf6aSEric Van Hensbergen { 959e82cf6aSEric Van Hensbergen char *p; 969e82cf6aSEric Van Hensbergen substring_t args[MAX_OPT_ARGS]; 979e82cf6aSEric Van Hensbergen int option; 989e82cf6aSEric Van Hensbergen int ret; 999e82cf6aSEric Van Hensbergen 1009e82cf6aSEric Van Hensbergen /* setup defaults */ 1019e82cf6aSEric Van Hensbergen v9ses->port = V9FS_PORT; 1029e82cf6aSEric Van Hensbergen v9ses->maxdata = 9000; 1039e82cf6aSEric Van Hensbergen v9ses->proto = PROTO_TCP; 1049e82cf6aSEric Van Hensbergen v9ses->extended = 1; 1059e82cf6aSEric Van Hensbergen v9ses->afid = ~0; 1069e82cf6aSEric Van Hensbergen v9ses->debug = 0; 1079e82cf6aSEric Van Hensbergen v9ses->rfdno = ~0; 1089e82cf6aSEric Van Hensbergen v9ses->wfdno = ~0; 1099e82cf6aSEric Van Hensbergen 1109e82cf6aSEric Van Hensbergen if (!options) 1119e82cf6aSEric Van Hensbergen return; 1129e82cf6aSEric Van Hensbergen 1139e82cf6aSEric Van Hensbergen while ((p = strsep(&options, ",")) != NULL) { 1149e82cf6aSEric Van Hensbergen int token; 1159e82cf6aSEric Van Hensbergen if (!*p) 1169e82cf6aSEric Van Hensbergen continue; 1179e82cf6aSEric Van Hensbergen token = match_token(p, tokens, args); 11867543e50SEric Van Hensbergen if (token < Opt_uname) { 1199e82cf6aSEric Van Hensbergen if ((ret = match_int(&args[0], &option)) < 0) { 1209e82cf6aSEric Van Hensbergen dprintk(DEBUG_ERROR, 1219e82cf6aSEric Van Hensbergen "integer field, but no integer?\n"); 1229e82cf6aSEric Van Hensbergen continue; 1239e82cf6aSEric Van Hensbergen } 1249e82cf6aSEric Van Hensbergen 1259e82cf6aSEric Van Hensbergen } 1269e82cf6aSEric Van Hensbergen switch (token) { 1279e82cf6aSEric Van Hensbergen case Opt_port: 1289e82cf6aSEric Van Hensbergen v9ses->port = option; 1299e82cf6aSEric Van Hensbergen break; 1309e82cf6aSEric Van Hensbergen case Opt_msize: 1319e82cf6aSEric Van Hensbergen v9ses->maxdata = option; 1329e82cf6aSEric Van Hensbergen break; 1339e82cf6aSEric Van Hensbergen case Opt_uid: 1349e82cf6aSEric Van Hensbergen v9ses->uid = option; 1359e82cf6aSEric Van Hensbergen break; 1369e82cf6aSEric Van Hensbergen case Opt_gid: 1379e82cf6aSEric Van Hensbergen v9ses->gid = option; 1389e82cf6aSEric Van Hensbergen break; 1399e82cf6aSEric Van Hensbergen case Opt_afid: 1409e82cf6aSEric Van Hensbergen v9ses->afid = option; 1419e82cf6aSEric Van Hensbergen break; 1429e82cf6aSEric Van Hensbergen case Opt_rfdno: 1439e82cf6aSEric Van Hensbergen v9ses->rfdno = option; 1449e82cf6aSEric Van Hensbergen break; 1459e82cf6aSEric Van Hensbergen case Opt_wfdno: 1469e82cf6aSEric Van Hensbergen v9ses->wfdno = option; 1479e82cf6aSEric Van Hensbergen break; 1489e82cf6aSEric Van Hensbergen case Opt_debug: 1499e82cf6aSEric Van Hensbergen v9ses->debug = option; 1509e82cf6aSEric Van Hensbergen break; 1519e82cf6aSEric Van Hensbergen case Opt_tcp: 1529e82cf6aSEric Van Hensbergen v9ses->proto = PROTO_TCP; 1539e82cf6aSEric Van Hensbergen break; 1549e82cf6aSEric Van Hensbergen case Opt_unix: 1559e82cf6aSEric Van Hensbergen v9ses->proto = PROTO_UNIX; 1569e82cf6aSEric Van Hensbergen break; 1579e82cf6aSEric Van Hensbergen case Opt_fd: 1589e82cf6aSEric Van Hensbergen v9ses->proto = PROTO_FD; 1599e82cf6aSEric Van Hensbergen break; 16067543e50SEric Van Hensbergen case Opt_uname: 1619e82cf6aSEric Van Hensbergen match_strcpy(v9ses->name, &args[0]); 1629e82cf6aSEric Van Hensbergen break; 1639e82cf6aSEric Van Hensbergen case Opt_remotename: 1649e82cf6aSEric Van Hensbergen match_strcpy(v9ses->remotename, &args[0]); 1659e82cf6aSEric Van Hensbergen break; 1669e82cf6aSEric Van Hensbergen case Opt_legacy: 1679e82cf6aSEric Van Hensbergen v9ses->extended = 0; 1689e82cf6aSEric Van Hensbergen break; 1699e82cf6aSEric Van Hensbergen case Opt_nodevmap: 1709e82cf6aSEric Van Hensbergen v9ses->nodev = 1; 1719e82cf6aSEric Van Hensbergen break; 1729e82cf6aSEric Van Hensbergen default: 1739e82cf6aSEric Van Hensbergen continue; 1749e82cf6aSEric Van Hensbergen } 1759e82cf6aSEric Van Hensbergen } 1769e82cf6aSEric Van Hensbergen } 1779e82cf6aSEric Van Hensbergen 1789e82cf6aSEric Van Hensbergen /** 1799e82cf6aSEric Van Hensbergen * v9fs_inode2v9ses - safely extract v9fs session info from super block 1809e82cf6aSEric Van Hensbergen * @inode: inode to extract information from 1819e82cf6aSEric Van Hensbergen * 1829e82cf6aSEric Van Hensbergen * Paranoid function to extract v9ses information from superblock, 1839e82cf6aSEric Van Hensbergen * if anything is missing it will report an error. 1849e82cf6aSEric Van Hensbergen * 1859e82cf6aSEric Van Hensbergen */ 1869e82cf6aSEric Van Hensbergen 1879e82cf6aSEric Van Hensbergen struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) 1889e82cf6aSEric Van Hensbergen { 1899e82cf6aSEric Van Hensbergen return (inode->i_sb->s_fs_info); 1909e82cf6aSEric Van Hensbergen } 1919e82cf6aSEric Van Hensbergen 1929e82cf6aSEric Van Hensbergen /** 1939e82cf6aSEric Van Hensbergen * v9fs_get_idpool - allocate numeric id from pool 1949e82cf6aSEric Van Hensbergen * @p - pool to allocate from 1959e82cf6aSEric Van Hensbergen * 1969e82cf6aSEric Van Hensbergen * XXX - This seems to be an awful generic function, should it be in idr.c with 1979e82cf6aSEric Van Hensbergen * the lock included in struct idr? 1989e82cf6aSEric Van Hensbergen */ 1999e82cf6aSEric Van Hensbergen 2009e82cf6aSEric Van Hensbergen int v9fs_get_idpool(struct v9fs_idpool *p) 2019e82cf6aSEric Van Hensbergen { 2029e82cf6aSEric Van Hensbergen int i = 0; 2039e82cf6aSEric Van Hensbergen int error; 2049e82cf6aSEric Van Hensbergen 2059e82cf6aSEric Van Hensbergen retry: 2069e82cf6aSEric Van Hensbergen if (idr_pre_get(&p->pool, GFP_KERNEL) == 0) 2079e82cf6aSEric Van Hensbergen return 0; 2089e82cf6aSEric Van Hensbergen 2099e82cf6aSEric Van Hensbergen if (down_interruptible(&p->lock) == -EINTR) { 2109e82cf6aSEric Van Hensbergen eprintk(KERN_WARNING, "Interrupted while locking\n"); 2119e82cf6aSEric Van Hensbergen return -1; 2129e82cf6aSEric Van Hensbergen } 2139e82cf6aSEric Van Hensbergen 2143cf6429aSLatchesar Ionkov /* no need to store exactly p, we just need something non-null */ 2153cf6429aSLatchesar Ionkov error = idr_get_new(&p->pool, p, &i); 2169e82cf6aSEric Van Hensbergen up(&p->lock); 2179e82cf6aSEric Van Hensbergen 2189e82cf6aSEric Van Hensbergen if (error == -EAGAIN) 2199e82cf6aSEric Van Hensbergen goto retry; 2209e82cf6aSEric Van Hensbergen else if (error) 2219e82cf6aSEric Van Hensbergen return -1; 2229e82cf6aSEric Van Hensbergen 2239e82cf6aSEric Van Hensbergen return i; 2249e82cf6aSEric Van Hensbergen } 2259e82cf6aSEric Van Hensbergen 2269e82cf6aSEric Van Hensbergen /** 2279e82cf6aSEric Van Hensbergen * v9fs_put_idpool - release numeric id from pool 2289e82cf6aSEric Van Hensbergen * @p - pool to allocate from 2299e82cf6aSEric Van Hensbergen * 2309e82cf6aSEric Van Hensbergen * XXX - This seems to be an awful generic function, should it be in idr.c with 2319e82cf6aSEric Van Hensbergen * the lock included in struct idr? 2329e82cf6aSEric Van Hensbergen */ 2339e82cf6aSEric Van Hensbergen 2349e82cf6aSEric Van Hensbergen void v9fs_put_idpool(int id, struct v9fs_idpool *p) 2359e82cf6aSEric Van Hensbergen { 2369e82cf6aSEric Van Hensbergen if (down_interruptible(&p->lock) == -EINTR) { 2379e82cf6aSEric Van Hensbergen eprintk(KERN_WARNING, "Interrupted while locking\n"); 2389e82cf6aSEric Van Hensbergen return; 2399e82cf6aSEric Van Hensbergen } 2409e82cf6aSEric Van Hensbergen idr_remove(&p->pool, id); 2419e82cf6aSEric Van Hensbergen up(&p->lock); 2429e82cf6aSEric Van Hensbergen } 2439e82cf6aSEric Van Hensbergen 2449e82cf6aSEric Van Hensbergen /** 2453cf6429aSLatchesar Ionkov * v9fs_check_idpool - check if the specified id is available 2463cf6429aSLatchesar Ionkov * @id - id to check 2473cf6429aSLatchesar Ionkov * @p - pool 2483cf6429aSLatchesar Ionkov */ 2493cf6429aSLatchesar Ionkov int v9fs_check_idpool(int id, struct v9fs_idpool *p) 2503cf6429aSLatchesar Ionkov { 2513cf6429aSLatchesar Ionkov return idr_find(&p->pool, id) != NULL; 2523cf6429aSLatchesar Ionkov } 2533cf6429aSLatchesar Ionkov 2543cf6429aSLatchesar Ionkov /** 2559e82cf6aSEric Van Hensbergen * v9fs_session_init - initialize session 2569e82cf6aSEric Van Hensbergen * @v9ses: session information structure 2579e82cf6aSEric Van Hensbergen * @dev_name: device being mounted 2589e82cf6aSEric Van Hensbergen * @data: options 2599e82cf6aSEric Van Hensbergen * 2609e82cf6aSEric Van Hensbergen */ 2619e82cf6aSEric Van Hensbergen 2629e82cf6aSEric Van Hensbergen int 2639e82cf6aSEric Van Hensbergen v9fs_session_init(struct v9fs_session_info *v9ses, 2649e82cf6aSEric Van Hensbergen const char *dev_name, char *data) 2659e82cf6aSEric Van Hensbergen { 2669e82cf6aSEric Van Hensbergen struct v9fs_fcall *fcall = NULL; 2679e82cf6aSEric Van Hensbergen struct v9fs_transport *trans_proto; 2689e82cf6aSEric Van Hensbergen int n = 0; 2699e82cf6aSEric Van Hensbergen int newfid = -1; 2709e82cf6aSEric Van Hensbergen int retval = -EINVAL; 2711dac06b2SLatchesar Ionkov struct v9fs_str *version; 2729e82cf6aSEric Van Hensbergen 2739e82cf6aSEric Van Hensbergen v9ses->name = __getname(); 2749e82cf6aSEric Van Hensbergen if (!v9ses->name) 2759e82cf6aSEric Van Hensbergen return -ENOMEM; 2769e82cf6aSEric Van Hensbergen 2779e82cf6aSEric Van Hensbergen v9ses->remotename = __getname(); 2789e82cf6aSEric Van Hensbergen if (!v9ses->remotename) { 279ce44eeb6SDavi Arnaut __putname(v9ses->name); 2809e82cf6aSEric Van Hensbergen return -ENOMEM; 2819e82cf6aSEric Van Hensbergen } 2829e82cf6aSEric Van Hensbergen 2839e82cf6aSEric Van Hensbergen strcpy(v9ses->name, V9FS_DEFUSER); 2849e82cf6aSEric Van Hensbergen strcpy(v9ses->remotename, V9FS_DEFANAME); 2859e82cf6aSEric Van Hensbergen 2869e82cf6aSEric Van Hensbergen v9fs_parse_options(data, v9ses); 2879e82cf6aSEric Van Hensbergen 2889e82cf6aSEric Van Hensbergen /* set global debug level */ 2899e82cf6aSEric Van Hensbergen v9fs_debug_level = v9ses->debug; 2909e82cf6aSEric Van Hensbergen 2914a26c242SRuss Cox /* id pools that are session-dependent: fids and tags */ 2929e82cf6aSEric Van Hensbergen idr_init(&v9ses->fidpool.pool); 2939e82cf6aSEric Van Hensbergen init_MUTEX(&v9ses->fidpool.lock); 2949e82cf6aSEric Van Hensbergen 2959e82cf6aSEric Van Hensbergen switch (v9ses->proto) { 2969e82cf6aSEric Van Hensbergen case PROTO_TCP: 2979e82cf6aSEric Van Hensbergen trans_proto = &v9fs_trans_tcp; 2989e82cf6aSEric Van Hensbergen break; 2999e82cf6aSEric Van Hensbergen case PROTO_UNIX: 3009e82cf6aSEric Van Hensbergen trans_proto = &v9fs_trans_unix; 3019e82cf6aSEric Van Hensbergen *v9ses->remotename = 0; 3029e82cf6aSEric Van Hensbergen break; 3039e82cf6aSEric Van Hensbergen case PROTO_FD: 3049e82cf6aSEric Van Hensbergen trans_proto = &v9fs_trans_fd; 3059e82cf6aSEric Van Hensbergen *v9ses->remotename = 0; 3069e82cf6aSEric Van Hensbergen break; 3079e82cf6aSEric Van Hensbergen default: 3089e82cf6aSEric Van Hensbergen printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto); 3099e82cf6aSEric Van Hensbergen retval = -ENOPROTOOPT; 3109e82cf6aSEric Van Hensbergen goto SessCleanUp; 3119e82cf6aSEric Van Hensbergen }; 3129e82cf6aSEric Van Hensbergen 313a8e63bffSLatchesar Ionkov v9ses->transport = kmalloc(sizeof(*v9ses->transport), GFP_KERNEL); 314a8e63bffSLatchesar Ionkov if (!v9ses->transport) { 315a8e63bffSLatchesar Ionkov retval = -ENOMEM; 316a8e63bffSLatchesar Ionkov goto SessCleanUp; 317a8e63bffSLatchesar Ionkov } 318a8e63bffSLatchesar Ionkov 319a8e63bffSLatchesar Ionkov memmove(v9ses->transport, trans_proto, sizeof(*v9ses->transport)); 3209e82cf6aSEric Van Hensbergen 3219e82cf6aSEric Van Hensbergen if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) { 3229e82cf6aSEric Van Hensbergen eprintk(KERN_ERR, "problem initializing transport\n"); 3239e82cf6aSEric Van Hensbergen goto SessCleanUp; 3249e82cf6aSEric Van Hensbergen } 3259e82cf6aSEric Van Hensbergen 3269e82cf6aSEric Van Hensbergen v9ses->inprogress = 0; 3279e82cf6aSEric Van Hensbergen v9ses->shutdown = 0; 3289e82cf6aSEric Van Hensbergen v9ses->session_hung = 0; 3299e82cf6aSEric Van Hensbergen 3303cf6429aSLatchesar Ionkov v9ses->mux = v9fs_mux_init(v9ses->transport, v9ses->maxdata + V9FS_IOHDRSZ, 3313cf6429aSLatchesar Ionkov &v9ses->extended); 3323cf6429aSLatchesar Ionkov 3333cf6429aSLatchesar Ionkov if (IS_ERR(v9ses->mux)) { 3343cf6429aSLatchesar Ionkov retval = PTR_ERR(v9ses->mux); 3353cf6429aSLatchesar Ionkov v9ses->mux = NULL; 3369e82cf6aSEric Van Hensbergen dprintk(DEBUG_ERROR, "problem initializing mux\n"); 3379e82cf6aSEric Van Hensbergen goto SessCleanUp; 3389e82cf6aSEric Van Hensbergen } 3399e82cf6aSEric Van Hensbergen 3409e82cf6aSEric Van Hensbergen if (v9ses->afid == ~0) { 3419e82cf6aSEric Van Hensbergen if (v9ses->extended) 3429e82cf6aSEric Van Hensbergen retval = 3439e82cf6aSEric Van Hensbergen v9fs_t_version(v9ses, v9ses->maxdata, "9P2000.u", 3449e82cf6aSEric Van Hensbergen &fcall); 3459e82cf6aSEric Van Hensbergen else 3469e82cf6aSEric Van Hensbergen retval = v9fs_t_version(v9ses, v9ses->maxdata, "9P2000", 3479e82cf6aSEric Van Hensbergen &fcall); 3489e82cf6aSEric Van Hensbergen 3499e82cf6aSEric Van Hensbergen if (retval < 0) { 3509e82cf6aSEric Van Hensbergen dprintk(DEBUG_ERROR, "v9fs_t_version failed\n"); 3519e82cf6aSEric Van Hensbergen goto FreeFcall; 3529e82cf6aSEric Van Hensbergen } 3539e82cf6aSEric Van Hensbergen 3541dac06b2SLatchesar Ionkov version = &fcall->params.rversion.version; 3551dac06b2SLatchesar Ionkov if (version->len==8 && !memcmp(version->str, "9P2000.u", 8)) { 3569e82cf6aSEric Van Hensbergen dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n"); 3579e82cf6aSEric Van Hensbergen v9ses->extended = 1; 3581dac06b2SLatchesar Ionkov } else if (version->len==6 && !memcmp(version->str, "9P2000", 6)) { 3599e82cf6aSEric Van Hensbergen dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n"); 3609e82cf6aSEric Van Hensbergen v9ses->extended = 0; 3611dac06b2SLatchesar Ionkov } else { 3621dac06b2SLatchesar Ionkov retval = -EREMOTEIO; 3631dac06b2SLatchesar Ionkov goto FreeFcall; 3649e82cf6aSEric Van Hensbergen } 3659e82cf6aSEric Van Hensbergen 3669e82cf6aSEric Van Hensbergen n = fcall->params.rversion.msize; 3679e82cf6aSEric Van Hensbergen kfree(fcall); 3689e82cf6aSEric Van Hensbergen 3699e82cf6aSEric Van Hensbergen if (n < v9ses->maxdata) 3709e82cf6aSEric Van Hensbergen v9ses->maxdata = n; 3719e82cf6aSEric Van Hensbergen } 3729e82cf6aSEric Van Hensbergen 3739e82cf6aSEric Van Hensbergen newfid = v9fs_get_idpool(&v9ses->fidpool); 3749e82cf6aSEric Van Hensbergen if (newfid < 0) { 3759e82cf6aSEric Van Hensbergen eprintk(KERN_WARNING, "couldn't allocate FID\n"); 3769e82cf6aSEric Van Hensbergen retval = -ENOMEM; 3779e82cf6aSEric Van Hensbergen goto SessCleanUp; 3789e82cf6aSEric Van Hensbergen } 3799e82cf6aSEric Van Hensbergen /* it is a little bit ugly, but we have to prevent newfid */ 3809e82cf6aSEric Van Hensbergen /* being the same as afid, so if it is, get a new fid */ 3819e82cf6aSEric Van Hensbergen if (v9ses->afid != ~0 && newfid == v9ses->afid) { 3829e82cf6aSEric Van Hensbergen newfid = v9fs_get_idpool(&v9ses->fidpool); 3839e82cf6aSEric Van Hensbergen if (newfid < 0) { 3849e82cf6aSEric Van Hensbergen eprintk(KERN_WARNING, "couldn't allocate FID\n"); 3859e82cf6aSEric Van Hensbergen retval = -ENOMEM; 3869e82cf6aSEric Van Hensbergen goto SessCleanUp; 3879e82cf6aSEric Van Hensbergen } 3889e82cf6aSEric Van Hensbergen } 3899e82cf6aSEric Van Hensbergen 3909e82cf6aSEric Van Hensbergen if ((retval = 3919e82cf6aSEric Van Hensbergen v9fs_t_attach(v9ses, v9ses->name, v9ses->remotename, newfid, 3929e82cf6aSEric Van Hensbergen v9ses->afid, NULL)) 3939e82cf6aSEric Van Hensbergen < 0) { 3949e82cf6aSEric Van Hensbergen dprintk(DEBUG_ERROR, "cannot attach\n"); 3959e82cf6aSEric Van Hensbergen goto SessCleanUp; 3969e82cf6aSEric Van Hensbergen } 3979e82cf6aSEric Van Hensbergen 3989e82cf6aSEric Van Hensbergen if (v9ses->afid != ~0) { 39946f6dac2SEric Van Hensbergen dprintk(DEBUG_ERROR, "afid not equal to ~0\n"); 4003cf6429aSLatchesar Ionkov if (v9fs_t_clunk(v9ses, v9ses->afid)) 4019e82cf6aSEric Van Hensbergen dprintk(DEBUG_ERROR, "clunk failed\n"); 4029e82cf6aSEric Van Hensbergen } 4039e82cf6aSEric Van Hensbergen 4049e82cf6aSEric Van Hensbergen return newfid; 4059e82cf6aSEric Van Hensbergen 4069e82cf6aSEric Van Hensbergen FreeFcall: 4079e82cf6aSEric Van Hensbergen kfree(fcall); 4089e82cf6aSEric Van Hensbergen 4099e82cf6aSEric Van Hensbergen SessCleanUp: 4109e82cf6aSEric Van Hensbergen v9fs_session_close(v9ses); 4119e82cf6aSEric Van Hensbergen return retval; 4129e82cf6aSEric Van Hensbergen } 4139e82cf6aSEric Van Hensbergen 4149e82cf6aSEric Van Hensbergen /** 4159e82cf6aSEric Van Hensbergen * v9fs_session_close - shutdown a session 4169e82cf6aSEric Van Hensbergen * @v9ses: session information structure 4179e82cf6aSEric Van Hensbergen * 4189e82cf6aSEric Van Hensbergen */ 4199e82cf6aSEric Van Hensbergen 4209e82cf6aSEric Van Hensbergen void v9fs_session_close(struct v9fs_session_info *v9ses) 4219e82cf6aSEric Van Hensbergen { 4223cf6429aSLatchesar Ionkov if (v9ses->mux) { 4233cf6429aSLatchesar Ionkov v9fs_mux_destroy(v9ses->mux); 4243cf6429aSLatchesar Ionkov v9ses->mux = NULL; 4259e82cf6aSEric Van Hensbergen } 4269e82cf6aSEric Van Hensbergen 4273cf6429aSLatchesar Ionkov if (v9ses->transport) { 4289e82cf6aSEric Van Hensbergen v9ses->transport->close(v9ses->transport); 4293cf6429aSLatchesar Ionkov kfree(v9ses->transport); 4303cf6429aSLatchesar Ionkov v9ses->transport = NULL; 4313cf6429aSLatchesar Ionkov } 4329e82cf6aSEric Van Hensbergen 433ce44eeb6SDavi Arnaut __putname(v9ses->name); 434ce44eeb6SDavi Arnaut __putname(v9ses->remotename); 4359e82cf6aSEric Van Hensbergen } 4369e82cf6aSEric Van Hensbergen 437322b329aSEric Van Hensbergen /** 438322b329aSEric Van Hensbergen * v9fs_session_cancel - mark transport as disconnected 439322b329aSEric Van Hensbergen * and cancel all pending requests. 440322b329aSEric Van Hensbergen */ 441322b329aSEric Van Hensbergen void v9fs_session_cancel(struct v9fs_session_info *v9ses) { 4423cf6429aSLatchesar Ionkov dprintk(DEBUG_ERROR, "cancel session %p\n", v9ses); 443322b329aSEric Van Hensbergen v9ses->transport->status = Disconnected; 4443cf6429aSLatchesar Ionkov v9fs_mux_cancel(v9ses->mux, -EIO); 445322b329aSEric Van Hensbergen } 446322b329aSEric Van Hensbergen 4479e82cf6aSEric Van Hensbergen extern int v9fs_error_init(void); 4489e82cf6aSEric Van Hensbergen 4499e82cf6aSEric Van Hensbergen /** 4509e82cf6aSEric Van Hensbergen * v9fs_init - Initialize module 4519e82cf6aSEric Van Hensbergen * 4529e82cf6aSEric Van Hensbergen */ 4539e82cf6aSEric Van Hensbergen 4549e82cf6aSEric Van Hensbergen static int __init init_v9fs(void) 4559e82cf6aSEric Van Hensbergen { 4561dac06b2SLatchesar Ionkov int ret; 4571dac06b2SLatchesar Ionkov 4589e82cf6aSEric Van Hensbergen v9fs_error_init(); 4599e82cf6aSEric Van Hensbergen 460f94b3470SEric Van Hensbergen printk(KERN_INFO "Installing v9fs 9p2000 file system support\n"); 4619e82cf6aSEric Van Hensbergen 4621dac06b2SLatchesar Ionkov ret = v9fs_mux_global_init(); 463f94b3470SEric Van Hensbergen if (ret) { 464f94b3470SEric Van Hensbergen printk(KERN_WARNING "v9fs: starting mux failed\n"); 465d826380bSAlexey Dobriyan return ret; 466f94b3470SEric Van Hensbergen } 4671dac06b2SLatchesar Ionkov ret = register_filesystem(&v9fs_fs_type); 468f94b3470SEric Van Hensbergen if (ret) { 469f94b3470SEric Van Hensbergen printk(KERN_WARNING "v9fs: registering file system failed\n"); 470d826380bSAlexey Dobriyan v9fs_mux_global_exit(); 471f94b3470SEric Van Hensbergen } 472f94b3470SEric Van Hensbergen 4731dac06b2SLatchesar Ionkov return ret; 4749e82cf6aSEric Van Hensbergen } 4759e82cf6aSEric Van Hensbergen 4769e82cf6aSEric Van Hensbergen /** 4779e82cf6aSEric Van Hensbergen * v9fs_init - shutdown module 4789e82cf6aSEric Van Hensbergen * 4799e82cf6aSEric Van Hensbergen */ 4809e82cf6aSEric Van Hensbergen 4819e82cf6aSEric Van Hensbergen static void __exit exit_v9fs(void) 4829e82cf6aSEric Van Hensbergen { 4833cf6429aSLatchesar Ionkov v9fs_mux_global_exit(); 4849e82cf6aSEric Van Hensbergen unregister_filesystem(&v9fs_fs_type); 4859e82cf6aSEric Van Hensbergen } 4869e82cf6aSEric Van Hensbergen 4879e82cf6aSEric Van Hensbergen module_init(init_v9fs) 4889e82cf6aSEric Van Hensbergen module_exit(exit_v9fs) 4899e82cf6aSEric Van Hensbergen 4909e82cf6aSEric Van Hensbergen MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); 4919e82cf6aSEric Van Hensbergen MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>"); 4929e82cf6aSEric Van Hensbergen MODULE_LICENSE("GPL"); 493