LCOV - code coverage report
Current view: top level - net/9p - client.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 3 1196 0.3 %
Date: 2021-04-22 12:43:58 Functions: 1 60 1.7 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  * net/9p/clnt.c
       4             :  *
       5             :  * 9P Client
       6             :  *
       7             :  *  Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
       8             :  *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
       9             :  */
      10             : 
      11             : #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      12             : 
      13             : #include <linux/module.h>
      14             : #include <linux/errno.h>
      15             : #include <linux/fs.h>
      16             : #include <linux/poll.h>
      17             : #include <linux/idr.h>
      18             : #include <linux/mutex.h>
      19             : #include <linux/slab.h>
      20             : #include <linux/sched/signal.h>
      21             : #include <linux/uaccess.h>
      22             : #include <linux/uio.h>
      23             : #include <net/9p/9p.h>
      24             : #include <linux/parser.h>
      25             : #include <linux/seq_file.h>
      26             : #include <net/9p/client.h>
      27             : #include <net/9p/transport.h>
      28             : #include "protocol.h"
      29             : 
      30             : #define CREATE_TRACE_POINTS
      31             : #include <trace/events/9p.h>
      32             : 
      33             : /*
      34             :   * Client Option Parsing (code inspired by NFS code)
      35             :   *  - a little lazy - parse all client options
      36             :   */
      37             : 
      38             : enum {
      39             :         Opt_msize,
      40             :         Opt_trans,
      41             :         Opt_legacy,
      42             :         Opt_version,
      43             :         Opt_err,
      44             : };
      45             : 
      46             : static const match_table_t tokens = {
      47             :         {Opt_msize, "msize=%u"},
      48             :         {Opt_legacy, "noextend"},
      49             :         {Opt_trans, "trans=%s"},
      50             :         {Opt_version, "version=%s"},
      51             :         {Opt_err, NULL},
      52             : };
      53             : 
      54           0 : inline int p9_is_proto_dotl(struct p9_client *clnt)
      55             : {
      56           0 :         return clnt->proto_version == p9_proto_2000L;
      57             : }
      58             : EXPORT_SYMBOL(p9_is_proto_dotl);
      59             : 
      60           0 : inline int p9_is_proto_dotu(struct p9_client *clnt)
      61             : {
      62           0 :         return clnt->proto_version == p9_proto_2000u;
      63             : }
      64             : EXPORT_SYMBOL(p9_is_proto_dotu);
      65             : 
      66           0 : int p9_show_client_options(struct seq_file *m, struct p9_client *clnt)
      67             : {
      68           0 :         if (clnt->msize != 8192)
      69           0 :                 seq_printf(m, ",msize=%u", clnt->msize);
      70           0 :         seq_printf(m, ",trans=%s", clnt->trans_mod->name);
      71             : 
      72           0 :         switch (clnt->proto_version) {
      73           0 :         case p9_proto_legacy:
      74           0 :                 seq_puts(m, ",noextend");
      75           0 :                 break;
      76           0 :         case p9_proto_2000u:
      77           0 :                 seq_puts(m, ",version=9p2000.u");
      78           0 :                 break;
      79             :         case p9_proto_2000L:
      80             :                 /* Default */
      81             :                 break;
      82             :         }
      83             : 
      84           0 :         if (clnt->trans_mod->show_options)
      85           0 :                 return clnt->trans_mod->show_options(m, clnt);
      86             :         return 0;
      87             : }
      88             : EXPORT_SYMBOL(p9_show_client_options);
      89             : 
      90             : /*
      91             :  * Some error codes are taken directly from the server replies,
      92             :  * make sure they are valid.
      93             :  */
      94           0 : static int safe_errno(int err)
      95             : {
      96           0 :         if ((err > 0) || (err < -MAX_ERRNO)) {
      97           0 :                 p9_debug(P9_DEBUG_ERROR, "Invalid error code %d\n", err);
      98           0 :                 return -EPROTO;
      99             :         }
     100             :         return err;
     101             : }
     102             : 
     103             : 
     104             : /* Interpret mount option for protocol version */
     105           0 : static int get_protocol_version(char *s)
     106             : {
     107           0 :         int version = -EINVAL;
     108             : 
     109           0 :         if (!strcmp(s, "9p2000")) {
     110             :                 version = p9_proto_legacy;
     111             :                 p9_debug(P9_DEBUG_9P, "Protocol version: Legacy\n");
     112           0 :         } else if (!strcmp(s, "9p2000.u")) {
     113             :                 version = p9_proto_2000u;
     114             :                 p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
     115           0 :         } else if (!strcmp(s, "9p2000.L")) {
     116             :                 version = p9_proto_2000L;
     117             :                 p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.L\n");
     118             :         } else
     119           0 :                 pr_info("Unknown protocol version %s\n", s);
     120             : 
     121           0 :         return version;
     122             : }
     123             : 
     124             : /**
     125             :  * parse_options - parse mount options into client structure
     126             :  * @opts: options string passed from mount
     127             :  * @clnt: existing v9fs client information
     128             :  *
     129             :  * Return 0 upon success, -ERRNO upon failure
     130             :  */
     131             : 
     132           0 : static int parse_opts(char *opts, struct p9_client *clnt)
     133             : {
     134           0 :         char *options, *tmp_options;
     135           0 :         char *p;
     136           0 :         substring_t args[MAX_OPT_ARGS];
     137           0 :         int option;
     138           0 :         char *s;
     139           0 :         int ret = 0;
     140             : 
     141           0 :         clnt->proto_version = p9_proto_2000L;
     142           0 :         clnt->msize = 8192;
     143             : 
     144           0 :         if (!opts)
     145             :                 return 0;
     146             : 
     147           0 :         tmp_options = kstrdup(opts, GFP_KERNEL);
     148           0 :         if (!tmp_options) {
     149             :                 p9_debug(P9_DEBUG_ERROR,
     150             :                          "failed to allocate copy of option string\n");
     151             :                 return -ENOMEM;
     152             :         }
     153           0 :         options = tmp_options;
     154             : 
     155           0 :         while ((p = strsep(&options, ",")) != NULL) {
     156           0 :                 int token, r;
     157           0 :                 if (!*p)
     158           0 :                         continue;
     159           0 :                 token = match_token(p, tokens, args);
     160           0 :                 switch (token) {
     161           0 :                 case Opt_msize:
     162           0 :                         r = match_int(&args[0], &option);
     163           0 :                         if (r < 0) {
     164           0 :                                 p9_debug(P9_DEBUG_ERROR,
     165             :                                          "integer field, but no integer?\n");
     166           0 :                                 ret = r;
     167           0 :                                 continue;
     168             :                         }
     169           0 :                         if (option < 4096) {
     170           0 :                                 p9_debug(P9_DEBUG_ERROR,
     171             :                                          "msize should be at least 4k\n");
     172           0 :                                 ret = -EINVAL;
     173           0 :                                 continue;
     174             :                         }
     175           0 :                         clnt->msize = option;
     176           0 :                         break;
     177           0 :                 case Opt_trans:
     178           0 :                         s = match_strdup(&args[0]);
     179           0 :                         if (!s) {
     180           0 :                                 ret = -ENOMEM;
     181           0 :                                 p9_debug(P9_DEBUG_ERROR,
     182             :                                          "problem allocating copy of trans arg\n");
     183           0 :                                 goto free_and_return;
     184             :                         }
     185             : 
     186           0 :                         v9fs_put_trans(clnt->trans_mod);
     187           0 :                         clnt->trans_mod = v9fs_get_trans_by_name(s);
     188           0 :                         if (clnt->trans_mod == NULL) {
     189           0 :                                 pr_info("Could not find request transport: %s\n",
     190             :                                         s);
     191           0 :                                 ret = -EINVAL;
     192             :                         }
     193           0 :                         kfree(s);
     194           0 :                         break;
     195           0 :                 case Opt_legacy:
     196           0 :                         clnt->proto_version = p9_proto_legacy;
     197           0 :                         break;
     198           0 :                 case Opt_version:
     199           0 :                         s = match_strdup(&args[0]);
     200           0 :                         if (!s) {
     201           0 :                                 ret = -ENOMEM;
     202           0 :                                 p9_debug(P9_DEBUG_ERROR,
     203             :                                          "problem allocating copy of version arg\n");
     204           0 :                                 goto free_and_return;
     205             :                         }
     206           0 :                         r = get_protocol_version(s);
     207           0 :                         if (r < 0)
     208             :                                 ret = r;
     209             :                         else
     210           0 :                                 clnt->proto_version = r;
     211           0 :                         kfree(s);
     212           0 :                         break;
     213           0 :                 default:
     214           0 :                         continue;
     215             :                 }
     216             :         }
     217             : 
     218           0 : free_and_return:
     219           0 :         if (ret)
     220           0 :                 v9fs_put_trans(clnt->trans_mod);
     221           0 :         kfree(tmp_options);
     222           0 :         return ret;
     223             : }
     224             : 
     225           0 : static int p9_fcall_init(struct p9_client *c, struct p9_fcall *fc,
     226             :                          int alloc_msize)
     227             : {
     228           0 :         if (likely(c->fcall_cache) && alloc_msize == c->msize) {
     229           0 :                 fc->sdata = kmem_cache_alloc(c->fcall_cache, GFP_NOFS);
     230           0 :                 fc->cache = c->fcall_cache;
     231             :         } else {
     232           0 :                 fc->sdata = kmalloc(alloc_msize, GFP_NOFS);
     233           0 :                 fc->cache = NULL;
     234             :         }
     235           0 :         if (!fc->sdata)
     236             :                 return -ENOMEM;
     237           0 :         fc->capacity = alloc_msize;
     238           0 :         return 0;
     239             : }
     240             : 
     241           0 : void p9_fcall_fini(struct p9_fcall *fc)
     242             : {
     243             :         /* sdata can be NULL for interrupted requests in trans_rdma,
     244             :          * and kmem_cache_free does not do NULL-check for us
     245             :          */
     246           0 :         if (unlikely(!fc->sdata))
     247             :                 return;
     248             : 
     249           0 :         if (fc->cache)
     250           0 :                 kmem_cache_free(fc->cache, fc->sdata);
     251             :         else
     252           0 :                 kfree(fc->sdata);
     253             : }
     254             : EXPORT_SYMBOL(p9_fcall_fini);
     255             : 
     256             : static struct kmem_cache *p9_req_cache;
     257             : 
     258             : /**
     259             :  * p9_req_alloc - Allocate a new request.
     260             :  * @c: Client session.
     261             :  * @type: Transaction type.
     262             :  * @max_size: Maximum packet size for this request.
     263             :  *
     264             :  * Context: Process context.
     265             :  * Return: Pointer to new request.
     266             :  */
     267             : static struct p9_req_t *
     268           0 : p9_tag_alloc(struct p9_client *c, int8_t type, unsigned int max_size)
     269             : {
     270           0 :         struct p9_req_t *req = kmem_cache_alloc(p9_req_cache, GFP_NOFS);
     271           0 :         int alloc_msize = min(c->msize, max_size);
     272           0 :         int tag;
     273             : 
     274           0 :         if (!req)
     275           0 :                 return ERR_PTR(-ENOMEM);
     276             : 
     277           0 :         if (p9_fcall_init(c, &req->tc, alloc_msize))
     278           0 :                 goto free_req;
     279           0 :         if (p9_fcall_init(c, &req->rc, alloc_msize))
     280           0 :                 goto free;
     281             : 
     282           0 :         p9pdu_reset(&req->tc);
     283           0 :         p9pdu_reset(&req->rc);
     284           0 :         req->t_err = 0;
     285           0 :         req->status = REQ_STATUS_ALLOC;
     286           0 :         init_waitqueue_head(&req->wq);
     287           0 :         INIT_LIST_HEAD(&req->req_list);
     288             : 
     289           0 :         idr_preload(GFP_NOFS);
     290           0 :         spin_lock_irq(&c->lock);
     291           0 :         if (type == P9_TVERSION)
     292           0 :                 tag = idr_alloc(&c->reqs, req, P9_NOTAG, P9_NOTAG + 1,
     293             :                                 GFP_NOWAIT);
     294             :         else
     295           0 :                 tag = idr_alloc(&c->reqs, req, 0, P9_NOTAG, GFP_NOWAIT);
     296           0 :         req->tc.tag = tag;
     297           0 :         spin_unlock_irq(&c->lock);
     298           0 :         idr_preload_end();
     299           0 :         if (tag < 0)
     300           0 :                 goto free;
     301             : 
     302             :         /* Init ref to two because in the general case there is one ref
     303             :          * that is put asynchronously by a writer thread, one ref
     304             :          * temporarily given by p9_tag_lookup and put by p9_client_cb
     305             :          * in the recv thread, and one ref put by p9_tag_remove in the
     306             :          * main thread. The only exception is virtio that does not use
     307             :          * p9_tag_lookup but does not have a writer thread either
     308             :          * (the write happens synchronously in the request/zc_request
     309             :          * callback), so p9_client_cb eats the second ref there
     310             :          * as the pointer is duplicated directly by virtqueue_add_sgs()
     311             :          */
     312           0 :         refcount_set(&req->refcount.refcount, 2);
     313             : 
     314           0 :         return req;
     315             : 
     316           0 : free:
     317           0 :         p9_fcall_fini(&req->tc);
     318           0 :         p9_fcall_fini(&req->rc);
     319           0 : free_req:
     320           0 :         kmem_cache_free(p9_req_cache, req);
     321           0 :         return ERR_PTR(-ENOMEM);
     322             : }
     323             : 
     324             : /**
     325             :  * p9_tag_lookup - Look up a request by tag.
     326             :  * @c: Client session.
     327             :  * @tag: Transaction ID.
     328             :  *
     329             :  * Context: Any context.
     330             :  * Return: A request, or %NULL if there is no request with that tag.
     331             :  */
     332           0 : struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
     333             : {
     334           0 :         struct p9_req_t *req;
     335             : 
     336           0 :         rcu_read_lock();
     337             : again:
     338           0 :         req = idr_find(&c->reqs, tag);
     339           0 :         if (req) {
     340             :                 /* We have to be careful with the req found under rcu_read_lock
     341             :                  * Thanks to SLAB_TYPESAFE_BY_RCU we can safely try to get the
     342             :                  * ref again without corrupting other data, then check again
     343             :                  * that the tag matches once we have the ref
     344             :                  */
     345           0 :                 if (!p9_req_try_get(req))
     346           0 :                         goto again;
     347           0 :                 if (req->tc.tag != tag) {
     348           0 :                         p9_req_put(req);
     349           0 :                         goto again;
     350             :                 }
     351             :         }
     352           0 :         rcu_read_unlock();
     353             : 
     354           0 :         return req;
     355             : }
     356             : EXPORT_SYMBOL(p9_tag_lookup);
     357             : 
     358             : /**
     359             :  * p9_tag_remove - Remove a tag.
     360             :  * @c: Client session.
     361             :  * @r: Request of reference.
     362             :  *
     363             :  * Context: Any context.
     364             :  */
     365           0 : static int p9_tag_remove(struct p9_client *c, struct p9_req_t *r)
     366             : {
     367           0 :         unsigned long flags;
     368           0 :         u16 tag = r->tc.tag;
     369             : 
     370           0 :         p9_debug(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
     371           0 :         spin_lock_irqsave(&c->lock, flags);
     372           0 :         idr_remove(&c->reqs, tag);
     373           0 :         spin_unlock_irqrestore(&c->lock, flags);
     374           0 :         return p9_req_put(r);
     375             : }
     376             : 
     377           0 : static void p9_req_free(struct kref *ref)
     378             : {
     379           0 :         struct p9_req_t *r = container_of(ref, struct p9_req_t, refcount);
     380           0 :         p9_fcall_fini(&r->tc);
     381           0 :         p9_fcall_fini(&r->rc);
     382           0 :         kmem_cache_free(p9_req_cache, r);
     383           0 : }
     384             : 
     385           0 : int p9_req_put(struct p9_req_t *r)
     386             : {
     387           0 :         return kref_put(&r->refcount, p9_req_free);
     388             : }
     389             : EXPORT_SYMBOL(p9_req_put);
     390             : 
     391             : /**
     392             :  * p9_tag_cleanup - cleans up tags structure and reclaims resources
     393             :  * @c:  v9fs client struct
     394             :  *
     395             :  * This frees resources associated with the tags structure
     396             :  *
     397             :  */
     398           0 : static void p9_tag_cleanup(struct p9_client *c)
     399             : {
     400           0 :         struct p9_req_t *req;
     401           0 :         int id;
     402             : 
     403           0 :         rcu_read_lock();
     404           0 :         idr_for_each_entry(&c->reqs, req, id) {
     405           0 :                 pr_info("Tag %d still in use\n", id);
     406           0 :                 if (p9_tag_remove(c, req) == 0)
     407           0 :                         pr_warn("Packet with tag %d has still references",
     408             :                                 req->tc.tag);
     409             :         }
     410           0 :         rcu_read_unlock();
     411           0 : }
     412             : 
     413             : /**
     414             :  * p9_client_cb - call back from transport to client
     415             :  * @c: client state
     416             :  * @req: request received
     417             :  * @status: request status, one of REQ_STATUS_*
     418             :  *
     419             :  */
     420           0 : void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status)
     421             : {
     422           0 :         p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc.tag);
     423             : 
     424             :         /*
     425             :          * This barrier is needed to make sure any change made to req before
     426             :          * the status change is visible to another thread
     427             :          */
     428           0 :         smp_wmb();
     429           0 :         req->status = status;
     430             : 
     431           0 :         wake_up(&req->wq);
     432           0 :         p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc.tag);
     433           0 :         p9_req_put(req);
     434           0 : }
     435             : EXPORT_SYMBOL(p9_client_cb);
     436             : 
     437             : /**
     438             :  * p9_parse_header - parse header arguments out of a packet
     439             :  * @pdu: packet to parse
     440             :  * @size: size of packet
     441             :  * @type: type of request
     442             :  * @tag: tag of packet
     443             :  * @rewind: set if we need to rewind offset afterwards
     444             :  */
     445             : 
     446             : int
     447           0 : p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag,
     448             :                                                                 int rewind)
     449             : {
     450           0 :         int8_t r_type;
     451           0 :         int16_t r_tag;
     452           0 :         int32_t r_size;
     453           0 :         int offset = pdu->offset;
     454           0 :         int err;
     455             : 
     456           0 :         pdu->offset = 0;
     457             : 
     458           0 :         err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag);
     459           0 :         if (err)
     460           0 :                 goto rewind_and_exit;
     461             : 
     462           0 :         if (type)
     463           0 :                 *type = r_type;
     464           0 :         if (tag)
     465           0 :                 *tag = r_tag;
     466           0 :         if (size)
     467           0 :                 *size = r_size;
     468             : 
     469           0 :         if (pdu->size != r_size || r_size < 7) {
     470           0 :                 err = -EINVAL;
     471           0 :                 goto rewind_and_exit;
     472             :         }
     473             : 
     474           0 :         pdu->id = r_type;
     475           0 :         pdu->tag = r_tag;
     476             : 
     477           0 :         p9_debug(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n",
     478             :                  pdu->size, pdu->id, pdu->tag);
     479             : 
     480           0 : rewind_and_exit:
     481           0 :         if (rewind)
     482           0 :                 pdu->offset = offset;
     483           0 :         return err;
     484             : }
     485             : EXPORT_SYMBOL(p9_parse_header);
     486             : 
     487             : /**
     488             :  * p9_check_errors - check 9p packet for error return and process it
     489             :  * @c: current client instance
     490             :  * @req: request to parse and check for error conditions
     491             :  *
     492             :  * returns error code if one is discovered, otherwise returns 0
     493             :  *
     494             :  * this will have to be more complicated if we have multiple
     495             :  * error packet types
     496             :  */
     497             : 
     498           0 : static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
     499             : {
     500           0 :         int8_t type;
     501           0 :         int err;
     502           0 :         int ecode;
     503             : 
     504           0 :         err = p9_parse_header(&req->rc, NULL, &type, NULL, 0);
     505           0 :         if (req->rc.size >= c->msize) {
     506             :                 p9_debug(P9_DEBUG_ERROR,
     507             :                          "requested packet size too big: %d\n",
     508             :                          req->rc.size);
     509             :                 return -EIO;
     510             :         }
     511             :         /*
     512             :          * dump the response from server
     513             :          * This should be after check errors which poplulate pdu_fcall.
     514             :          */
     515           0 :         trace_9p_protocol_dump(c, &req->rc);
     516           0 :         if (err) {
     517             :                 p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
     518             :                 return err;
     519             :         }
     520           0 :         if (type != P9_RERROR && type != P9_RLERROR)
     521             :                 return 0;
     522             : 
     523           0 :         if (!p9_is_proto_dotl(c)) {
     524           0 :                 char *ename;
     525           0 :                 err = p9pdu_readf(&req->rc, c->proto_version, "s?d",
     526             :                                   &ename, &ecode);
     527           0 :                 if (err)
     528           0 :                         goto out_err;
     529             : 
     530           0 :                 if (p9_is_proto_dotu(c) && ecode < 512)
     531           0 :                         err = -ecode;
     532             : 
     533           0 :                 if (!err) {
     534           0 :                         err = p9_errstr2errno(ename, strlen(ename));
     535             : 
     536           0 :                         p9_debug(P9_DEBUG_9P, "<<< RERROR (%d) %s\n",
     537             :                                  -ecode, ename);
     538             :                 }
     539           0 :                 kfree(ename);
     540             :         } else {
     541           0 :                 err = p9pdu_readf(&req->rc, c->proto_version, "d", &ecode);
     542           0 :                 err = -ecode;
     543             : 
     544           0 :                 p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
     545             :         }
     546             : 
     547             :         return err;
     548             : 
     549           0 : out_err:
     550           0 :         p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
     551             : 
     552           0 :         return err;
     553             : }
     554             : 
     555             : /**
     556             :  * p9_check_zc_errors - check 9p packet for error return and process it
     557             :  * @c: current client instance
     558             :  * @req: request to parse and check for error conditions
     559             :  * @uidata: external buffer containing error
     560             :  * @in_hdrlen: Size of response protocol buffer.
     561             :  *
     562             :  * returns error code if one is discovered, otherwise returns 0
     563             :  *
     564             :  * this will have to be more complicated if we have multiple
     565             :  * error packet types
     566             :  */
     567             : 
     568           0 : static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
     569             :                               struct iov_iter *uidata, int in_hdrlen)
     570             : {
     571           0 :         int err;
     572           0 :         int ecode;
     573           0 :         int8_t type;
     574           0 :         char *ename = NULL;
     575             : 
     576           0 :         err = p9_parse_header(&req->rc, NULL, &type, NULL, 0);
     577             :         /*
     578             :          * dump the response from server
     579             :          * This should be after parse_header which poplulate pdu_fcall.
     580             :          */
     581           0 :         trace_9p_protocol_dump(c, &req->rc);
     582           0 :         if (err) {
     583             :                 p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
     584             :                 return err;
     585             :         }
     586             : 
     587           0 :         if (type != P9_RERROR && type != P9_RLERROR)
     588             :                 return 0;
     589             : 
     590           0 :         if (!p9_is_proto_dotl(c)) {
     591             :                 /* Error is reported in string format */
     592           0 :                 int len;
     593             :                 /* 7 = header size for RERROR; */
     594           0 :                 int inline_len = in_hdrlen - 7;
     595             : 
     596           0 :                 len = req->rc.size - req->rc.offset;
     597           0 :                 if (len > (P9_ZC_HDR_SZ - 7)) {
     598           0 :                         err = -EFAULT;
     599           0 :                         goto out_err;
     600             :                 }
     601             : 
     602           0 :                 ename = &req->rc.sdata[req->rc.offset];
     603           0 :                 if (len > inline_len) {
     604             :                         /* We have error in external buffer */
     605           0 :                         if (!copy_from_iter_full(ename + inline_len,
     606           0 :                                              len - inline_len, uidata)) {
     607           0 :                                 err = -EFAULT;
     608           0 :                                 goto out_err;
     609             :                         }
     610             :                 }
     611           0 :                 ename = NULL;
     612           0 :                 err = p9pdu_readf(&req->rc, c->proto_version, "s?d",
     613             :                                   &ename, &ecode);
     614           0 :                 if (err)
     615           0 :                         goto out_err;
     616             : 
     617           0 :                 if (p9_is_proto_dotu(c) && ecode < 512)
     618           0 :                         err = -ecode;
     619             : 
     620           0 :                 if (!err) {
     621           0 :                         err = p9_errstr2errno(ename, strlen(ename));
     622             : 
     623           0 :                         p9_debug(P9_DEBUG_9P, "<<< RERROR (%d) %s\n",
     624             :                                  -ecode, ename);
     625             :                 }
     626           0 :                 kfree(ename);
     627             :         } else {
     628           0 :                 err = p9pdu_readf(&req->rc, c->proto_version, "d", &ecode);
     629           0 :                 err = -ecode;
     630             : 
     631           0 :                 p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
     632             :         }
     633             :         return err;
     634             : 
     635             : out_err:
     636             :         p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
     637             :         return err;
     638             : }
     639             : 
     640             : static struct p9_req_t *
     641             : p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
     642             : 
     643             : /**
     644             :  * p9_client_flush - flush (cancel) a request
     645             :  * @c: client state
     646             :  * @oldreq: request to cancel
     647             :  *
     648             :  * This sents a flush for a particular request and links
     649             :  * the flush request to the original request.  The current
     650             :  * code only supports a single flush request although the protocol
     651             :  * allows for multiple flush requests to be sent for a single request.
     652             :  *
     653             :  */
     654             : 
     655           0 : static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
     656             : {
     657           0 :         struct p9_req_t *req;
     658           0 :         int16_t oldtag;
     659           0 :         int err;
     660             : 
     661           0 :         err = p9_parse_header(&oldreq->tc, NULL, NULL, &oldtag, 1);
     662           0 :         if (err)
     663             :                 return err;
     664             : 
     665           0 :         p9_debug(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag);
     666             : 
     667           0 :         req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag);
     668           0 :         if (IS_ERR(req))
     669           0 :                 return PTR_ERR(req);
     670             : 
     671             :         /*
     672             :          * if we haven't received a response for oldreq,
     673             :          * remove it from the list
     674             :          */
     675           0 :         if (oldreq->status == REQ_STATUS_SENT) {
     676           0 :                 if (c->trans_mod->cancelled)
     677           0 :                         c->trans_mod->cancelled(c, oldreq);
     678             :         }
     679             : 
     680           0 :         p9_tag_remove(c, req);
     681           0 :         return 0;
     682             : }
     683             : 
     684           0 : static struct p9_req_t *p9_client_prepare_req(struct p9_client *c,
     685             :                                               int8_t type, int req_size,
     686             :                                               const char *fmt, va_list ap)
     687             : {
     688           0 :         int err;
     689           0 :         struct p9_req_t *req;
     690             : 
     691           0 :         p9_debug(P9_DEBUG_MUX, "client %p op %d\n", c, type);
     692             : 
     693             :         /* we allow for any status other than disconnected */
     694           0 :         if (c->status == Disconnected)
     695           0 :                 return ERR_PTR(-EIO);
     696             : 
     697             :         /* if status is begin_disconnected we allow only clunk request */
     698           0 :         if ((c->status == BeginDisconnect) && (type != P9_TCLUNK))
     699           0 :                 return ERR_PTR(-EIO);
     700             : 
     701           0 :         req = p9_tag_alloc(c, type, req_size);
     702           0 :         if (IS_ERR(req))
     703             :                 return req;
     704             : 
     705             :         /* marshall the data */
     706           0 :         p9pdu_prepare(&req->tc, req->tc.tag, type);
     707           0 :         err = p9pdu_vwritef(&req->tc, c->proto_version, fmt, ap);
     708           0 :         if (err)
     709           0 :                 goto reterr;
     710           0 :         p9pdu_finalize(c, &req->tc);
     711           0 :         trace_9p_client_req(c, type, req->tc.tag);
     712           0 :         return req;
     713           0 : reterr:
     714           0 :         p9_tag_remove(c, req);
     715             :         /* We have to put also the 2nd reference as it won't be used */
     716           0 :         p9_req_put(req);
     717           0 :         return ERR_PTR(err);
     718             : }
     719             : 
     720             : /**
     721             :  * p9_client_rpc - issue a request and wait for a response
     722             :  * @c: client session
     723             :  * @type: type of request
     724             :  * @fmt: protocol format string (see protocol.c)
     725             :  *
     726             :  * Returns request structure (which client must free using p9_tag_remove)
     727             :  */
     728             : 
     729             : static struct p9_req_t *
     730           0 : p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
     731             : {
     732           0 :         va_list ap;
     733           0 :         int sigpending, err;
     734           0 :         unsigned long flags;
     735           0 :         struct p9_req_t *req;
     736             : 
     737           0 :         va_start(ap, fmt);
     738           0 :         req = p9_client_prepare_req(c, type, c->msize, fmt, ap);
     739           0 :         va_end(ap);
     740           0 :         if (IS_ERR(req))
     741             :                 return req;
     742             : 
     743           0 :         if (signal_pending(current)) {
     744           0 :                 sigpending = 1;
     745           0 :                 clear_thread_flag(TIF_SIGPENDING);
     746             :         } else
     747             :                 sigpending = 0;
     748             : 
     749           0 :         err = c->trans_mod->request(c, req);
     750           0 :         if (err < 0) {
     751             :                 /* write won't happen */
     752           0 :                 p9_req_put(req);
     753           0 :                 if (err != -ERESTARTSYS && err != -EFAULT)
     754           0 :                         c->status = Disconnected;
     755           0 :                 goto recalc_sigpending;
     756             :         }
     757           0 : again:
     758             :         /* Wait for the response */
     759           0 :         err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD);
     760             : 
     761             :         /*
     762             :          * Make sure our req is coherent with regard to updates in other
     763             :          * threads - echoes to wmb() in the callback
     764             :          */
     765           0 :         smp_rmb();
     766             : 
     767           0 :         if ((err == -ERESTARTSYS) && (c->status == Connected)
     768           0 :                                   && (type == P9_TFLUSH)) {
     769           0 :                 sigpending = 1;
     770           0 :                 clear_thread_flag(TIF_SIGPENDING);
     771           0 :                 goto again;
     772             :         }
     773             : 
     774           0 :         if (req->status == REQ_STATUS_ERROR) {
     775           0 :                 p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
     776           0 :                 err = req->t_err;
     777             :         }
     778           0 :         if ((err == -ERESTARTSYS) && (c->status == Connected)) {
     779           0 :                 p9_debug(P9_DEBUG_MUX, "flushing\n");
     780           0 :                 sigpending = 1;
     781           0 :                 clear_thread_flag(TIF_SIGPENDING);
     782             : 
     783           0 :                 if (c->trans_mod->cancel(c, req))
     784           0 :                         p9_client_flush(c, req);
     785             : 
     786             :                 /* if we received the response anyway, don't signal error */
     787           0 :                 if (req->status == REQ_STATUS_RCVD)
     788             :                         err = 0;
     789             :         }
     790           0 : recalc_sigpending:
     791           0 :         if (sigpending) {
     792           0 :                 spin_lock_irqsave(&current->sighand->siglock, flags);
     793           0 :                 recalc_sigpending();
     794           0 :                 spin_unlock_irqrestore(&current->sighand->siglock, flags);
     795             :         }
     796           0 :         if (err < 0)
     797           0 :                 goto reterr;
     798             : 
     799           0 :         err = p9_check_errors(c, req);
     800           0 :         trace_9p_client_res(c, type, req->rc.tag, err);
     801           0 :         if (!err)
     802             :                 return req;
     803           0 : reterr:
     804           0 :         p9_tag_remove(c, req);
     805           0 :         return ERR_PTR(safe_errno(err));
     806             : }
     807             : 
     808             : /**
     809             :  * p9_client_zc_rpc - issue a request and wait for a response
     810             :  * @c: client session
     811             :  * @type: type of request
     812             :  * @uidata: destination for zero copy read
     813             :  * @uodata: source for zero copy write
     814             :  * @inlen: read buffer size
     815             :  * @olen: write buffer size
     816             :  * @in_hdrlen: reader header size, This is the size of response protocol data
     817             :  * @fmt: protocol format string (see protocol.c)
     818             :  *
     819             :  * Returns request structure (which client must free using p9_tag_remove)
     820             :  */
     821           0 : static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
     822             :                                          struct iov_iter *uidata,
     823             :                                          struct iov_iter *uodata,
     824             :                                          int inlen, int olen, int in_hdrlen,
     825             :                                          const char *fmt, ...)
     826             : {
     827           0 :         va_list ap;
     828           0 :         int sigpending, err;
     829           0 :         unsigned long flags;
     830           0 :         struct p9_req_t *req;
     831             : 
     832           0 :         va_start(ap, fmt);
     833             :         /*
     834             :          * We allocate a inline protocol data of only 4k bytes.
     835             :          * The actual content is passed in zero-copy fashion.
     836             :          */
     837           0 :         req = p9_client_prepare_req(c, type, P9_ZC_HDR_SZ, fmt, ap);
     838           0 :         va_end(ap);
     839           0 :         if (IS_ERR(req))
     840             :                 return req;
     841             : 
     842           0 :         if (signal_pending(current)) {
     843           0 :                 sigpending = 1;
     844           0 :                 clear_thread_flag(TIF_SIGPENDING);
     845             :         } else
     846             :                 sigpending = 0;
     847             : 
     848           0 :         err = c->trans_mod->zc_request(c, req, uidata, uodata,
     849             :                                        inlen, olen, in_hdrlen);
     850           0 :         if (err < 0) {
     851           0 :                 if (err == -EIO)
     852           0 :                         c->status = Disconnected;
     853           0 :                 if (err != -ERESTARTSYS)
     854           0 :                         goto recalc_sigpending;
     855             :         }
     856           0 :         if (req->status == REQ_STATUS_ERROR) {
     857           0 :                 p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
     858           0 :                 err = req->t_err;
     859             :         }
     860           0 :         if ((err == -ERESTARTSYS) && (c->status == Connected)) {
     861           0 :                 p9_debug(P9_DEBUG_MUX, "flushing\n");
     862           0 :                 sigpending = 1;
     863           0 :                 clear_thread_flag(TIF_SIGPENDING);
     864             : 
     865           0 :                 if (c->trans_mod->cancel(c, req))
     866           0 :                         p9_client_flush(c, req);
     867             : 
     868             :                 /* if we received the response anyway, don't signal error */
     869           0 :                 if (req->status == REQ_STATUS_RCVD)
     870             :                         err = 0;
     871             :         }
     872           0 : recalc_sigpending:
     873           0 :         if (sigpending) {
     874           0 :                 spin_lock_irqsave(&current->sighand->siglock, flags);
     875           0 :                 recalc_sigpending();
     876           0 :                 spin_unlock_irqrestore(&current->sighand->siglock, flags);
     877             :         }
     878           0 :         if (err < 0)
     879           0 :                 goto reterr;
     880             : 
     881           0 :         err = p9_check_zc_errors(c, req, uidata, in_hdrlen);
     882           0 :         trace_9p_client_res(c, type, req->rc.tag, err);
     883           0 :         if (!err)
     884             :                 return req;
     885           0 : reterr:
     886           0 :         p9_tag_remove(c, req);
     887           0 :         return ERR_PTR(safe_errno(err));
     888             : }
     889             : 
     890           0 : static struct p9_fid *p9_fid_create(struct p9_client *clnt)
     891             : {
     892           0 :         int ret;
     893           0 :         struct p9_fid *fid;
     894             : 
     895           0 :         p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt);
     896           0 :         fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
     897           0 :         if (!fid)
     898             :                 return NULL;
     899             : 
     900           0 :         memset(&fid->qid, 0, sizeof(struct p9_qid));
     901           0 :         fid->mode = -1;
     902           0 :         fid->uid = current_fsuid();
     903           0 :         fid->clnt = clnt;
     904           0 :         fid->rdir = NULL;
     905           0 :         fid->fid = 0;
     906           0 :         refcount_set(&fid->count, 1);
     907             : 
     908           0 :         idr_preload(GFP_KERNEL);
     909           0 :         spin_lock_irq(&clnt->lock);
     910           0 :         ret = idr_alloc_u32(&clnt->fids, fid, &fid->fid, P9_NOFID - 1,
     911             :                             GFP_NOWAIT);
     912           0 :         spin_unlock_irq(&clnt->lock);
     913           0 :         idr_preload_end();
     914           0 :         if (!ret)
     915             :                 return fid;
     916             : 
     917           0 :         kfree(fid);
     918           0 :         return NULL;
     919             : }
     920             : 
     921           0 : static void p9_fid_destroy(struct p9_fid *fid)
     922             : {
     923           0 :         struct p9_client *clnt;
     924           0 :         unsigned long flags;
     925             : 
     926           0 :         p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid);
     927           0 :         clnt = fid->clnt;
     928           0 :         spin_lock_irqsave(&clnt->lock, flags);
     929           0 :         idr_remove(&clnt->fids, fid->fid);
     930           0 :         spin_unlock_irqrestore(&clnt->lock, flags);
     931           0 :         kfree(fid->rdir);
     932           0 :         kfree(fid);
     933           0 : }
     934             : 
     935           0 : static int p9_client_version(struct p9_client *c)
     936             : {
     937           0 :         int err = 0;
     938           0 :         struct p9_req_t *req;
     939           0 :         char *version = NULL;
     940           0 :         int msize;
     941             : 
     942           0 :         p9_debug(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n",
     943             :                  c->msize, c->proto_version);
     944             : 
     945           0 :         switch (c->proto_version) {
     946           0 :         case p9_proto_2000L:
     947           0 :                 req = p9_client_rpc(c, P9_TVERSION, "ds",
     948             :                                         c->msize, "9P2000.L");
     949           0 :                 break;
     950           0 :         case p9_proto_2000u:
     951           0 :                 req = p9_client_rpc(c, P9_TVERSION, "ds",
     952             :                                         c->msize, "9P2000.u");
     953           0 :                 break;
     954           0 :         case p9_proto_legacy:
     955           0 :                 req = p9_client_rpc(c, P9_TVERSION, "ds",
     956             :                                         c->msize, "9P2000");
     957           0 :                 break;
     958             :         default:
     959             :                 return -EINVAL;
     960             :         }
     961             : 
     962           0 :         if (IS_ERR(req))
     963           0 :                 return PTR_ERR(req);
     964             : 
     965           0 :         err = p9pdu_readf(&req->rc, c->proto_version, "ds", &msize, &version);
     966           0 :         if (err) {
     967           0 :                 p9_debug(P9_DEBUG_9P, "version error %d\n", err);
     968           0 :                 trace_9p_protocol_dump(c, &req->rc);
     969           0 :                 goto error;
     970             :         }
     971             : 
     972           0 :         p9_debug(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
     973           0 :         if (!strncmp(version, "9P2000.L", 8))
     974           0 :                 c->proto_version = p9_proto_2000L;
     975           0 :         else if (!strncmp(version, "9P2000.u", 8))
     976           0 :                 c->proto_version = p9_proto_2000u;
     977           0 :         else if (!strncmp(version, "9P2000", 6))
     978           0 :                 c->proto_version = p9_proto_legacy;
     979             :         else {
     980           0 :                 p9_debug(P9_DEBUG_ERROR,
     981             :                          "server returned an unknown version: %s\n", version);
     982           0 :                 err = -EREMOTEIO;
     983           0 :                 goto error;
     984             :         }
     985             : 
     986           0 :         if (msize < 4096) {
     987           0 :                 p9_debug(P9_DEBUG_ERROR,
     988             :                          "server returned a msize < 4096: %d\n", msize);
     989           0 :                 err = -EREMOTEIO;
     990           0 :                 goto error;
     991             :         }
     992           0 :         if (msize < c->msize)
     993           0 :                 c->msize = msize;
     994             : 
     995           0 : error:
     996           0 :         kfree(version);
     997           0 :         p9_tag_remove(c, req);
     998             : 
     999           0 :         return err;
    1000             : }
    1001             : 
    1002           0 : struct p9_client *p9_client_create(const char *dev_name, char *options)
    1003             : {
    1004           0 :         int err;
    1005           0 :         struct p9_client *clnt;
    1006           0 :         char *client_id;
    1007             : 
    1008           0 :         err = 0;
    1009           0 :         clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL);
    1010           0 :         if (!clnt)
    1011           0 :                 return ERR_PTR(-ENOMEM);
    1012             : 
    1013           0 :         clnt->trans_mod = NULL;
    1014           0 :         clnt->trans = NULL;
    1015           0 :         clnt->fcall_cache = NULL;
    1016             : 
    1017           0 :         client_id = utsname()->nodename;
    1018           0 :         memcpy(clnt->name, client_id, strlen(client_id) + 1);
    1019             : 
    1020           0 :         spin_lock_init(&clnt->lock);
    1021           0 :         idr_init(&clnt->fids);
    1022           0 :         idr_init(&clnt->reqs);
    1023             : 
    1024           0 :         err = parse_opts(options, clnt);
    1025           0 :         if (err < 0)
    1026           0 :                 goto free_client;
    1027             : 
    1028           0 :         if (!clnt->trans_mod)
    1029           0 :                 clnt->trans_mod = v9fs_get_default_trans();
    1030             : 
    1031           0 :         if (clnt->trans_mod == NULL) {
    1032           0 :                 err = -EPROTONOSUPPORT;
    1033           0 :                 p9_debug(P9_DEBUG_ERROR,
    1034             :                          "No transport defined or default transport\n");
    1035           0 :                 goto free_client;
    1036             :         }
    1037             : 
    1038           0 :         p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n",
    1039             :                  clnt, clnt->trans_mod, clnt->msize, clnt->proto_version);
    1040             : 
    1041           0 :         err = clnt->trans_mod->create(clnt, dev_name, options);
    1042           0 :         if (err)
    1043           0 :                 goto put_trans;
    1044             : 
    1045           0 :         if (clnt->msize > clnt->trans_mod->maxsize)
    1046           0 :                 clnt->msize = clnt->trans_mod->maxsize;
    1047             : 
    1048           0 :         if (clnt->msize < 4096) {
    1049           0 :                 p9_debug(P9_DEBUG_ERROR,
    1050             :                          "Please specify a msize of at least 4k\n");
    1051           0 :                 err = -EINVAL;
    1052           0 :                 goto close_trans;
    1053             :         }
    1054             : 
    1055           0 :         err = p9_client_version(clnt);
    1056           0 :         if (err)
    1057           0 :                 goto close_trans;
    1058             : 
    1059             :         /* P9_HDRSZ + 4 is the smallest packet header we can have that is
    1060             :          * followed by data accessed from userspace by read
    1061             :          */
    1062           0 :         clnt->fcall_cache =
    1063           0 :                 kmem_cache_create_usercopy("9p-fcall-cache", clnt->msize,
    1064             :                                            0, 0, P9_HDRSZ + 4,
    1065           0 :                                            clnt->msize - (P9_HDRSZ + 4),
    1066             :                                            NULL);
    1067             : 
    1068           0 :         return clnt;
    1069             : 
    1070           0 : close_trans:
    1071           0 :         clnt->trans_mod->close(clnt);
    1072           0 : put_trans:
    1073           0 :         v9fs_put_trans(clnt->trans_mod);
    1074           0 : free_client:
    1075           0 :         kfree(clnt);
    1076           0 :         return ERR_PTR(err);
    1077             : }
    1078             : EXPORT_SYMBOL(p9_client_create);
    1079             : 
    1080           0 : void p9_client_destroy(struct p9_client *clnt)
    1081             : {
    1082           0 :         struct p9_fid *fid;
    1083           0 :         int id;
    1084             : 
    1085           0 :         p9_debug(P9_DEBUG_MUX, "clnt %p\n", clnt);
    1086             : 
    1087           0 :         if (clnt->trans_mod)
    1088           0 :                 clnt->trans_mod->close(clnt);
    1089             : 
    1090           0 :         v9fs_put_trans(clnt->trans_mod);
    1091             : 
    1092           0 :         idr_for_each_entry(&clnt->fids, fid, id) {
    1093           0 :                 pr_info("Found fid %d not clunked\n", fid->fid);
    1094           0 :                 p9_fid_destroy(fid);
    1095             :         }
    1096             : 
    1097           0 :         p9_tag_cleanup(clnt);
    1098             : 
    1099           0 :         kmem_cache_destroy(clnt->fcall_cache);
    1100           0 :         kfree(clnt);
    1101           0 : }
    1102             : EXPORT_SYMBOL(p9_client_destroy);
    1103             : 
    1104           0 : void p9_client_disconnect(struct p9_client *clnt)
    1105             : {
    1106           0 :         p9_debug(P9_DEBUG_9P, "clnt %p\n", clnt);
    1107           0 :         clnt->status = Disconnected;
    1108           0 : }
    1109             : EXPORT_SYMBOL(p9_client_disconnect);
    1110             : 
    1111           0 : void p9_client_begin_disconnect(struct p9_client *clnt)
    1112             : {
    1113           0 :         p9_debug(P9_DEBUG_9P, "clnt %p\n", clnt);
    1114           0 :         clnt->status = BeginDisconnect;
    1115           0 : }
    1116             : EXPORT_SYMBOL(p9_client_begin_disconnect);
    1117             : 
    1118           0 : struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
    1119             :         const char *uname, kuid_t n_uname, const char *aname)
    1120             : {
    1121           0 :         int err = 0;
    1122           0 :         struct p9_req_t *req;
    1123           0 :         struct p9_fid *fid;
    1124           0 :         struct p9_qid qid;
    1125             : 
    1126             : 
    1127           0 :         p9_debug(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
    1128             :                  afid ? afid->fid : -1, uname, aname);
    1129           0 :         fid = p9_fid_create(clnt);
    1130           0 :         if (!fid) {
    1131           0 :                 err = -ENOMEM;
    1132           0 :                 goto error;
    1133             :         }
    1134           0 :         fid->uid = n_uname;
    1135             : 
    1136           0 :         req = p9_client_rpc(clnt, P9_TATTACH, "ddss?u", fid->fid,
    1137             :                         afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
    1138           0 :         if (IS_ERR(req)) {
    1139           0 :                 err = PTR_ERR(req);
    1140           0 :                 goto error;
    1141             :         }
    1142             : 
    1143           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", &qid);
    1144           0 :         if (err) {
    1145           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    1146           0 :                 p9_tag_remove(clnt, req);
    1147           0 :                 goto error;
    1148             :         }
    1149             : 
    1150           0 :         p9_debug(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n",
    1151             :                  qid.type, (unsigned long long)qid.path, qid.version);
    1152             : 
    1153           0 :         memmove(&fid->qid, &qid, sizeof(struct p9_qid));
    1154             : 
    1155           0 :         p9_tag_remove(clnt, req);
    1156           0 :         return fid;
    1157             : 
    1158           0 : error:
    1159           0 :         if (fid)
    1160           0 :                 p9_fid_destroy(fid);
    1161           0 :         return ERR_PTR(err);
    1162             : }
    1163             : EXPORT_SYMBOL(p9_client_attach);
    1164             : 
    1165           0 : struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
    1166             :                 const unsigned char * const *wnames, int clone)
    1167             : {
    1168           0 :         int err;
    1169           0 :         struct p9_client *clnt;
    1170           0 :         struct p9_fid *fid;
    1171           0 :         struct p9_qid *wqids;
    1172           0 :         struct p9_req_t *req;
    1173           0 :         uint16_t nwqids, count;
    1174             : 
    1175           0 :         err = 0;
    1176           0 :         wqids = NULL;
    1177           0 :         clnt = oldfid->clnt;
    1178           0 :         if (clone) {
    1179           0 :                 fid = p9_fid_create(clnt);
    1180           0 :                 if (!fid) {
    1181           0 :                         err = -ENOMEM;
    1182           0 :                         goto error;
    1183             :                 }
    1184             : 
    1185           0 :                 fid->uid = oldfid->uid;
    1186             :         } else
    1187             :                 fid = oldfid;
    1188             : 
    1189             : 
    1190           0 :         p9_debug(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %ud wname[0] %s\n",
    1191             :                  oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
    1192           0 :         req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
    1193             :                                                                 nwname, wnames);
    1194           0 :         if (IS_ERR(req)) {
    1195           0 :                 err = PTR_ERR(req);
    1196           0 :                 goto error;
    1197             :         }
    1198             : 
    1199           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "R", &nwqids, &wqids);
    1200           0 :         if (err) {
    1201           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    1202           0 :                 p9_tag_remove(clnt, req);
    1203           0 :                 goto clunk_fid;
    1204             :         }
    1205           0 :         p9_tag_remove(clnt, req);
    1206             : 
    1207           0 :         p9_debug(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);
    1208             : 
    1209           0 :         if (nwqids != nwname) {
    1210           0 :                 err = -ENOENT;
    1211           0 :                 goto clunk_fid;
    1212             :         }
    1213             : 
    1214           0 :         for (count = 0; count < nwqids; count++)
    1215             :                 p9_debug(P9_DEBUG_9P, "<<<     [%d] %x.%llx.%x\n",
    1216             :                         count, wqids[count].type,
    1217             :                         (unsigned long long)wqids[count].path,
    1218             :                         wqids[count].version);
    1219             : 
    1220           0 :         if (nwname)
    1221           0 :                 memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid));
    1222             :         else
    1223           0 :                 memmove(&fid->qid, &oldfid->qid, sizeof(struct p9_qid));
    1224             : 
    1225           0 :         kfree(wqids);
    1226           0 :         return fid;
    1227             : 
    1228           0 : clunk_fid:
    1229           0 :         kfree(wqids);
    1230           0 :         p9_client_clunk(fid);
    1231           0 :         fid = NULL;
    1232             : 
    1233           0 : error:
    1234           0 :         if (fid && (fid != oldfid))
    1235           0 :                 p9_fid_destroy(fid);
    1236             : 
    1237           0 :         return ERR_PTR(err);
    1238             : }
    1239             : EXPORT_SYMBOL(p9_client_walk);
    1240             : 
    1241           0 : int p9_client_open(struct p9_fid *fid, int mode)
    1242             : {
    1243           0 :         int err;
    1244           0 :         struct p9_client *clnt;
    1245           0 :         struct p9_req_t *req;
    1246           0 :         struct p9_qid qid;
    1247           0 :         int iounit;
    1248             : 
    1249           0 :         clnt = fid->clnt;
    1250           0 :         p9_debug(P9_DEBUG_9P, ">>> %s fid %d mode %d\n",
    1251             :                 p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN", fid->fid, mode);
    1252           0 :         err = 0;
    1253             : 
    1254           0 :         if (fid->mode != -1)
    1255             :                 return -EINVAL;
    1256             : 
    1257           0 :         if (p9_is_proto_dotl(clnt))
    1258           0 :                 req = p9_client_rpc(clnt, P9_TLOPEN, "dd", fid->fid, mode);
    1259             :         else
    1260           0 :                 req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode);
    1261           0 :         if (IS_ERR(req)) {
    1262           0 :                 err = PTR_ERR(req);
    1263           0 :                 goto error;
    1264             :         }
    1265             : 
    1266           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "Qd", &qid, &iounit);
    1267           0 :         if (err) {
    1268           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    1269           0 :                 goto free_and_error;
    1270             :         }
    1271             : 
    1272           0 :         p9_debug(P9_DEBUG_9P, "<<< %s qid %x.%llx.%x iounit %x\n",
    1273             :                 p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN",  qid.type,
    1274             :                 (unsigned long long)qid.path, qid.version, iounit);
    1275             : 
    1276           0 :         memmove(&fid->qid, &qid, sizeof(struct p9_qid));
    1277           0 :         fid->mode = mode;
    1278           0 :         fid->iounit = iounit;
    1279             : 
    1280           0 : free_and_error:
    1281           0 :         p9_tag_remove(clnt, req);
    1282             : error:
    1283             :         return err;
    1284             : }
    1285             : EXPORT_SYMBOL(p9_client_open);
    1286             : 
    1287           0 : int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32 mode,
    1288             :                 kgid_t gid, struct p9_qid *qid)
    1289             : {
    1290           0 :         int err = 0;
    1291           0 :         struct p9_client *clnt;
    1292           0 :         struct p9_req_t *req;
    1293           0 :         int iounit;
    1294             : 
    1295           0 :         p9_debug(P9_DEBUG_9P,
    1296             :                         ">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n",
    1297             :                         ofid->fid, name, flags, mode,
    1298             :                         from_kgid(&init_user_ns, gid));
    1299           0 :         clnt = ofid->clnt;
    1300             : 
    1301           0 :         if (ofid->mode != -1)
    1302             :                 return -EINVAL;
    1303             : 
    1304           0 :         req = p9_client_rpc(clnt, P9_TLCREATE, "dsddg", ofid->fid, name, flags,
    1305             :                         mode, gid);
    1306           0 :         if (IS_ERR(req)) {
    1307           0 :                 err = PTR_ERR(req);
    1308           0 :                 goto error;
    1309             :         }
    1310             : 
    1311           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "Qd", qid, &iounit);
    1312           0 :         if (err) {
    1313           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    1314           0 :                 goto free_and_error;
    1315             :         }
    1316             : 
    1317           0 :         p9_debug(P9_DEBUG_9P, "<<< RLCREATE qid %x.%llx.%x iounit %x\n",
    1318             :                         qid->type,
    1319             :                         (unsigned long long)qid->path,
    1320             :                         qid->version, iounit);
    1321             : 
    1322           0 :         memmove(&ofid->qid, qid, sizeof(struct p9_qid));
    1323           0 :         ofid->mode = mode;
    1324           0 :         ofid->iounit = iounit;
    1325             : 
    1326           0 : free_and_error:
    1327           0 :         p9_tag_remove(clnt, req);
    1328             : error:
    1329             :         return err;
    1330             : }
    1331             : EXPORT_SYMBOL(p9_client_create_dotl);
    1332             : 
    1333           0 : int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode,
    1334             :                      char *extension)
    1335             : {
    1336           0 :         int err;
    1337           0 :         struct p9_client *clnt;
    1338           0 :         struct p9_req_t *req;
    1339           0 :         struct p9_qid qid;
    1340           0 :         int iounit;
    1341             : 
    1342           0 :         p9_debug(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n",
    1343             :                                                 fid->fid, name, perm, mode);
    1344           0 :         err = 0;
    1345           0 :         clnt = fid->clnt;
    1346             : 
    1347           0 :         if (fid->mode != -1)
    1348             :                 return -EINVAL;
    1349             : 
    1350           0 :         req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm,
    1351             :                                 mode, extension);
    1352           0 :         if (IS_ERR(req)) {
    1353           0 :                 err = PTR_ERR(req);
    1354           0 :                 goto error;
    1355             :         }
    1356             : 
    1357           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "Qd", &qid, &iounit);
    1358           0 :         if (err) {
    1359           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    1360           0 :                 goto free_and_error;
    1361             :         }
    1362             : 
    1363           0 :         p9_debug(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
    1364             :                                 qid.type,
    1365             :                                 (unsigned long long)qid.path,
    1366             :                                 qid.version, iounit);
    1367             : 
    1368           0 :         memmove(&fid->qid, &qid, sizeof(struct p9_qid));
    1369           0 :         fid->mode = mode;
    1370           0 :         fid->iounit = iounit;
    1371             : 
    1372           0 : free_and_error:
    1373           0 :         p9_tag_remove(clnt, req);
    1374             : error:
    1375             :         return err;
    1376             : }
    1377             : EXPORT_SYMBOL(p9_client_fcreate);
    1378             : 
    1379           0 : int p9_client_symlink(struct p9_fid *dfid, const char *name,
    1380             :                 const char *symtgt, kgid_t gid, struct p9_qid *qid)
    1381             : {
    1382           0 :         int err = 0;
    1383           0 :         struct p9_client *clnt;
    1384           0 :         struct p9_req_t *req;
    1385             : 
    1386           0 :         p9_debug(P9_DEBUG_9P, ">>> TSYMLINK dfid %d name %s  symtgt %s\n",
    1387             :                         dfid->fid, name, symtgt);
    1388           0 :         clnt = dfid->clnt;
    1389             : 
    1390           0 :         req = p9_client_rpc(clnt, P9_TSYMLINK, "dssg", dfid->fid, name, symtgt,
    1391             :                         gid);
    1392           0 :         if (IS_ERR(req)) {
    1393           0 :                 err = PTR_ERR(req);
    1394           0 :                 goto error;
    1395             :         }
    1396             : 
    1397           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", qid);
    1398           0 :         if (err) {
    1399           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    1400           0 :                 goto free_and_error;
    1401             :         }
    1402             : 
    1403             :         p9_debug(P9_DEBUG_9P, "<<< RSYMLINK qid %x.%llx.%x\n",
    1404             :                         qid->type, (unsigned long long)qid->path, qid->version);
    1405             : 
    1406           0 : free_and_error:
    1407           0 :         p9_tag_remove(clnt, req);
    1408           0 : error:
    1409           0 :         return err;
    1410             : }
    1411             : EXPORT_SYMBOL(p9_client_symlink);
    1412             : 
    1413           0 : int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, const char *newname)
    1414             : {
    1415           0 :         struct p9_client *clnt;
    1416           0 :         struct p9_req_t *req;
    1417             : 
    1418           0 :         p9_debug(P9_DEBUG_9P, ">>> TLINK dfid %d oldfid %d newname %s\n",
    1419             :                         dfid->fid, oldfid->fid, newname);
    1420           0 :         clnt = dfid->clnt;
    1421           0 :         req = p9_client_rpc(clnt, P9_TLINK, "dds", dfid->fid, oldfid->fid,
    1422             :                         newname);
    1423           0 :         if (IS_ERR(req))
    1424           0 :                 return PTR_ERR(req);
    1425             : 
    1426           0 :         p9_debug(P9_DEBUG_9P, "<<< RLINK\n");
    1427           0 :         p9_tag_remove(clnt, req);
    1428           0 :         return 0;
    1429             : }
    1430             : EXPORT_SYMBOL(p9_client_link);
    1431             : 
    1432           0 : int p9_client_fsync(struct p9_fid *fid, int datasync)
    1433             : {
    1434           0 :         int err;
    1435           0 :         struct p9_client *clnt;
    1436           0 :         struct p9_req_t *req;
    1437             : 
    1438           0 :         p9_debug(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n",
    1439             :                         fid->fid, datasync);
    1440           0 :         err = 0;
    1441           0 :         clnt = fid->clnt;
    1442             : 
    1443           0 :         req = p9_client_rpc(clnt, P9_TFSYNC, "dd", fid->fid, datasync);
    1444           0 :         if (IS_ERR(req)) {
    1445           0 :                 err = PTR_ERR(req);
    1446           0 :                 goto error;
    1447             :         }
    1448             : 
    1449           0 :         p9_debug(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid);
    1450             : 
    1451           0 :         p9_tag_remove(clnt, req);
    1452             : 
    1453           0 : error:
    1454           0 :         return err;
    1455             : }
    1456             : EXPORT_SYMBOL(p9_client_fsync);
    1457             : 
    1458           0 : int p9_client_clunk(struct p9_fid *fid)
    1459             : {
    1460           0 :         int err;
    1461           0 :         struct p9_client *clnt;
    1462           0 :         struct p9_req_t *req;
    1463           0 :         int retries = 0;
    1464             : 
    1465           0 :         if (!fid || IS_ERR(fid)) {
    1466           0 :                 pr_warn("%s (%d): Trying to clunk with invalid fid\n",
    1467             :                         __func__, task_pid_nr(current));
    1468           0 :                 dump_stack();
    1469           0 :                 return 0;
    1470             :         }
    1471           0 :         if (!refcount_dec_and_test(&fid->count))
    1472             :                 return 0;
    1473             : 
    1474           0 : again:
    1475           0 :         p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n", fid->fid,
    1476             :                                                                 retries);
    1477           0 :         err = 0;
    1478           0 :         clnt = fid->clnt;
    1479             : 
    1480           0 :         req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid);
    1481           0 :         if (IS_ERR(req)) {
    1482           0 :                 err = PTR_ERR(req);
    1483           0 :                 goto error;
    1484             :         }
    1485             : 
    1486           0 :         p9_debug(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
    1487             : 
    1488           0 :         p9_tag_remove(clnt, req);
    1489           0 : error:
    1490             :         /*
    1491             :          * Fid is not valid even after a failed clunk
    1492             :          * If interrupted, retry once then give up and
    1493             :          * leak fid until umount.
    1494             :          */
    1495           0 :         if (err == -ERESTARTSYS) {
    1496           0 :                 if (retries++ == 0)
    1497           0 :                         goto again;
    1498             :         } else
    1499           0 :                 p9_fid_destroy(fid);
    1500             :         return err;
    1501             : }
    1502             : EXPORT_SYMBOL(p9_client_clunk);
    1503             : 
    1504           0 : int p9_client_remove(struct p9_fid *fid)
    1505             : {
    1506           0 :         int err;
    1507           0 :         struct p9_client *clnt;
    1508           0 :         struct p9_req_t *req;
    1509             : 
    1510           0 :         p9_debug(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid);
    1511           0 :         err = 0;
    1512           0 :         clnt = fid->clnt;
    1513             : 
    1514           0 :         req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid);
    1515           0 :         if (IS_ERR(req)) {
    1516           0 :                 err = PTR_ERR(req);
    1517           0 :                 goto error;
    1518             :         }
    1519             : 
    1520           0 :         p9_debug(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid);
    1521             : 
    1522           0 :         p9_tag_remove(clnt, req);
    1523           0 : error:
    1524           0 :         if (err == -ERESTARTSYS)
    1525           0 :                 p9_client_clunk(fid);
    1526             :         else
    1527           0 :                 p9_fid_destroy(fid);
    1528           0 :         return err;
    1529             : }
    1530             : EXPORT_SYMBOL(p9_client_remove);
    1531             : 
    1532           0 : int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags)
    1533             : {
    1534           0 :         int err = 0;
    1535           0 :         struct p9_req_t *req;
    1536           0 :         struct p9_client *clnt;
    1537             : 
    1538           0 :         p9_debug(P9_DEBUG_9P, ">>> TUNLINKAT fid %d %s %d\n",
    1539             :                    dfid->fid, name, flags);
    1540             : 
    1541           0 :         clnt = dfid->clnt;
    1542           0 :         req = p9_client_rpc(clnt, P9_TUNLINKAT, "dsd", dfid->fid, name, flags);
    1543           0 :         if (IS_ERR(req)) {
    1544           0 :                 err = PTR_ERR(req);
    1545           0 :                 goto error;
    1546             :         }
    1547           0 :         p9_debug(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name);
    1548             : 
    1549           0 :         p9_tag_remove(clnt, req);
    1550           0 : error:
    1551           0 :         return err;
    1552             : }
    1553             : EXPORT_SYMBOL(p9_client_unlinkat);
    1554             : 
    1555             : int
    1556           0 : p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
    1557             : {
    1558           0 :         int total = 0;
    1559           0 :         *err = 0;
    1560             : 
    1561           0 :         while (iov_iter_count(to)) {
    1562           0 :                 int count;
    1563             : 
    1564           0 :                 count = p9_client_read_once(fid, offset, to, err);
    1565           0 :                 if (!count || *err)
    1566             :                         break;
    1567           0 :                 offset += count;
    1568           0 :                 total += count;
    1569             :         }
    1570           0 :         return total;
    1571             : }
    1572             : EXPORT_SYMBOL(p9_client_read);
    1573             : 
    1574             : int
    1575           0 : p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
    1576             :                     int *err)
    1577             : {
    1578           0 :         struct p9_client *clnt = fid->clnt;
    1579           0 :         struct p9_req_t *req;
    1580           0 :         int count = iov_iter_count(to);
    1581           0 :         int rsize, non_zc = 0;
    1582           0 :         char *dataptr;
    1583             : 
    1584           0 :         *err = 0;
    1585           0 :         p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n",
    1586             :                    fid->fid, (unsigned long long) offset, (int)iov_iter_count(to));
    1587             : 
    1588           0 :         rsize = fid->iounit;
    1589           0 :         if (!rsize || rsize > clnt->msize - P9_IOHDRSZ)
    1590           0 :                 rsize = clnt->msize - P9_IOHDRSZ;
    1591             : 
    1592           0 :         if (count < rsize)
    1593             :                 rsize = count;
    1594             : 
    1595             :         /* Don't bother zerocopy for small IO (< 1024) */
    1596           0 :         if (clnt->trans_mod->zc_request && rsize > 1024) {
    1597             :                 /* response header len is 11
    1598             :                  * PDU Header(7) + IO Size (4)
    1599             :                  */
    1600           0 :                 req = p9_client_zc_rpc(clnt, P9_TREAD, to, NULL, rsize,
    1601             :                                        0, 11, "dqd", fid->fid,
    1602             :                                        offset, rsize);
    1603             :         } else {
    1604           0 :                 non_zc = 1;
    1605           0 :                 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
    1606             :                                     rsize);
    1607             :         }
    1608           0 :         if (IS_ERR(req)) {
    1609           0 :                 *err = PTR_ERR(req);
    1610           0 :                 return 0;
    1611             :         }
    1612             : 
    1613           0 :         *err = p9pdu_readf(&req->rc, clnt->proto_version,
    1614             :                            "D", &count, &dataptr);
    1615           0 :         if (*err) {
    1616           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    1617           0 :                 p9_tag_remove(clnt, req);
    1618           0 :                 return 0;
    1619             :         }
    1620           0 :         if (rsize < count) {
    1621           0 :                 pr_err("bogus RREAD count (%d > %d)\n", count, rsize);
    1622           0 :                 count = rsize;
    1623             :         }
    1624             : 
    1625           0 :         p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
    1626             : 
    1627           0 :         if (non_zc) {
    1628           0 :                 int n = copy_to_iter(dataptr, count, to);
    1629             : 
    1630           0 :                 if (n != count) {
    1631           0 :                         *err = -EFAULT;
    1632           0 :                         p9_tag_remove(clnt, req);
    1633           0 :                         return n;
    1634             :                 }
    1635             :         } else {
    1636           0 :                 iov_iter_advance(to, count);
    1637             :         }
    1638           0 :         p9_tag_remove(clnt, req);
    1639           0 :         return count;
    1640             : }
    1641             : EXPORT_SYMBOL(p9_client_read_once);
    1642             : 
    1643             : int
    1644           0 : p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
    1645             : {
    1646           0 :         struct p9_client *clnt = fid->clnt;
    1647           0 :         struct p9_req_t *req;
    1648           0 :         int total = 0;
    1649           0 :         *err = 0;
    1650             : 
    1651           0 :         p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %zd\n",
    1652             :                                 fid->fid, (unsigned long long) offset,
    1653             :                                 iov_iter_count(from));
    1654             : 
    1655           0 :         while (iov_iter_count(from)) {
    1656           0 :                 int count = iov_iter_count(from);
    1657           0 :                 int rsize = fid->iounit;
    1658           0 :                 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
    1659           0 :                         rsize = clnt->msize - P9_IOHDRSZ;
    1660             : 
    1661           0 :                 if (count < rsize)
    1662             :                         rsize = count;
    1663             : 
    1664             :                 /* Don't bother zerocopy for small IO (< 1024) */
    1665           0 :                 if (clnt->trans_mod->zc_request && rsize > 1024) {
    1666           0 :                         req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, from, 0,
    1667             :                                                rsize, P9_ZC_HDR_SZ, "dqd",
    1668             :                                                fid->fid, offset, rsize);
    1669             :                 } else {
    1670           0 :                         req = p9_client_rpc(clnt, P9_TWRITE, "dqV", fid->fid,
    1671             :                                                     offset, rsize, from);
    1672             :                 }
    1673           0 :                 if (IS_ERR(req)) {
    1674           0 :                         *err = PTR_ERR(req);
    1675           0 :                         break;
    1676             :                 }
    1677             : 
    1678           0 :                 *err = p9pdu_readf(&req->rc, clnt->proto_version, "d", &count);
    1679           0 :                 if (*err) {
    1680           0 :                         trace_9p_protocol_dump(clnt, &req->rc);
    1681           0 :                         p9_tag_remove(clnt, req);
    1682           0 :                         break;
    1683             :                 }
    1684           0 :                 if (rsize < count) {
    1685           0 :                         pr_err("bogus RWRITE count (%d > %d)\n", count, rsize);
    1686           0 :                         count = rsize;
    1687             :                 }
    1688             : 
    1689           0 :                 p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
    1690             : 
    1691           0 :                 p9_tag_remove(clnt, req);
    1692           0 :                 iov_iter_advance(from, count);
    1693           0 :                 total += count;
    1694           0 :                 offset += count;
    1695             :         }
    1696           0 :         return total;
    1697             : }
    1698             : EXPORT_SYMBOL(p9_client_write);
    1699             : 
    1700           0 : struct p9_wstat *p9_client_stat(struct p9_fid *fid)
    1701             : {
    1702           0 :         int err;
    1703           0 :         struct p9_client *clnt;
    1704           0 :         struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL);
    1705           0 :         struct p9_req_t *req;
    1706           0 :         u16 ignored;
    1707             : 
    1708           0 :         p9_debug(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid);
    1709             : 
    1710           0 :         if (!ret)
    1711           0 :                 return ERR_PTR(-ENOMEM);
    1712             : 
    1713           0 :         err = 0;
    1714           0 :         clnt = fid->clnt;
    1715             : 
    1716           0 :         req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid);
    1717           0 :         if (IS_ERR(req)) {
    1718           0 :                 err = PTR_ERR(req);
    1719           0 :                 goto error;
    1720             :         }
    1721             : 
    1722           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "wS", &ignored, ret);
    1723           0 :         if (err) {
    1724           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    1725           0 :                 p9_tag_remove(clnt, req);
    1726           0 :                 goto error;
    1727             :         }
    1728             : 
    1729           0 :         p9_debug(P9_DEBUG_9P,
    1730             :                 "<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
    1731             :                 "<<<    mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
    1732             :                 "<<<    name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
    1733             :                 "<<<    uid=%d gid=%d n_muid=%d\n",
    1734             :                 ret->size, ret->type, ret->dev, ret->qid.type,
    1735             :                 (unsigned long long)ret->qid.path, ret->qid.version, ret->mode,
    1736             :                 ret->atime, ret->mtime, (unsigned long long)ret->length,
    1737             :                 ret->name, ret->uid, ret->gid, ret->muid, ret->extension,
    1738             :                 from_kuid(&init_user_ns, ret->n_uid),
    1739             :                 from_kgid(&init_user_ns, ret->n_gid),
    1740             :                 from_kuid(&init_user_ns, ret->n_muid));
    1741             : 
    1742           0 :         p9_tag_remove(clnt, req);
    1743           0 :         return ret;
    1744             : 
    1745           0 : error:
    1746           0 :         kfree(ret);
    1747           0 :         return ERR_PTR(err);
    1748             : }
    1749             : EXPORT_SYMBOL(p9_client_stat);
    1750             : 
    1751           0 : struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
    1752             :                                                         u64 request_mask)
    1753             : {
    1754           0 :         int err;
    1755           0 :         struct p9_client *clnt;
    1756           0 :         struct p9_stat_dotl *ret = kmalloc(sizeof(struct p9_stat_dotl),
    1757             :                                                                 GFP_KERNEL);
    1758           0 :         struct p9_req_t *req;
    1759             : 
    1760           0 :         p9_debug(P9_DEBUG_9P, ">>> TGETATTR fid %d, request_mask %lld\n",
    1761             :                                                         fid->fid, request_mask);
    1762             : 
    1763           0 :         if (!ret)
    1764           0 :                 return ERR_PTR(-ENOMEM);
    1765             : 
    1766           0 :         err = 0;
    1767           0 :         clnt = fid->clnt;
    1768             : 
    1769           0 :         req = p9_client_rpc(clnt, P9_TGETATTR, "dq", fid->fid, request_mask);
    1770           0 :         if (IS_ERR(req)) {
    1771           0 :                 err = PTR_ERR(req);
    1772           0 :                 goto error;
    1773             :         }
    1774             : 
    1775           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "A", ret);
    1776           0 :         if (err) {
    1777           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    1778           0 :                 p9_tag_remove(clnt, req);
    1779           0 :                 goto error;
    1780             :         }
    1781             : 
    1782           0 :         p9_debug(P9_DEBUG_9P,
    1783             :                 "<<< RGETATTR st_result_mask=%lld\n"
    1784             :                 "<<< qid=%x.%llx.%x\n"
    1785             :                 "<<< st_mode=%8.8x st_nlink=%llu\n"
    1786             :                 "<<< st_uid=%d st_gid=%d\n"
    1787             :                 "<<< st_rdev=%llx st_size=%llx st_blksize=%llu st_blocks=%llu\n"
    1788             :                 "<<< st_atime_sec=%lld st_atime_nsec=%lld\n"
    1789             :                 "<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n"
    1790             :                 "<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n"
    1791             :                 "<<< st_btime_sec=%lld st_btime_nsec=%lld\n"
    1792             :                 "<<< st_gen=%lld st_data_version=%lld\n",
    1793             :                 ret->st_result_mask, ret->qid.type, ret->qid.path,
    1794             :                 ret->qid.version, ret->st_mode, ret->st_nlink,
    1795             :                 from_kuid(&init_user_ns, ret->st_uid),
    1796             :                 from_kgid(&init_user_ns, ret->st_gid),
    1797             :                 ret->st_rdev, ret->st_size, ret->st_blksize,
    1798             :                 ret->st_blocks, ret->st_atime_sec, ret->st_atime_nsec,
    1799             :                 ret->st_mtime_sec, ret->st_mtime_nsec, ret->st_ctime_sec,
    1800             :                 ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec,
    1801             :                 ret->st_gen, ret->st_data_version);
    1802             : 
    1803           0 :         p9_tag_remove(clnt, req);
    1804           0 :         return ret;
    1805             : 
    1806           0 : error:
    1807           0 :         kfree(ret);
    1808           0 :         return ERR_PTR(err);
    1809             : }
    1810             : EXPORT_SYMBOL(p9_client_getattr_dotl);
    1811             : 
    1812           0 : static int p9_client_statsize(struct p9_wstat *wst, int proto_version)
    1813             : {
    1814           0 :         int ret;
    1815             : 
    1816             :         /* NOTE: size shouldn't include its own length */
    1817             :         /* size[2] type[2] dev[4] qid[13] */
    1818             :         /* mode[4] atime[4] mtime[4] length[8]*/
    1819             :         /* name[s] uid[s] gid[s] muid[s] */
    1820           0 :         ret = 2+4+13+4+4+4+8+2+2+2+2;
    1821             : 
    1822           0 :         if (wst->name)
    1823           0 :                 ret += strlen(wst->name);
    1824           0 :         if (wst->uid)
    1825           0 :                 ret += strlen(wst->uid);
    1826           0 :         if (wst->gid)
    1827           0 :                 ret += strlen(wst->gid);
    1828           0 :         if (wst->muid)
    1829           0 :                 ret += strlen(wst->muid);
    1830             : 
    1831           0 :         if ((proto_version == p9_proto_2000u) ||
    1832             :                 (proto_version == p9_proto_2000L)) {
    1833           0 :                 ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */
    1834           0 :                 if (wst->extension)
    1835           0 :                         ret += strlen(wst->extension);
    1836             :         }
    1837             : 
    1838           0 :         return ret;
    1839             : }
    1840             : 
    1841           0 : int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
    1842             : {
    1843           0 :         int err;
    1844           0 :         struct p9_req_t *req;
    1845           0 :         struct p9_client *clnt;
    1846             : 
    1847           0 :         err = 0;
    1848           0 :         clnt = fid->clnt;
    1849           0 :         wst->size = p9_client_statsize(wst, clnt->proto_version);
    1850           0 :         p9_debug(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
    1851           0 :         p9_debug(P9_DEBUG_9P,
    1852             :                 "     sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
    1853             :                 "     mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
    1854             :                 "     name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
    1855             :                 "     uid=%d gid=%d n_muid=%d\n",
    1856             :                 wst->size, wst->type, wst->dev, wst->qid.type,
    1857             :                 (unsigned long long)wst->qid.path, wst->qid.version, wst->mode,
    1858             :                 wst->atime, wst->mtime, (unsigned long long)wst->length,
    1859             :                 wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
    1860             :                 from_kuid(&init_user_ns, wst->n_uid),
    1861             :                 from_kgid(&init_user_ns, wst->n_gid),
    1862             :                 from_kuid(&init_user_ns, wst->n_muid));
    1863             : 
    1864           0 :         req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst);
    1865           0 :         if (IS_ERR(req)) {
    1866           0 :                 err = PTR_ERR(req);
    1867           0 :                 goto error;
    1868             :         }
    1869             : 
    1870           0 :         p9_debug(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid);
    1871             : 
    1872           0 :         p9_tag_remove(clnt, req);
    1873           0 : error:
    1874           0 :         return err;
    1875             : }
    1876             : EXPORT_SYMBOL(p9_client_wstat);
    1877             : 
    1878           0 : int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr)
    1879             : {
    1880           0 :         int err;
    1881           0 :         struct p9_req_t *req;
    1882           0 :         struct p9_client *clnt;
    1883             : 
    1884           0 :         err = 0;
    1885           0 :         clnt = fid->clnt;
    1886           0 :         p9_debug(P9_DEBUG_9P, ">>> TSETATTR fid %d\n", fid->fid);
    1887           0 :         p9_debug(P9_DEBUG_9P,
    1888             :                 "    valid=%x mode=%x uid=%d gid=%d size=%lld\n"
    1889             :                 "    atime_sec=%lld atime_nsec=%lld\n"
    1890             :                 "    mtime_sec=%lld mtime_nsec=%lld\n",
    1891             :                 p9attr->valid, p9attr->mode,
    1892             :                 from_kuid(&init_user_ns, p9attr->uid),
    1893             :                 from_kgid(&init_user_ns, p9attr->gid),
    1894             :                 p9attr->size, p9attr->atime_sec, p9attr->atime_nsec,
    1895             :                 p9attr->mtime_sec, p9attr->mtime_nsec);
    1896             : 
    1897           0 :         req = p9_client_rpc(clnt, P9_TSETATTR, "dI", fid->fid, p9attr);
    1898             : 
    1899           0 :         if (IS_ERR(req)) {
    1900           0 :                 err = PTR_ERR(req);
    1901           0 :                 goto error;
    1902             :         }
    1903           0 :         p9_debug(P9_DEBUG_9P, "<<< RSETATTR fid %d\n", fid->fid);
    1904           0 :         p9_tag_remove(clnt, req);
    1905           0 : error:
    1906           0 :         return err;
    1907             : }
    1908             : EXPORT_SYMBOL(p9_client_setattr);
    1909             : 
    1910           0 : int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb)
    1911             : {
    1912           0 :         int err;
    1913           0 :         struct p9_req_t *req;
    1914           0 :         struct p9_client *clnt;
    1915             : 
    1916           0 :         err = 0;
    1917           0 :         clnt = fid->clnt;
    1918             : 
    1919           0 :         p9_debug(P9_DEBUG_9P, ">>> TSTATFS fid %d\n", fid->fid);
    1920             : 
    1921           0 :         req = p9_client_rpc(clnt, P9_TSTATFS, "d", fid->fid);
    1922           0 :         if (IS_ERR(req)) {
    1923           0 :                 err = PTR_ERR(req);
    1924           0 :                 goto error;
    1925             :         }
    1926             : 
    1927           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type,
    1928             :                           &sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail,
    1929             :                           &sb->files, &sb->ffree, &sb->fsid, &sb->namelen);
    1930           0 :         if (err) {
    1931           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    1932           0 :                 p9_tag_remove(clnt, req);
    1933           0 :                 goto error;
    1934             :         }
    1935             : 
    1936           0 :         p9_debug(P9_DEBUG_9P, "<<< RSTATFS fid %d type 0x%lx bsize %ld "
    1937             :                 "blocks %llu bfree %llu bavail %llu files %llu ffree %llu "
    1938             :                 "fsid %llu namelen %ld\n",
    1939             :                 fid->fid, (long unsigned int)sb->type, (long int)sb->bsize,
    1940             :                 sb->blocks, sb->bfree, sb->bavail, sb->files,  sb->ffree,
    1941             :                 sb->fsid, (long int)sb->namelen);
    1942             : 
    1943           0 :         p9_tag_remove(clnt, req);
    1944           0 : error:
    1945           0 :         return err;
    1946             : }
    1947             : EXPORT_SYMBOL(p9_client_statfs);
    1948             : 
    1949           0 : int p9_client_rename(struct p9_fid *fid,
    1950             :                      struct p9_fid *newdirfid, const char *name)
    1951             : {
    1952           0 :         int err;
    1953           0 :         struct p9_req_t *req;
    1954           0 :         struct p9_client *clnt;
    1955             : 
    1956           0 :         err = 0;
    1957           0 :         clnt = fid->clnt;
    1958             : 
    1959           0 :         p9_debug(P9_DEBUG_9P, ">>> TRENAME fid %d newdirfid %d name %s\n",
    1960             :                         fid->fid, newdirfid->fid, name);
    1961             : 
    1962           0 :         req = p9_client_rpc(clnt, P9_TRENAME, "dds", fid->fid,
    1963             :                         newdirfid->fid, name);
    1964           0 :         if (IS_ERR(req)) {
    1965           0 :                 err = PTR_ERR(req);
    1966           0 :                 goto error;
    1967             :         }
    1968             : 
    1969           0 :         p9_debug(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid);
    1970             : 
    1971           0 :         p9_tag_remove(clnt, req);
    1972           0 : error:
    1973           0 :         return err;
    1974             : }
    1975             : EXPORT_SYMBOL(p9_client_rename);
    1976             : 
    1977           0 : int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
    1978             :                        struct p9_fid *newdirfid, const char *new_name)
    1979             : {
    1980           0 :         int err;
    1981           0 :         struct p9_req_t *req;
    1982           0 :         struct p9_client *clnt;
    1983             : 
    1984           0 :         err = 0;
    1985           0 :         clnt = olddirfid->clnt;
    1986             : 
    1987           0 :         p9_debug(P9_DEBUG_9P, ">>> TRENAMEAT olddirfid %d old name %s"
    1988             :                    " newdirfid %d new name %s\n", olddirfid->fid, old_name,
    1989             :                    newdirfid->fid, new_name);
    1990             : 
    1991           0 :         req = p9_client_rpc(clnt, P9_TRENAMEAT, "dsds", olddirfid->fid,
    1992             :                             old_name, newdirfid->fid, new_name);
    1993           0 :         if (IS_ERR(req)) {
    1994           0 :                 err = PTR_ERR(req);
    1995           0 :                 goto error;
    1996             :         }
    1997             : 
    1998           0 :         p9_debug(P9_DEBUG_9P, "<<< RRENAMEAT newdirfid %d new name %s\n",
    1999             :                    newdirfid->fid, new_name);
    2000             : 
    2001           0 :         p9_tag_remove(clnt, req);
    2002           0 : error:
    2003           0 :         return err;
    2004             : }
    2005             : EXPORT_SYMBOL(p9_client_renameat);
    2006             : 
    2007             : /*
    2008             :  * An xattrwalk without @attr_name gives the fid for the lisxattr namespace
    2009             :  */
    2010           0 : struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
    2011             :                                 const char *attr_name, u64 *attr_size)
    2012             : {
    2013           0 :         int err;
    2014           0 :         struct p9_req_t *req;
    2015           0 :         struct p9_client *clnt;
    2016           0 :         struct p9_fid *attr_fid;
    2017             : 
    2018           0 :         err = 0;
    2019           0 :         clnt = file_fid->clnt;
    2020           0 :         attr_fid = p9_fid_create(clnt);
    2021           0 :         if (!attr_fid) {
    2022           0 :                 err = -ENOMEM;
    2023           0 :                 goto error;
    2024             :         }
    2025           0 :         p9_debug(P9_DEBUG_9P,
    2026             :                 ">>> TXATTRWALK file_fid %d, attr_fid %d name %s\n",
    2027             :                 file_fid->fid, attr_fid->fid, attr_name);
    2028             : 
    2029           0 :         req = p9_client_rpc(clnt, P9_TXATTRWALK, "dds",
    2030             :                         file_fid->fid, attr_fid->fid, attr_name);
    2031           0 :         if (IS_ERR(req)) {
    2032           0 :                 err = PTR_ERR(req);
    2033           0 :                 goto error;
    2034             :         }
    2035           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "q", attr_size);
    2036           0 :         if (err) {
    2037           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    2038           0 :                 p9_tag_remove(clnt, req);
    2039           0 :                 goto clunk_fid;
    2040             :         }
    2041           0 :         p9_tag_remove(clnt, req);
    2042           0 :         p9_debug(P9_DEBUG_9P, "<<<  RXATTRWALK fid %d size %llu\n",
    2043             :                 attr_fid->fid, *attr_size);
    2044           0 :         return attr_fid;
    2045           0 : clunk_fid:
    2046           0 :         p9_client_clunk(attr_fid);
    2047           0 :         attr_fid = NULL;
    2048           0 : error:
    2049           0 :         if (attr_fid && (attr_fid != file_fid))
    2050           0 :                 p9_fid_destroy(attr_fid);
    2051             : 
    2052           0 :         return ERR_PTR(err);
    2053             : }
    2054             : EXPORT_SYMBOL_GPL(p9_client_xattrwalk);
    2055             : 
    2056           0 : int p9_client_xattrcreate(struct p9_fid *fid, const char *name,
    2057             :                         u64 attr_size, int flags)
    2058             : {
    2059           0 :         int err;
    2060           0 :         struct p9_req_t *req;
    2061           0 :         struct p9_client *clnt;
    2062             : 
    2063           0 :         p9_debug(P9_DEBUG_9P,
    2064             :                 ">>> TXATTRCREATE fid %d name  %s size %lld flag %d\n",
    2065             :                 fid->fid, name, (long long)attr_size, flags);
    2066           0 :         err = 0;
    2067           0 :         clnt = fid->clnt;
    2068           0 :         req = p9_client_rpc(clnt, P9_TXATTRCREATE, "dsqd",
    2069             :                         fid->fid, name, attr_size, flags);
    2070           0 :         if (IS_ERR(req)) {
    2071           0 :                 err = PTR_ERR(req);
    2072           0 :                 goto error;
    2073             :         }
    2074           0 :         p9_debug(P9_DEBUG_9P, "<<< RXATTRCREATE fid %d\n", fid->fid);
    2075           0 :         p9_tag_remove(clnt, req);
    2076           0 : error:
    2077           0 :         return err;
    2078             : }
    2079             : EXPORT_SYMBOL_GPL(p9_client_xattrcreate);
    2080             : 
    2081           0 : int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
    2082             : {
    2083           0 :         int err, rsize, non_zc = 0;
    2084           0 :         struct p9_client *clnt;
    2085           0 :         struct p9_req_t *req;
    2086           0 :         char *dataptr;
    2087           0 :         struct kvec kv = {.iov_base = data, .iov_len = count};
    2088           0 :         struct iov_iter to;
    2089             : 
    2090           0 :         iov_iter_kvec(&to, READ, &kv, 1, count);
    2091             : 
    2092           0 :         p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n",
    2093             :                                 fid->fid, (unsigned long long) offset, count);
    2094             : 
    2095           0 :         err = 0;
    2096           0 :         clnt = fid->clnt;
    2097             : 
    2098           0 :         rsize = fid->iounit;
    2099           0 :         if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ)
    2100           0 :                 rsize = clnt->msize - P9_READDIRHDRSZ;
    2101             : 
    2102           0 :         if (count < rsize)
    2103           0 :                 rsize = count;
    2104             : 
    2105             :         /* Don't bother zerocopy for small IO (< 1024) */
    2106           0 :         if (clnt->trans_mod->zc_request && rsize > 1024) {
    2107             :                 /*
    2108             :                  * response header len is 11
    2109             :                  * PDU Header(7) + IO Size (4)
    2110             :                  */
    2111           0 :                 req = p9_client_zc_rpc(clnt, P9_TREADDIR, &to, NULL, rsize, 0,
    2112             :                                        11, "dqd", fid->fid, offset, rsize);
    2113             :         } else {
    2114           0 :                 non_zc = 1;
    2115           0 :                 req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid,
    2116             :                                     offset, rsize);
    2117             :         }
    2118           0 :         if (IS_ERR(req)) {
    2119           0 :                 err = PTR_ERR(req);
    2120           0 :                 goto error;
    2121             :         }
    2122             : 
    2123           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "D", &count, &dataptr);
    2124           0 :         if (err) {
    2125           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    2126           0 :                 goto free_and_error;
    2127             :         }
    2128           0 :         if (rsize < count) {
    2129           0 :                 pr_err("bogus RREADDIR count (%d > %d)\n", count, rsize);
    2130           0 :                 count = rsize;
    2131             :         }
    2132             : 
    2133           0 :         p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
    2134             : 
    2135           0 :         if (non_zc)
    2136           0 :                 memmove(data, dataptr, count);
    2137             : 
    2138           0 :         p9_tag_remove(clnt, req);
    2139           0 :         return count;
    2140             : 
    2141           0 : free_and_error:
    2142           0 :         p9_tag_remove(clnt, req);
    2143             : error:
    2144             :         return err;
    2145             : }
    2146             : EXPORT_SYMBOL(p9_client_readdir);
    2147             : 
    2148           0 : int p9_client_mknod_dotl(struct p9_fid *fid, const char *name, int mode,
    2149             :                         dev_t rdev, kgid_t gid, struct p9_qid *qid)
    2150             : {
    2151           0 :         int err;
    2152           0 :         struct p9_client *clnt;
    2153           0 :         struct p9_req_t *req;
    2154             : 
    2155           0 :         err = 0;
    2156           0 :         clnt = fid->clnt;
    2157           0 :         p9_debug(P9_DEBUG_9P, ">>> TMKNOD fid %d name %s mode %d major %d "
    2158             :                 "minor %d\n", fid->fid, name, mode, MAJOR(rdev), MINOR(rdev));
    2159           0 :         req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddg", fid->fid, name, mode,
    2160           0 :                 MAJOR(rdev), MINOR(rdev), gid);
    2161           0 :         if (IS_ERR(req))
    2162           0 :                 return PTR_ERR(req);
    2163             : 
    2164           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", qid);
    2165           0 :         if (err) {
    2166           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    2167           0 :                 goto error;
    2168             :         }
    2169             :         p9_debug(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type,
    2170             :                                 (unsigned long long)qid->path, qid->version);
    2171             : 
    2172           0 : error:
    2173           0 :         p9_tag_remove(clnt, req);
    2174           0 :         return err;
    2175             : 
    2176             : }
    2177             : EXPORT_SYMBOL(p9_client_mknod_dotl);
    2178             : 
    2179           0 : int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode,
    2180             :                                 kgid_t gid, struct p9_qid *qid)
    2181             : {
    2182           0 :         int err;
    2183           0 :         struct p9_client *clnt;
    2184           0 :         struct p9_req_t *req;
    2185             : 
    2186           0 :         err = 0;
    2187           0 :         clnt = fid->clnt;
    2188           0 :         p9_debug(P9_DEBUG_9P, ">>> TMKDIR fid %d name %s mode %d gid %d\n",
    2189             :                  fid->fid, name, mode, from_kgid(&init_user_ns, gid));
    2190           0 :         req = p9_client_rpc(clnt, P9_TMKDIR, "dsdg", fid->fid, name, mode,
    2191             :                 gid);
    2192           0 :         if (IS_ERR(req))
    2193           0 :                 return PTR_ERR(req);
    2194             : 
    2195           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", qid);
    2196           0 :         if (err) {
    2197           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    2198           0 :                 goto error;
    2199             :         }
    2200             :         p9_debug(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type,
    2201             :                                 (unsigned long long)qid->path, qid->version);
    2202             : 
    2203           0 : error:
    2204           0 :         p9_tag_remove(clnt, req);
    2205           0 :         return err;
    2206             : 
    2207             : }
    2208             : EXPORT_SYMBOL(p9_client_mkdir_dotl);
    2209             : 
    2210           0 : int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status)
    2211             : {
    2212           0 :         int err;
    2213           0 :         struct p9_client *clnt;
    2214           0 :         struct p9_req_t *req;
    2215             : 
    2216           0 :         err = 0;
    2217           0 :         clnt = fid->clnt;
    2218           0 :         p9_debug(P9_DEBUG_9P, ">>> TLOCK fid %d type %i flags %d "
    2219             :                         "start %lld length %lld proc_id %d client_id %s\n",
    2220             :                         fid->fid, flock->type, flock->flags, flock->start,
    2221             :                         flock->length, flock->proc_id, flock->client_id);
    2222             : 
    2223           0 :         req = p9_client_rpc(clnt, P9_TLOCK, "dbdqqds", fid->fid, flock->type,
    2224             :                                 flock->flags, flock->start, flock->length,
    2225             :                                         flock->proc_id, flock->client_id);
    2226             : 
    2227           0 :         if (IS_ERR(req))
    2228           0 :                 return PTR_ERR(req);
    2229             : 
    2230           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "b", status);
    2231           0 :         if (err) {
    2232           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    2233           0 :                 goto error;
    2234             :         }
    2235             :         p9_debug(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status);
    2236           0 : error:
    2237           0 :         p9_tag_remove(clnt, req);
    2238           0 :         return err;
    2239             : 
    2240             : }
    2241             : EXPORT_SYMBOL(p9_client_lock_dotl);
    2242             : 
    2243           0 : int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock)
    2244             : {
    2245           0 :         int err;
    2246           0 :         struct p9_client *clnt;
    2247           0 :         struct p9_req_t *req;
    2248             : 
    2249           0 :         err = 0;
    2250           0 :         clnt = fid->clnt;
    2251           0 :         p9_debug(P9_DEBUG_9P, ">>> TGETLOCK fid %d, type %i start %lld "
    2252             :                 "length %lld proc_id %d client_id %s\n", fid->fid, glock->type,
    2253             :                 glock->start, glock->length, glock->proc_id, glock->client_id);
    2254             : 
    2255           0 :         req = p9_client_rpc(clnt, P9_TGETLOCK, "dbqqds", fid->fid,  glock->type,
    2256             :                 glock->start, glock->length, glock->proc_id, glock->client_id);
    2257             : 
    2258           0 :         if (IS_ERR(req))
    2259           0 :                 return PTR_ERR(req);
    2260             : 
    2261           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "bqqds", &glock->type,
    2262             :                           &glock->start, &glock->length, &glock->proc_id,
    2263             :                           &glock->client_id);
    2264           0 :         if (err) {
    2265           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    2266           0 :                 goto error;
    2267             :         }
    2268             :         p9_debug(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld "
    2269             :                 "proc_id %d client_id %s\n", glock->type, glock->start,
    2270             :                 glock->length, glock->proc_id, glock->client_id);
    2271           0 : error:
    2272           0 :         p9_tag_remove(clnt, req);
    2273           0 :         return err;
    2274             : }
    2275             : EXPORT_SYMBOL(p9_client_getlock_dotl);
    2276             : 
    2277           0 : int p9_client_readlink(struct p9_fid *fid, char **target)
    2278             : {
    2279           0 :         int err;
    2280           0 :         struct p9_client *clnt;
    2281           0 :         struct p9_req_t *req;
    2282             : 
    2283           0 :         err = 0;
    2284           0 :         clnt = fid->clnt;
    2285           0 :         p9_debug(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid);
    2286             : 
    2287           0 :         req = p9_client_rpc(clnt, P9_TREADLINK, "d", fid->fid);
    2288           0 :         if (IS_ERR(req))
    2289           0 :                 return PTR_ERR(req);
    2290             : 
    2291           0 :         err = p9pdu_readf(&req->rc, clnt->proto_version, "s", target);
    2292           0 :         if (err) {
    2293           0 :                 trace_9p_protocol_dump(clnt, &req->rc);
    2294           0 :                 goto error;
    2295             :         }
    2296             :         p9_debug(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
    2297           0 : error:
    2298           0 :         p9_tag_remove(clnt, req);
    2299           0 :         return err;
    2300             : }
    2301             : EXPORT_SYMBOL(p9_client_readlink);
    2302             : 
    2303           1 : int __init p9_client_init(void)
    2304             : {
    2305           1 :         p9_req_cache = KMEM_CACHE(p9_req_t, SLAB_TYPESAFE_BY_RCU);
    2306           1 :         return p9_req_cache ? 0 : -ENOMEM;
    2307             : }
    2308             : 
    2309           0 : void __exit p9_client_exit(void)
    2310             : {
    2311           0 :         kmem_cache_destroy(p9_req_cache);
    2312           0 : }

Generated by: LCOV version 1.14