xref: /openbmc/linux/fs/9p/v9fs.c (revision b4caecd4)
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  *
68a0dc95fSEric Van Hensbergen  *  Copyright (C) 2004-2008 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 
265d385153SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
275d385153SJoe Perches 
289e82cf6aSEric Van Hensbergen #include <linux/module.h>
299e82cf6aSEric Van Hensbergen #include <linux/errno.h>
309e82cf6aSEric Van Hensbergen #include <linux/fs.h>
31914e2637SAl Viro #include <linux/sched.h>
329e82cf6aSEric Van Hensbergen #include <linux/parser.h>
339e82cf6aSEric Van Hensbergen #include <linux/idr.h>
345a0e3ad6STejun Heo #include <linux/slab.h>
35bd238fb4SLatchesar Ionkov #include <net/9p/9p.h>
36bd238fb4SLatchesar Ionkov #include <net/9p/client.h>
378b81ef58SEric Van Hensbergen #include <net/9p/transport.h>
389e82cf6aSEric Van Hensbergen #include "v9fs.h"
399e82cf6aSEric Van Hensbergen #include "v9fs_vfs.h"
4060e78d2cSAbhishek Kulkarni #include "cache.h"
4160e78d2cSAbhishek Kulkarni 
4260e78d2cSAbhishek Kulkarni static DEFINE_SPINLOCK(v9fs_sessionlist_lock);
4360e78d2cSAbhishek Kulkarni static LIST_HEAD(v9fs_sessionlist);
44a78ce05dSAneesh Kumar K.V struct kmem_cache *v9fs_inode_cache;
459e82cf6aSEric Van Hensbergen 
469e82cf6aSEric Van Hensbergen /*
47a80d923eSEric Van Hensbergen  * Option Parsing (code inspired by NFS code)
48a80d923eSEric Van Hensbergen  *  NOTE: each transport will parse its own options
49a80d923eSEric Van Hensbergen  */
50a80d923eSEric Van Hensbergen 
519e82cf6aSEric Van Hensbergen enum {
529e82cf6aSEric Van Hensbergen 	/* Options that take integer arguments */
538a0dc95fSEric Van Hensbergen 	Opt_debug, Opt_dfltuid, Opt_dfltgid, Opt_afid,
549e82cf6aSEric Van Hensbergen 	/* String options */
5560e78d2cSAbhishek Kulkarni 	Opt_uname, Opt_remotename, Opt_trans, Opt_cache, Opt_cachetag,
569e82cf6aSEric Van Hensbergen 	/* Options that take no arguments */
578a0dc95fSEric Van Hensbergen 	Opt_nodevmap,
58e03abc0cSEric Van Hensbergen 	/* Cache options */
59fb89b45cSDominique Martinet 	Opt_cache_loose, Opt_fscache, Opt_mmap,
60ba17674fSLatchesar Ionkov 	/* Access options */
61e782ef71SVenkateswararao Jujjuri (JV) 	Opt_access, Opt_posixacl,
629e82cf6aSEric Van Hensbergen 	/* Error token */
639e82cf6aSEric Van Hensbergen 	Opt_err
649e82cf6aSEric Van Hensbergen };
659e82cf6aSEric Van Hensbergen 
66a447c093SSteven Whitehouse static const match_table_t tokens = {
679e2f6688SEric Van Hensbergen 	{Opt_debug, "debug=%x"},
68bd32b82dSLatchesar Ionkov 	{Opt_dfltuid, "dfltuid=%u"},
69bd32b82dSLatchesar Ionkov 	{Opt_dfltgid, "dfltgid=%u"},
709e82cf6aSEric Van Hensbergen 	{Opt_afid, "afid=%u"},
7167543e50SEric Van Hensbergen 	{Opt_uname, "uname=%s"},
729e82cf6aSEric Van Hensbergen 	{Opt_remotename, "aname=%s"},
739e82cf6aSEric Van Hensbergen 	{Opt_nodevmap, "nodevmap"},
7460e78d2cSAbhishek Kulkarni 	{Opt_cache, "cache=%s"},
75e03abc0cSEric Van Hensbergen 	{Opt_cache_loose, "loose"},
7660e78d2cSAbhishek Kulkarni 	{Opt_fscache, "fscache"},
77fb89b45cSDominique Martinet 	{Opt_mmap, "mmap"},
7860e78d2cSAbhishek Kulkarni 	{Opt_cachetag, "cachetag=%s"},
79ba17674fSLatchesar Ionkov 	{Opt_access, "access=%s"},
80e782ef71SVenkateswararao Jujjuri (JV) 	{Opt_posixacl, "posixacl"},
819e82cf6aSEric Van Hensbergen 	{Opt_err, NULL}
829e82cf6aSEric Van Hensbergen };
839e82cf6aSEric Van Hensbergen 
84a2dd43bbSPrem Karat /* Interpret mount options for cache mode */
85a2dd43bbSPrem Karat static int get_cache_mode(char *s)
86a2dd43bbSPrem Karat {
87a2dd43bbSPrem Karat 	int version = -EINVAL;
88a2dd43bbSPrem Karat 
89a2dd43bbSPrem Karat 	if (!strcmp(s, "loose")) {
90a2dd43bbSPrem Karat 		version = CACHE_LOOSE;
915d385153SJoe Perches 		p9_debug(P9_DEBUG_9P, "Cache mode: loose\n");
92a2dd43bbSPrem Karat 	} else if (!strcmp(s, "fscache")) {
93a2dd43bbSPrem Karat 		version = CACHE_FSCACHE;
945d385153SJoe Perches 		p9_debug(P9_DEBUG_9P, "Cache mode: fscache\n");
95fb89b45cSDominique Martinet 	} else if (!strcmp(s, "mmap")) {
96fb89b45cSDominique Martinet 		version = CACHE_MMAP;
97fb89b45cSDominique Martinet 		p9_debug(P9_DEBUG_9P, "Cache mode: mmap\n");
98a2dd43bbSPrem Karat 	} else if (!strcmp(s, "none")) {
99a2dd43bbSPrem Karat 		version = CACHE_NONE;
1005d385153SJoe Perches 		p9_debug(P9_DEBUG_9P, "Cache mode: none\n");
101a2dd43bbSPrem Karat 	} else
1025d385153SJoe Perches 		pr_info("Unknown Cache mode %s\n", s);
103a2dd43bbSPrem Karat 	return version;
104a2dd43bbSPrem Karat }
105a2dd43bbSPrem Karat 
1069e82cf6aSEric Van Hensbergen /**
1079e82cf6aSEric Van Hensbergen  * v9fs_parse_options - parse mount options into session structure
1089e82cf6aSEric Van Hensbergen  * @v9ses: existing v9fs session information
1099e82cf6aSEric Van Hensbergen  *
110ab31267dSJim Meyering  * Return 0 upon success, -ERRNO upon failure.
1119e82cf6aSEric Van Hensbergen  */
1129e82cf6aSEric Van Hensbergen 
1134b53e4b5SAbhishek Kulkarni static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
1149e82cf6aSEric Van Hensbergen {
115d8c8a9e3SEric Van Hensbergen 	char *options, *tmp_options;
1169e82cf6aSEric Van Hensbergen 	substring_t args[MAX_OPT_ARGS];
117a80d923eSEric Van Hensbergen 	char *p;
1188a0dc95fSEric Van Hensbergen 	int option = 0;
119ba17674fSLatchesar Ionkov 	char *s, *e;
120ab31267dSJim Meyering 	int ret = 0;
1219e82cf6aSEric Van Hensbergen 
1229e82cf6aSEric Van Hensbergen 	/* setup defaults */
1239e82cf6aSEric Van Hensbergen 	v9ses->afid = ~0;
1249e82cf6aSEric Van Hensbergen 	v9ses->debug = 0;
125a2dd43bbSPrem Karat 	v9ses->cache = CACHE_NONE;
12660e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE
12760e78d2cSAbhishek Kulkarni 	v9ses->cachetag = NULL;
12860e78d2cSAbhishek Kulkarni #endif
1299e82cf6aSEric Van Hensbergen 
1304b53e4b5SAbhishek Kulkarni 	if (!opts)
131ab31267dSJim Meyering 		return 0;
1329e82cf6aSEric Van Hensbergen 
133d8c8a9e3SEric Van Hensbergen 	tmp_options = kstrdup(opts, GFP_KERNEL);
134bf2d29c6SEric Van Hensbergen 	if (!tmp_options) {
135bf2d29c6SEric Van Hensbergen 		ret = -ENOMEM;
13660e78d2cSAbhishek Kulkarni 		goto fail_option_alloc;
137bf2d29c6SEric Van Hensbergen 	}
138d8c8a9e3SEric Van Hensbergen 	options = tmp_options;
139ab31267dSJim Meyering 
1409e82cf6aSEric Van Hensbergen 	while ((p = strsep(&options, ",")) != NULL) {
1414d5077f1SAneesh Kumar K.V 		int token, r;
1429e82cf6aSEric Van Hensbergen 		if (!*p)
1439e82cf6aSEric Van Hensbergen 			continue;
1449e82cf6aSEric Van Hensbergen 		token = match_token(p, tokens, args);
1454d5077f1SAneesh Kumar K.V 		switch (token) {
1464d5077f1SAneesh Kumar K.V 		case Opt_debug:
1474d5077f1SAneesh Kumar K.V 			r = match_int(&args[0], &option);
148ab31267dSJim Meyering 			if (r < 0) {
1495d385153SJoe Perches 				p9_debug(P9_DEBUG_ERROR,
1509e82cf6aSEric Van Hensbergen 					 "integer field, but no integer?\n");
151ab31267dSJim Meyering 				ret = r;
1529e82cf6aSEric Van Hensbergen 				continue;
1539e82cf6aSEric Van Hensbergen 			}
1549e2f6688SEric Van Hensbergen 			v9ses->debug = option;
15510fa16e7SEric Van Hensbergen #ifdef CONFIG_NET_9P_DEBUG
1569e2f6688SEric Van Hensbergen 			p9_debug_level = option;
15710fa16e7SEric Van Hensbergen #endif
1589e2f6688SEric Van Hensbergen 			break;
1598a0dc95fSEric Van Hensbergen 
160bd32b82dSLatchesar Ionkov 		case Opt_dfltuid:
1614d5077f1SAneesh Kumar K.V 			r = match_int(&args[0], &option);
1624d5077f1SAneesh Kumar K.V 			if (r < 0) {
1635d385153SJoe Perches 				p9_debug(P9_DEBUG_ERROR,
1644d5077f1SAneesh Kumar K.V 					 "integer field, but no integer?\n");
1654d5077f1SAneesh Kumar K.V 				ret = r;
1664d5077f1SAneesh Kumar K.V 				continue;
1674d5077f1SAneesh Kumar K.V 			}
16876ed23a5SEric W. Biederman 			v9ses->dfltuid = make_kuid(current_user_ns(), option);
16976ed23a5SEric W. Biederman 			if (!uid_valid(v9ses->dfltuid)) {
17076ed23a5SEric W. Biederman 				p9_debug(P9_DEBUG_ERROR,
17176ed23a5SEric W. Biederman 					 "uid field, but not a uid?\n");
17276ed23a5SEric W. Biederman 				ret = -EINVAL;
17376ed23a5SEric W. Biederman 				continue;
17476ed23a5SEric W. Biederman 			}
1759e82cf6aSEric Van Hensbergen 			break;
176bd32b82dSLatchesar Ionkov 		case Opt_dfltgid:
1774d5077f1SAneesh Kumar K.V 			r = match_int(&args[0], &option);
1784d5077f1SAneesh Kumar K.V 			if (r < 0) {
1795d385153SJoe Perches 				p9_debug(P9_DEBUG_ERROR,
1804d5077f1SAneesh Kumar K.V 					 "integer field, but no integer?\n");
1814d5077f1SAneesh Kumar K.V 				ret = r;
1824d5077f1SAneesh Kumar K.V 				continue;
1834d5077f1SAneesh Kumar K.V 			}
18476ed23a5SEric W. Biederman 			v9ses->dfltgid = make_kgid(current_user_ns(), option);
18576ed23a5SEric W. Biederman 			if (!gid_valid(v9ses->dfltgid)) {
18676ed23a5SEric W. Biederman 				p9_debug(P9_DEBUG_ERROR,
18776ed23a5SEric W. Biederman 					 "gid field, but not a gid?\n");
18876ed23a5SEric W. Biederman 				ret = -EINVAL;
18976ed23a5SEric W. Biederman 				continue;
19076ed23a5SEric W. Biederman 			}
1919e82cf6aSEric Van Hensbergen 			break;
1929e82cf6aSEric Van Hensbergen 		case Opt_afid:
1934d5077f1SAneesh Kumar K.V 			r = match_int(&args[0], &option);
1944d5077f1SAneesh Kumar K.V 			if (r < 0) {
1955d385153SJoe Perches 				p9_debug(P9_DEBUG_ERROR,
1964d5077f1SAneesh Kumar K.V 					 "integer field, but no integer?\n");
1974d5077f1SAneesh Kumar K.V 				ret = r;
1984d5077f1SAneesh Kumar K.V 				continue;
1994d5077f1SAneesh Kumar K.V 			}
2009e82cf6aSEric Van Hensbergen 			v9ses->afid = option;
2019e82cf6aSEric Van Hensbergen 			break;
20267543e50SEric Van Hensbergen 		case Opt_uname:
203e549c133SJeff Layton 			kfree(v9ses->uname);
204e549c133SJeff Layton 			v9ses->uname = match_strdup(&args[0]);
205e549c133SJeff Layton 			if (!v9ses->uname) {
206e549c133SJeff Layton 				ret = -ENOMEM;
207e549c133SJeff Layton 				goto free_and_return;
208e549c133SJeff Layton 			}
2099e82cf6aSEric Van Hensbergen 			break;
2109e82cf6aSEric Van Hensbergen 		case Opt_remotename:
211e549c133SJeff Layton 			kfree(v9ses->aname);
212e549c133SJeff Layton 			v9ses->aname = match_strdup(&args[0]);
213e549c133SJeff Layton 			if (!v9ses->aname) {
214e549c133SJeff Layton 				ret = -ENOMEM;
215e549c133SJeff Layton 				goto free_and_return;
216e549c133SJeff Layton 			}
2179e82cf6aSEric Van Hensbergen 			break;
2189e82cf6aSEric Van Hensbergen 		case Opt_nodevmap:
2199e82cf6aSEric Van Hensbergen 			v9ses->nodev = 1;
2209e82cf6aSEric Van Hensbergen 			break;
221e03abc0cSEric Van Hensbergen 		case Opt_cache_loose:
222e03abc0cSEric Van Hensbergen 			v9ses->cache = CACHE_LOOSE;
223e03abc0cSEric Van Hensbergen 			break;
22460e78d2cSAbhishek Kulkarni 		case Opt_fscache:
22560e78d2cSAbhishek Kulkarni 			v9ses->cache = CACHE_FSCACHE;
22660e78d2cSAbhishek Kulkarni 			break;
227fb89b45cSDominique Martinet 		case Opt_mmap:
228fb89b45cSDominique Martinet 			v9ses->cache = CACHE_MMAP;
229fb89b45cSDominique Martinet 			break;
23060e78d2cSAbhishek Kulkarni 		case Opt_cachetag:
23160e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE
23260e78d2cSAbhishek Kulkarni 			v9ses->cachetag = match_strdup(&args[0]);
23360e78d2cSAbhishek Kulkarni #endif
23460e78d2cSAbhishek Kulkarni 			break;
23560e78d2cSAbhishek Kulkarni 		case Opt_cache:
23660e78d2cSAbhishek Kulkarni 			s = match_strdup(&args[0]);
237bf2d29c6SEric Van Hensbergen 			if (!s) {
238bf2d29c6SEric Van Hensbergen 				ret = -ENOMEM;
2395d385153SJoe Perches 				p9_debug(P9_DEBUG_ERROR,
240bf2d29c6SEric Van Hensbergen 					 "problem allocating copy of cache arg\n");
241bf2d29c6SEric Van Hensbergen 				goto free_and_return;
242bf2d29c6SEric Van Hensbergen 			}
243a2dd43bbSPrem Karat 			ret = get_cache_mode(s);
244a2dd43bbSPrem Karat 			if (ret == -EINVAL) {
245a2dd43bbSPrem Karat 				kfree(s);
246a2dd43bbSPrem Karat 				goto free_and_return;
247a2dd43bbSPrem Karat 			}
24860e78d2cSAbhishek Kulkarni 
249a2dd43bbSPrem Karat 			v9ses->cache = ret;
25060e78d2cSAbhishek Kulkarni 			kfree(s);
25160e78d2cSAbhishek Kulkarni 			break;
252ba17674fSLatchesar Ionkov 
253ba17674fSLatchesar Ionkov 		case Opt_access:
254ba17674fSLatchesar Ionkov 			s = match_strdup(&args[0]);
255bf2d29c6SEric Van Hensbergen 			if (!s) {
256bf2d29c6SEric Van Hensbergen 				ret = -ENOMEM;
2575d385153SJoe Perches 				p9_debug(P9_DEBUG_ERROR,
258bf2d29c6SEric Van Hensbergen 					 "problem allocating copy of access arg\n");
259bf2d29c6SEric Van Hensbergen 				goto free_and_return;
260bf2d29c6SEric Van Hensbergen 			}
26160e78d2cSAbhishek Kulkarni 
262ba17674fSLatchesar Ionkov 			v9ses->flags &= ~V9FS_ACCESS_MASK;
263ba17674fSLatchesar Ionkov 			if (strcmp(s, "user") == 0)
264ba17674fSLatchesar Ionkov 				v9ses->flags |= V9FS_ACCESS_USER;
265ba17674fSLatchesar Ionkov 			else if (strcmp(s, "any") == 0)
266ba17674fSLatchesar Ionkov 				v9ses->flags |= V9FS_ACCESS_ANY;
26776381a42SAneesh Kumar K.V 			else if (strcmp(s, "client") == 0) {
26876381a42SAneesh Kumar K.V 				v9ses->flags |= V9FS_ACCESS_CLIENT;
26976381a42SAneesh Kumar K.V 			} else {
27076ed23a5SEric W. Biederman 				uid_t uid;
271ba17674fSLatchesar Ionkov 				v9ses->flags |= V9FS_ACCESS_SINGLE;
27276ed23a5SEric W. Biederman 				uid = simple_strtoul(s, &e, 10);
273a2dd43bbSPrem Karat 				if (*e != '\0') {
274a2dd43bbSPrem Karat 					ret = -EINVAL;
2755d385153SJoe Perches 					pr_info("Unknown access argument %s\n",
2765d385153SJoe Perches 						s);
277a2dd43bbSPrem Karat 					kfree(s);
278a2dd43bbSPrem Karat 					goto free_and_return;
279ba17674fSLatchesar Ionkov 				}
28076ed23a5SEric W. Biederman 				v9ses->uid = make_kuid(current_user_ns(), uid);
28176ed23a5SEric W. Biederman 				if (!uid_valid(v9ses->uid)) {
28276ed23a5SEric W. Biederman 					ret = -EINVAL;
28376ed23a5SEric W. Biederman 					pr_info("Uknown uid %s\n", s);
28476ed23a5SEric W. Biederman 					kfree(s);
28576ed23a5SEric W. Biederman 					goto free_and_return;
28676ed23a5SEric W. Biederman 				}
287a2dd43bbSPrem Karat 			}
288a2dd43bbSPrem Karat 
2890a976297SAdrian Bunk 			kfree(s);
290ba17674fSLatchesar Ionkov 			break;
291ba17674fSLatchesar Ionkov 
292e782ef71SVenkateswararao Jujjuri (JV) 		case Opt_posixacl:
293e782ef71SVenkateswararao Jujjuri (JV) #ifdef CONFIG_9P_FS_POSIX_ACL
294e782ef71SVenkateswararao Jujjuri (JV) 			v9ses->flags |= V9FS_POSIX_ACL;
295e782ef71SVenkateswararao Jujjuri (JV) #else
2965d385153SJoe Perches 			p9_debug(P9_DEBUG_ERROR,
2975d385153SJoe Perches 				 "Not defined CONFIG_9P_FS_POSIX_ACL. Ignoring posixacl option\n");
298e782ef71SVenkateswararao Jujjuri (JV) #endif
299e782ef71SVenkateswararao Jujjuri (JV) 			break;
300e782ef71SVenkateswararao Jujjuri (JV) 
3019e82cf6aSEric Van Hensbergen 		default:
3029e82cf6aSEric Van Hensbergen 			continue;
3039e82cf6aSEric Van Hensbergen 		}
3049e82cf6aSEric Van Hensbergen 	}
305d8c8a9e3SEric Van Hensbergen 
306bf2d29c6SEric Van Hensbergen free_and_return:
307d8c8a9e3SEric Van Hensbergen 	kfree(tmp_options);
30860e78d2cSAbhishek Kulkarni fail_option_alloc:
309bf2d29c6SEric Van Hensbergen 	return ret;
3109e82cf6aSEric Van Hensbergen }
3119e82cf6aSEric Van Hensbergen 
3129e82cf6aSEric Van Hensbergen /**
3139e82cf6aSEric Van Hensbergen  * v9fs_session_init - initialize session
3149e82cf6aSEric Van Hensbergen  * @v9ses: session information structure
3159e82cf6aSEric Van Hensbergen  * @dev_name: device being mounted
3169e82cf6aSEric Van Hensbergen  * @data: options
3179e82cf6aSEric Van Hensbergen  *
3189e82cf6aSEric Van Hensbergen  */
3199e82cf6aSEric Van Hensbergen 
320bd238fb4SLatchesar Ionkov struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
3219e82cf6aSEric Van Hensbergen 		  const char *dev_name, char *data)
3229e82cf6aSEric Van Hensbergen {
3239e82cf6aSEric Van Hensbergen 	int retval = -EINVAL;
324bd238fb4SLatchesar Ionkov 	struct p9_fid *fid;
325ab31267dSJim Meyering 	int rc;
3269e82cf6aSEric Van Hensbergen 
327e549c133SJeff Layton 	v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL);
328ba17674fSLatchesar Ionkov 	if (!v9ses->uname)
329bd238fb4SLatchesar Ionkov 		return ERR_PTR(-ENOMEM);
3309e82cf6aSEric Van Hensbergen 
331e549c133SJeff Layton 	v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL);
332ba17674fSLatchesar Ionkov 	if (!v9ses->aname) {
333e549c133SJeff Layton 		kfree(v9ses->uname);
334bd238fb4SLatchesar Ionkov 		return ERR_PTR(-ENOMEM);
3359e82cf6aSEric Van Hensbergen 	}
336a534c8d1SAneesh Kumar K.V 	init_rwsem(&v9ses->rename_sem);
3379e82cf6aSEric Van Hensbergen 
338b4caecd4SChristoph Hellwig 	rc = bdi_setup_and_register(&v9ses->bdi, "9p");
3390ed07ddbSJens Axboe 	if (rc) {
340e549c133SJeff Layton 		kfree(v9ses->aname);
341e549c133SJeff Layton 		kfree(v9ses->uname);
3420ed07ddbSJens Axboe 		return ERR_PTR(rc);
3430ed07ddbSJens Axboe 	}
3440ed07ddbSJens Axboe 
34560e78d2cSAbhishek Kulkarni 	spin_lock(&v9fs_sessionlist_lock);
34660e78d2cSAbhishek Kulkarni 	list_add(&v9ses->slist, &v9fs_sessionlist);
34760e78d2cSAbhishek Kulkarni 	spin_unlock(&v9fs_sessionlist_lock);
34860e78d2cSAbhishek Kulkarni 
34976ed23a5SEric W. Biederman 	v9ses->uid = INVALID_UID;
350bd32b82dSLatchesar Ionkov 	v9ses->dfltuid = V9FS_DEFUID;
351bd32b82dSLatchesar Ionkov 	v9ses->dfltgid = V9FS_DEFGID;
352ab31267dSJim Meyering 
3534b53e4b5SAbhishek Kulkarni 	v9ses->clnt = p9_client_create(dev_name, data);
354bd238fb4SLatchesar Ionkov 	if (IS_ERR(v9ses->clnt)) {
355bd238fb4SLatchesar Ionkov 		retval = PTR_ERR(v9ses->clnt);
356bd238fb4SLatchesar Ionkov 		v9ses->clnt = NULL;
3575d385153SJoe Perches 		p9_debug(P9_DEBUG_ERROR, "problem initializing 9p client\n");
358bd238fb4SLatchesar Ionkov 		goto error;
3599e82cf6aSEric Van Hensbergen 	}
3609e82cf6aSEric Van Hensbergen 
3616752a1ebSVenkateswararao Jujjuri (JV) 	v9ses->flags = V9FS_ACCESS_USER;
3626752a1ebSVenkateswararao Jujjuri (JV) 
3636752a1ebSVenkateswararao Jujjuri (JV) 	if (p9_is_proto_dotl(v9ses->clnt)) {
3646752a1ebSVenkateswararao Jujjuri (JV) 		v9ses->flags = V9FS_ACCESS_CLIENT;
365476ada04SSripathi Kodi 		v9ses->flags |= V9FS_PROTO_2000L;
3666752a1ebSVenkateswararao Jujjuri (JV) 	} else if (p9_is_proto_dotu(v9ses->clnt)) {
367476ada04SSripathi Kodi 		v9ses->flags |= V9FS_PROTO_2000U;
3686752a1ebSVenkateswararao Jujjuri (JV) 	}
3696752a1ebSVenkateswararao Jujjuri (JV) 
3706752a1ebSVenkateswararao Jujjuri (JV) 	rc = v9fs_parse_options(v9ses, data);
3716752a1ebSVenkateswararao Jujjuri (JV) 	if (rc < 0) {
3726752a1ebSVenkateswararao Jujjuri (JV) 		retval = rc;
3736752a1ebSVenkateswararao Jujjuri (JV) 		goto error;
3746752a1ebSVenkateswararao Jujjuri (JV) 	}
375ba17674fSLatchesar Ionkov 
376fbedadc1SEric Van Hensbergen 	v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ;
3778a0dc95fSEric Van Hensbergen 
37876381a42SAneesh Kumar K.V 	if (!v9fs_proto_dotl(v9ses) &&
37976381a42SAneesh Kumar K.V 	    ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) {
38076381a42SAneesh Kumar K.V 		/*
38176381a42SAneesh Kumar K.V 		 * We support ACCESS_CLIENT only for dotl.
38276381a42SAneesh Kumar K.V 		 * Fall back to ACCESS_USER
38376381a42SAneesh Kumar K.V 		 */
38476381a42SAneesh Kumar K.V 		v9ses->flags &= ~V9FS_ACCESS_MASK;
38576381a42SAneesh Kumar K.V 		v9ses->flags |= V9FS_ACCESS_USER;
38676381a42SAneesh Kumar K.V 	}
38776381a42SAneesh Kumar K.V 	/*FIXME !! */
388ba17674fSLatchesar Ionkov 	/* for legacy mode, fall back to V9FS_ACCESS_ANY */
3899ffaf63eSAneesh Kumar K.V 	if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) &&
390ba17674fSLatchesar Ionkov 		((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {
391ba17674fSLatchesar Ionkov 
392ba17674fSLatchesar Ionkov 		v9ses->flags &= ~V9FS_ACCESS_MASK;
393ba17674fSLatchesar Ionkov 		v9ses->flags |= V9FS_ACCESS_ANY;
39476ed23a5SEric W. Biederman 		v9ses->uid = INVALID_UID;
395ba17674fSLatchesar Ionkov 	}
396e782ef71SVenkateswararao Jujjuri (JV) 	if (!v9fs_proto_dotl(v9ses) ||
397e782ef71SVenkateswararao Jujjuri (JV) 		!((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) {
398e782ef71SVenkateswararao Jujjuri (JV) 		/*
399e782ef71SVenkateswararao Jujjuri (JV) 		 * We support ACL checks on clinet only if the protocol is
400e782ef71SVenkateswararao Jujjuri (JV) 		 * 9P2000.L and access is V9FS_ACCESS_CLIENT.
401e782ef71SVenkateswararao Jujjuri (JV) 		 */
402e782ef71SVenkateswararao Jujjuri (JV) 		v9ses->flags &= ~V9FS_ACL_MASK;
403e782ef71SVenkateswararao Jujjuri (JV) 	}
404ba17674fSLatchesar Ionkov 
405f791f7c5SEric W. Biederman 	fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, INVALID_UID,
406ba17674fSLatchesar Ionkov 							v9ses->aname);
407bd238fb4SLatchesar Ionkov 	if (IS_ERR(fid)) {
408bd238fb4SLatchesar Ionkov 		retval = PTR_ERR(fid);
409bd238fb4SLatchesar Ionkov 		fid = NULL;
4105d385153SJoe Perches 		p9_debug(P9_DEBUG_ERROR, "cannot attach\n");
411bd238fb4SLatchesar Ionkov 		goto error;
4129e82cf6aSEric Van Hensbergen 	}
4139e82cf6aSEric Van Hensbergen 
414ba17674fSLatchesar Ionkov 	if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_SINGLE)
415ba17674fSLatchesar Ionkov 		fid->uid = v9ses->uid;
416ba17674fSLatchesar Ionkov 	else
417b4642556SEric W. Biederman 		fid->uid = INVALID_UID;
418ba17674fSLatchesar Ionkov 
41960e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE
42060e78d2cSAbhishek Kulkarni 	/* register the session for caching */
42160e78d2cSAbhishek Kulkarni 	v9fs_cache_session_get_cookie(v9ses);
42260e78d2cSAbhishek Kulkarni #endif
42360e78d2cSAbhishek Kulkarni 
424bd238fb4SLatchesar Ionkov 	return fid;
4259e82cf6aSEric Van Hensbergen 
426bd238fb4SLatchesar Ionkov error:
4270ed07ddbSJens Axboe 	bdi_destroy(&v9ses->bdi);
428bd238fb4SLatchesar Ionkov 	return ERR_PTR(retval);
4299e82cf6aSEric Van Hensbergen }
4309e82cf6aSEric Van Hensbergen 
4319e82cf6aSEric Van Hensbergen /**
4329e82cf6aSEric Van Hensbergen  * v9fs_session_close - shutdown a session
4339e82cf6aSEric Van Hensbergen  * @v9ses: session information structure
4349e82cf6aSEric Van Hensbergen  *
4359e82cf6aSEric Van Hensbergen  */
4369e82cf6aSEric Van Hensbergen 
4379e82cf6aSEric Van Hensbergen void v9fs_session_close(struct v9fs_session_info *v9ses)
4389e82cf6aSEric Van Hensbergen {
439bd238fb4SLatchesar Ionkov 	if (v9ses->clnt) {
440bd238fb4SLatchesar Ionkov 		p9_client_destroy(v9ses->clnt);
441bd238fb4SLatchesar Ionkov 		v9ses->clnt = NULL;
4423cf6429aSLatchesar Ionkov 	}
4439e82cf6aSEric Van Hensbergen 
44460e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE
44560e78d2cSAbhishek Kulkarni 	if (v9ses->fscache) {
44660e78d2cSAbhishek Kulkarni 		v9fs_cache_session_put_cookie(v9ses);
44760e78d2cSAbhishek Kulkarni 		kfree(v9ses->cachetag);
44860e78d2cSAbhishek Kulkarni 	}
44960e78d2cSAbhishek Kulkarni #endif
450e549c133SJeff Layton 	kfree(v9ses->uname);
451e549c133SJeff Layton 	kfree(v9ses->aname);
45260e78d2cSAbhishek Kulkarni 
4530ed07ddbSJens Axboe 	bdi_destroy(&v9ses->bdi);
4540ed07ddbSJens Axboe 
45560e78d2cSAbhishek Kulkarni 	spin_lock(&v9fs_sessionlist_lock);
45660e78d2cSAbhishek Kulkarni 	list_del(&v9ses->slist);
45760e78d2cSAbhishek Kulkarni 	spin_unlock(&v9fs_sessionlist_lock);
4589e82cf6aSEric Van Hensbergen }
4599e82cf6aSEric Van Hensbergen 
460322b329aSEric Van Hensbergen /**
461ee443996SEric Van Hensbergen  * v9fs_session_cancel - terminate a session
462ee443996SEric Van Hensbergen  * @v9ses: session to terminate
463ee443996SEric Van Hensbergen  *
464ee443996SEric Van Hensbergen  * mark transport as disconnected and cancel all pending requests.
465322b329aSEric Van Hensbergen  */
466ee443996SEric Van Hensbergen 
467322b329aSEric Van Hensbergen void v9fs_session_cancel(struct v9fs_session_info *v9ses) {
4685d385153SJoe Perches 	p9_debug(P9_DEBUG_ERROR, "cancel session %p\n", v9ses);
469bd238fb4SLatchesar Ionkov 	p9_client_disconnect(v9ses->clnt);
470322b329aSEric Van Hensbergen }
471322b329aSEric Van Hensbergen 
4726d96d3abSAneesh Kumar K.V /**
4736d96d3abSAneesh Kumar K.V  * v9fs_session_begin_cancel - Begin terminate of a session
4746d96d3abSAneesh Kumar K.V  * @v9ses: session to terminate
4756d96d3abSAneesh Kumar K.V  *
4766d96d3abSAneesh Kumar K.V  * After this call we don't allow any request other than clunk.
4776d96d3abSAneesh Kumar K.V  */
4786d96d3abSAneesh Kumar K.V 
4796d96d3abSAneesh Kumar K.V void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses)
4806d96d3abSAneesh Kumar K.V {
4815d385153SJoe Perches 	p9_debug(P9_DEBUG_ERROR, "begin cancel session %p\n", v9ses);
4826d96d3abSAneesh Kumar K.V 	p9_client_begin_disconnect(v9ses->clnt);
4836d96d3abSAneesh Kumar K.V }
4846d96d3abSAneesh Kumar K.V 
4859e82cf6aSEric Van Hensbergen extern int v9fs_error_init(void);
4869e82cf6aSEric Van Hensbergen 
48760e78d2cSAbhishek Kulkarni static struct kobject *v9fs_kobj;
48860e78d2cSAbhishek Kulkarni 
48960e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE
4909e82cf6aSEric Van Hensbergen /**
49160e78d2cSAbhishek Kulkarni  * caches_show - list caches associated with a session
49260e78d2cSAbhishek Kulkarni  *
49360e78d2cSAbhishek Kulkarni  * Returns the size of buffer written.
49460e78d2cSAbhishek Kulkarni  */
49560e78d2cSAbhishek Kulkarni 
49660e78d2cSAbhishek Kulkarni static ssize_t caches_show(struct kobject *kobj,
49760e78d2cSAbhishek Kulkarni 			   struct kobj_attribute *attr,
49860e78d2cSAbhishek Kulkarni 			   char *buf)
49960e78d2cSAbhishek Kulkarni {
50060e78d2cSAbhishek Kulkarni 	ssize_t n = 0, count = 0, limit = PAGE_SIZE;
50160e78d2cSAbhishek Kulkarni 	struct v9fs_session_info *v9ses;
50260e78d2cSAbhishek Kulkarni 
50360e78d2cSAbhishek Kulkarni 	spin_lock(&v9fs_sessionlist_lock);
50460e78d2cSAbhishek Kulkarni 	list_for_each_entry(v9ses, &v9fs_sessionlist, slist) {
50560e78d2cSAbhishek Kulkarni 		if (v9ses->cachetag) {
50660e78d2cSAbhishek Kulkarni 			n = snprintf(buf, limit, "%s\n", v9ses->cachetag);
50760e78d2cSAbhishek Kulkarni 			if (n < 0) {
50860e78d2cSAbhishek Kulkarni 				count = n;
50960e78d2cSAbhishek Kulkarni 				break;
51060e78d2cSAbhishek Kulkarni 			}
51160e78d2cSAbhishek Kulkarni 
51260e78d2cSAbhishek Kulkarni 			count += n;
51360e78d2cSAbhishek Kulkarni 			limit -= n;
51460e78d2cSAbhishek Kulkarni 		}
51560e78d2cSAbhishek Kulkarni 	}
51660e78d2cSAbhishek Kulkarni 
51760e78d2cSAbhishek Kulkarni 	spin_unlock(&v9fs_sessionlist_lock);
51860e78d2cSAbhishek Kulkarni 	return count;
51960e78d2cSAbhishek Kulkarni }
52060e78d2cSAbhishek Kulkarni 
52160e78d2cSAbhishek Kulkarni static struct kobj_attribute v9fs_attr_cache = __ATTR_RO(caches);
52260e78d2cSAbhishek Kulkarni #endif /* CONFIG_9P_FSCACHE */
52360e78d2cSAbhishek Kulkarni 
52460e78d2cSAbhishek Kulkarni static struct attribute *v9fs_attrs[] = {
52560e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE
52660e78d2cSAbhishek Kulkarni 	&v9fs_attr_cache.attr,
52760e78d2cSAbhishek Kulkarni #endif
52860e78d2cSAbhishek Kulkarni 	NULL,
52960e78d2cSAbhishek Kulkarni };
53060e78d2cSAbhishek Kulkarni 
53160e78d2cSAbhishek Kulkarni static struct attribute_group v9fs_attr_group = {
53260e78d2cSAbhishek Kulkarni 	.attrs = v9fs_attrs,
53360e78d2cSAbhishek Kulkarni };
53460e78d2cSAbhishek Kulkarni 
53560e78d2cSAbhishek Kulkarni /**
53660e78d2cSAbhishek Kulkarni  * v9fs_sysfs_init - Initialize the v9fs sysfs interface
53760e78d2cSAbhishek Kulkarni  *
53860e78d2cSAbhishek Kulkarni  */
53960e78d2cSAbhishek Kulkarni 
540bdbeacdeSFabian Frederick static int __init v9fs_sysfs_init(void)
54160e78d2cSAbhishek Kulkarni {
54260e78d2cSAbhishek Kulkarni 	v9fs_kobj = kobject_create_and_add("9p", fs_kobj);
54360e78d2cSAbhishek Kulkarni 	if (!v9fs_kobj)
54460e78d2cSAbhishek Kulkarni 		return -ENOMEM;
54560e78d2cSAbhishek Kulkarni 
54660e78d2cSAbhishek Kulkarni 	if (sysfs_create_group(v9fs_kobj, &v9fs_attr_group)) {
54760e78d2cSAbhishek Kulkarni 		kobject_put(v9fs_kobj);
54860e78d2cSAbhishek Kulkarni 		return -ENOMEM;
54960e78d2cSAbhishek Kulkarni 	}
55060e78d2cSAbhishek Kulkarni 
55160e78d2cSAbhishek Kulkarni 	return 0;
55260e78d2cSAbhishek Kulkarni }
55360e78d2cSAbhishek Kulkarni 
55460e78d2cSAbhishek Kulkarni /**
55560e78d2cSAbhishek Kulkarni  * v9fs_sysfs_cleanup - Unregister the v9fs sysfs interface
55660e78d2cSAbhishek Kulkarni  *
55760e78d2cSAbhishek Kulkarni  */
55860e78d2cSAbhishek Kulkarni 
55960e78d2cSAbhishek Kulkarni static void v9fs_sysfs_cleanup(void)
56060e78d2cSAbhishek Kulkarni {
56160e78d2cSAbhishek Kulkarni 	sysfs_remove_group(v9fs_kobj, &v9fs_attr_group);
56260e78d2cSAbhishek Kulkarni 	kobject_put(v9fs_kobj);
56360e78d2cSAbhishek Kulkarni }
56460e78d2cSAbhishek Kulkarni 
565a78ce05dSAneesh Kumar K.V static void v9fs_inode_init_once(void *foo)
566a78ce05dSAneesh Kumar K.V {
567a78ce05dSAneesh Kumar K.V 	struct v9fs_inode *v9inode = (struct v9fs_inode *)foo;
568a78ce05dSAneesh Kumar K.V #ifdef CONFIG_9P_FSCACHE
569a78ce05dSAneesh Kumar K.V 	v9inode->fscache = NULL;
570a78ce05dSAneesh Kumar K.V #endif
571fd2421f5SAneesh Kumar K.V 	memset(&v9inode->qid, 0, sizeof(v9inode->qid));
572a78ce05dSAneesh Kumar K.V 	inode_init_once(&v9inode->vfs_inode);
573a78ce05dSAneesh Kumar K.V }
574a78ce05dSAneesh Kumar K.V 
575a78ce05dSAneesh Kumar K.V /**
576a78ce05dSAneesh Kumar K.V  * v9fs_init_inode_cache - initialize a cache for 9P
577a78ce05dSAneesh Kumar K.V  * Returns 0 on success.
578a78ce05dSAneesh Kumar K.V  */
579a78ce05dSAneesh Kumar K.V static int v9fs_init_inode_cache(void)
580a78ce05dSAneesh Kumar K.V {
581a78ce05dSAneesh Kumar K.V 	v9fs_inode_cache = kmem_cache_create("v9fs_inode_cache",
582a78ce05dSAneesh Kumar K.V 					  sizeof(struct v9fs_inode),
583a78ce05dSAneesh Kumar K.V 					  0, (SLAB_RECLAIM_ACCOUNT|
584a78ce05dSAneesh Kumar K.V 					      SLAB_MEM_SPREAD),
585a78ce05dSAneesh Kumar K.V 					  v9fs_inode_init_once);
586a78ce05dSAneesh Kumar K.V 	if (!v9fs_inode_cache)
587a78ce05dSAneesh Kumar K.V 		return -ENOMEM;
588a78ce05dSAneesh Kumar K.V 
589a78ce05dSAneesh Kumar K.V 	return 0;
590a78ce05dSAneesh Kumar K.V }
591a78ce05dSAneesh Kumar K.V 
592a78ce05dSAneesh Kumar K.V /**
593a78ce05dSAneesh Kumar K.V  * v9fs_destroy_inode_cache - destroy the cache of 9P inode
594a78ce05dSAneesh Kumar K.V  *
595a78ce05dSAneesh Kumar K.V  */
596a78ce05dSAneesh Kumar K.V static void v9fs_destroy_inode_cache(void)
597a78ce05dSAneesh Kumar K.V {
5988c0a8537SKirill A. Shutemov 	/*
5998c0a8537SKirill A. Shutemov 	 * Make sure all delayed rcu free inodes are flushed before we
6008c0a8537SKirill A. Shutemov 	 * destroy cache.
6018c0a8537SKirill A. Shutemov 	 */
6028c0a8537SKirill A. Shutemov 	rcu_barrier();
603a78ce05dSAneesh Kumar K.V 	kmem_cache_destroy(v9fs_inode_cache);
604a78ce05dSAneesh Kumar K.V }
605a78ce05dSAneesh Kumar K.V 
606a78ce05dSAneesh Kumar K.V static int v9fs_cache_register(void)
607a78ce05dSAneesh Kumar K.V {
608a78ce05dSAneesh Kumar K.V 	int ret;
609a78ce05dSAneesh Kumar K.V 	ret = v9fs_init_inode_cache();
610a78ce05dSAneesh Kumar K.V 	if (ret < 0)
611a78ce05dSAneesh Kumar K.V 		return ret;
612a78ce05dSAneesh Kumar K.V #ifdef CONFIG_9P_FSCACHE
6138061a6faSAl Viro 	ret = fscache_register_netfs(&v9fs_cache_netfs);
6148061a6faSAl Viro 	if (ret < 0)
6158061a6faSAl Viro 		v9fs_destroy_inode_cache();
616a78ce05dSAneesh Kumar K.V #endif
6178061a6faSAl Viro 	return ret;
618a78ce05dSAneesh Kumar K.V }
619a78ce05dSAneesh Kumar K.V 
620a78ce05dSAneesh Kumar K.V static void v9fs_cache_unregister(void)
621a78ce05dSAneesh Kumar K.V {
622a78ce05dSAneesh Kumar K.V 	v9fs_destroy_inode_cache();
623a78ce05dSAneesh Kumar K.V #ifdef CONFIG_9P_FSCACHE
624a78ce05dSAneesh Kumar K.V 	fscache_unregister_netfs(&v9fs_cache_netfs);
625a78ce05dSAneesh Kumar K.V #endif
626a78ce05dSAneesh Kumar K.V }
627a78ce05dSAneesh Kumar K.V 
62860e78d2cSAbhishek Kulkarni /**
62960e78d2cSAbhishek Kulkarni  * init_v9fs - Initialize module
6309e82cf6aSEric Van Hensbergen  *
6319e82cf6aSEric Van Hensbergen  */
6329e82cf6aSEric Van Hensbergen 
6339e82cf6aSEric Van Hensbergen static int __init init_v9fs(void)
6349e82cf6aSEric Van Hensbergen {
63560e78d2cSAbhishek Kulkarni 	int err;
6365d385153SJoe Perches 	pr_info("Installing v9fs 9p2000 file system support\n");
637a80d923eSEric Van Hensbergen 	/* TODO: Setup list of registered trasnport modules */
63860e78d2cSAbhishek Kulkarni 
63960e78d2cSAbhishek Kulkarni 	err = v9fs_cache_register();
64060e78d2cSAbhishek Kulkarni 	if (err < 0) {
6415d385153SJoe Perches 		pr_err("Failed to register v9fs for caching\n");
6422226a288SAl Viro 		return err;
64360e78d2cSAbhishek Kulkarni 	}
64460e78d2cSAbhishek Kulkarni 
64560e78d2cSAbhishek Kulkarni 	err = v9fs_sysfs_init();
64660e78d2cSAbhishek Kulkarni 	if (err < 0) {
6475d385153SJoe Perches 		pr_err("Failed to register with sysfs\n");
6482226a288SAl Viro 		goto out_cache;
6492226a288SAl Viro 	}
6502226a288SAl Viro 	err = register_filesystem(&v9fs_fs_type);
6512226a288SAl Viro 	if (err < 0) {
6522226a288SAl Viro 		pr_err("Failed to register filesystem\n");
65360e78d2cSAbhishek Kulkarni 		goto out_sysfs_cleanup;
65460e78d2cSAbhishek Kulkarni 	}
65560e78d2cSAbhishek Kulkarni 
65660e78d2cSAbhishek Kulkarni 	return 0;
65760e78d2cSAbhishek Kulkarni 
65860e78d2cSAbhishek Kulkarni out_sysfs_cleanup:
65960e78d2cSAbhishek Kulkarni 	v9fs_sysfs_cleanup();
66060e78d2cSAbhishek Kulkarni 
6612226a288SAl Viro out_cache:
6622226a288SAl Viro 	v9fs_cache_unregister();
66360e78d2cSAbhishek Kulkarni 
66460e78d2cSAbhishek Kulkarni 	return err;
6659e82cf6aSEric Van Hensbergen }
6669e82cf6aSEric Van Hensbergen 
6679e82cf6aSEric Van Hensbergen /**
66860e78d2cSAbhishek Kulkarni  * exit_v9fs - shutdown module
6699e82cf6aSEric Van Hensbergen  *
6709e82cf6aSEric Van Hensbergen  */
6719e82cf6aSEric Van Hensbergen 
6729e82cf6aSEric Van Hensbergen static void __exit exit_v9fs(void)
6739e82cf6aSEric Van Hensbergen {
67460e78d2cSAbhishek Kulkarni 	v9fs_sysfs_cleanup();
67560e78d2cSAbhishek Kulkarni 	v9fs_cache_unregister();
6769e82cf6aSEric Van Hensbergen 	unregister_filesystem(&v9fs_fs_type);
6779e82cf6aSEric Van Hensbergen }
6789e82cf6aSEric Van Hensbergen 
6799e82cf6aSEric Van Hensbergen module_init(init_v9fs)
6809e82cf6aSEric Van Hensbergen module_exit(exit_v9fs)
6819e82cf6aSEric Van Hensbergen 
682bd238fb4SLatchesar Ionkov MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
6839e82cf6aSEric Van Hensbergen MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
6849e82cf6aSEric Van Hensbergen MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
6859e82cf6aSEric Van Hensbergen MODULE_LICENSE("GPL");
686