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