| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  *  linux/fs/9p/v9fs.c | 
 | 3 |  * | 
 | 4 |  *  This file contains functions assisting in mapping VFS to 9P2000 | 
 | 5 |  * | 
 | 6 |  *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> | 
 | 7 |  *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> | 
 | 8 |  * | 
 | 9 |  *  This program is free software; you can redistribute it and/or modify | 
| Eric Van Hensbergen | 42e8c50 | 2006-03-25 03:07:28 -0800 | [diff] [blame] | 10 |  *  it under the terms of the GNU General Public License version 2 | 
 | 11 |  *  as published by the Free Software Foundation. | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 12 |  * | 
 | 13 |  *  This program is distributed in the hope that it will be useful, | 
 | 14 |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 15 |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 | 16 |  *  GNU General Public License for more details. | 
 | 17 |  * | 
 | 18 |  *  You should have received a copy of the GNU General Public License | 
 | 19 |  *  along with this program; if not, write to: | 
 | 20 |  *  Free Software Foundation | 
 | 21 |  *  51 Franklin Street, Fifth Floor | 
 | 22 |  *  Boston, MA  02111-1301  USA | 
 | 23 |  * | 
 | 24 |  */ | 
 | 25 |  | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 26 | #include <linux/module.h> | 
 | 27 | #include <linux/errno.h> | 
 | 28 | #include <linux/fs.h> | 
