xref: /openbmc/linux/fs/9p/v9fs.c (revision e6ab0b91)
11f327613SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
29e82cf6aSEric Van Hensbergen /*
39e82cf6aSEric Van Hensbergen  *  This file contains functions assisting in mapping VFS to 9P2000
49e82cf6aSEric Van Hensbergen  *
58a0dc95fSEric Van Hensbergen  *  Copyright (C) 2004-2008 by Eric Van Hensbergen <ericvh@gmail.com>
69e82cf6aSEric Van Hensbergen  *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
79e82cf6aSEric Van Hensbergen  */
89e82cf6aSEric Van Hensbergen 
95d385153SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
105d385153SJoe Perches 
119e82cf6aSEric Van Hensbergen #include <linux/module.h>
129e82cf6aSEric Van Hensbergen #include <linux/errno.h>
139e82cf6aSEric Van Hensbergen #include <linux/fs.h>
14914e2637SAl Viro #include <linux/sched.h>
155b825c3aSIngo Molnar #include <linux/cred.h>
169e82cf6aSEric Van Hensbergen #include <linux/parser.h>
175a0e3ad6STejun Heo #include <linux/slab.h>
18c4fac910SDavid Howells #include <linux/seq_file.h>
19bd238fb4SLatchesar Ionkov #include <net/9p/9p.h>
20bd238fb4SLatchesar Ionkov #include <net/9p/client.h>
218b81ef58SEric Van Hensbergen #include <net/9p/transport.h>
229e82cf6aSEric Van Hensbergen #include "v9fs.h"
239e82cf6aSEric Van Hensbergen #include "v9fs_vfs.h"
2460e78d2cSAbhishek Kulkarni #include "cache.h"
2560e78d2cSAbhishek Kulkarni 
2660e78d2cSAbhishek Kulkarni static DEFINE_SPINLOCK(v9fs_sessionlist_lock);
2760e78d2cSAbhishek Kulkarni static LIST_HEAD(v9fs_sessionlist);
28a78ce05dSAneesh Kumar K.V struct kmem_cache *v9fs_inode_cache;
299e82cf6aSEric Van Hensbergen 
309e82cf6aSEric Van Hensbergen /*
31a80d923eSEric Van Hensbergen  * Option Parsing (code inspired by NFS code)
32a80d923eSEric Van Hensbergen  *  NOTE: each transport will parse its own options
33a80d923eSEric Van Hensbergen  */
34a80d923eSEric Van Hensbergen 
359e82cf6aSEric Van Hensbergen enum {
369e82cf6aSEric Van Hensbergen 	/* Options that take integer arguments */
378a0dc95fSEric Van Hensbergen 	Opt_debug, Opt_dfltuid, Opt_dfltgid, Opt_afid,
389e82cf6aSEric Van Hensbergen 	/* String options */
39cb9af418SFabian Frederick 	Opt_uname, Opt_remotename, Opt_cache, Opt_cachetag,
409e82cf6aSEric Van Hensbergen 	/* Options that take no arguments */
416deffc89SEric Van Hensbergen 	Opt_nodevmap, Opt_noxattr, Opt_directio, Opt_ignoreqv,
42ba17674fSLatchesar Ionkov 	/* Access options */
43e782ef71SVenkateswararao Jujjuri (JV) 	Opt_access, Opt_posixacl,
445e172f75SDinu-Razvan Chis-Serban 	/* Lock timeout option */
455e172f75SDinu-Razvan Chis-Serban 	Opt_locktimeout,
469e82cf6aSEric Van Hensbergen 	/* Error token */
479e82cf6aSEric Van Hensbergen 	Opt_err
489e82cf6aSEric Van Hensbergen };
499e82cf6aSEric Van Hensbergen 
50a447c093SSteven Whitehouse static const match_table_t tokens = {
519e2f6688SEric Van Hensbergen 	{Opt_debug, "debug=%x"},
52bd32b82dSLatchesar Ionkov 	{Opt_dfltuid, "dfltuid=%u"},
53bd32b82dSLatchesar Ionkov 	{Opt_dfltgid, "dfltgid=%u"},
549e82cf6aSEric Van Hensbergen 	{Opt_afid, "afid=%u"},
5567543e50SEric Van Hensbergen 	{Opt_uname, "uname=%s"},
569e82cf6aSEric Van Hensbergen 	{Opt_remotename, "aname=%s"},
579e82cf6aSEric Van Hensbergen 	{Opt_nodevmap, "nodevmap"},
588142db4fSEric Van Hensbergen 	{Opt_noxattr, "noxattr"},
596deffc89SEric Van Hensbergen 	{Opt_directio, "directio"},
606deffc89SEric Van Hensbergen 	{Opt_ignoreqv, "ignoreqv"},
6160e78d2cSAbhishek Kulkarni 	{Opt_cache, "cache=%s"},
6260e78d2cSAbhishek Kulkarni 	{Opt_cachetag, "cachetag=%s"},
63ba17674fSLatchesar Ionkov 	{Opt_access, "access=%s"},
64e782ef71SVenkateswararao Jujjuri (JV) 	{Opt_posixacl, "posixacl"},
655e172f75SDinu-Razvan Chis-Serban 	{Opt_locktimeout, "locktimeout=%u"},
669e82cf6aSEric Van Hensbergen 	{Opt_err, NULL}
679e82cf6aSEric Van Hensbergen };
689e82cf6aSEric Van Hensbergen 
69a2dd43bbSPrem Karat /* Interpret mount options for cache mode */
get_cache_mode(char * s)70a2dd43bbSPrem Karat static int get_cache_mode(char *s)
71a2dd43bbSPrem Karat {
72a2dd43bbSPrem Karat 	int version = -EINVAL;
73a2dd43bbSPrem Karat 
74a2dd43bbSPrem Karat 	if (!strcmp(s, "loose")) {
75*4eb31178SEric Van Hensbergen 		version = CACHE_SC_LOOSE;
765d385153SJoe Perches 		p9_debug(P9_DEBUG_9P, "Cache mode: loose\n");
77a2dd43bbSPrem Karat 	} else if (!strcmp(s, "fscache")) {
78*4eb31178SEric Van Hensbergen 		version = CACHE_SC_FSCACHE;
795d385153SJoe Perches 		p9_debug(P9_DEBUG_9P, "Cache mode: fscache\n");
80fb89b45cSDominique Martinet 	} else if (!strcmp(s, "mmap")) {
81*4eb31178SEric Van Hensbergen 		version = CACHE_SC_MMAP;
82fb89b45cSDominique Martinet 		p9_debug(P9_DEBUG_9P, "Cache mode: mmap\n");
83d9bc0d11SEric Van Hensbergen 	} else if (!strcmp(s, "readahead")) {
84*4eb31178SEric Van Hensbergen 		version = CACHE_SC_READAHEAD;
85d9bc0d11SEric Van Hensbergen 		p9_debug(P9_DEBUG_9P, "Cache mode: readahead\n");
86a2dd43bbSPrem Karat 	} else if (!strcmp(s, "none")) {
87*4eb31178SEric Van Hensbergen 		version = CACHE_SC_NONE;
885d385153SJoe Perches 		p9_debug(P9_DEBUG_9P, "Cache mode: none\n");
89*4eb31178SEric Van Hensbergen 	} else if (kstrtoint(s, 0, &version) != 0) {
90*4eb31178SEric Van Hensbergen 		version = -EINVAL;
91*4eb31178SEric Van Hensbergen 		pr_info("Unknown Cache mode or invalid value %s\n", s);
92*4eb31178SEric Van Hensbergen 	}
93a2dd43bbSPrem Karat 	return version;
94a2dd43bbSPrem Karat }
95a2dd43bbSPrem Karat 
96c4fac910SDavid Howells /*
97c4fac910SDavid Howells  * Display the mount options in /proc/mounts.
98c4fac910SDavid Howells  */
v9fs_show_options(struct seq_file * m,struct dentry * root)99c4fac910SDavid Howells int v9fs_show_options(struct seq_file *m, struct dentry *root)
100c4fac910SDavid Howells {
101c4fac910SDavid Howells 	struct v9fs_session_info *v9ses = root->d_sb->s_fs_info;
102c4fac910SDavid Howells 
103c4fac910SDavid Howells 	if (v9ses->debug)
104c4fac910SDavid Howells 		seq_printf(m, ",debug=%x", v9ses->debug);
105c4fac910SDavid Howells 	if (!uid_eq(v9ses->dfltuid, V9FS_DEFUID))
106c4fac910SDavid Howells 		seq_printf(m, ",dfltuid=%u",
107c4fac910SDavid Howells 			   from_kuid_munged(&init_user_ns, v9ses->dfltuid));
108c4fac910SDavid Howells 	if (!gid_eq(v9ses->dfltgid, V9FS_DEFGID))
109c4fac910SDavid Howells 		seq_printf(m, ",dfltgid=%u",
110c4fac910SDavid Howells 			   from_kgid_munged(&init_user_ns, v9ses->dfltgid));
111c4fac910SDavid Howells 	if (v9ses->afid != ~0)
112c4fac910SDavid Howells 		seq_printf(m, ",afid=%u", v9ses->afid);
113c4fac910SDavid Howells 	if (strcmp(v9ses->uname, V9FS_DEFUSER) != 0)
114c4fac910SDavid Howells 		seq_printf(m, ",uname=%s", v9ses->uname);
115c4fac910SDavid Howells 	if (strcmp(v9ses->aname, V9FS_DEFANAME) != 0)
116c4fac910SDavid Howells 		seq_printf(m, ",aname=%s", v9ses->aname);
117c4fac910SDavid Howells 	if (v9ses->nodev)
118c4fac910SDavid Howells 		seq_puts(m, ",nodevmap");
119c4fac910SDavid Howells 	if (v9ses->cache)
120*4eb31178SEric Van Hensbergen 		seq_printf(m, ",cache=%x", v9ses->cache);
121c4fac910SDavid Howells #ifdef CONFIG_9P_FSCACHE
122*4eb31178SEric Van Hensbergen 	if (v9ses->cachetag && (v9ses->cache & CACHE_FSCACHE))
123c4fac910SDavid Howells 		seq_printf(m, ",cachetag=%s", v9ses->cachetag);
124c4fac910SDavid Howells #endif
125c4fac910SDavid Howells 
126c4fac910SDavid Howells 	switch (v9ses->flags & V9FS_ACCESS_MASK) {
127c4fac910SDavid Howells 	case V9FS_ACCESS_USER:
128c4fac910SDavid Howells 		seq_puts(m, ",access=user");
129c4fac910SDavid Howells 		break;
130c4fac910SDavid Howells 	case V9FS_ACCESS_ANY:
131c4fac910SDavid Howells 		seq_puts(m, ",access=any");
132c4fac910SDavid Howells 		break;
133c4fac910SDavid Howells 	case V9FS_ACCESS_CLIENT:
134c4fac910SDavid Howells 		seq_puts(m, ",access=client");
135c4fac910SDavid Howells 		break;
136c4fac910SDavid Howells 	case V9FS_ACCESS_SINGLE:
137c4fac910SDavid Howells 		seq_printf(m, ",access=%u",
138c4fac910SDavid Howells 			   from_kuid_munged(&init_user_ns, v9ses->uid));
139c4fac910SDavid Howells 		break;
140c4fac910SDavid Howells 	}
141c4fac910SDavid Howells 
1426deffc89SEric Van Hensbergen 	if (v9ses->flags & V9FS_IGNORE_QV)
1436deffc89SEric Van Hensbergen 		seq_puts(m, ",ignoreqv");
1446deffc89SEric Van Hensbergen 	if (v9ses->flags & V9FS_DIRECT_IO)
1456deffc89SEric Van Hensbergen 		seq_puts(m, ",directio");
146c4fac910SDavid Howells 	if (v9ses->flags & V9FS_POSIX_ACL)
147c4fac910SDavid Howells 		seq_puts(m, ",posixacl");
148c4fac910SDavid Howells 
1498142db4fSEric Van Hensbergen 	if (v9ses->flags & V9FS_NO_XATTR)
1508142db4fSEric Van Hensbergen 		seq_puts(m, ",noxattr");
1518142db4fSEric Van Hensbergen 
152c4fac910SDavid Howells 	return p9_show_client_options(m, v9ses->clnt);
153c4fac910SDavid Howells }
154c4fac910SDavid Howells 
1559e82cf6aSEric Van Hensbergen /**
1569e82cf6aSEric Van Hensbergen  * v9fs_parse_options - parse mount options into session structure
1579e82cf6aSEric Van Hensbergen  * @v9ses: existing v9fs session information
158bc868036SDavid Howells  * @opts: The mount option string
1599e82cf6aSEric Van Hensbergen  *
160ab31267dSJim Meyering  * Return 0 upon success, -ERRNO upon failure.
1619e82cf6aSEric Van Hensbergen  */
1629e82cf6aSEric Van Hensbergen 
v9fs_parse_options(struct v9fs_session_info * v9ses,char * opts)1634b53e4b5SAbhishek Kulkarni static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
1649e82cf6aSEric Van Hensbergen {
165d8c8a9e3SEric Van Hensbergen 	char *options, *tmp_options;
1669e82cf6aSEric Van Hensbergen 	substring_t args[MAX_OPT_ARGS];
167a80d923eSEric Van Hensbergen 	char *p;
1688a0dc95fSEric Van Hensbergen 	int option = 0;
16910c69a0dSDominique Martinet 	char *s;
170ab31267dSJim Meyering 	int ret = 0;
1719e82cf6aSEric Van Hensbergen 
1729e82cf6aSEric Van Hensbergen 	/* setup defaults */
1739e82cf6aSEric Van Hensbergen 	v9ses->afid = ~0;
1749e82cf6aSEric Van Hensbergen 	v9ses->debug = 0;
175a2dd43bbSPrem Karat 	v9ses->cache = CACHE_NONE;
17660e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE
17760e78d2cSAbhishek Kulkarni 	v9ses->cachetag = NULL;
17860e78d2cSAbhishek Kulkarni #endif
1795e172f75SDinu-Razvan Chis-Serban 	v9ses->session_lock_timeout = P9_LOCK_TIMEOUT;
1809e82cf6aSEric Van Hensbergen 
1814b53e4b5SAbhishek Kulkarni 	if (!opts)
182ab31267dSJim Meyering 		return 0;
1839e82cf6aSEric Van Hensbergen 
184d8c8a9e3SEric Van Hensbergen 	tmp_options = kstrdup(opts, GFP_KERNEL);
185bf2d29c6SEric Van Hensbergen 	if (!tmp_options) {
186bf2d29c6SEric Van Hensbergen 		ret = -ENOMEM;
18760e78d2cSAbhishek Kulkarni 		goto fail_option_alloc;
188bf2d29c6SEric Van Hensbergen 	}
189d8c8a9e3SEric Van Hensbergen 	options = tmp_options;
190ab31267dSJim Meyering 
1919e82cf6aSEric Van Hensbergen 	while ((p = strsep(&options, ",")) != NULL) {
1924d5077f1SAneesh Kumar K.V 		int token, r;
1936e195b0fSDominique Martinet 
1949e82cf6aSEric Van Hensbergen 		if (!*p)
1959e82cf6aSEric Van Hensbergen 			continue;
1966e195b0fSDominique Martinet 
1979e82cf6aSEric Van Hensbergen 		token = match_token(p, tokens, args);
1984d5077f1SAneesh Kumar K.V 		switch (token) {
1994d5077f1SAneesh Kumar K.V 		case Opt_debug:
2004d5077f1SAneesh Kumar K.V 			r = match_int(&args[0], &option);
201ab31267dSJim Meyering 			if (r < 0) {
2025d385153SJoe Perches 				p9_debug(P9_DEBUG_ERROR,
2039e82cf6aSEric Van Hensbergen 					 "integer field, but no integer?\n");
204ab31267dSJim Meyering 				ret = r;
205478ae0caSChengguang Xu 			} else {
2069e2f6688SEric Van Hensbergen 				v9ses->debug = option;
20710fa16e7SEric Van Hensbergen #ifdef CONFIG_NET_9P_DEBUG
2089e2f6688SEric Van Hensbergen 				p9_debug_level = option;
20910fa16e7SEric Van Hensbergen #endif
210478ae0caSChengguang Xu 			}
2119e2f6688SEric Van Hensbergen 			break;
2128a0dc95fSEric Van Hensbergen 
213bd32b82dSLatchesar Ionkov 		case Opt_dfltuid:
2144d5077f1SAneesh Kumar K.V 			r = match_int(&args[0], &option);
2154d5077f1SAneesh Kumar K.V 			if (r < 0) {
2165d385153SJoe Perches 				p9_debug(P9_DEBUG_ERROR,
2174d5077f1SAneesh Kumar K.V 					 "integer field, but no integer?\n");
2184d5077f1SAneesh Kumar K.V 				ret = r;
2194d5077f1SAneesh Kumar K.V 				continue;
2204d5077f1SAneesh Kumar K.V 			}
22176ed23a5SEric W. Biederman 			v9ses->dfltuid = make_kuid(current_user_ns(), option);
22276ed23a5SEric W. Biederman 			if (!uid_valid(v9ses->dfltuid)) {
22376ed23a5SEric W. Biederman 				p9_debug(P9_DEBUG_ERROR,
22476ed23a5SEric W. Biederman 					 "uid field, but not a uid?\n");
22576ed23a5SEric W. Biederman 				ret = -EINVAL;
22676ed23a5SEric W. Biederman 			}
2279e82cf6aSEric Van Hensbergen 			break;
228bd32b82dSLatchesar Ionkov 		case Opt_dfltgid:
2294d5077f1SAneesh Kumar K.V 			r = match_int(&args[0], &option);
2304d5077f1SAneesh Kumar K.V 			if (r < 0) {
2315d385153SJoe Perches 				p9_debug(P9_DEBUG_ERROR,
2324d5077f1SAneesh Kumar K.V 					 "integer field, but no integer?\n");
2334d5077f1SAneesh Kumar K.V 				ret = r;
2344d5077f1SAneesh Kumar K.V 				continue;
2354d5077f1SAneesh Kumar K.V 			}
23676ed23a5SEric W. Biederman 			v9ses->dfltgid = make_kgid(current_user_ns(), option);
23776ed23a5SEric W. Biederman 			if (!gid_valid(v9ses->dfltgid)) {
23876ed23a5SEric W. Biederman 				p9_debug(P9_DEBUG_ERROR,
23976ed23a5SEric W. Biederman 					 "gid field, but not a gid?\n");
24076ed23a5SEric W. Biederman 				ret = -EINVAL;
24176ed23a5SEric W. Biederman 			}
2429e82cf6aSEric Van Hensbergen 			break;
2439e82cf6aSEric Van Hensbergen 		case Opt_afid:
2444d5077f1SAneesh Kumar K.V 			r = match_int(&args[0], &option);
2454d5077f1SAneesh Kumar K.V 			if (r < 0) {
2465d385153SJoe Perches 				p9_debug(P9_DEBUG_ERROR,
2474d5077f1SAneesh Kumar K.V 					 "integer field, but no integer?\n");
2484d5077f1SAneesh Kumar K.V 				ret = r;
249478ae0caSChengguang Xu 			} else {
2509e82cf6aSEric Van Hensbergen 				v9ses->afid = option;
251478ae0caSChengguang Xu 			}
2529e82cf6aSEric Van Hensbergen 			break;
25367543e50SEric Van Hensbergen 		case Opt_uname:
254e549c133SJeff Layton 			kfree(v9ses->uname);
255e549c133SJeff Layton 			v9ses->uname = match_strdup(&args[0]);
256e549c133SJeff Layton 			if (!v9ses->uname) {
257e549c133SJeff Layton 				ret = -ENOMEM;
258e549c133SJeff Layton 				goto free_and_return;
259e549c133SJeff Layton 			}
2609e82cf6aSEric Van Hensbergen 			break;
2619e82cf6aSEric Van Hensbergen 		case Opt_remotename:
262e549c133SJeff Layton 			kfree(v9ses->aname);
263e549c133SJeff Layton 			v9ses->aname = match_strdup(&args[0]);
264e549c133SJeff Layton 			if (!v9ses->aname) {
265e549c133SJeff Layton 				ret = -ENOMEM;
266e549c133SJeff Layton 				goto free_and_return;
267e549c133SJeff Layton 			}
2689e82cf6aSEric Van Hensbergen 			break;
2699e82cf6aSEric Van Hensbergen 		case Opt_nodevmap:
2709e82cf6aSEric Van Hensbergen 			v9ses->nodev = 1;
2719e82cf6aSEric Van Hensbergen 			break;
2728142db4fSEric Van Hensbergen 		case Opt_noxattr:
2738142db4fSEric Van Hensbergen 			v9ses->flags |= V9FS_NO_XATTR;
2748142db4fSEric Van Hensbergen 			break;
2756deffc89SEric Van Hensbergen 		case Opt_directio:
2766deffc89SEric Van Hensbergen 			v9ses->flags |= V9FS_DIRECT_IO;
2776deffc89SEric Van Hensbergen 			break;
2786deffc89SEric Van Hensbergen 		case Opt_ignoreqv:
2796deffc89SEric Van Hensbergen 			v9ses->flags |= V9FS_IGNORE_QV;
2806deffc89SEric Van Hensbergen 			break;
28160e78d2cSAbhishek Kulkarni 		case Opt_cachetag:
28260e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE
283c4fac910SDavid Howells 			kfree(v9ses->cachetag);
28460e78d2cSAbhishek Kulkarni 			v9ses->cachetag = match_strdup(&args[0]);
285a25c3657SChengguang Xu 			if (!v9ses->cachetag) {
286a25c3657SChengguang Xu 				ret = -ENOMEM;
287a25c3657SChengguang Xu 				goto free_and_return;
288a25c3657SChengguang Xu 			}
28960e78d2cSAbhishek Kulkarni #endif
29060e78d2cSAbhishek Kulkarni 			break;
29160e78d2cSAbhishek Kulkarni 		case Opt_cache:
29260e78d2cSAbhishek Kulkarni 			s = match_strdup(&args[0]);
293bf2d29c6SEric Van Hensbergen 			if (!s) {
294bf2d29c6SEric Van Hensbergen 				ret = -ENOMEM;
2955d385153SJoe Perches 				p9_debug(P9_DEBUG_ERROR,
296bf2d29c6SEric Van Hensbergen 					 "problem allocating copy of cache arg\n");
297bf2d29c6SEric Van Hensbergen 				goto free_and_return;
298bf2d29c6SEric Van Hensbergen 			}
299478ae0caSChengguang Xu 			r = get_cache_mode(s);
300478ae0caSChengguang Xu 			if (r < 0)
301478ae0caSChengguang Xu 				ret = r;
302478ae0caSChengguang Xu 			else
303478ae0caSChengguang Xu 				v9ses->cache = r;
30460e78d2cSAbhishek Kulkarni 
30560e78d2cSAbhishek Kulkarni 			kfree(s);
30660e78d2cSAbhishek Kulkarni 			break;
307ba17674fSLatchesar Ionkov 
308ba17674fSLatchesar Ionkov 		case Opt_access:
309ba17674fSLatchesar Ionkov 			s = match_strdup(&args[0]);
310bf2d29c6SEric Van Hensbergen 			if (!s) {
311bf2d29c6SEric Van Hensbergen 				ret = -ENOMEM;
3125d385153SJoe Perches 				p9_debug(P9_DEBUG_ERROR,
313bf2d29c6SEric Van Hensbergen 					 "problem allocating copy of access arg\n");
314bf2d29c6SEric Van Hensbergen 				goto free_and_return;
315bf2d29c6SEric Van Hensbergen 			}
31660e78d2cSAbhishek Kulkarni 
317ba17674fSLatchesar Ionkov 			v9ses->flags &= ~V9FS_ACCESS_MASK;
318ba17674fSLatchesar Ionkov 			if (strcmp(s, "user") == 0)
319ba17674fSLatchesar Ionkov 				v9ses->flags |= V9FS_ACCESS_USER;
320ba17674fSLatchesar Ionkov 			else if (strcmp(s, "any") == 0)
321ba17674fSLatchesar Ionkov 				v9ses->flags |= V9FS_ACCESS_ANY;
32276381a42SAneesh Kumar K.V 			else if (strcmp(s, "client") == 0) {
32376381a42SAneesh Kumar K.V 				v9ses->flags |= V9FS_ACCESS_CLIENT;
32476381a42SAneesh Kumar K.V 			} else {
32576ed23a5SEric W. Biederman 				uid_t uid;
32610c69a0dSDominique Martinet 
327ba17674fSLatchesar Ionkov 				v9ses->flags |= V9FS_ACCESS_SINGLE;
32810c69a0dSDominique Martinet 				r = kstrtouint(s, 10, &uid);
32910c69a0dSDominique Martinet 				if (r) {
33010c69a0dSDominique Martinet 					ret = r;
33110c69a0dSDominique Martinet 					pr_info("Unknown access argument %s: %d\n",
33210c69a0dSDominique Martinet 						s, r);
333a2dd43bbSPrem Karat 					kfree(s);
334478ae0caSChengguang Xu 					continue;
335ba17674fSLatchesar Ionkov 				}
33676ed23a5SEric W. Biederman 				v9ses->uid = make_kuid(current_user_ns(), uid);
33776ed23a5SEric W. Biederman 				if (!uid_valid(v9ses->uid)) {
33876ed23a5SEric W. Biederman 					ret = -EINVAL;
3396baaac09SColin Ian King 					pr_info("Unknown uid %s\n", s);
34076ed23a5SEric W. Biederman 				}
341a2dd43bbSPrem Karat 			}
342a2dd43bbSPrem Karat 
3430a976297SAdrian Bunk 			kfree(s);
344ba17674fSLatchesar Ionkov 			break;
345ba17674fSLatchesar Ionkov 
346e782ef71SVenkateswararao Jujjuri (JV) 		case Opt_posixacl:
347e782ef71SVenkateswararao Jujjuri (JV) #ifdef CONFIG_9P_FS_POSIX_ACL
348e782ef71SVenkateswararao Jujjuri (JV) 			v9ses->flags |= V9FS_POSIX_ACL;
349e782ef71SVenkateswararao Jujjuri (JV) #else
3505d385153SJoe Perches 			p9_debug(P9_DEBUG_ERROR,
3515d385153SJoe Perches 				 "Not defined CONFIG_9P_FS_POSIX_ACL. Ignoring posixacl option\n");
352e782ef71SVenkateswararao Jujjuri (JV) #endif
353e782ef71SVenkateswararao Jujjuri (JV) 			break;
354e782ef71SVenkateswararao Jujjuri (JV) 
3555e172f75SDinu-Razvan Chis-Serban 		case Opt_locktimeout:
3565e172f75SDinu-Razvan Chis-Serban 			r = match_int(&args[0], &option);
3575e172f75SDinu-Razvan Chis-Serban 			if (r < 0) {
3585e172f75SDinu-Razvan Chis-Serban 				p9_debug(P9_DEBUG_ERROR,
3595e172f75SDinu-Razvan Chis-Serban 					 "integer field, but no integer?\n");
3605e172f75SDinu-Razvan Chis-Serban 				ret = r;
3615e172f75SDinu-Razvan Chis-Serban 				continue;
3625e172f75SDinu-Razvan Chis-Serban 			}
3635e172f75SDinu-Razvan Chis-Serban 			if (option < 1) {
3645e172f75SDinu-Razvan Chis-Serban 				p9_debug(P9_DEBUG_ERROR,
3655e172f75SDinu-Razvan Chis-Serban 					 "locktimeout must be a greater than zero integer.\n");
3665e172f75SDinu-Razvan Chis-Serban 				ret = -EINVAL;
3675e172f75SDinu-Razvan Chis-Serban 				continue;
3685e172f75SDinu-Razvan Chis-Serban 			}
3695e172f75SDinu-Razvan Chis-Serban 			v9ses->session_lock_timeout = (long)option * HZ;
3705e172f75SDinu-Razvan Chis-Serban 			break;
3715e172f75SDinu-Razvan Chis-Serban 
3729e82cf6aSEric Van Hensbergen 		default:
3739e82cf6aSEric Van Hensbergen 			continue;
3749e82cf6aSEric Van Hensbergen 		}
3759e82cf6aSEric Van Hensbergen 	}
376d8c8a9e3SEric Van Hensbergen 
377bf2d29c6SEric Van Hensbergen free_and_return:
378d8c8a9e3SEric Van Hensbergen 	kfree(tmp_options);
37960e78d2cSAbhishek Kulkarni fail_option_alloc:
380bf2d29c6SEric Van Hensbergen 	return ret;
3819e82cf6aSEric Van Hensbergen }
3829e82cf6aSEric Van Hensbergen 
3839e82cf6aSEric Van Hensbergen /**
3849e82cf6aSEric Van Hensbergen  * v9fs_session_init - initialize session
3859e82cf6aSEric Van Hensbergen  * @v9ses: session information structure
3869e82cf6aSEric Van Hensbergen  * @dev_name: device being mounted
3879e82cf6aSEric Van Hensbergen  * @data: options
3889e82cf6aSEric Van Hensbergen  *
3899e82cf6aSEric Van Hensbergen  */
3909e82cf6aSEric Van Hensbergen 
v9fs_session_init(struct v9fs_session_info * v9ses,const char * dev_name,char * data)391bd238fb4SLatchesar Ionkov struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
3929e82cf6aSEric Van Hensbergen 		  const char *dev_name, char *data)
3939e82cf6aSEric Van Hensbergen {
394bd238fb4SLatchesar Ionkov 	struct p9_fid *fid;
395412a19b6STejun Heo 	int rc = -ENOMEM;
3969e82cf6aSEric Van Hensbergen 
397e549c133SJeff Layton 	v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL);
398ba17674fSLatchesar Ionkov 	if (!v9ses->uname)
399412a19b6STejun Heo 		goto err_names;
4009e82cf6aSEric Van Hensbergen 
401e549c133SJeff Layton 	v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL);
402412a19b6STejun Heo 	if (!v9ses->aname)
403412a19b6STejun Heo 		goto err_names;
404a534c8d1SAneesh Kumar K.V 	init_rwsem(&v9ses->rename_sem);
4059e82cf6aSEric Van Hensbergen 
40676ed23a5SEric W. Biederman 	v9ses->uid = INVALID_UID;
407bd32b82dSLatchesar Ionkov 	v9ses->dfltuid = V9FS_DEFUID;
408bd32b82dSLatchesar Ionkov 	v9ses->dfltgid = V9FS_DEFGID;
409ab31267dSJim Meyering 
4104b53e4b5SAbhishek Kulkarni 	v9ses->clnt = p9_client_create(dev_name, data);
411bd238fb4SLatchesar Ionkov 	if (IS_ERR(v9ses->clnt)) {
412412a19b6STejun Heo 		rc = PTR_ERR(v9ses->clnt);
4135d385153SJoe Perches 		p9_debug(P9_DEBUG_ERROR, "problem initializing 9p client\n");
41471304febSJan Kara 		goto err_names;
4159e82cf6aSEric Van Hensbergen 	}
4169e82cf6aSEric Van Hensbergen 
4176752a1ebSVenkateswararao Jujjuri (JV) 	v9ses->flags = V9FS_ACCESS_USER;
4186752a1ebSVenkateswararao Jujjuri (JV) 
4196752a1ebSVenkateswararao Jujjuri (JV) 	if (p9_is_proto_dotl(v9ses->clnt)) {
4206752a1ebSVenkateswararao Jujjuri (JV) 		v9ses->flags = V9FS_ACCESS_CLIENT;
421476ada04SSripathi Kodi 		v9ses->flags |= V9FS_PROTO_2000L;
4226752a1ebSVenkateswararao Jujjuri (JV) 	} else if (p9_is_proto_dotu(v9ses->clnt)) {
423476ada04SSripathi Kodi 		v9ses->flags |= V9FS_PROTO_2000U;
4246752a1ebSVenkateswararao Jujjuri (JV) 	}
4256752a1ebSVenkateswararao Jujjuri (JV) 
4266752a1ebSVenkateswararao Jujjuri (JV) 	rc = v9fs_parse_options(v9ses, data);
427412a19b6STejun Heo 	if (rc < 0)
428412a19b6STejun Heo 		goto err_clnt;
429ba17674fSLatchesar Ionkov 
430fbedadc1SEric Van Hensbergen 	v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ;
4318a0dc95fSEric Van Hensbergen 
43276381a42SAneesh Kumar K.V 	if (!v9fs_proto_dotl(v9ses) &&
43376381a42SAneesh Kumar K.V 	    ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) {
43476381a42SAneesh Kumar K.V 		/*
43576381a42SAneesh Kumar K.V 		 * We support ACCESS_CLIENT only for dotl.
43676381a42SAneesh Kumar K.V 		 * Fall back to ACCESS_USER
43776381a42SAneesh Kumar K.V 		 */
43876381a42SAneesh Kumar K.V 		v9ses->flags &= ~V9FS_ACCESS_MASK;
43976381a42SAneesh Kumar K.V 		v9ses->flags |= V9FS_ACCESS_USER;
44076381a42SAneesh Kumar K.V 	}
44176381a42SAneesh Kumar K.V 	/*FIXME !! */
442ba17674fSLatchesar Ionkov 	/* for legacy mode, fall back to V9FS_ACCESS_ANY */
4439ffaf63eSAneesh Kumar K.V 	if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) &&
444ba17674fSLatchesar Ionkov 		((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {
445ba17674fSLatchesar Ionkov 
446ba17674fSLatchesar Ionkov 		v9ses->flags &= ~V9FS_ACCESS_MASK;
447ba17674fSLatchesar Ionkov 		v9ses->flags |= V9FS_ACCESS_ANY;
44876ed23a5SEric W. Biederman 		v9ses->uid = INVALID_UID;
449ba17674fSLatchesar Ionkov 	}
450e782ef71SVenkateswararao Jujjuri (JV) 	if (!v9fs_proto_dotl(v9ses) ||
451e782ef71SVenkateswararao Jujjuri (JV) 		!((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) {
452e782ef71SVenkateswararao Jujjuri (JV) 		/*
453e782ef71SVenkateswararao Jujjuri (JV) 		 * We support ACL checks on clinet only if the protocol is
454e782ef71SVenkateswararao Jujjuri (JV) 		 * 9P2000.L and access is V9FS_ACCESS_CLIENT.
455e782ef71SVenkateswararao Jujjuri (JV) 		 */
456e782ef71SVenkateswararao Jujjuri (JV) 		v9ses->flags &= ~V9FS_ACL_MASK;
457e782ef71SVenkateswararao Jujjuri (JV) 	}
458ba17674fSLatchesar Ionkov 
459f791f7c5SEric W. Biederman 	fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, INVALID_UID,
460ba17674fSLatchesar Ionkov 							v9ses->aname);
461bd238fb4SLatchesar Ionkov 	if (IS_ERR(fid)) {
462412a19b6STejun Heo 		rc = PTR_ERR(fid);
4635d385153SJoe Perches 		p9_debug(P9_DEBUG_ERROR, "cannot attach\n");
464412a19b6STejun Heo 		goto err_clnt;
4659e82cf6aSEric Van Hensbergen 	}
4669e82cf6aSEric Van Hensbergen 
467ba17674fSLatchesar Ionkov 	if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_SINGLE)
468ba17674fSLatchesar Ionkov 		fid->uid = v9ses->uid;
469ba17674fSLatchesar Ionkov 	else
470b4642556SEric W. Biederman 		fid->uid = INVALID_UID;
471ba17674fSLatchesar Ionkov 
47260e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE
47360e78d2cSAbhishek Kulkarni 	/* register the session for caching */
474*4eb31178SEric Van Hensbergen 	if (v9ses->cache & CACHE_FSCACHE) {
47524e42e32SDavid Howells 		rc = v9fs_cache_session_get_cookie(v9ses, dev_name);
47624e42e32SDavid Howells 		if (rc < 0)
47724e42e32SDavid Howells 			goto err_clnt;
47824e42e32SDavid Howells 	}
47960e78d2cSAbhishek Kulkarni #endif
480412a19b6STejun Heo 	spin_lock(&v9fs_sessionlist_lock);
481412a19b6STejun Heo 	list_add(&v9ses->slist, &v9fs_sessionlist);
482412a19b6STejun Heo 	spin_unlock(&v9fs_sessionlist_lock);
48360e78d2cSAbhishek Kulkarni 
484bd238fb4SLatchesar Ionkov 	return fid;
4859e82cf6aSEric Van Hensbergen 
486412a19b6STejun Heo err_clnt:
487a25c3657SChengguang Xu #ifdef CONFIG_9P_FSCACHE
488a25c3657SChengguang Xu 	kfree(v9ses->cachetag);
489a25c3657SChengguang Xu #endif
490412a19b6STejun Heo 	p9_client_destroy(v9ses->clnt);
491412a19b6STejun Heo err_names:
492412a19b6STejun Heo 	kfree(v9ses->uname);
493412a19b6STejun Heo 	kfree(v9ses->aname);
494412a19b6STejun Heo 	return ERR_PTR(rc);
4959e82cf6aSEric Van Hensbergen }
4969e82cf6aSEric Van Hensbergen 
4979e82cf6aSEric Van Hensbergen /**
4989e82cf6aSEric Van Hensbergen  * v9fs_session_close - shutdown a session
4999e82cf6aSEric Van Hensbergen  * @v9ses: session information structure
5009e82cf6aSEric Van Hensbergen  *
5019e82cf6aSEric Van Hensbergen  */
5029e82cf6aSEric Van Hensbergen 
v9fs_session_close(struct v9fs_session_info * v9ses)5039e82cf6aSEric Van Hensbergen void v9fs_session_close(struct v9fs_session_info *v9ses)
5049e82cf6aSEric Van Hensbergen {
505bd238fb4SLatchesar Ionkov 	if (v9ses->clnt) {
506bd238fb4SLatchesar Ionkov 		p9_client_destroy(v9ses->clnt);
507bd238fb4SLatchesar Ionkov 		v9ses->clnt = NULL;
5083cf6429aSLatchesar Ionkov 	}
5099e82cf6aSEric Van Hensbergen 
51060e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE
51124e42e32SDavid Howells 	fscache_relinquish_volume(v9fs_session_cache(v9ses), NULL, false);
51260e78d2cSAbhishek Kulkarni 	kfree(v9ses->cachetag);
51360e78d2cSAbhishek Kulkarni #endif
514e549c133SJeff Layton 	kfree(v9ses->uname);
515e549c133SJeff Layton 	kfree(v9ses->aname);
51660e78d2cSAbhishek Kulkarni 
51760e78d2cSAbhishek Kulkarni 	spin_lock(&v9fs_sessionlist_lock);
51860e78d2cSAbhishek Kulkarni 	list_del(&v9ses->slist);
51960e78d2cSAbhishek Kulkarni 	spin_unlock(&v9fs_sessionlist_lock);
5209e82cf6aSEric Van Hensbergen }
5219e82cf6aSEric Van Hensbergen 
522322b329aSEric Van Hensbergen /**
523ee443996SEric Van Hensbergen  * v9fs_session_cancel - terminate a session
524ee443996SEric Van Hensbergen  * @v9ses: session to terminate
525ee443996SEric Van Hensbergen  *
526ee443996SEric Van Hensbergen  * mark transport as disconnected and cancel all pending requests.
527322b329aSEric Van Hensbergen  */
528ee443996SEric Van Hensbergen 
v9fs_session_cancel(struct v9fs_session_info * v9ses)529e4eeefbaSSohaib Mohamed void v9fs_session_cancel(struct v9fs_session_info *v9ses)
530e4eeefbaSSohaib Mohamed {
5315d385153SJoe Perches 	p9_debug(P9_DEBUG_ERROR, "cancel session %p\n", v9ses);
532bd238fb4SLatchesar Ionkov 	p9_client_disconnect(v9ses->clnt);
533322b329aSEric Van Hensbergen }
534322b329aSEric Van Hensbergen 
5356d96d3abSAneesh Kumar K.V /**
5366d96d3abSAneesh Kumar K.V  * v9fs_session_begin_cancel - Begin terminate of a session
5376d96d3abSAneesh Kumar K.V  * @v9ses: session to terminate
5386d96d3abSAneesh Kumar K.V  *
5396d96d3abSAneesh Kumar K.V  * After this call we don't allow any request other than clunk.
5406d96d3abSAneesh Kumar K.V  */
5416d96d3abSAneesh Kumar K.V 
v9fs_session_begin_cancel(struct v9fs_session_info * v9ses)5426d96d3abSAneesh Kumar K.V void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses)
5436d96d3abSAneesh Kumar K.V {
5445d385153SJoe Perches 	p9_debug(P9_DEBUG_ERROR, "begin cancel session %p\n", v9ses);
5456d96d3abSAneesh Kumar K.V 	p9_client_begin_disconnect(v9ses->clnt);
5466d96d3abSAneesh Kumar K.V }
5476d96d3abSAneesh Kumar K.V 
54860e78d2cSAbhishek Kulkarni static struct kobject *v9fs_kobj;
54960e78d2cSAbhishek Kulkarni 
55060e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE
551bc868036SDavid Howells /*
552bc868036SDavid Howells  * List caches associated with a session
55360e78d2cSAbhishek Kulkarni  */
caches_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)55460e78d2cSAbhishek Kulkarni static ssize_t caches_show(struct kobject *kobj,
55560e78d2cSAbhishek Kulkarni 			   struct kobj_attribute *attr,
55660e78d2cSAbhishek Kulkarni 			   char *buf)
55760e78d2cSAbhishek Kulkarni {
55860e78d2cSAbhishek Kulkarni 	ssize_t n = 0, count = 0, limit = PAGE_SIZE;
55960e78d2cSAbhishek Kulkarni 	struct v9fs_session_info *v9ses;
56060e78d2cSAbhishek Kulkarni 
56160e78d2cSAbhishek Kulkarni 	spin_lock(&v9fs_sessionlist_lock);
56260e78d2cSAbhishek Kulkarni 	list_for_each_entry(v9ses, &v9fs_sessionlist, slist) {
56360e78d2cSAbhishek Kulkarni 		if (v9ses->cachetag) {
56460e78d2cSAbhishek Kulkarni 			n = snprintf(buf, limit, "%s\n", v9ses->cachetag);
56560e78d2cSAbhishek Kulkarni 			if (n < 0) {
56660e78d2cSAbhishek Kulkarni 				count = n;
56760e78d2cSAbhishek Kulkarni 				break;
56860e78d2cSAbhishek Kulkarni 			}
56960e78d2cSAbhishek Kulkarni 
57060e78d2cSAbhishek Kulkarni 			count += n;
57160e78d2cSAbhishek Kulkarni 			limit -= n;
57260e78d2cSAbhishek Kulkarni 		}
57360e78d2cSAbhishek Kulkarni 	}
57460e78d2cSAbhishek Kulkarni 
57560e78d2cSAbhishek Kulkarni 	spin_unlock(&v9fs_sessionlist_lock);
57660e78d2cSAbhishek Kulkarni 	return count;
57760e78d2cSAbhishek Kulkarni }
57860e78d2cSAbhishek Kulkarni 
57960e78d2cSAbhishek Kulkarni static struct kobj_attribute v9fs_attr_cache = __ATTR_RO(caches);
58060e78d2cSAbhishek Kulkarni #endif /* CONFIG_9P_FSCACHE */
58160e78d2cSAbhishek Kulkarni 
58260e78d2cSAbhishek Kulkarni static struct attribute *v9fs_attrs[] = {
58360e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE
58460e78d2cSAbhishek Kulkarni 	&v9fs_attr_cache.attr,
58560e78d2cSAbhishek Kulkarni #endif
58660e78d2cSAbhishek Kulkarni 	NULL,
58760e78d2cSAbhishek Kulkarni };
58860e78d2cSAbhishek Kulkarni 
5890dae5228SRikard Falkeborn static const struct attribute_group v9fs_attr_group = {
59060e78d2cSAbhishek Kulkarni 	.attrs = v9fs_attrs,
59160e78d2cSAbhishek Kulkarni };
59260e78d2cSAbhishek Kulkarni 
59360e78d2cSAbhishek Kulkarni /**
59460e78d2cSAbhishek Kulkarni  * v9fs_sysfs_init - Initialize the v9fs sysfs interface
59560e78d2cSAbhishek Kulkarni  *
59660e78d2cSAbhishek Kulkarni  */
59760e78d2cSAbhishek Kulkarni 
v9fs_sysfs_init(void)598bdbeacdeSFabian Frederick static int __init v9fs_sysfs_init(void)
59960e78d2cSAbhishek Kulkarni {
60060e78d2cSAbhishek Kulkarni 	v9fs_kobj = kobject_create_and_add("9p", fs_kobj);
60160e78d2cSAbhishek Kulkarni 	if (!v9fs_kobj)
60260e78d2cSAbhishek Kulkarni 		return -ENOMEM;
60360e78d2cSAbhishek Kulkarni 
60460e78d2cSAbhishek Kulkarni 	if (sysfs_create_group(v9fs_kobj, &v9fs_attr_group)) {
60560e78d2cSAbhishek Kulkarni 		kobject_put(v9fs_kobj);
60660e78d2cSAbhishek Kulkarni 		return -ENOMEM;
60760e78d2cSAbhishek Kulkarni 	}
60860e78d2cSAbhishek Kulkarni 
60960e78d2cSAbhishek Kulkarni 	return 0;
61060e78d2cSAbhishek Kulkarni }
61160e78d2cSAbhishek Kulkarni 
61260e78d2cSAbhishek Kulkarni /**
61360e78d2cSAbhishek Kulkarni  * v9fs_sysfs_cleanup - Unregister the v9fs sysfs interface
61460e78d2cSAbhishek Kulkarni  *
61560e78d2cSAbhishek Kulkarni  */
61660e78d2cSAbhishek Kulkarni 
v9fs_sysfs_cleanup(void)61760e78d2cSAbhishek Kulkarni static void v9fs_sysfs_cleanup(void)
61860e78d2cSAbhishek Kulkarni {
61960e78d2cSAbhishek Kulkarni 	sysfs_remove_group(v9fs_kobj, &v9fs_attr_group);
62060e78d2cSAbhishek Kulkarni 	kobject_put(v9fs_kobj);
62160e78d2cSAbhishek Kulkarni }
62260e78d2cSAbhishek Kulkarni 
v9fs_inode_init_once(void * foo)623a78ce05dSAneesh Kumar K.V static void v9fs_inode_init_once(void *foo)
624a78ce05dSAneesh Kumar K.V {
625a78ce05dSAneesh Kumar K.V 	struct v9fs_inode *v9inode = (struct v9fs_inode *)foo;
626bc899ee1SDavid Howells 
627fd2421f5SAneesh Kumar K.V 	memset(&v9inode->qid, 0, sizeof(v9inode->qid));
628874c8ca1SDavid Howells 	inode_init_once(&v9inode->netfs.inode);
629a78ce05dSAneesh Kumar K.V }
630a78ce05dSAneesh Kumar K.V 
631a78ce05dSAneesh Kumar K.V /**
632a78ce05dSAneesh Kumar K.V  * v9fs_init_inode_cache - initialize a cache for 9P
633a78ce05dSAneesh Kumar K.V  * Returns 0 on success.
634a78ce05dSAneesh Kumar K.V  */
v9fs_init_inode_cache(void)635a78ce05dSAneesh Kumar K.V static int v9fs_init_inode_cache(void)
636a78ce05dSAneesh Kumar K.V {
637a78ce05dSAneesh Kumar K.V 	v9fs_inode_cache = kmem_cache_create("v9fs_inode_cache",
638a78ce05dSAneesh Kumar K.V 					  sizeof(struct v9fs_inode),
639a78ce05dSAneesh Kumar K.V 					  0, (SLAB_RECLAIM_ACCOUNT|
6405d097056SVladimir Davydov 					      SLAB_MEM_SPREAD|SLAB_ACCOUNT),
641a78ce05dSAneesh Kumar K.V 					  v9fs_inode_init_once);
642a78ce05dSAneesh Kumar K.V 	if (!v9fs_inode_cache)
643a78ce05dSAneesh Kumar K.V 		return -ENOMEM;
644a78ce05dSAneesh Kumar K.V 
645a78ce05dSAneesh Kumar K.V 	return 0;
646a78ce05dSAneesh Kumar K.V }
647a78ce05dSAneesh Kumar K.V 
648a78ce05dSAneesh Kumar K.V /**
649a78ce05dSAneesh Kumar K.V  * v9fs_destroy_inode_cache - destroy the cache of 9P inode
650a78ce05dSAneesh Kumar K.V  *
651a78ce05dSAneesh Kumar K.V  */
v9fs_destroy_inode_cache(void)652a78ce05dSAneesh Kumar K.V static void v9fs_destroy_inode_cache(void)
653a78ce05dSAneesh Kumar K.V {
6548c0a8537SKirill A. Shutemov 	/*
6558c0a8537SKirill A. Shutemov 	 * Make sure all delayed rcu free inodes are flushed before we
6568c0a8537SKirill A. Shutemov 	 * destroy cache.
6578c0a8537SKirill A. Shutemov 	 */
6588c0a8537SKirill A. Shutemov 	rcu_barrier();
659a78ce05dSAneesh Kumar K.V 	kmem_cache_destroy(v9fs_inode_cache);
660a78ce05dSAneesh Kumar K.V }
661a78ce05dSAneesh Kumar K.V 
v9fs_cache_register(void)662a78ce05dSAneesh Kumar K.V static int v9fs_cache_register(void)
663a78ce05dSAneesh Kumar K.V {
664a78ce05dSAneesh Kumar K.V 	int ret;
6656e195b0fSDominique Martinet 
666a78ce05dSAneesh Kumar K.V 	ret = v9fs_init_inode_cache();
667a78ce05dSAneesh Kumar K.V 	if (ret < 0)
668a78ce05dSAneesh Kumar K.V 		return ret;
6698061a6faSAl Viro 	return ret;
670a78ce05dSAneesh Kumar K.V }
671a78ce05dSAneesh Kumar K.V 
v9fs_cache_unregister(void)672a78ce05dSAneesh Kumar K.V static void v9fs_cache_unregister(void)
673a78ce05dSAneesh Kumar K.V {
674a78ce05dSAneesh Kumar K.V 	v9fs_destroy_inode_cache();
675a78ce05dSAneesh Kumar K.V }
676a78ce05dSAneesh Kumar K.V 
67760e78d2cSAbhishek Kulkarni /**
67860e78d2cSAbhishek Kulkarni  * init_v9fs - Initialize module
6799e82cf6aSEric Van Hensbergen  *
6809e82cf6aSEric Van Hensbergen  */
6819e82cf6aSEric Van Hensbergen 
init_v9fs(void)6829e82cf6aSEric Van Hensbergen static int __init init_v9fs(void)
6839e82cf6aSEric Van Hensbergen {
68460e78d2cSAbhishek Kulkarni 	int err;
6856e195b0fSDominique Martinet 
6865d385153SJoe Perches 	pr_info("Installing v9fs 9p2000 file system support\n");
687a80d923eSEric Van Hensbergen 	/* TODO: Setup list of registered trasnport modules */
68860e78d2cSAbhishek Kulkarni 
68960e78d2cSAbhishek Kulkarni 	err = v9fs_cache_register();
69060e78d2cSAbhishek Kulkarni 	if (err < 0) {
6915d385153SJoe Perches 		pr_err("Failed to register v9fs for caching\n");
6922226a288SAl Viro 		return err;
69360e78d2cSAbhishek Kulkarni 	}
69460e78d2cSAbhishek Kulkarni 
69560e78d2cSAbhishek Kulkarni 	err = v9fs_sysfs_init();
69660e78d2cSAbhishek Kulkarni 	if (err < 0) {
6975d385153SJoe Perches 		pr_err("Failed to register with sysfs\n");
6982226a288SAl Viro 		goto out_cache;
6992226a288SAl Viro 	}
7002226a288SAl Viro 	err = register_filesystem(&v9fs_fs_type);
7012226a288SAl Viro 	if (err < 0) {
7022226a288SAl Viro 		pr_err("Failed to register filesystem\n");
70360e78d2cSAbhishek Kulkarni 		goto out_sysfs_cleanup;
70460e78d2cSAbhishek Kulkarni 	}
70560e78d2cSAbhishek Kulkarni 
70660e78d2cSAbhishek Kulkarni 	return 0;
70760e78d2cSAbhishek Kulkarni 
70860e78d2cSAbhishek Kulkarni out_sysfs_cleanup:
70960e78d2cSAbhishek Kulkarni 	v9fs_sysfs_cleanup();
71060e78d2cSAbhishek Kulkarni 
7112226a288SAl Viro out_cache:
7122226a288SAl Viro 	v9fs_cache_unregister();
71360e78d2cSAbhishek Kulkarni 
71460e78d2cSAbhishek Kulkarni 	return err;
7159e82cf6aSEric Van Hensbergen }
7169e82cf6aSEric Van Hensbergen 
7179e82cf6aSEric Van Hensbergen /**
71860e78d2cSAbhishek Kulkarni  * exit_v9fs - shutdown module
7199e82cf6aSEric Van Hensbergen  *
7209e82cf6aSEric Van Hensbergen  */
7219e82cf6aSEric Van Hensbergen 
exit_v9fs(void)7229e82cf6aSEric Van Hensbergen static void __exit exit_v9fs(void)
7239e82cf6aSEric Van Hensbergen {
72460e78d2cSAbhishek Kulkarni 	v9fs_sysfs_cleanup();
72560e78d2cSAbhishek Kulkarni 	v9fs_cache_unregister();
7269e82cf6aSEric Van Hensbergen 	unregister_filesystem(&v9fs_fs_type);
7279e82cf6aSEric Van Hensbergen }
7289e82cf6aSEric Van Hensbergen 
7299e82cf6aSEric Van Hensbergen module_init(init_v9fs)
7309e82cf6aSEric Van Hensbergen module_exit(exit_v9fs)
7319e82cf6aSEric Van Hensbergen 
732bd238fb4SLatchesar Ionkov MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
7339e82cf6aSEric Van Hensbergen MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
7349e82cf6aSEric Van Hensbergen MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
7359e82cf6aSEric Van Hensbergen MODULE_LICENSE("GPL");
736