linux/net/9p/client.c
<<
>>
Prefs
   1/*
   2 * net/9p/clnt.c
   3 *
   4 * 9P Client
   5 *
   6 *  Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
   7 *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
   8 *
   9 *  This program is free software; you can redistribute it and/or modify
  10 *  it under the terms of the GNU General Public License version 2
  11 *  as published by the Free Software Foundation.
  12 *
  13 *  This program is distributed in the hope that it will be useful,
  14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 *  GNU General Public License for more details.
  17 *
  18 *  You should have received a copy of the GNU General Public License
  19 *  along with this program; if not, write to:
  20 *  Free Software Foundation
  21 *  51 Franklin Street, Fifth Floor
  22 *  Boston, MA  02111-1301  USA
  23 *
  24 */
  25
  26#include <linux/module.h>
  27#include <linux/errno.h>
  28#include <linux/fs.h>
  29#include <linux/poll.h>
  30#include <linux/idr.h>
  31#include <linux/mutex.h>
  32#include <linux/slab.h>
  33#include <linux/sched.h>
  34#include <linux/uaccess.h>
  35#include <net/9p/9p.h>
  36#include <linux/parser.h>
  37#include <net/9p/client.h>
  38#include <net/9p/transport.h>
  39#include "protocol.h"
  40
  41/*
  42  * Client Option Parsing (code inspired by NFS code)
  43  *  - a little lazy - parse all client options
  44  */
  45
  46enum {
  47        Opt_msize,
  48        Opt_trans,
  49        Opt_legacy,
  50        Opt_version,
  51        Opt_err,
  52};
  53
  54static const match_table_t tokens = {
  55        {Opt_msize, "msize=%u"},
  56        {Opt_legacy, "noextend"},
  57        {Opt_trans, "trans=%s"},
  58        {Opt_version, "version=%s"},
  59        {Opt_err, NULL},
  60};
  61
  62inline int p9_is_proto_dotl(struct p9_client *clnt)
  63{
  64        return clnt->proto_version == p9_proto_2000L;
  65}
  66EXPORT_SYMBOL(p9_is_proto_dotl);
  67
  68inline int p9_is_proto_dotu(struct p9_client *clnt)
  69{
  70        return clnt->proto_version == p9_proto_2000u;
  71}
  72EXPORT_SYMBOL(p9_is_proto_dotu);
  73
  74/* Interpret mount option for protocol version */
  75static int get_protocol_version(const substring_t *name)
  76{
  77        int version = -EINVAL;
  78
  79        if (!strncmp("9p2000", name->from, name->to-name->from)) {
  80                version = p9_proto_legacy;
  81                P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n");
  82        } else if (!strncmp("9p2000.u", name->from, name->to-name->from)) {
  83                version = p9_proto_2000u;
  84                P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
  85        } else if (!strncmp("9p2000.L", name->from, name->to-name->from)) {
  86                version = p9_proto_2000L;
  87                P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.L\n");
  88        } else {
  89                P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ",
  90                                                        name->from);
  91        }
  92        return version;
  93}
  94
  95static struct p9_req_t *
  96p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
  97
  98/**
  99 * parse_options - parse mount options into client structure
 100 * @opts: options string passed from mount
 101 * @clnt: existing v9fs client information
 102 *
 103 * Return 0 upon success, -ERRNO upon failure
 104 */
 105
 106static int parse_opts(char *opts, struct p9_client *clnt)
 107{
 108        char *options, *tmp_options;
 109        char *p;
 110        substring_t args[MAX_OPT_ARGS];
 111        int option;
 112        int ret = 0;
 113
 114        clnt->proto_version = p9_proto_2000u;
 115        clnt->msize = 8192;
 116
 117        if (!opts)
 118                return 0;
 119
 120        tmp_options = kstrdup(opts, GFP_KERNEL);
 121        if (!tmp_options) {
 122                P9_DPRINTK(P9_DEBUG_ERROR,
 123                                "failed to allocate copy of option string\n");
 124                return -ENOMEM;
 125        }
 126        options = tmp_options;
 127
 128        while ((p = strsep(&options, ",")) != NULL) {
 129                int token;
 130                if (!*p)
 131                        continue;
 132                token = match_token(p, tokens, args);
 133                if (token < Opt_trans) {
 134                        int r = match_int(&args[0], &option);
 135                        if (r < 0) {
 136                                P9_DPRINTK(P9_DEBUG_ERROR,
 137                                        "integer field, but no integer?\n");
 138                                ret = r;
 139                                continue;
 140                        }
 141                }
 142                switch (token) {
 143                case Opt_msize:
 144                        clnt->msize = option;
 145                        break;
 146                case Opt_trans:
 147                        clnt->trans_mod = v9fs_get_trans_by_name(&args[0]);
 148                        if(clnt->trans_mod == NULL) {
 149                                P9_DPRINTK(P9_DEBUG_ERROR,
 150                                   "Could not find request transport: %s\n",
 151                                   (char *) &args[0]);
 152                                ret = -EINVAL;
 153                                goto free_and_return;
 154                        }
 155                        break;
 156                case Opt_legacy:
 157                        clnt->proto_version = p9_proto_legacy;
 158                        break;
 159                case Opt_version:
 160                        ret = get_protocol_version(&args[0]);
 161                        if (ret == -EINVAL)
 162                                goto free_and_return;
 163                        clnt->proto_version = ret;
 164                        break;
 165                default:
 166                        continue;
 167                }
 168        }
 169
 170free_and_return:
 171        kfree(tmp_options);
 172        return ret;
 173}
 174
 175/**
 176 * p9_tag_alloc - lookup/allocate a request by tag
 177 * @c: client session to lookup tag within
 178 * @tag: numeric id for transaction
 179 *
 180 * this is a simple array lookup, but will grow the
 181 * request_slots as necessary to accomodate transaction
 182 * ids which did not previously have a slot.
 183 *
 184 * this code relies on the client spinlock to manage locks, its
 185 * possible we should switch to something else, but I'd rather
 186 * stick with something low-overhead for the common case.
 187 *
 188 */
 189
 190static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
 191{
 192        unsigned long flags;
 193        int row, col;
 194        struct p9_req_t *req;
 195
 196        /* This looks up the original request by tag so we know which
 197         * buffer to read the data into */
 198        tag++;
 199
 200        if (tag >= c->max_tag) {
 201                spin_lock_irqsave(&c->lock, flags);
 202                /* check again since original check was outside of lock */
 203                while (tag >= c->max_tag) {
 204                        row = (tag / P9_ROW_MAXTAG);
 205                        c->reqs[row] = kcalloc(P9_ROW_MAXTAG,
 206                                        sizeof(struct p9_req_t), GFP_ATOMIC);
 207
 208                        if (!c->reqs[row]) {
 209                                printk(KERN_ERR "Couldn't grow tag array\n");
 210                                spin_unlock_irqrestore(&c->lock, flags);
 211                                return ERR_PTR(-ENOMEM);
 212                        }
 213                        for (col = 0; col < P9_ROW_MAXTAG; col++) {
 214                                c->reqs[row][col].status = REQ_STATUS_IDLE;
 215                                c->reqs[row][col].tc = NULL;
 216                        }
 217                        c->max_tag += P9_ROW_MAXTAG;
 218                }
 219                spin_unlock_irqrestore(&c->lock, flags);
 220        }
 221        row = tag / P9_ROW_MAXTAG;
 222        col = tag % P9_ROW_MAXTAG;
 223
 224        req = &c->reqs[row][col];
 225        if (!req->tc) {
 226                req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
 227                if (!req->wq) {
 228                        printk(KERN_ERR "Couldn't grow tag array\n");
 229                        return ERR_PTR(-ENOMEM);
 230                }
 231                init_waitqueue_head(req->wq);
 232                req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize,
 233                                                                GFP_KERNEL);
 234                req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize,
 235                                                                GFP_KERNEL);
 236                if ((!req->tc) || (!req->rc)) {
 237                        printk(KERN_ERR "Couldn't grow tag array\n");
 238                        kfree(req->tc);
 239                        kfree(req->rc);
 240                        kfree(req->wq);
 241                        req->tc = req->rc = NULL;
 242                        req->wq = NULL;
 243                        return ERR_PTR(-ENOMEM);
 244                }
 245                req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall);
 246                req->tc->capacity = c->msize;
 247                req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall);
 248                req->rc->capacity = c->msize;
 249        }
 250
 251        p9pdu_reset(req->tc);
 252        p9pdu_reset(req->rc);
 253
 254        req->tc->tag = tag-1;
 255        req->status = REQ_STATUS_ALLOC;
 256
 257        return &c->reqs[row][col];
 258}
 259
 260/**
 261 * p9_tag_lookup - lookup a request by tag
 262 * @c: client session to lookup tag within
 263 * @tag: numeric id for transaction
 264 *
 265 */
 266
 267struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
 268{
 269        int row, col;
 270
 271        /* This looks up the original request by tag so we know which
 272         * buffer to read the data into */
 273        tag++;
 274
 275        BUG_ON(tag >= c->max_tag);
 276
 277        row = tag / P9_ROW_MAXTAG;
 278        col = tag % P9_ROW_MAXTAG;
 279
 280        return &c->reqs[row][col];
 281}
 282EXPORT_SYMBOL(p9_tag_lookup);
 283
 284/**
 285 * p9_tag_init - setup tags structure and contents
 286 * @c:  v9fs client struct
 287 *
 288 * This initializes the tags structure for each client instance.
 289 *
 290 */
 291
 292static int p9_tag_init(struct p9_client *c)
 293{
 294        int err = 0;
 295
 296        c->tagpool = p9_idpool_create();
 297        if (IS_ERR(c->tagpool)) {
 298                err = PTR_ERR(c->tagpool);
 299                c->tagpool = NULL;
 300                goto error;
 301        }
 302
 303        p9_idpool_get(c->tagpool); /* reserve tag 0 */
 304
 305        c->max_tag = 0;
 306error:
 307        return err;
 308}
 309
 310/**
 311 * p9_tag_cleanup - cleans up tags structure and reclaims resources
 312 * @c:  v9fs client struct
 313 *
 314 * This frees resources associated with the tags structure
 315 *
 316 */
 317static void p9_tag_cleanup(struct p9_client *c)
 318{
 319        int row, col;
 320
 321        /* check to insure all requests are idle */
 322        for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
 323                for (col = 0; col < P9_ROW_MAXTAG; col++) {
 324                        if (c->reqs[row][col].status != REQ_STATUS_IDLE) {
 325                                P9_DPRINTK(P9_DEBUG_MUX,
 326                                  "Attempting to cleanup non-free tag %d,%d\n",
 327                                  row, col);
 328                                /* TODO: delay execution of cleanup */
 329                                return;
 330                        }
 331                }
 332        }
 333
 334        if (c->tagpool) {
 335                p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */
 336                p9_idpool_destroy(c->tagpool);
 337        }
 338
 339        /* free requests associated with tags */
 340        for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
 341                for (col = 0; col < P9_ROW_MAXTAG; col++) {
 342                        kfree(c->reqs[row][col].wq);
 343                        kfree(c->reqs[row][col].tc);
 344                        kfree(c->reqs[row][col].rc);
 345                }
 346                kfree(c->reqs[row]);
 347        }
 348        c->max_tag = 0;
 349}
 350
 351/**
 352 * p9_free_req - free a request and clean-up as necessary
 353 * c: client state
 354 * r: request to release
 355 *
 356 */
 357
 358static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
 359{
 360        int tag = r->tc->tag;
 361        P9_DPRINTK(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
 362
 363        r->status = REQ_STATUS_IDLE;
 364        if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool))
 365                p9_idpool_put(tag, c->tagpool);
 366}
 367
 368/**
 369 * p9_client_cb - call back from transport to client
 370 * c: client state
 371 * req: request received
 372 *
 373 */
 374void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
 375{
 376        P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
 377        wake_up(req->wq);
 378        P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
 379}
 380EXPORT_SYMBOL(p9_client_cb);
 381
 382/**
 383 * p9_parse_header - parse header arguments out of a packet
 384 * @pdu: packet to parse
 385 * @size: size of packet
 386 * @type: type of request
 387 * @tag: tag of packet
 388 * @rewind: set if we need to rewind offset afterwards
 389 */
 390
 391int
 392p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag,
 393                                                                int rewind)
 394{
 395        int8_t r_type;
 396        int16_t r_tag;
 397        int32_t r_size;
 398        int offset = pdu->offset;
 399        int err;
 400
 401        pdu->offset = 0;
 402        if (pdu->size == 0)
 403                pdu->size = 7;
 404
 405        err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag);
 406        if (err)
 407                goto rewind_and_exit;
 408
 409        pdu->size = r_size;
 410        pdu->id = r_type;
 411        pdu->tag = r_tag;
 412
 413        P9_DPRINTK(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n", pdu->size,
 414                                                        pdu->id, pdu->tag);
 415
 416        if (type)
 417                *type = r_type;
 418        if (tag)
 419                *tag = r_tag;
 420        if (size)
 421                *size = r_size;
 422
 423
 424rewind_and_exit:
 425        if (rewind)
 426                pdu->offset = offset;
 427        return err;
 428}
 429EXPORT_SYMBOL(p9_parse_header);
 430
 431/**
 432 * p9_check_errors - check 9p packet for error return and process it
 433 * @c: current client instance
 434 * @req: request to parse and check for error conditions
 435 *
 436 * returns error code if one is discovered, otherwise returns 0
 437 *
 438 * this will have to be more complicated if we have multiple
 439 * error packet types
 440 */
 441
 442static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
 443{
 444        int8_t type;
 445        int err;
 446
 447        err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
 448        if (err) {
 449                P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
 450                return err;
 451        }
 452
 453        if (type == P9_RERROR || type == P9_RLERROR) {
 454                int ecode;
 455
 456                if (!p9_is_proto_dotl(c)) {
 457                        char *ename;
 458
 459                        err = p9pdu_readf(req->rc, c->proto_version, "s?d",
 460                                                                &ename, &ecode);
 461                        if (err)
 462                                goto out_err;
 463
 464                        if (p9_is_proto_dotu(c))
 465                                err = -ecode;
 466
 467                        if (!err || !IS_ERR_VALUE(err)) {
 468                                err = p9_errstr2errno(ename, strlen(ename));
 469
 470                                P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);
 471
 472                                kfree(ename);
 473                        }
 474                } else {
 475                        err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
 476                        err = -ecode;
 477
 478                        P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
 479                }
 480
 481        } else
 482                err = 0;
 483
 484        return err;
 485
 486out_err:
 487        P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
 488
 489        return err;
 490}
 491
 492/**
 493 * p9_client_flush - flush (cancel) a request
 494 * @c: client state
 495 * @oldreq: request to cancel
 496 *
 497 * This sents a flush for a particular requests and links
 498 * the flush request to the original request.  The current
 499 * code only supports a single flush request although the protocol
 500 * allows for multiple flush requests to be sent for a single request.
 501 *
 502 */
 503
 504static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
 505{
 506        struct p9_req_t *req;
 507        int16_t oldtag;
 508        int err;
 509
 510        err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1);
 511        if (err)
 512                return err;
 513
 514        P9_DPRINTK(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag);
 515
 516        req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag);
 517        if (IS_ERR(req))
 518                return PTR_ERR(req);
 519
 520
 521        /* if we haven't received a response for oldreq,
 522           remove it from the list. */
 523        spin_lock(&c->lock);
 524        if (oldreq->status == REQ_STATUS_FLSH)
 525                list_del(&oldreq->req_list);
 526        spin_unlock(&c->lock);
 527
 528        p9_free_req(c, req);
 529        return 0;
 530}
 531
 532/**
 533 * p9_client_rpc - issue a request and wait for a response
 534 * @c: client session
 535 * @type: type of request
 536 * @fmt: protocol format string (see protocol.c)
 537 *
 538 * Returns request structure (which client must free using p9_free_req)
 539 */
 540
 541static struct p9_req_t *
 542p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
 543{
 544        va_list ap;
 545        int tag, err;
 546        struct p9_req_t *req;
 547        unsigned long flags;
 548        int sigpending;
 549
 550        P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
 551
 552        /* we allow for any status other than disconnected */
 553        if (c->status == Disconnected)
 554                return ERR_PTR(-EIO);
 555
 556        /* if status is begin_disconnected we allow only clunk request */
 557        if ((c->status == BeginDisconnect) && (type != P9_TCLUNK))
 558                return ERR_PTR(-EIO);
 559
 560        if (signal_pending(current)) {
 561                sigpending = 1;
 562                clear_thread_flag(TIF_SIGPENDING);
 563        } else
 564                sigpending = 0;
 565
 566        tag = P9_NOTAG;
 567        if (type != P9_TVERSION) {
 568                tag = p9_idpool_get(c->tagpool);
 569                if (tag < 0)
 570                        return ERR_PTR(-ENOMEM);
 571        }
 572
 573        req = p9_tag_alloc(c, tag);
 574        if (IS_ERR(req))
 575                return req;
 576
 577        /* marshall the data */
 578        p9pdu_prepare(req->tc, tag, type);
 579        va_start(ap, fmt);
 580        err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap);
 581        va_end(ap);
 582        if (err)
 583                goto reterr;
 584        p9pdu_finalize(req->tc);
 585
 586        err = c->trans_mod->request(c, req);
 587        if (err < 0) {
 588                if (err != -ERESTARTSYS)
 589                        c->status = Disconnected;
 590                goto reterr;
 591        }
 592
 593        P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag);
 594        err = wait_event_interruptible(*req->wq,
 595                                                req->status >= REQ_STATUS_RCVD);
 596        P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n",
 597                                                req->wq, tag, err);
 598
 599        if (req->status == REQ_STATUS_ERROR) {
 600                P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
 601                err = req->t_err;
 602        }
 603
 604        if ((err == -ERESTARTSYS) && (c->status == Connected)) {
 605                P9_DPRINTK(P9_DEBUG_MUX, "flushing\n");
 606                sigpending = 1;
 607                clear_thread_flag(TIF_SIGPENDING);
 608
 609                if (c->trans_mod->cancel(c, req))
 610                        p9_client_flush(c, req);
 611
 612                /* if we received the response anyway, don't signal error */
 613                if (req->status == REQ_STATUS_RCVD)
 614                        err = 0;
 615        }
 616
 617        if (sigpending) {
 618                spin_lock_irqsave(&current->sighand->siglock, flags);
 619                recalc_sigpending();
 620                spin_unlock_irqrestore(&current->sighand->siglock, flags);
 621        }
 622
 623        if (err < 0)
 624                goto reterr;
 625
 626        err = p9_check_errors(c, req);
 627        if (!err) {
 628                P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type);
 629                return req;
 630        }
 631
 632reterr:
 633        P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d error: %d\n", c, type,
 634                                                                        err);
 635        p9_free_req(c, req);
 636        return ERR_PTR(err);
 637}
 638
 639static struct p9_fid *p9_fid_create(struct p9_client *clnt)
 640{
 641        int ret;
 642        struct p9_fid *fid;
 643        unsigned long flags;
 644
 645        P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt);
 646        fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
 647        if (!fid)
 648                return ERR_PTR(-ENOMEM);
 649
 650        ret = p9_idpool_get(clnt->fidpool);
 651        if (ret < 0) {
 652                ret = -ENOSPC;
 653                goto error;
 654        }
 655        fid->fid = ret;
 656
 657        memset(&fid->qid, 0, sizeof(struct p9_qid));
 658        fid->mode = -1;
 659        fid->uid = current_fsuid();
 660        fid->clnt = clnt;
 661        fid->rdir = NULL;
 662        spin_lock_irqsave(&clnt->lock, flags);
 663        list_add(&fid->flist, &clnt->fidlist);
 664        spin_unlock_irqrestore(&clnt->lock, flags);
 665
 666        return fid;
 667
 668error:
 669        kfree(fid);
 670        return ERR_PTR(ret);
 671}
 672
 673static void p9_fid_destroy(struct p9_fid *fid)
 674{
 675        struct p9_client *clnt;
 676        unsigned long flags;
 677
 678        P9_DPRINTK(P9_DEBUG_FID, "fid %d\n", fid->fid);
 679        clnt = fid->clnt;
 680        p9_idpool_put(fid->fid, clnt->fidpool);
 681        spin_lock_irqsave(&clnt->lock, flags);
 682        list_del(&fid->flist);
 683        spin_unlock_irqrestore(&clnt->lock, flags);
 684        kfree(fid->rdir);
 685        kfree(fid);
 686}
 687
 688static int p9_client_version(struct p9_client *c)
 689{
 690        int err = 0;
 691        struct p9_req_t *req;
 692        char *version;
 693        int msize;
 694
 695        P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n",
 696                                                c->msize, c->proto_version);
 697
 698        switch (c->proto_version) {
 699        case p9_proto_2000L:
 700                req = p9_client_rpc(c, P9_TVERSION, "ds",
 701                                        c->msize, "9P2000.L");
 702                break;
 703        case p9_proto_2000u:
 704                req = p9_client_rpc(c, P9_TVERSION, "ds",
 705                                        c->msize, "9P2000.u");
 706                break;
 707        case p9_proto_legacy:
 708                req = p9_client_rpc(c, P9_TVERSION, "ds",
 709                                        c->msize, "9P2000");
 710                break;
 711        default:
 712                return -EINVAL;
 713                break;
 714        }
 715
 716        if (IS_ERR(req))
 717                return PTR_ERR(req);
 718
 719        err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version);
 720        if (err) {
 721                P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err);
 722                p9pdu_dump(1, req->rc);
 723                goto error;
 724        }
 725
 726        P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
 727        if (!strncmp(version, "9P2000.L", 8))
 728                c->proto_version = p9_proto_2000L;
 729        else if (!strncmp(version, "9P2000.u", 8))
 730                c->proto_version = p9_proto_2000u;
 731        else if (!strncmp(version, "9P2000", 6))
 732                c->proto_version = p9_proto_legacy;
 733        else {
 734                err = -EREMOTEIO;
 735                goto error;
 736        }
 737
 738        if (msize < c->msize)
 739                c->msize = msize;
 740
 741error:
 742        kfree(version);
 743        p9_free_req(c, req);
 744
 745        return err;
 746}
 747
 748struct p9_client *p9_client_create(const char *dev_name, char *options)
 749{
 750        int err;
 751        struct p9_client *clnt;
 752
 753        err = 0;
 754        clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL);
 755        if (!clnt)
 756                return ERR_PTR(-ENOMEM);
 757
 758        clnt->trans_mod = NULL;
 759        clnt->trans = NULL;
 760        spin_lock_init(&clnt->lock);
 761        INIT_LIST_HEAD(&clnt->fidlist);
 762
 763        p9_tag_init(clnt);
 764
 765        err = parse_opts(options, clnt);
 766        if (err < 0)
 767                goto free_client;
 768
 769        if (!clnt->trans_mod)
 770                clnt->trans_mod = v9fs_get_default_trans();
 771
 772        if (clnt->trans_mod == NULL) {
 773                err = -EPROTONOSUPPORT;
 774                P9_DPRINTK(P9_DEBUG_ERROR,
 775                                "No transport defined or default transport\n");
 776                goto free_client;
 777        }
 778
 779        clnt->fidpool = p9_idpool_create();
 780        if (IS_ERR(clnt->fidpool)) {
 781                err = PTR_ERR(clnt->fidpool);
 782                clnt->fidpool = NULL;
 783                goto put_trans;
 784        }
 785
 786        P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n",
 787                clnt, clnt->trans_mod, clnt->msize, clnt->proto_version);
 788
 789        err = clnt->trans_mod->create(clnt, dev_name, options);
 790        if (err)
 791                goto destroy_fidpool;
 792
 793        if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize)
 794                clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ;
 795
 796        err = p9_client_version(clnt);
 797        if (err)
 798                goto close_trans;
 799
 800        return clnt;
 801
 802close_trans:
 803        clnt->trans_mod->close(clnt);
 804destroy_fidpool:
 805        p9_idpool_destroy(clnt->fidpool);
 806put_trans:
 807        v9fs_put_trans(clnt->trans_mod);
 808free_client:
 809        kfree(clnt);
 810        return ERR_PTR(err);
 811}
 812EXPORT_SYMBOL(p9_client_create);
 813
 814void p9_client_destroy(struct p9_client *clnt)
 815{
 816        struct p9_fid *fid, *fidptr;
 817
 818        P9_DPRINTK(P9_DEBUG_MUX, "clnt %p\n", clnt);
 819
 820        if (clnt->trans_mod)
 821                clnt->trans_mod->close(clnt);
 822
 823        v9fs_put_trans(clnt->trans_mod);
 824
 825        list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) {
 826                printk(KERN_INFO "Found fid %d not clunked\n", fid->fid);
 827                p9_fid_destroy(fid);
 828        }
 829
 830        if (clnt->fidpool)
 831                p9_idpool_destroy(clnt->fidpool);
 832
 833        p9_tag_cleanup(clnt);
 834
 835        kfree(clnt);
 836}
 837EXPORT_SYMBOL(p9_client_destroy);
 838
 839void p9_client_disconnect(struct p9_client *clnt)
 840{
 841        P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
 842        clnt->status = Disconnected;
 843}
 844EXPORT_SYMBOL(p9_client_disconnect);
 845
 846void p9_client_begin_disconnect(struct p9_client *clnt)
 847{
 848        P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
 849        clnt->status = BeginDisconnect;
 850}
 851EXPORT_SYMBOL(p9_client_begin_disconnect);
 852
 853struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
 854        char *uname, u32 n_uname, char *aname)
 855{
 856        int err;
 857        struct p9_req_t *req;
 858        struct p9_fid *fid;
 859        struct p9_qid qid;
 860
 861        P9_DPRINTK(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
 862                                        afid ? afid->fid : -1, uname, aname);
 863        err = 0;
 864
 865        fid = p9_fid_create(clnt);
 866        if (IS_ERR(fid)) {
 867                err = PTR_ERR(fid);
 868                fid = NULL;
 869                goto error;
 870        }
 871
 872        req = p9_client_rpc(clnt, P9_TATTACH, "ddss?d", fid->fid,
 873                        afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
 874        if (IS_ERR(req)) {
 875                err = PTR_ERR(req);
 876                goto error;
 877        }
 878
 879        err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
 880        if (err) {
 881                p9pdu_dump(1, req->rc);
 882                p9_free_req(clnt, req);
 883                goto error;
 884        }
 885
 886        P9_DPRINTK(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n",
 887                                        qid.type,
 888                                        (unsigned long long)qid.path,
 889                                        qid.version);
 890
 891        memmove(&fid->qid, &qid, sizeof(struct p9_qid));
 892
 893        p9_free_req(clnt, req);
 894        return fid;
 895
 896error:
 897        if (fid)
 898                p9_fid_destroy(fid);
 899        return ERR_PTR(err);
 900}
 901EXPORT_SYMBOL(p9_client_attach);
 902
 903struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
 904        int clone)
 905{
 906        int err;
 907        struct p9_client *clnt;
 908        struct p9_fid *fid;
 909        struct p9_qid *wqids;
 910        struct p9_req_t *req;
 911        int16_t nwqids, count;
 912
 913        err = 0;
 914        wqids = NULL;
 915        clnt = oldfid->clnt;
 916        if (clone) {
 917                fid = p9_fid_create(clnt);
 918                if (IS_ERR(fid)) {
 919                        err = PTR_ERR(fid);
 920                        fid = NULL;
 921                        goto error;
 922                }
 923
 924                fid->uid = oldfid->uid;
 925        } else
 926                fid = oldfid;
 927
 928
 929        P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n",
 930                oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
 931
 932        req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
 933                                                                nwname, wnames);
 934        if (IS_ERR(req)) {
 935                err = PTR_ERR(req);
 936                goto error;
 937        }
 938
 939        err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids);
 940        if (err) {
 941                p9pdu_dump(1, req->rc);
 942                p9_free_req(clnt, req);
 943                goto clunk_fid;
 944        }
 945        p9_free_req(clnt, req);
 946
 947        P9_DPRINTK(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);
 948
 949        if (nwqids != nwname) {
 950                err = -ENOENT;
 951                goto clunk_fid;
 952        }
 953
 954        for (count = 0; count < nwqids; count++)
 955                P9_DPRINTK(P9_DEBUG_9P, "<<<     [%d] %x.%llx.%x\n",
 956                        count, wqids[count].type,
 957                        (unsigned long long)wqids[count].path,
 958                        wqids[count].version);
 959
 960        if (nwname)
 961                memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid));
 962        else
 963                fid->qid = oldfid->qid;
 964
 965        kfree(wqids);
 966        return fid;
 967
 968clunk_fid:
 969        kfree(wqids);
 970        p9_client_clunk(fid);
 971        fid = NULL;
 972
 973error:
 974        if (fid && (fid != oldfid))
 975                p9_fid_destroy(fid);
 976
 977        return ERR_PTR(err);
 978}
 979EXPORT_SYMBOL(p9_client_walk);
 980
 981int p9_client_open(struct p9_fid *fid, int mode)
 982{
 983        int err;
 984        struct p9_client *clnt;
 985        struct p9_req_t *req;
 986        struct p9_qid qid;
 987        int iounit;
 988
 989        clnt = fid->clnt;
 990        P9_DPRINTK(P9_DEBUG_9P, ">>> %s fid %d mode %d\n",
 991                p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN", fid->fid, mode);
 992        err = 0;
 993
 994        if (fid->mode != -1)
 995                return -EINVAL;
 996
 997        if (p9_is_proto_dotl(clnt))
 998                req = p9_client_rpc(clnt, P9_TLOPEN, "dd", fid->fid, mode);
 999        else
1000                req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode);
1001        if (IS_ERR(req)) {
1002                err = PTR_ERR(req);
1003                goto error;
1004        }
1005
1006        err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
1007        if (err) {
1008                p9pdu_dump(1, req->rc);
1009                goto free_and_error;
1010        }
1011
1012        P9_DPRINTK(P9_DEBUG_9P, "<<< %s qid %x.%llx.%x iounit %x\n",
1013                p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN",  qid.type,
1014                (unsigned long long)qid.path, qid.version, iounit);
1015
1016        fid->mode = mode;
1017        fid->iounit = iounit;
1018
1019free_and_error:
1020        p9_free_req(clnt, req);
1021error:
1022        return err;
1023}
1024EXPORT_SYMBOL(p9_client_open);
1025
1026int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
1027                gid_t gid, struct p9_qid *qid)
1028{
1029        int err = 0;
1030        struct p9_client *clnt;
1031        struct p9_req_t *req;
1032        int iounit;
1033
1034        P9_DPRINTK(P9_DEBUG_9P,
1035                        ">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n",
1036                        ofid->fid, name, flags, mode, gid);
1037        clnt = ofid->clnt;
1038
1039        if (ofid->mode != -1)
1040                return -EINVAL;
1041
1042        req = p9_client_rpc(clnt, P9_TLCREATE, "dsddd", ofid->fid, name, flags,
1043                        mode, gid);
1044        if (IS_ERR(req)) {
1045                err = PTR_ERR(req);
1046                goto error;
1047        }
1048
1049        err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", qid, &iounit);
1050        if (err) {
1051                p9pdu_dump(1, req->rc);
1052                goto free_and_error;
1053        }
1054
1055        P9_DPRINTK(P9_DEBUG_9P, "<<< RLCREATE qid %x.%llx.%x iounit %x\n",
1056                        qid->type,
1057                        (unsigned long long)qid->path,
1058                        qid->version, iounit);
1059
1060        ofid->mode = mode;
1061        ofid->iounit = iounit;
1062
1063free_and_error:
1064        p9_free_req(clnt, req);
1065error:
1066        return err;
1067}
1068EXPORT_SYMBOL(p9_client_create_dotl);
1069
1070int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
1071                     char *extension)
1072{
1073        int err;
1074        struct p9_client *clnt;
1075        struct p9_req_t *req;
1076        struct p9_qid qid;
1077        int iounit;
1078
1079        P9_DPRINTK(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n",
1080                                                fid->fid, name, perm, mode);
1081        err = 0;
1082        clnt = fid->clnt;
1083
1084        if (fid->mode != -1)
1085                return -EINVAL;
1086
1087        req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm,
1088                                mode, extension);
1089        if (IS_ERR(req)) {
1090                err = PTR_ERR(req);
1091                goto error;
1092        }
1093
1094        err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
1095        if (err) {
1096                p9pdu_dump(1, req->rc);
1097                goto free_and_error;
1098        }
1099
1100        P9_DPRINTK(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
1101                                qid.type,
1102                                (unsigned long long)qid.path,
1103                                qid.version, iounit);
1104
1105        fid->mode = mode;
1106        fid->iounit = iounit;
1107
1108free_and_error:
1109        p9_free_req(clnt, req);
1110error:
1111        return err;
1112}
1113EXPORT_SYMBOL(p9_client_fcreate);
1114
1115int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid,
1116                struct p9_qid *qid)
1117{
1118        int err = 0;
1119        struct p9_client *clnt;
1120        struct p9_req_t *req;
1121
1122        P9_DPRINTK(P9_DEBUG_9P, ">>> TSYMLINK dfid %d name %s  symtgt %s\n",
1123                        dfid->fid, name, symtgt);
1124        clnt = dfid->clnt;
1125
1126        req = p9_client_rpc(clnt, P9_TSYMLINK, "dssd", dfid->fid, name, symtgt,
1127                        gid);
1128        if (IS_ERR(req)) {
1129                err = PTR_ERR(req);
1130                goto error;
1131        }
1132
1133        err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
1134        if (err) {
1135                p9pdu_dump(1, req->rc);
1136                goto free_and_error;
1137        }
1138
1139        P9_DPRINTK(P9_DEBUG_9P, "<<< RSYMLINK qid %x.%llx.%x\n",
1140                        qid->type, (unsigned long long)qid->path, qid->version);
1141
1142free_and_error:
1143        p9_free_req(clnt, req);
1144error:
1145        return err;
1146}
1147EXPORT_SYMBOL(p9_client_symlink);
1148
1149int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname)
1150{
1151        struct p9_client *clnt;
1152        struct p9_req_t *req;
1153
1154        P9_DPRINTK(P9_DEBUG_9P, ">>> TLINK dfid %d oldfid %d newname %s\n",
1155                        dfid->fid, oldfid->fid, newname);
1156        clnt = dfid->clnt;
1157        req = p9_client_rpc(clnt, P9_TLINK, "dds", dfid->fid, oldfid->fid,
1158                        newname);
1159        if (IS_ERR(req))
1160                return PTR_ERR(req);
1161
1162        P9_DPRINTK(P9_DEBUG_9P, "<<< RLINK\n");
1163        p9_free_req(clnt, req);
1164        return 0;
1165}
1166EXPORT_SYMBOL(p9_client_link);
1167
1168int p9_client_fsync(struct p9_fid *fid, int datasync)
1169{
1170        int err;
1171        struct p9_client *clnt;
1172        struct p9_req_t *req;
1173
1174        P9_DPRINTK(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n",
1175                        fid->fid, datasync);
1176        err = 0;
1177        clnt = fid->clnt;
1178
1179        req = p9_client_rpc(clnt, P9_TFSYNC, "dd", fid->fid, datasync);
1180        if (IS_ERR(req)) {
1181                err = PTR_ERR(req);
1182                goto error;
1183        }
1184
1185        P9_DPRINTK(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid);
1186
1187        p9_free_req(clnt, req);
1188
1189error:
1190        return err;
1191}
1192EXPORT_SYMBOL(p9_client_fsync);
1193
1194int p9_client_clunk(struct p9_fid *fid)
1195{
1196        int err;
1197        struct p9_client *clnt;
1198        struct p9_req_t *req;
1199
1200        if (!fid) {
1201                P9_EPRINTK(KERN_WARNING, "Trying to clunk with NULL fid\n");
1202                dump_stack();
1203                return 0;
1204        }
1205
1206        P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid);
1207        err = 0;
1208        clnt = fid->clnt;
1209
1210        req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid);
1211        if (IS_ERR(req)) {
1212                err = PTR_ERR(req);
1213                goto error;
1214        }
1215
1216        P9_DPRINTK(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
1217
1218        p9_free_req(clnt, req);
1219        p9_fid_destroy(fid);
1220
1221error:
1222        return err;
1223}
1224EXPORT_SYMBOL(p9_client_clunk);
1225
1226int p9_client_remove(struct p9_fid *fid)
1227{
1228        int err;
1229        struct p9_client *clnt;
1230        struct p9_req_t *req;
1231
1232        P9_DPRINTK(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid);
1233        err = 0;
1234        clnt = fid->clnt;
1235
1236        req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid);
1237        if (IS_ERR(req)) {
1238                err = PTR_ERR(req);
1239                goto error;
1240        }
1241
1242        P9_DPRINTK(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid);
1243
1244        p9_free_req(clnt, req);
1245error:
1246        p9_fid_destroy(fid);
1247        return err;
1248}
1249EXPORT_SYMBOL(p9_client_remove);
1250
1251int
1252p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1253                                                                u32 count)
1254{
1255        int err, rsize, total;
1256        struct p9_client *clnt;
1257        struct p9_req_t *req;
1258        char *dataptr;
1259
1260        P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", fid->fid,
1261                                        (long long unsigned) offset, count);
1262        err = 0;
1263        clnt = fid->clnt;
1264        total = 0;
1265
1266        rsize = fid->iounit;
1267        if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1268                rsize = clnt->msize - P9_IOHDRSZ;
1269
1270        if (count < rsize)
1271                rsize = count;
1272
1273        req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize);
1274        if (IS_ERR(req)) {
1275                err = PTR_ERR(req);
1276                goto error;
1277        }
1278
1279        err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
1280        if (err) {
1281                p9pdu_dump(1, req->rc);
1282                goto free_and_error;
1283        }
1284
1285        P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
1286
1287        if (data) {
1288                memmove(data, dataptr, count);
1289        } else {
1290                err = copy_to_user(udata, dataptr, count);
1291                if (err) {
1292                        err = -EFAULT;
1293                        goto free_and_error;
1294                }
1295        }
1296        p9_free_req(clnt, req);
1297        return count;
1298
1299free_and_error:
1300        p9_free_req(clnt, req);
1301error:
1302        return err;
1303}
1304EXPORT_SYMBOL(p9_client_read);
1305
1306int
1307p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1308                                                        u64 offset, u32 count)
1309{
1310        int err, rsize, total;
1311        struct p9_client *clnt;
1312        struct p9_req_t *req;
1313
1314        P9_DPRINTK(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n",
1315                                fid->fid, (long long unsigned) offset, count);
1316        err = 0;
1317        clnt = fid->clnt;
1318        total = 0;
1319
1320        rsize = fid->iounit;
1321        if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1322                rsize = clnt->msize - P9_IOHDRSZ;
1323
1324        if (count < rsize)
1325                rsize = count;
1326        if (data)
1327                req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, offset,
1328                                                                rsize, data);
1329        else
1330                req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, offset,
1331                                                                rsize, udata);
1332        if (IS_ERR(req)) {
1333                err = PTR_ERR(req);
1334                goto error;
1335        }
1336
1337        err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count);
1338        if (err) {
1339                p9pdu_dump(1, req->rc);
1340                goto free_and_error;
1341        }
1342
1343        P9_DPRINTK(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
1344
1345        p9_free_req(clnt, req);
1346        return count;
1347
1348free_and_error:
1349        p9_free_req(clnt, req);
1350error:
1351        return err;
1352}
1353EXPORT_SYMBOL(p9_client_write);
1354
1355struct p9_wstat *p9_client_stat(struct p9_fid *fid)
1356{
1357        int err;
1358        struct p9_client *clnt;
1359        struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL);
1360        struct p9_req_t *req;
1361        u16 ignored;
1362
1363        P9_DPRINTK(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid);
1364
1365        if (!ret)
1366                return ERR_PTR(-ENOMEM);
1367
1368        err = 0;
1369        clnt = fid->clnt;
1370
1371        req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid);
1372        if (IS_ERR(req)) {
1373                err = PTR_ERR(req);
1374                goto error;
1375        }
1376
1377        err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret);
1378        if (err) {
1379                p9pdu_dump(1, req->rc);
1380                p9_free_req(clnt, req);
1381                goto error;
1382        }
1383
1384        P9_DPRINTK(P9_DEBUG_9P,
1385                "<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
1386                "<<<    mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
1387                "<<<    name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
1388                "<<<    uid=%d gid=%d n_muid=%d\n",
1389                ret->size, ret->type, ret->dev, ret->qid.type,
1390                (unsigned long long)ret->qid.path, ret->qid.version, ret->mode,
1391                ret->atime, ret->mtime, (unsigned long long)ret->length,
1392                ret->name, ret->uid, ret->gid, ret->muid, ret->extension,
1393                ret->n_uid, ret->n_gid, ret->n_muid);
1394
1395        p9_free_req(clnt, req);
1396        return ret;
1397
1398error:
1399        kfree(ret);
1400        return ERR_PTR(err);
1401}
1402EXPORT_SYMBOL(p9_client_stat);
1403
1404struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
1405                                                        u64 request_mask)
1406{
1407        int err;
1408        struct p9_client *clnt;
1409        struct p9_stat_dotl *ret = kmalloc(sizeof(struct p9_stat_dotl),
1410                                                                GFP_KERNEL);
1411        struct p9_req_t *req;
1412
1413        P9_DPRINTK(P9_DEBUG_9P, ">>> TGETATTR fid %d, request_mask %lld\n",
1414                                                        fid->fid, request_mask);
1415
1416        if (!ret)
1417                return ERR_PTR(-ENOMEM);
1418
1419        err = 0;
1420        clnt = fid->clnt;
1421
1422        req = p9_client_rpc(clnt, P9_TGETATTR, "dq", fid->fid, request_mask);
1423        if (IS_ERR(req)) {
1424                err = PTR_ERR(req);
1425                goto error;
1426        }
1427
1428        err = p9pdu_readf(req->rc, clnt->proto_version, "A", ret);
1429        if (err) {
1430                p9pdu_dump(1, req->rc);
1431                p9_free_req(clnt, req);
1432                goto error;
1433        }
1434
1435        P9_DPRINTK(P9_DEBUG_9P,
1436                "<<< RGETATTR st_result_mask=%lld\n"
1437                "<<< qid=%x.%llx.%x\n"
1438                "<<< st_mode=%8.8x st_nlink=%llu\n"
1439                "<<< st_uid=%d st_gid=%d\n"
1440                "<<< st_rdev=%llx st_size=%llx st_blksize=%llu st_blocks=%llu\n"
1441                "<<< st_atime_sec=%lld st_atime_nsec=%lld\n"
1442                "<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n"
1443                "<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n"
1444                "<<< st_btime_sec=%lld st_btime_nsec=%lld\n"
1445                "<<< st_gen=%lld st_data_version=%lld",
1446                ret->st_result_mask, ret->qid.type, ret->qid.path,
1447                ret->qid.version, ret->st_mode, ret->st_nlink, ret->st_uid,
1448                ret->st_gid, ret->st_rdev, ret->st_size, ret->st_blksize,
1449                ret->st_blocks, ret->st_atime_sec, ret->st_atime_nsec,
1450                ret->st_mtime_sec, ret->st_mtime_nsec, ret->st_ctime_sec,
1451                ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec,
1452                ret->st_gen, ret->st_data_version);
1453
1454        p9_free_req(clnt, req);
1455        return ret;
1456
1457error:
1458        kfree(ret);
1459        return ERR_PTR(err);
1460}
1461EXPORT_SYMBOL(p9_client_getattr_dotl);
1462
1463static int p9_client_statsize(struct p9_wstat *wst, int proto_version)
1464{
1465        int ret;
1466
1467        /* NOTE: size shouldn't include its own length */
1468        /* size[2] type[2] dev[4] qid[13] */
1469        /* mode[4] atime[4] mtime[4] length[8]*/
1470        /* name[s] uid[s] gid[s] muid[s] */
1471        ret = 2+4+13+4+4+4+8+2+2+2+2;
1472
1473        if (wst->name)
1474                ret += strlen(wst->name);
1475        if (wst->uid)
1476                ret += strlen(wst->uid);
1477        if (wst->gid)
1478                ret += strlen(wst->gid);
1479        if (wst->muid)
1480                ret += strlen(wst->muid);
1481
1482        if ((proto_version == p9_proto_2000u) ||
1483                (proto_version == p9_proto_2000L)) {
1484                ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */
1485                if (wst->extension)
1486                        ret += strlen(wst->extension);
1487        }
1488
1489        return ret;
1490}
1491
1492int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
1493{
1494        int err;
1495        struct p9_req_t *req;
1496        struct p9_client *clnt;
1497
1498        err = 0;
1499        clnt = fid->clnt;
1500        wst->size = p9_client_statsize(wst, clnt->proto_version);
1501        P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
1502        P9_DPRINTK(P9_DEBUG_9P,
1503                "     sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
1504                "     mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
1505                "     name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
1506                "     uid=%d gid=%d n_muid=%d\n",
1507                wst->size, wst->type, wst->dev, wst->qid.type,
1508                (unsigned long long)wst->qid.path, wst->qid.version, wst->mode,
1509                wst->atime, wst->mtime, (unsigned long long)wst->length,
1510                wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
1511                wst->n_uid, wst->n_gid, wst->n_muid);
1512
1513        req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst);
1514        if (IS_ERR(req)) {
1515                err = PTR_ERR(req);
1516                goto error;
1517        }
1518
1519        P9_DPRINTK(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid);
1520
1521        p9_free_req(clnt, req);
1522error:
1523        return err;
1524}
1525EXPORT_SYMBOL(p9_client_wstat);
1526
1527int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr)
1528{
1529        int err;
1530        struct p9_req_t *req;
1531        struct p9_client *clnt;
1532
1533        err = 0;
1534        clnt = fid->clnt;
1535        P9_DPRINTK(P9_DEBUG_9P, ">>> TSETATTR fid %d\n", fid->fid);
1536        P9_DPRINTK(P9_DEBUG_9P,
1537                "    valid=%x mode=%x uid=%d gid=%d size=%lld\n"
1538                "    atime_sec=%lld atime_nsec=%lld\n"
1539                "    mtime_sec=%lld mtime_nsec=%lld\n",
1540                p9attr->valid, p9attr->mode, p9attr->uid, p9attr->gid,
1541                p9attr->size, p9attr->atime_sec, p9attr->atime_nsec,
1542                p9attr->mtime_sec, p9attr->mtime_nsec);
1543
1544        req = p9_client_rpc(clnt, P9_TSETATTR, "dI", fid->fid, p9attr);
1545
1546        if (IS_ERR(req)) {
1547                err = PTR_ERR(req);
1548                goto error;
1549        }
1550        P9_DPRINTK(P9_DEBUG_9P, "<<< RSETATTR fid %d\n", fid->fid);
1551        p9_free_req(clnt, req);
1552error:
1553        return err;
1554}
1555EXPORT_SYMBOL(p9_client_setattr);
1556
1557int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb)
1558{
1559        int err;
1560        struct p9_req_t *req;
1561        struct p9_client *clnt;
1562
1563        err = 0;
1564        clnt = fid->clnt;
1565
1566        P9_DPRINTK(P9_DEBUG_9P, ">>> TSTATFS fid %d\n", fid->fid);
1567
1568        req = p9_client_rpc(clnt, P9_TSTATFS, "d", fid->fid);
1569        if (IS_ERR(req)) {
1570                err = PTR_ERR(req);
1571                goto error;
1572        }
1573
1574        err = p9pdu_readf(req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type,
1575                &sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail,
1576                &sb->files, &sb->ffree, &sb->fsid, &sb->namelen);
1577        if (err) {
1578                p9pdu_dump(1, req->rc);
1579                p9_free_req(clnt, req);
1580                goto error;
1581        }
1582
1583        P9_DPRINTK(P9_DEBUG_9P, "<<< RSTATFS fid %d type 0x%lx bsize %ld "
1584                "blocks %llu bfree %llu bavail %llu files %llu ffree %llu "
1585                "fsid %llu namelen %ld\n",
1586                fid->fid, (long unsigned int)sb->type, (long int)sb->bsize,
1587                sb->blocks, sb->bfree, sb->bavail, sb->files,  sb->ffree,
1588                sb->fsid, (long int)sb->namelen);
1589
1590        p9_free_req(clnt, req);
1591error:
1592        return err;
1593}
1594EXPORT_SYMBOL(p9_client_statfs);
1595
1596int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, char *name)
1597{
1598        int err;
1599        struct p9_req_t *req;
1600        struct p9_client *clnt;
1601
1602        err = 0;
1603        clnt = fid->clnt;
1604
1605        P9_DPRINTK(P9_DEBUG_9P, ">>> TRENAME fid %d newdirfid %d name %s\n",
1606                        fid->fid, newdirfid->fid, name);
1607
1608        req = p9_client_rpc(clnt, P9_TRENAME, "dds", fid->fid,
1609                        newdirfid->fid, name);
1610        if (IS_ERR(req)) {
1611                err = PTR_ERR(req);
1612                goto error;
1613        }
1614
1615        P9_DPRINTK(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid);
1616
1617        p9_free_req(clnt, req);
1618error:
1619        return err;
1620}
1621EXPORT_SYMBOL(p9_client_rename);
1622
1623/*
1624 * An xattrwalk without @attr_name gives the fid for the lisxattr namespace
1625 */
1626struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
1627                                const char *attr_name, u64 *attr_size)
1628{
1629        int err;
1630        struct p9_req_t *req;
1631        struct p9_client *clnt;
1632        struct p9_fid *attr_fid;
1633
1634        err = 0;
1635        clnt = file_fid->clnt;
1636        attr_fid = p9_fid_create(clnt);
1637        if (IS_ERR(attr_fid)) {
1638                err = PTR_ERR(attr_fid);
1639                attr_fid = NULL;
1640                goto error;
1641        }
1642        P9_DPRINTK(P9_DEBUG_9P,
1643                ">>> TXATTRWALK file_fid %d, attr_fid %d name %s\n",
1644                file_fid->fid, attr_fid->fid, attr_name);
1645
1646        req = p9_client_rpc(clnt, P9_TXATTRWALK, "dds",
1647                        file_fid->fid, attr_fid->fid, attr_name);
1648        if (IS_ERR(req)) {
1649                err = PTR_ERR(req);
1650                goto error;
1651        }
1652        err = p9pdu_readf(req->rc, clnt->proto_version, "q", attr_size);
1653        if (err) {
1654                p9pdu_dump(1, req->rc);
1655                p9_free_req(clnt, req);
1656                goto clunk_fid;
1657        }
1658        p9_free_req(clnt, req);
1659        P9_DPRINTK(P9_DEBUG_9P, "<<<  RXATTRWALK fid %d size %llu\n",
1660                attr_fid->fid, *attr_size);
1661        return attr_fid;
1662clunk_fid:
1663        p9_client_clunk(attr_fid);
1664        attr_fid = NULL;
1665error:
1666        if (attr_fid && (attr_fid != file_fid))
1667                p9_fid_destroy(attr_fid);
1668
1669        return ERR_PTR(err);
1670}
1671EXPORT_SYMBOL_GPL(p9_client_xattrwalk);
1672
1673int p9_client_xattrcreate(struct p9_fid *fid, const char *name,
1674                        u64 attr_size, int flags)
1675{
1676        int err;
1677        struct p9_req_t *req;
1678        struct p9_client *clnt;
1679
1680        P9_DPRINTK(P9_DEBUG_9P,
1681                ">>> TXATTRCREATE fid %d name  %s size %lld flag %d\n",
1682                fid->fid, name, (long long)attr_size, flags);
1683        err = 0;
1684        clnt = fid->clnt;
1685        req = p9_client_rpc(clnt, P9_TXATTRCREATE, "dsqd",
1686                        fid->fid, name, attr_size, flags);
1687        if (IS_ERR(req)) {
1688                err = PTR_ERR(req);
1689                goto error;
1690        }
1691        P9_DPRINTK(P9_DEBUG_9P, "<<< RXATTRCREATE fid %d\n", fid->fid);
1692        p9_free_req(clnt, req);
1693error:
1694        return err;
1695}
1696EXPORT_SYMBOL_GPL(p9_client_xattrcreate);
1697
1698int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
1699{
1700        int err, rsize, total;
1701        struct p9_client *clnt;
1702        struct p9_req_t *req;
1703        char *dataptr;
1704
1705        P9_DPRINTK(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n",
1706                                fid->fid, (long long unsigned) offset, count);
1707
1708        err = 0;
1709        clnt = fid->clnt;
1710        total = 0;
1711
1712        rsize = fid->iounit;
1713        if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ)
1714                rsize = clnt->msize - P9_READDIRHDRSZ;
1715
1716        if (count < rsize)
1717                rsize = count;
1718
1719        req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, offset, rsize);
1720        if (IS_ERR(req)) {
1721                err = PTR_ERR(req);
1722                goto error;
1723        }
1724
1725        err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
1726        if (err) {
1727                p9pdu_dump(1, req->rc);
1728                goto free_and_error;
1729        }
1730
1731        P9_DPRINTK(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
1732
1733        if (data)
1734                memmove(data, dataptr, count);
1735
1736        p9_free_req(clnt, req);
1737        return count;
1738
1739free_and_error:
1740        p9_free_req(clnt, req);
1741error:
1742        return err;
1743}
1744EXPORT_SYMBOL(p9_client_readdir);
1745
1746int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode,
1747                        dev_t rdev, gid_t gid, struct p9_qid *qid)
1748{
1749        int err;
1750        struct p9_client *clnt;
1751        struct p9_req_t *req;
1752
1753        err = 0;
1754        clnt = fid->clnt;
1755        P9_DPRINTK(P9_DEBUG_9P, ">>> TMKNOD fid %d name %s mode %d major %d "
1756                "minor %d\n", fid->fid, name, mode, MAJOR(rdev), MINOR(rdev));
1757        req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddd", fid->fid, name, mode,
1758                MAJOR(rdev), MINOR(rdev), gid);
1759        if (IS_ERR(req))
1760                return PTR_ERR(req);
1761
1762        err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
1763        if (err) {
1764                p9pdu_dump(1, req->rc);
1765                goto error;
1766        }
1767        P9_DPRINTK(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type,
1768                                (unsigned long long)qid->path, qid->version);
1769
1770error:
1771        p9_free_req(clnt, req);
1772        return err;
1773
1774}
1775EXPORT_SYMBOL(p9_client_mknod_dotl);
1776
1777int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
1778                                gid_t gid, struct p9_qid *qid)
1779{
1780        int err;
1781        struct p9_client *clnt;
1782        struct p9_req_t *req;
1783
1784        err = 0;
1785        clnt = fid->clnt;
1786        P9_DPRINTK(P9_DEBUG_9P, ">>> TMKDIR fid %d name %s mode %d gid %d\n",
1787                 fid->fid, name, mode, gid);
1788        req = p9_client_rpc(clnt, P9_TMKDIR, "dsdd", fid->fid, name, mode,
1789                gid);
1790        if (IS_ERR(req))
1791                return PTR_ERR(req);
1792
1793        err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
1794        if (err) {
1795                p9pdu_dump(1, req->rc);
1796                goto error;
1797        }
1798        P9_DPRINTK(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type,
1799                                (unsigned long long)qid->path, qid->version);
1800
1801error:
1802        p9_free_req(clnt, req);
1803        return err;
1804
1805}
1806EXPORT_SYMBOL(p9_client_mkdir_dotl);
1807
1808int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status)
1809{
1810        int err;
1811        struct p9_client *clnt;
1812        struct p9_req_t *req;
1813
1814        err = 0;
1815        clnt = fid->clnt;
1816        P9_DPRINTK(P9_DEBUG_9P, ">>> TLOCK fid %d type %i flags %d "
1817                        "start %lld length %lld proc_id %d client_id %s\n",
1818                        fid->fid, flock->type, flock->flags, flock->start,
1819                        flock->length, flock->proc_id, flock->client_id);
1820
1821        req = p9_client_rpc(clnt, P9_TLOCK, "dbdqqds", fid->fid, flock->type,
1822                                flock->flags, flock->start, flock->length,
1823                                        flock->proc_id, flock->client_id);
1824
1825        if (IS_ERR(req))
1826                return PTR_ERR(req);
1827
1828        err = p9pdu_readf(req->rc, clnt->proto_version, "b", status);
1829        if (err) {
1830                p9pdu_dump(1, req->rc);
1831                goto error;
1832        }
1833        P9_DPRINTK(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status);
1834error:
1835        p9_free_req(clnt, req);
1836        return err;
1837
1838}
1839EXPORT_SYMBOL(p9_client_lock_dotl);
1840
1841int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock)
1842{
1843        int err;
1844        struct p9_client *clnt;
1845        struct p9_req_t *req;
1846
1847        err = 0;
1848        clnt = fid->clnt;
1849        P9_DPRINTK(P9_DEBUG_9P, ">>> TGETLOCK fid %d, type %i start %lld "
1850                "length %lld proc_id %d client_id %s\n", fid->fid, glock->type,
1851                glock->start, glock->length, glock->proc_id, glock->client_id);
1852
1853        req = p9_client_rpc(clnt, P9_TGETLOCK, "dbqqds", fid->fid,  glock->type,
1854                glock->start, glock->length, glock->proc_id, glock->client_id);
1855
1856        if (IS_ERR(req))
1857                return PTR_ERR(req);
1858
1859        err = p9pdu_readf(req->rc, clnt->proto_version, "bqqds", &glock->type,
1860                        &glock->start, &glock->length, &glock->proc_id,
1861                        &glock->client_id);
1862        if (err) {
1863                p9pdu_dump(1, req->rc);
1864                goto error;
1865        }
1866        P9_DPRINTK(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld "
1867                "proc_id %d client_id %s\n", glock->type, glock->start,
1868                glock->length, glock->proc_id, glock->client_id);
1869error:
1870        p9_free_req(clnt, req);
1871        return err;
1872}
1873EXPORT_SYMBOL(p9_client_getlock_dotl);
1874
1875int p9_client_readlink(struct p9_fid *fid, char **target)
1876{
1877        int err;
1878        struct p9_client *clnt;
1879        struct p9_req_t *req;
1880
1881        err = 0;
1882        clnt = fid->clnt;
1883        P9_DPRINTK(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid);
1884
1885        req = p9_client_rpc(clnt, P9_TREADLINK, "d", fid->fid);
1886        if (IS_ERR(req))
1887                return PTR_ERR(req);
1888
1889        err = p9pdu_readf(req->rc, clnt->proto_version, "s", target);
1890        if (err) {
1891                p9pdu_dump(1, req->rc);
1892                goto error;
1893        }
1894        P9_DPRINTK(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
1895error:
1896        p9_free_req(clnt, req);
1897        return err;
1898}
1899EXPORT_SYMBOL(p9_client_readlink);
1900