| Al Viro | 914e263 | 2006-10-18 13:55:46 -0400 | [diff] [blame] | 29 | #include <linux/sched.h> | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 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" | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 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) | 
 | 45 |   * | 
 | 46 |   */ | 
 | 47 |  | 
 | 48 | enum { | 
 | 49 | 	/* Options that take integer arguments */ | 
 | 50 | 	Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, Opt_debug, | 
 | 51 | 	Opt_rfdno, Opt_wfdno, | 
 | 52 | 	/* String options */ | 
| Eric Van Hensbergen | 67543e5 | 2006-03-25 03:07:29 -0800 | [diff] [blame] | 53 | 	Opt_uname, Opt_remotename, | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 54 | 	/* Options that take no arguments */ | 
 | 55 | 	Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, | 
 | 56 | 	/* Error token */ | 
 | 57 | 	Opt_err | 
 | 58 | }; | 
 | 59 |  | 
 | 60 | static match_table_t tokens = { | 
 | 61 | 	{Opt_port, "port=%u"}, | 
 | 62 | 	{Opt_msize, "msize=%u"}, | 
 | 63 | 	{Opt_uid, "uid=%u"}, | 
 | 64 | 	{Opt_gid, "gid=%u"}, | 
 | 65 | 	{Opt_afid, "afid=%u"}, | 
 | 66 | 	{Opt_rfdno, "rfdno=%u"}, | 
 | 67 | 	{Opt_wfdno, "wfdno=%u"}, | 
| Eric Van Hensbergen | e1c9211 | 2006-02-20 18:28:05 -0800 | [diff] [blame] | 68 | 	{Opt_debug, "debug=%x"}, | 
| Eric Van Hensbergen | 67543e5 | 2006-03-25 03:07:29 -0800 | [diff] [blame] | 69 | 	{Opt_uname, "uname=%s"}, | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 70 | 	{Opt_remotename, "aname=%s"}, | 
 | 71 | 	{Opt_unix, "proto=unix"}, | 
 | 72 | 	{Opt_tcp, "proto=tcp"}, | 
 | 73 | 	{Opt_fd, "proto=fd"}, | 
 | 74 | 	{Opt_tcp, "tcp"}, | 
 | 75 | 	{Opt_unix, "unix"}, | 
 | 76 | 	{Opt_fd, "fd"}, | 
 | 77 | 	{Opt_legacy, "noextend"}, | 
 | 78 | 	{Opt_nodevmap, "nodevmap"}, | 
 | 79 | 	{Opt_err, NULL} | 
 | 80 | }; | 
 | 81 |  | 
 | 82 | /* | 
 | 83 |  *  Parse option string. | 
 | 84 |  */ | 
 | 85 |  | 
 | 86 | /** | 
 | 87 |  * v9fs_parse_options - parse mount options into session structure | 
 | 88 |  * @options: options string passed from mount | 
 | 89 |  * @v9ses: existing v9fs session information | 
 | 90 |  * | 
 | 91 |  */ | 
 | 92 |  | 
 | 93 | static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) | 
 | 94 | { | 
 | 95 | 	char *p; | 
 | 96 | 	substring_t args[MAX_OPT_ARGS]; | 
 | 97 | 	int option; | 
 | 98 | 	int ret; | 
 | 99 |  | 
 | 100 | 	/* setup defaults */ | 
 | 101 | 	v9ses->port = V9FS_PORT; | 
 | 102 | 	v9ses->maxdata = 9000; | 
 | 103 | 	v9ses->proto = PROTO_TCP; | 
 | 104 | 	v9ses->extended = 1; | 
 | 105 | 	v9ses->afid = ~0; | 
 | 106 | 	v9ses->debug = 0; | 
 | 107 | 	v9ses->rfdno = ~0; | 
 | 108 | 	v9ses->wfdno = ~0; | 
 | 109 |  | 
 | 110 | 	if (!options) | 
 | 111 | 		return; | 
 | 112 |  | 
 | 113 | 	while ((p = strsep(&options, ",")) != NULL) { | 
 | 114 | 		int token; | 
 | 115 | 		if (!*p) | 
 | 116 | 			continue; | 
 | 117 | 		token = match_token(p, tokens, args); | 
| Eric Van Hensbergen | 67543e5 | 2006-03-25 03:07:29 -0800 | [diff] [blame] | 118 | 		if (token < Opt_uname) { | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 119 | 			if ((ret = match_int(&args[0], &option)) < 0) { | 
 | 120 | 				dprintk(DEBUG_ERROR, | 
 | 121 | 					"integer field, but no integer?\n"); | 
 | 122 | 				continue; | 
 | 123 | 			} | 
 | 124 |  | 
 | 125 | 		} | 
 | 126 | 		switch (token) { | 
 | 127 | 		case Opt_port: | 
 | 128 | 			v9ses->port = option; | 
 | 129 | 			break; | 
 | 130 | 		case Opt_msize: | 
 | 131 | 			v9ses->maxdata = option; | 
 | 132 | 			break; | 
 | 133 | 		case Opt_uid: | 
 | 134 | 			v9ses->uid = option; | 
 | 135 | 			break; | 
 | 136 | 		case Opt_gid: | 
 | 137 | 			v9ses->gid = option; | 
 | 138 | 			break; | 
 | 139 | 		case Opt_afid: | 
 | 140 | 			v9ses->afid = option; | 
 | 141 | 			break; | 
 | 142 | 		case Opt_rfdno: | 
 | 143 | 			v9ses->rfdno = option; | 
 | 144 | 			break; | 
 | 145 | 		case Opt_wfdno: | 
 | 146 | 			v9ses->wfdno = option; | 
 | 147 | 			break; | 
 | 148 | 		case Opt_debug: | 
 | 149 | 			v9ses->debug = option; | 
 | 150 | 			break; | 
 | 151 | 		case Opt_tcp: | 
 | 152 | 			v9ses->proto = PROTO_TCP; | 
 | 153 | 			break; | 
 | 154 | 		case Opt_unix: | 
 | 155 | 			v9ses->proto = PROTO_UNIX; | 
 | 156 | 			break; | 
 | 157 | 		case Opt_fd: | 
 | 158 | 			v9ses->proto = PROTO_FD; | 
 | 159 | 			break; | 
| Eric Van Hensbergen | 67543e5 | 2006-03-25 03:07:29 -0800 | [diff] [blame] | 160 | 		case Opt_uname: | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 161 | 			match_strcpy(v9ses->name, &args[0]); | 
 | 162 | 			break; | 
 | 163 | 		case Opt_remotename: | 
 | 164 | 			match_strcpy(v9ses->remotename, &args[0]); | 
 | 165 | 			break; | 
 | 166 | 		case Opt_legacy: | 
 | 167 | 			v9ses->extended = 0; | 
 | 168 | 			break; | 
 | 169 | 		case Opt_nodevmap: | 
 | 170 | 			v9ses->nodev = 1; | 
 | 171 | 			break; | 
 | 172 | 		default: | 
 | 173 | 			continue; | 
 | 174 | 		} | 
 | 175 | 	} | 
 | 176 | } | 
 | 177 |  | 
 | 178 | /** | 
 | 179 |  * v9fs_inode2v9ses - safely extract v9fs session info from super block | 
 | 180 |  * @inode: inode to extract information from | 
 | 181 |  * | 
 | 182 |  * Paranoid function to extract v9ses information from superblock, | 
 | 183 |  * if anything is missing it will report an error. | 
 | 184 |  * | 
 | 185 |  */ | 
 | 186 |  | 
 | 187 | struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) | 
 | 188 | { | 
 | 189 | 	return (inode->i_sb->s_fs_info); | 
 | 190 | } | 
 | 191 |  | 
 | 192 | /** | 
 | 193 |  * v9fs_get_idpool - allocate numeric id from pool | 
 | 194 |  * @p - pool to allocate from | 
 | 195 |  * | 
 | 196 |  * XXX - This seems to be an awful generic function, should it be in idr.c with | 
 | 197 |  *            the lock included in struct idr? | 
 | 198 |  */ | 
 | 199 |  | 
 | 200 | int v9fs_get_idpool(struct v9fs_idpool *p) | 
 | 201 | { | 
 | 202 | 	int i = 0; | 
 | 203 | 	int error; | 
 | 204 |  | 
 | 205 | retry: | 
 | 206 | 	if (idr_pre_get(&p->pool, GFP_KERNEL) == 0) | 
 | 207 | 		return 0; | 
 | 208 |  | 
 | 209 | 	if (down_interruptible(&p->lock) == -EINTR) { | 
 | 210 | 		eprintk(KERN_WARNING, "Interrupted while locking\n"); | 
 | 211 | 		return -1; | 
 | 212 | 	} | 
 | 213 |  | 
| Latchesar Ionkov | 3cf6429 | 2006-01-08 01:04:58 -0800 | [diff] [blame] | 214 | 	/* no need to store exactly p, we just need something non-null */ | 
 | 215 | 	error = idr_get_new(&p->pool, p, &i); | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 216 | 	up(&p->lock); | 
 | 217 |  | 
 | 218 | 	if (error == -EAGAIN) | 
 | 219 | 		goto retry; | 
 | 220 | 	else if (error) | 
 | 221 | 		return -1; | 
 | 222 |  | 
 | 223 | 	return i; | 
 | 224 | } | 
 | 225 |  | 
 | 226 | /** | 
 | 227 |  * v9fs_put_idpool - release numeric id from pool | 
 | 228 |  * @p - pool to allocate from | 
 | 229 |  * | 
 | 230 |  * XXX - This seems to be an awful generic function, should it be in idr.c with | 
 | 231 |  *            the lock included in struct idr? | 
 | 232 |  */ | 
 | 233 |  | 
 | 234 | void v9fs_put_idpool(int id, struct v9fs_idpool *p) | 
 | 235 | { | 
 | 236 | 	if (down_interruptible(&p->lock) == -EINTR) { | 
 | 237 | 		eprintk(KERN_WARNING, "Interrupted while locking\n"); | 
 | 238 | 		return; | 
 | 239 | 	} | 
 | 240 | 	idr_remove(&p->pool, id); | 
 | 241 | 	up(&p->lock); | 
 | 242 | } | 
 | 243 |  | 
 | 244 | /** | 
| Latchesar Ionkov | 3cf6429 | 2006-01-08 01:04:58 -0800 | [diff] [blame] | 245 |  * v9fs_check_idpool - check if the specified id is available | 
 | 246 |  * @id - id to check | 
 | 247 |  * @p - pool | 
 | 248 |  */ | 
 | 249 | int v9fs_check_idpool(int id, struct v9fs_idpool *p) | 
 | 250 | { | 
 | 251 | 	return idr_find(&p->pool, id) != NULL; | 
 | 252 | } | 
 | 253 |  | 
 | 254 | /** | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 255 |  * v9fs_session_init - initialize session | 
 | 256 |  * @v9ses: session information structure | 
 | 257 |  * @dev_name: device being mounted | 
 | 258 |  * @data: options | 
 | 259 |  * | 
 | 260 |  */ | 
 | 261 |  | 
 | 262 | int | 
 | 263 | v9fs_session_init(struct v9fs_session_info *v9ses, | 
 | 264 | 		  const char *dev_name, char *data) | 
 | 265 | { | 
 | 266 | 	struct v9fs_fcall *fcall = NULL; | 
 | 267 | 	struct v9fs_transport *trans_proto; | 
 | 268 | 	int n = 0; | 
 | 269 | 	int newfid = -1; | 
 | 270 | 	int retval = -EINVAL; | 
| Latchesar Ionkov | 1dac06b | 2006-01-08 01:05:02 -0800 | [diff] [blame] | 271 | 	struct v9fs_str *version; | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 272 |  | 
 | 273 | 	v9ses->name = __getname(); | 
 | 274 | 	if (!v9ses->name) | 
 | 275 | 		return -ENOMEM; | 
 | 276 |  | 
 | 277 | 	v9ses->remotename = __getname(); | 
 | 278 | 	if (!v9ses->remotename) { | 
| Davi Arnaut | ce44eeb | 2005-11-07 00:59:36 -0800 | [diff] [blame] | 279 | 		__putname(v9ses->name); | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 280 | 		return -ENOMEM; | 
 | 281 | 	} | 
 | 282 |  | 
 | 283 | 	strcpy(v9ses->name, V9FS_DEFUSER); | 
 | 284 | 	strcpy(v9ses->remotename, V9FS_DEFANAME); | 
 | 285 |  | 
 | 286 | 	v9fs_parse_options(data, v9ses); | 
 | 287 |  | 
 | 288 | 	/* set global debug level */ | 
 | 289 | 	v9fs_debug_level = v9ses->debug; | 
 | 290 |  | 
| Russ Cox | 4a26c24 | 2006-03-25 03:07:24 -0800 | [diff] [blame] | 291 | 	/* id pools that are session-dependent: fids and tags */ | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 292 | 	idr_init(&v9ses->fidpool.pool); | 
 | 293 | 	init_MUTEX(&v9ses->fidpool.lock); | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 294 |  | 
 | 295 | 	switch (v9ses->proto) { | 
 | 296 | 	case PROTO_TCP: | 
 | 297 | 		trans_proto = &v9fs_trans_tcp; | 
 | 298 | 		break; | 
 | 299 | 	case PROTO_UNIX: | 
 | 300 | 		trans_proto = &v9fs_trans_unix; | 
 | 301 | 		*v9ses->remotename = 0; | 
 | 302 | 		break; | 
 | 303 | 	case PROTO_FD: | 
 | 304 | 		trans_proto = &v9fs_trans_fd; | 
 | 305 | 		*v9ses->remotename = 0; | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 306 | 		break; | 
 | 307 | 	default: | 
 | 308 | 		printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto); | 
 | 309 | 		retval = -ENOPROTOOPT; | 
 | 310 | 		goto SessCleanUp; | 
 | 311 | 	}; | 
 | 312 |  | 
| Latchesar Ionkov | a8e63bf | 2005-09-22 21:43:51 -0700 | [diff] [blame] | 313 | 	v9ses->transport = kmalloc(sizeof(*v9ses->transport), GFP_KERNEL); | 
 | 314 | 	if (!v9ses->transport) { | 
 | 315 | 		retval = -ENOMEM; | 
 | 316 | 		goto SessCleanUp; | 
 | 317 | 	} | 
 | 318 |  | 
 | 319 | 	memmove(v9ses->transport, trans_proto, sizeof(*v9ses->transport)); | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 320 |  | 
 | 321 | 	if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) { | 
 | 322 | 		eprintk(KERN_ERR, "problem initializing transport\n"); | 
 | 323 | 		goto SessCleanUp; | 
 | 324 | 	} | 
 | 325 |  | 
 | 326 | 	v9ses->inprogress = 0; | 
 | 327 | 	v9ses->shutdown = 0; | 
 | 328 | 	v9ses->session_hung = 0; | 
 | 329 |  | 
| Latchesar Ionkov | 3cf6429 | 2006-01-08 01:04:58 -0800 | [diff] [blame] | 330 | 	v9ses->mux = v9fs_mux_init(v9ses->transport, v9ses->maxdata + V9FS_IOHDRSZ, | 
 | 331 | 		&v9ses->extended); | 
 | 332 |  | 
 | 333 | 	if (IS_ERR(v9ses->mux)) { | 
 | 334 | 		retval = PTR_ERR(v9ses->mux); | 
 | 335 | 		v9ses->mux = NULL; | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 336 | 		dprintk(DEBUG_ERROR, "problem initializing mux\n"); | 
 | 337 | 		goto SessCleanUp; | 
 | 338 | 	} | 
 | 339 |  | 
 | 340 | 	if (v9ses->afid == ~0) { | 
 | 341 | 		if (v9ses->extended) | 
 | 342 | 			retval = | 
 | 343 | 			    v9fs_t_version(v9ses, v9ses->maxdata, "9P2000.u", | 
 | 344 | 					   &fcall); | 
 | 345 | 		else | 
 | 346 | 			retval = v9fs_t_version(v9ses, v9ses->maxdata, "9P2000", | 
 | 347 | 						&fcall); | 
 | 348 |  | 
 | 349 | 		if (retval < 0) { | 
 | 350 | 			dprintk(DEBUG_ERROR, "v9fs_t_version failed\n"); | 
 | 351 | 			goto FreeFcall; | 
 | 352 | 		} | 
 | 353 |  | 
| Latchesar Ionkov | 1dac06b | 2006-01-08 01:05:02 -0800 | [diff] [blame] | 354 | 		version = &fcall->params.rversion.version; | 
 | 355 | 		if (version->len==8 && !memcmp(version->str, "9P2000.u", 8)) { | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 356 | 			dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n"); | 
 | 357 | 			v9ses->extended = 1; | 
| Latchesar Ionkov | 1dac06b | 2006-01-08 01:05:02 -0800 | [diff] [blame] | 358 | 		} else if (version->len==6 && !memcmp(version->str, "9P2000", 6)) { | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 359 | 			dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n"); | 
 | 360 | 			v9ses->extended = 0; | 
| Latchesar Ionkov | 1dac06b | 2006-01-08 01:05:02 -0800 | [diff] [blame] | 361 | 		} else { | 
 | 362 | 			retval = -EREMOTEIO; | 
 | 363 | 			goto FreeFcall; | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 364 | 		} | 
 | 365 |  | 
 | 366 | 		n = fcall->params.rversion.msize; | 
 | 367 | 		kfree(fcall); | 
 | 368 |  | 
 | 369 | 		if (n < v9ses->maxdata) | 
 | 370 | 			v9ses->maxdata = n; | 
 | 371 | 	} | 
 | 372 |  | 
 | 373 | 	newfid = v9fs_get_idpool(&v9ses->fidpool); | 
 | 374 | 	if (newfid < 0) { | 
 | 375 | 		eprintk(KERN_WARNING, "couldn't allocate FID\n"); | 
 | 376 | 		retval = -ENOMEM; | 
 | 377 | 		goto SessCleanUp; | 
 | 378 | 	} | 
 | 379 | 	/* it is a little bit ugly, but we have to prevent newfid */ | 
 | 380 | 	/* being the same as afid, so if it is, get a new fid     */ | 
 | 381 | 	if (v9ses->afid != ~0 && newfid == v9ses->afid) { | 
 | 382 | 		newfid = v9fs_get_idpool(&v9ses->fidpool); | 
 | 383 | 		if (newfid < 0) { | 
 | 384 | 			eprintk(KERN_WARNING, "couldn't allocate FID\n"); | 
 | 385 | 			retval = -ENOMEM; | 
 | 386 | 			goto SessCleanUp; | 
 | 387 | 		} | 
 | 388 | 	} | 
 | 389 |  | 
 | 390 | 	if ((retval = | 
 | 391 | 	     v9fs_t_attach(v9ses, v9ses->name, v9ses->remotename, newfid, | 
 | 392 | 			   v9ses->afid, NULL)) | 
 | 393 | 	    < 0) { | 
 | 394 | 		dprintk(DEBUG_ERROR, "cannot attach\n"); | 
 | 395 | 		goto SessCleanUp; | 
 | 396 | 	} | 
 | 397 |  | 
 | 398 | 	if (v9ses->afid != ~0) { | 
| Eric Van Hensbergen | 46f6dac | 2006-03-02 02:54:33 -0800 | [diff] [blame] | 399 | 		dprintk(DEBUG_ERROR, "afid not equal to ~0\n"); | 
| Latchesar Ionkov | 3cf6429 | 2006-01-08 01:04:58 -0800 | [diff] [blame] | 400 | 		if (v9fs_t_clunk(v9ses, v9ses->afid)) | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 401 | 			dprintk(DEBUG_ERROR, "clunk failed\n"); | 
 | 402 | 	} | 
 | 403 |  | 
 | 404 | 	return newfid; | 
 | 405 |  | 
 | 406 |       FreeFcall: | 
 | 407 | 	kfree(fcall); | 
 | 408 |  | 
 | 409 |       SessCleanUp: | 
 | 410 | 	v9fs_session_close(v9ses); | 
 | 411 | 	return retval; | 
 | 412 | } | 
 | 413 |  | 
 | 414 | /** | 
 | 415 |  * v9fs_session_close - shutdown a session | 
 | 416 |  * @v9ses: session information structure | 
 | 417 |  * | 
 | 418 |  */ | 
 | 419 |  | 
 | 420 | void v9fs_session_close(struct v9fs_session_info *v9ses) | 
 | 421 | { | 
| Latchesar Ionkov | 3cf6429 | 2006-01-08 01:04:58 -0800 | [diff] [blame] | 422 | 	if (v9ses->mux) { | 
 | 423 | 		v9fs_mux_destroy(v9ses->mux); | 
 | 424 | 		v9ses->mux = NULL; | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 425 | 	} | 
 | 426 |  | 
| Latchesar Ionkov | 3cf6429 | 2006-01-08 01:04:58 -0800 | [diff] [blame] | 427 | 	if (v9ses->transport) { | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 428 | 		v9ses->transport->close(v9ses->transport); | 
| Latchesar Ionkov | 3cf6429 | 2006-01-08 01:04:58 -0800 | [diff] [blame] | 429 | 		kfree(v9ses->transport); | 
 | 430 | 		v9ses->transport = NULL; | 
 | 431 | 	} | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 432 |  | 
| Davi Arnaut | ce44eeb | 2005-11-07 00:59:36 -0800 | [diff] [blame] | 433 | 	__putname(v9ses->name); | 
 | 434 | 	__putname(v9ses->remotename); | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 435 | } | 
 | 436 |  | 
| Eric Van Hensbergen | 322b329 | 2005-09-09 13:04:23 -0700 | [diff] [blame] | 437 | /** | 
 | 438 |  * v9fs_session_cancel - mark transport as disconnected | 
 | 439 |  * 	and cancel all pending requests. | 
 | 440 |  */ | 
 | 441 | void v9fs_session_cancel(struct v9fs_session_info *v9ses) { | 
| Latchesar Ionkov | 3cf6429 | 2006-01-08 01:04:58 -0800 | [diff] [blame] | 442 | 	dprintk(DEBUG_ERROR, "cancel session %p\n", v9ses); | 
| Eric Van Hensbergen | 322b329 | 2005-09-09 13:04:23 -0700 | [diff] [blame] | 443 | 	v9ses->transport->status = Disconnected; | 
| Latchesar Ionkov | 3cf6429 | 2006-01-08 01:04:58 -0800 | [diff] [blame] | 444 | 	v9fs_mux_cancel(v9ses->mux, -EIO); | 
| Eric Van Hensbergen | 322b329 | 2005-09-09 13:04:23 -0700 | [diff] [blame] | 445 | } | 
 | 446 |  | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 447 | extern int v9fs_error_init(void); | 
 | 448 |  | 
 | 449 | /** | 
 | 450 |  * v9fs_init - Initialize module | 
 | 451 |  * | 
 | 452 |  */ | 
 | 453 |  | 
 | 454 | static int __init init_v9fs(void) | 
 | 455 | { | 
| Latchesar Ionkov | 1dac06b | 2006-01-08 01:05:02 -0800 | [diff] [blame] | 456 | 	int ret; | 
 | 457 |  | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 458 | 	v9fs_error_init(); | 
 | 459 |  | 
 | 460 | 	printk(KERN_INFO "Installing v9fs 9P2000 file system support\n"); | 
 | 461 |  | 
| Latchesar Ionkov | 1dac06b | 2006-01-08 01:05:02 -0800 | [diff] [blame] | 462 | 	ret = v9fs_mux_global_init(); | 
 | 463 | 	if (!ret) | 
| Alexey Dobriyan | d826380 | 2006-09-29 02:01:06 -0700 | [diff] [blame] | 464 | 		return ret; | 
 | 465 | 	ret = register_filesystem(&v9fs_fs_type); | 
 | 466 | 	if (!ret) | 
 | 467 | 		v9fs_mux_global_exit(); | 
| Latchesar Ionkov | 1dac06b | 2006-01-08 01:05:02 -0800 | [diff] [blame] | 468 | 	return ret; | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 469 | } | 
 | 470 |  | 
 | 471 | /** | 
 | 472 |  * v9fs_init - shutdown module | 
 | 473 |  * | 
 | 474 |  */ | 
 | 475 |  | 
 | 476 | static void __exit exit_v9fs(void) | 
 | 477 | { | 
| Latchesar Ionkov | 3cf6429 | 2006-01-08 01:04:58 -0800 | [diff] [blame] | 478 | 	v9fs_mux_global_exit(); | 
| Eric Van Hensbergen | 9e82cf6 | 2005-09-09 13:04:20 -0700 | [diff] [blame] | 479 | 	unregister_filesystem(&v9fs_fs_type); | 
 | 480 | } | 
 | 481 |  | 
 | 482 | module_init(init_v9fs) | 
 | 483 | module_exit(exit_v9fs) | 
 | 484 |  | 
 | 485 | MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); | 
 | 486 | MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>"); | 
 | 487 | MODULE_LICENSE("GPL"); |