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/sched.h>
  33#include <linux/uaccess.h>
  34#include <net/9p/9p.h>
  35#include <linux/parser.h>
  36#include <net/9p/client.h>
  37#include <net/9p/transport.h>
  38#include "protocol.h"
  39
  40/*
  41  * Client Option Parsing (code inspired by NFS code)
  42  *  - a little lazy - parse all client options
  43  */
  44
  45enum {
  46        Opt_msize,
  47        Opt_trans,
  48        Opt_legacy,
  49        Opt_err,
  50};
  51
  52static const match_table_t tokens = {
  53        {Opt_msize, "msize=%u"},
  54        {Opt_legacy, "noextend"},
  55        {Opt_trans, "trans=%s"},
  56        {Opt_err, NULL},
  57};
  58
  59static struct p9_req_t *
  60p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
  61
  62/**
  63 * v9fs_parse_options - parse mount options into session structure
  64 * @options: options string passed from mount
  65 * @v9ses: existing v9fs session information
  66 *
  67 * Return 0 upon success, -ERRNO upon failure
  68 */
  69
  70static int parse_opts(char *opts, struct p9_client *clnt)
  71{
  72        char *options;
  73        char *p;
  74        substring_t args[MAX_OPT_ARGS];
  75        int option;
  76        int ret = 0;
  77
  78        clnt->dotu = 1;
  79        clnt->msize = 8192;
  80
  81        if (!opts)
  82                return 0;
  83
  84        options = kstrdup(opts, GFP_KERNEL);
  85        if (!options) {
  86                P9_DPRINTK(P9_DEBUG_ERROR,
  87                                "failed to allocate copy of option string\n");
  88                return -ENOMEM;
  89        }
  90
  91        while ((p = strsep(&options, ",")) != NULL) {
  92                int token;
  93                if (!*p)
  94                        continue;
  95                token = match_token(p, tokens, args);
  96                if (token < Opt_trans) {
  97                        int r = match_int(&args[0], &option);
  98                        if (r < 0) {
  99                                P9_DPRINTK(P9_DEBUG_ERROR,
 100                                        "integer field, but no integer?\n");
 101                                ret = r;
 102                                continue;
 103                        }
 104                }
 105                switch (token) {
 106                case Opt_msize:
 107                        clnt->msize = option;
 108                        break;
 109                case Opt_trans:
 110                        clnt->trans_mod = v9fs_get_trans_by_name(&args[0]);
 111                        break;
 112                case Opt_legacy:
 113                        clnt->dotu = 0;
 114                        break;
 115                default:
 116                        continue;
 117                }
 118        }
 119
 120        if (!clnt->trans_mod)
 121                clnt->trans_mod = v9fs_get_default_trans();
 122
 123        kfree(options);
 124        return ret;
 125}
 126
 127/**
 128 * p9_tag_alloc - lookup/allocate a request by tag
 129 * @c: client session to lookup tag within
 130 * @tag: numeric id for transaction
 131 *
 132 * this is a simple array lookup, but will grow the
 133 * request_slots as necessary to accomodate transaction
 134 * ids which did not previously have a slot.
 135 *
 136 * this code relies on the client spinlock to manage locks, its
 137 * possible we should switch to something else, but I'd rather
 138 * stick with something low-overhead for the common case.
 139 *
 140 */
 141
 142static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
 143{
 144        unsigned long flags;
 145        int row, col;
 146        struct p9_req_t *req;
 147
 148        /* This looks up the original request by tag so we know which
 149         * buffer to read the data into */
 150        tag++;
 151
 152        if (tag >= c->max_tag) {
 153                spin_lock_irqsave(&c->lock, flags);
 154                /* check again since original check was outside of lock */
 155                while (tag >= c->max_tag) {
 156                        row = (tag / P9_ROW_MAXTAG);
 157                        c->reqs[row] = kcalloc(P9_ROW_MAXTAG,
 158                                        sizeof(struct p9_req_t), GFP_ATOMIC);
 159
 160                        if (!c->reqs[row]) {
 161                                printk(KERN_ERR "Couldn't grow tag array\n");
 162                                spin_unlock_irqrestore(&c->lock, flags);
 163                                return ERR_PTR(-ENOMEM);
 164                        }
 165                        for (col = 0; col < P9_ROW_MAXTAG; col++) {
 166                                c->reqs[row][col].status = REQ_STATUS_IDLE;
 167                                c->reqs[row][col].tc = NULL;
 168                        }
 169                        c->max_tag += P9_ROW_MAXTAG;
 170                }
 171                spin_unlock_irqrestore(&c->lock, flags);
 172        }
 173        row = tag / P9_ROW_MAXTAG;
 174        col = tag % P9_ROW_MAXTAG;
 175
 176        req = &c->reqs[row][col];
 177        if (!req->tc) {
 178                req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
 179                if (!req->wq) {
 180                        printk(KERN_ERR "Couldn't grow tag array\n");
 181                        return ERR_PTR(-ENOMEM);
 182                }
 183                init_waitqueue_head(req->wq);
 184                req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize,
 185                                                                GFP_KERNEL);
 186                req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize,
 187                                                                GFP_KERNEL);
 188                if ((!req->tc) || (!req->rc)) {
 189                        printk(KERN_ERR "Couldn't grow tag array\n");
 190                        kfree(req->tc);
 191                        kfree(req->rc);
 192                        kfree(req->wq);
 193                        req->tc = req->rc = NULL;
 194                        req->wq = NULL;
 195                        return ERR_PTR(-ENOMEM);
 196                }
 197                req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall);
 198                req->tc->capacity = c->msize;
 199                req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall);
 200                req->rc->capacity = c->msize;
 201        }
 202
 203        p9pdu_reset(req->tc);
 204        p9pdu_reset(req->rc);
 205
 206        req->tc->tag = tag-1;
 207        req->status = REQ_STATUS_ALLOC;
 208
 209        return &c->reqs[row][col];
 210}
 211
 212/**
 213 * p9_tag_lookup - lookup a request by tag
 214 * @c: client session to lookup tag within
 215 * @tag: numeric id for transaction
 216 *
 217 */
 218
 219struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
 220{
 221        int row, col;
 222
 223        /* This looks up the original request by tag so we know which
 224         * buffer to read the data into */
 225        tag++;
 226
 227        BUG_ON(tag >= c->max_tag);
 228
 229        row = tag / P9_ROW_MAXTAG;
 230        col = tag % P9_ROW_MAXTAG;
 231
 232        return &c->reqs[row][col];
 233}
 234EXPORT_SYMBOL(p9_tag_lookup);
 235
 236/**
 237 * p9_tag_init - setup tags structure and contents
 238 * @tags: tags structure from the client struct
 239 *
 240 * This initializes the tags structure for each client instance.
 241 *
 242 */
 243
 244static int p9_tag_init(struct p9_client *c)
 245{
 246        int err = 0;
 247
 248        c->tagpool = p9_idpool_create();
 249        if (IS_ERR(c->tagpool)) {
 250                err = PTR_ERR(c->tagpool);
 251                c->tagpool = NULL;
 252                goto error;
 253        }
 254
 255        p9_idpool_get(c->tagpool); /* reserve tag 0 */
 256
 257        c->max_tag = 0;
 258error:
 259        return err;
 260}
 261
 262/**
 263 * p9_tag_cleanup - cleans up tags structure and reclaims resources
 264 * @tags: tags structure from the client struct
 265 *
 266 * This frees resources associated with the tags structure
 267 *
 268 */
 269static void p9_tag_cleanup(struct p9_client *c)
 270{
 271        int row, col;
 272
 273        /* check to insure all requests are idle */
 274        for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
 275                for (col = 0; col < P9_ROW_MAXTAG; col++) {
 276                        if (c->reqs[row][col].status != REQ_STATUS_IDLE) {
 277                                P9_DPRINTK(P9_DEBUG_MUX,
 278                                  "Attempting to cleanup non-free tag %d,%d\n",
 279                                  row, col);
 280                                /* TODO: delay execution of cleanup */
 281                                return;
 282                        }
 283                }
 284        }
 285
 286        if (c->tagpool)
 287                p9_idpool_destroy(c->tagpool);
 288
 289        /* free requests associated with tags */
 290        for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
 291                for (col = 0; col < P9_ROW_MAXTAG; col++) {
 292                        kfree(c->reqs[row][col].wq);
 293                        kfree(c->reqs[row][col].tc);
 294                        kfree(c->reqs[row][col].rc);
 295                }
 296                kfree(c->reqs[row]);
 297        }
 298        c->max_tag = 0;
 299}
 300
 301/**
 302 * p9_free_req - free a request and clean-up as necessary
 303 * c: client state
 304 * r: request to release
 305 *
 306 */
 307
 308static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
 309{
 310        int tag = r->tc->tag;
 311        P9_DPRINTK(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
 312
 313        r->status = REQ_STATUS_IDLE;
 314        if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool))
 315                p9_idpool_put(tag, c->tagpool);
 316}
 317
 318/**
 319 * p9_client_cb - call back from transport to client
 320 * c: client state
 321 * req: request received
 322 *
 323 */
 324void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
 325{
 326        P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
 327        wake_up(req->wq);
 328        P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
 329}
 330EXPORT_SYMBOL(p9_client_cb);
 331
 332/**
 333 * p9_parse_header - parse header arguments out of a packet
 334 * @pdu: packet to parse
 335 * @size: size of packet
 336 * @type: type of request
 337 * @tag: tag of packet
 338 * @rewind: set if we need to rewind offset afterwards
 339 */
 340
 341int
 342p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag,
 343                                                                int rewind)
 344{
 345        int8_t r_type;
 346        int16_t r_tag;
 347        int32_t r_size;
 348        int offset = pdu->offset;
 349        int err;
 350
 351        pdu->offset = 0;
 352        if (pdu->size == 0)
 353                pdu->size = 7;
 354
 355        err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag);
 356        if (err)
 357                goto rewind_and_exit;
 358
 359        pdu->size = r_size;
 360        pdu->id = r_type;
 361        pdu->tag = r_tag;
 362
 363        P9_DPRINTK(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n", pdu->size,
 364                                                        pdu->id, pdu->tag);
 365
 366        if (type)
 367                *type = r_type;
 368        if (tag)
 369                *tag = r_tag;
 370        if (size)
 371                *size = r_size;
 372
 373
 374rewind_and_exit:
 375        if (rewind)
 376                pdu->offset = offset;
 377        return err;
 378}
 379EXPORT_SYMBOL(p9_parse_header);
 380
 381/**
 382 * p9_check_errors - check 9p packet for error return and process it
 383 * @c: current client instance
 384 * @req: request to parse and check for error conditions
 385 *
 386 * returns error code if one is discovered, otherwise returns 0
 387 *
 388 * this will have to be more complicated if we have multiple
 389 * error packet types
 390 */
 391
 392static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
 393{
 394        int8_t type;
 395        int err;
 396
 397        err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
 398        if (err) {
 399                P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
 400                return err;
 401        }
 402
 403        if (type == P9_RERROR) {
 404                int ecode;
 405                char *ename;
 406
 407                err = p9pdu_readf(req->rc, c->dotu, "s?d", &ename, &ecode);
 408                if (err) {
 409                        P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n",
 410                                                                        err);
 411                        return err;
 412                }
 413
 414                if (c->dotu)
 415                        err = -ecode;
 416
 417                if (!err) {
 418                        err = p9_errstr2errno(ename, strlen(ename));
 419
 420                        /* string match failed */
 421                        if (!err)
 422                                err = -ESERVERFAULT;
 423                }
 424
 425                P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);
 426
 427                kfree(ename);
 428        } else
 429                err = 0;
 430
 431        return err;
 432}
 433
 434/**
 435 * p9_client_flush - flush (cancel) a request
 436 * c: client state
 437 * req: request to cancel
 438 *
 439 * This sents a flush for a particular requests and links
 440 * the flush request to the original request.  The current
 441 * code only supports a single flush request although the protocol
 442 * allows for multiple flush requests to be sent for a single request.
 443 *
 444 */
 445
 446static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
 447{
 448        struct p9_req_t *req;
 449        int16_t oldtag;
 450        int err;
 451
 452        err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1);
 453        if (err)
 454                return err;
 455
 456        P9_DPRINTK(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag);
 457
 458        req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag);
 459        if (IS_ERR(req))
 460                return PTR_ERR(req);
 461
 462
 463        /* if we haven't received a response for oldreq,
 464           remove it from the list. */
 465        spin_lock(&c->lock);
 466        if (oldreq->status == REQ_STATUS_FLSH)
 467                list_del(&oldreq->req_list);
 468        spin_unlock(&c->lock);
 469
 470        p9_free_req(c, req);
 471        return 0;
 472}
 473
 474/**
 475 * p9_client_rpc - issue a request and wait for a response
 476 * @c: client session
 477 * @type: type of request
 478 * @fmt: protocol format string (see protocol.c)
 479 *
 480 * Returns request structure (which client must free using p9_free_req)
 481 */
 482
 483static struct p9_req_t *
 484p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
 485{
 486        va_list ap;
 487        int tag, err;
 488        struct p9_req_t *req;
 489        unsigned long flags;
 490        int sigpending;
 491
 492        P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
 493
 494        if (c->status != Connected)
 495                return ERR_PTR(-EIO);
 496
 497        if (signal_pending(current)) {
 498                sigpending = 1;
 499                clear_thread_flag(TIF_SIGPENDING);
 500        } else
 501                sigpending = 0;
 502
 503        tag = P9_NOTAG;
 504        if (type != P9_TVERSION) {
 505                tag = p9_idpool_get(c->tagpool);
 506                if (tag < 0)
 507                        return ERR_PTR(-ENOMEM);
 508        }
 509
 510        req = p9_tag_alloc(c, tag);
 511        if (IS_ERR(req))
 512                return req;
 513
 514        /* marshall the data */
 515        p9pdu_prepare(req->tc, tag, type);
 516        va_start(ap, fmt);
 517        err = p9pdu_vwritef(req->tc, c->dotu, fmt, ap);
 518        va_end(ap);
 519        p9pdu_finalize(req->tc);
 520
 521        err = c->trans_mod->request(c, req);
 522        if (err < 0) {
 523                c->status = Disconnected;
 524                goto reterr;
 525        }
 526
 527        P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag);
 528        err = wait_event_interruptible(*req->wq,
 529                                                req->status >= REQ_STATUS_RCVD);
 530        P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n",
 531                                                req->wq, tag, err);
 532
 533        if (req->status == REQ_STATUS_ERROR) {
 534                P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
 535                err = req->t_err;
 536        }
 537
 538        if ((err == -ERESTARTSYS) && (c->status == Connected)) {
 539                P9_DPRINTK(P9_DEBUG_MUX, "flushing\n");
 540                sigpending = 1;
 541                clear_thread_flag(TIF_SIGPENDING);
 542
 543                if (c->trans_mod->cancel(c, req))
 544                        p9_client_flush(c, req);
 545
 546                /* if we received the response anyway, don't signal error */
 547                if (req->status == REQ_STATUS_RCVD)
 548                        err = 0;
 549        }
 550
 551        if (sigpending) {
 552                spin_lock_irqsave(&current->sighand->siglock, flags);
 553                recalc_sigpending();
 554                spin_unlock_irqrestore(&current->sighand->siglock, flags);
 555        }
 556
 557        if (err < 0)
 558                goto reterr;
 559
 560        err = p9_check_errors(c, req);
 561        if (!err) {
 562                P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type);
 563                return req;
 564        }
 565
 566reterr:
 567        P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d error: %d\n", c, type,
 568                                                                        err);
 569        p9_free_req(c, req);
 570        return ERR_PTR(err);
 571}
 572
 573static struct p9_fid *p9_fid_create(struct p9_client *clnt)
 574{
 575        int ret;
 576        struct p9_fid *fid;
 577        unsigned long flags;
 578
 579        P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt);
 580        fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
 581        if (!fid)
 582                return ERR_PTR(-ENOMEM);
 583
 584        ret = p9_idpool_get(clnt->fidpool);
 585        if (ret < 0) {
 586                ret = -ENOSPC;
 587                goto error;
 588        }
 589        fid->fid = ret;
 590
 591        memset(&fid->qid, 0, sizeof(struct p9_qid));
 592        fid->mode = -1;
 593        fid->rdir_fpos = 0;
 594        fid->uid = current_fsuid();
 595        fid->clnt = clnt;
 596        fid->aux = NULL;
 597
 598        spin_lock_irqsave(&clnt->lock, flags);
 599        list_add(&fid->flist, &clnt->fidlist);
 600        spin_unlock_irqrestore(&clnt->lock, flags);
 601
 602        return fid;
 603
 604error:
 605        kfree(fid);
 606        return ERR_PTR(ret);
 607}
 608
 609static void p9_fid_destroy(struct p9_fid *fid)
 610{
 611        struct p9_client *clnt;
 612        unsigned long flags;
 613
 614        P9_DPRINTK(P9_DEBUG_FID, "fid %d\n", fid->fid);
 615        clnt = fid->clnt;
 616        p9_idpool_put(fid->fid, clnt->fidpool);
 617        spin_lock_irqsave(&clnt->lock, flags);
 618        list_del(&fid->flist);
 619        spin_unlock_irqrestore(&clnt->lock, flags);
 620        kfree(fid);
 621}
 622
 623int p9_client_version(struct p9_client *c)
 624{
 625        int err = 0;
 626        struct p9_req_t *req;
 627        char *version;
 628        int msize;
 629
 630        P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d extended %d\n",
 631                                                        c->msize, c->dotu);
 632        req = p9_client_rpc(c, P9_TVERSION, "ds", c->msize,
 633                                c->dotu ? "9P2000.u" : "9P2000");
 634        if (IS_ERR(req))
 635                return PTR_ERR(req);
 636
 637        err = p9pdu_readf(req->rc, c->dotu, "ds", &msize, &version);
 638        if (err) {
 639                P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err);
 640                p9pdu_dump(1, req->rc);
 641                goto error;
 642        }
 643
 644        P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
 645        if (!memcmp(version, "9P2000.u", 8))
 646                c->dotu = 1;
 647        else if (!memcmp(version, "9P2000", 6))
 648                c->dotu = 0;
 649        else {
 650                err = -EREMOTEIO;
 651                goto error;
 652        }
 653
 654        if (msize < c->msize)
 655                c->msize = msize;
 656
 657error:
 658        kfree(version);
 659        p9_free_req(c, req);
 660
 661        return err;
 662}
 663EXPORT_SYMBOL(p9_client_version);
 664
 665struct p9_client *p9_client_create(const char *dev_name, char *options)
 666{
 667        int err;
 668        struct p9_client *clnt;
 669
 670        err = 0;
 671        clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL);
 672        if (!clnt)
 673                return ERR_PTR(-ENOMEM);
 674
 675        clnt->trans_mod = NULL;
 676        clnt->trans = NULL;
 677        spin_lock_init(&clnt->lock);
 678        INIT_LIST_HEAD(&clnt->fidlist);
 679        clnt->fidpool = p9_idpool_create();
 680        if (IS_ERR(clnt->fidpool)) {
 681                err = PTR_ERR(clnt->fidpool);
 682                clnt->fidpool = NULL;
 683                goto error;
 684        }
 685
 686        p9_tag_init(clnt);
 687
 688        err = parse_opts(options, clnt);
 689        if (err < 0)
 690                goto error;
 691
 692        if (clnt->trans_mod == NULL) {
 693                err = -EPROTONOSUPPORT;
 694                P9_DPRINTK(P9_DEBUG_ERROR,
 695                                "No transport defined or default transport\n");
 696                goto error;
 697        }
 698
 699        P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n",
 700                clnt, clnt->trans_mod, clnt->msize, clnt->dotu);
 701
 702        err = clnt->trans_mod->create(clnt, dev_name, options);
 703        if (err)
 704                goto error;
 705
 706        if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize)
 707                clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ;
 708
 709        err = p9_client_version(clnt);
 710        if (err)
 711                goto error;
 712
 713        return clnt;
 714
 715error:
 716        p9_client_destroy(clnt);
 717        return ERR_PTR(err);
 718}
 719EXPORT_SYMBOL(p9_client_create);
 720
 721void p9_client_destroy(struct p9_client *clnt)
 722{
 723        struct p9_fid *fid, *fidptr;
 724
 725        P9_DPRINTK(P9_DEBUG_MUX, "clnt %p\n", clnt);
 726
 727        if (clnt->trans_mod)
 728                clnt->trans_mod->close(clnt);
 729
 730        v9fs_put_trans(clnt->trans_mod);
 731
 732        list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist)
 733                p9_fid_destroy(fid);
 734
 735        if (clnt->fidpool)
 736                p9_idpool_destroy(clnt->fidpool);
 737
 738        p9_tag_cleanup(clnt);
 739
 740        kfree(clnt);
 741}
 742EXPORT_SYMBOL(p9_client_destroy);
 743
 744void p9_client_disconnect(struct p9_client *clnt)
 745{
 746        P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
 747        clnt->status = Disconnected;
 748}
 749EXPORT_SYMBOL(p9_client_disconnect);
 750
 751struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
 752        char *uname, u32 n_uname, char *aname)
 753{
 754        int err;
 755        struct p9_req_t *req;
 756        struct p9_fid *fid;
 757        struct p9_qid qid;
 758
 759        P9_DPRINTK(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
 760                                        afid ? afid->fid : -1, uname, aname);
 761        err = 0;
 762
 763        fid = p9_fid_create(clnt);
 764        if (IS_ERR(fid)) {
 765                err = PTR_ERR(fid);
 766                fid = NULL;
 767                goto error;
 768        }
 769
 770        req = p9_client_rpc(clnt, P9_TATTACH, "ddss?d", fid->fid,
 771                        afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
 772        if (IS_ERR(req)) {
 773                err = PTR_ERR(req);
 774                goto error;
 775        }
 776
 777        err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
 778        if (err) {
 779                p9pdu_dump(1, req->rc);
 780                p9_free_req(clnt, req);
 781                goto error;
 782        }
 783
 784        P9_DPRINTK(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n",
 785                                        qid.type,
 786                                        (unsigned long long)qid.path,
 787                                        qid.version);
 788
 789        memmove(&fid->qid, &qid, sizeof(struct p9_qid));
 790
 791        p9_free_req(clnt, req);
 792        return fid;
 793
 794error:
 795        if (fid)
 796                p9_fid_destroy(fid);
 797        return ERR_PTR(err);
 798}
 799EXPORT_SYMBOL(p9_client_attach);
 800
 801struct p9_fid *
 802p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname)
 803{
 804        int err;
 805        struct p9_req_t *req;
 806        struct p9_qid qid;
 807        struct p9_fid *afid;
 808
 809        P9_DPRINTK(P9_DEBUG_9P, ">>> TAUTH uname %s aname %s\n", uname, aname);
 810        err = 0;
 811
 812        afid = p9_fid_create(clnt);
 813        if (IS_ERR(afid)) {
 814                err = PTR_ERR(afid);
 815                afid = NULL;
 816                goto error;
 817        }
 818
 819        req = p9_client_rpc(clnt, P9_TAUTH, "dss?d",
 820                        afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
 821        if (IS_ERR(req)) {
 822                err = PTR_ERR(req);
 823                goto error;
 824        }
 825
 826        err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
 827        if (err) {
 828                p9pdu_dump(1, req->rc);
 829                p9_free_req(clnt, req);
 830                goto error;
 831        }
 832
 833        P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n",
 834                                        qid.type,
 835                                        (unsigned long long)qid.path,
 836                                        qid.version);
 837
 838        memmove(&afid->qid, &qid, sizeof(struct p9_qid));
 839        p9_free_req(clnt, req);
 840        return afid;
 841
 842error:
 843        if (afid)
 844                p9_fid_destroy(afid);
 845        return ERR_PTR(err);
 846}
 847EXPORT_SYMBOL(p9_client_auth);
 848
 849struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
 850        int clone)
 851{
 852        int err;
 853        struct p9_client *clnt;
 854        struct p9_fid *fid;
 855        struct p9_qid *wqids;
 856        struct p9_req_t *req;
 857        int16_t nwqids, count;
 858
 859        err = 0;
 860        clnt = oldfid->clnt;
 861        if (clone) {
 862                fid = p9_fid_create(clnt);
 863                if (IS_ERR(fid)) {
 864                        err = PTR_ERR(fid);
 865                        fid = NULL;
 866                        goto error;
 867                }
 868
 869                fid->uid = oldfid->uid;
 870        } else
 871                fid = oldfid;
 872
 873
 874        P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n",
 875                oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
 876
 877        req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
 878                                                                nwname, wnames);
 879        if (IS_ERR(req)) {
 880                err = PTR_ERR(req);
 881                goto error;
 882        }
 883
 884        err = p9pdu_readf(req->rc, clnt->dotu, "R", &nwqids, &wqids);
 885        if (err) {
 886                p9pdu_dump(1, req->rc);
 887                p9_free_req(clnt, req);
 888                goto clunk_fid;
 889        }
 890        p9_free_req(clnt, req);
 891
 892        P9_DPRINTK(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);
 893
 894        if (nwqids != nwname) {
 895                err = -ENOENT;
 896                goto clunk_fid;
 897        }
 898
 899        for (count = 0; count < nwqids; count++)
 900                P9_DPRINTK(P9_DEBUG_9P, "<<<     [%d] %x.%llx.%x\n",
 901                        count, wqids[count].type,
 902                        (unsigned long long)wqids[count].path,
 903                        wqids[count].version);
 904
 905        if (nwname)
 906                memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid));
 907        else
 908                fid->qid = oldfid->qid;
 909
 910        return fid;
 911
 912clunk_fid:
 913        p9_client_clunk(fid);
 914        fid = NULL;
 915
 916error:
 917        if (fid && (fid != oldfid))
 918                p9_fid_destroy(fid);
 919
 920        return ERR_PTR(err);
 921}
 922EXPORT_SYMBOL(p9_client_walk);
 923
 924int p9_client_open(struct p9_fid *fid, int mode)
 925{
 926        int err;
 927        struct p9_client *clnt;
 928        struct p9_req_t *req;
 929        struct p9_qid qid;
 930        int iounit;
 931
 932        P9_DPRINTK(P9_DEBUG_9P, ">>> TOPEN fid %d mode %d\n", fid->fid, mode);
 933        err = 0;
 934        clnt = fid->clnt;
 935
 936        if (fid->mode != -1)
 937                return -EINVAL;
 938
 939        req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode);
 940        if (IS_ERR(req)) {
 941                err = PTR_ERR(req);
 942                goto error;
 943        }
 944
 945        err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
 946        if (err) {
 947                p9pdu_dump(1, req->rc);
 948                goto free_and_error;
 949        }
 950
 951        P9_DPRINTK(P9_DEBUG_9P, "<<< ROPEN qid %x.%llx.%x iounit %x\n",
 952                                qid.type,
 953                                (unsigned long long)qid.path,
 954                                qid.version, iounit);
 955
 956        fid->mode = mode;
 957        fid->iounit = iounit;
 958
 959free_and_error:
 960        p9_free_req(clnt, req);
 961error:
 962        return err;
 963}
 964EXPORT_SYMBOL(p9_client_open);
 965
 966int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
 967                     char *extension)
 968{
 969        int err;
 970        struct p9_client *clnt;
 971        struct p9_req_t *req;
 972        struct p9_qid qid;
 973        int iounit;
 974
 975        P9_DPRINTK(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n",
 976                                                fid->fid, name, perm, mode);
 977        err = 0;
 978        clnt = fid->clnt;
 979
 980        if (fid->mode != -1)
 981                return -EINVAL;
 982
 983        req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm,
 984                                mode, extension);
 985        if (IS_ERR(req)) {
 986                err = PTR_ERR(req);
 987                goto error;
 988        }
 989
 990        err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
 991        if (err) {
 992                p9pdu_dump(1, req->rc);
 993                goto free_and_error;
 994        }
 995
 996        P9_DPRINTK(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
 997                                qid.type,
 998                                (unsigned long long)qid.path,
 999                                qid.version, iounit);
1000
1001        fid->mode = mode;
1002        fid->iounit = iounit;
1003
1004free_and_error:
1005        p9_free_req(clnt, req);
1006error:
1007        return err;
1008}
1009EXPORT_SYMBOL(p9_client_fcreate);
1010
1011int p9_client_clunk(struct p9_fid *fid)
1012{
1013        int err;
1014        struct p9_client *clnt;
1015        struct p9_req_t *req;
1016
1017        P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid);
1018        err = 0;
1019        clnt = fid->clnt;
1020
1021        req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid);
1022        if (IS_ERR(req)) {
1023                err = PTR_ERR(req);
1024                goto error;
1025        }
1026
1027        P9_DPRINTK(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
1028
1029        p9_free_req(clnt, req);
1030        p9_fid_destroy(fid);
1031
1032error:
1033        return err;
1034}
1035EXPORT_SYMBOL(p9_client_clunk);
1036
1037int p9_client_remove(struct p9_fid *fid)
1038{
1039        int err;
1040        struct p9_client *clnt;
1041        struct p9_req_t *req;
1042
1043        P9_DPRINTK(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid);
1044        err = 0;
1045        clnt = fid->clnt;
1046
1047        req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid);
1048        if (IS_ERR(req)) {
1049                err = PTR_ERR(req);
1050                goto error;
1051        }
1052
1053        P9_DPRINTK(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid);
1054
1055        p9_free_req(clnt, req);
1056        p9_fid_destroy(fid);
1057
1058error:
1059        return err;
1060}
1061EXPORT_SYMBOL(p9_client_remove);
1062
1063int
1064p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1065                                                                u32 count)
1066{
1067        int err, rsize, total;
1068        struct p9_client *clnt;
1069        struct p9_req_t *req;
1070        char *dataptr;
1071
1072        P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", fid->fid,
1073                                        (long long unsigned) offset, count);
1074        err = 0;
1075        clnt = fid->clnt;
1076        total = 0;
1077
1078        rsize = fid->iounit;
1079        if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1080                rsize = clnt->msize - P9_IOHDRSZ;
1081
1082        if (count < rsize)
1083                rsize = count;
1084
1085        req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize);
1086        if (IS_ERR(req)) {
1087                err = PTR_ERR(req);
1088                goto error;
1089        }
1090
1091        err = p9pdu_readf(req->rc, clnt->dotu, "D", &count, &dataptr);
1092        if (err) {
1093                p9pdu_dump(1, req->rc);
1094                goto free_and_error;
1095        }
1096
1097        P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
1098
1099        if (data) {
1100                memmove(data, dataptr, count);
1101                data += count;
1102        }
1103
1104        if (udata) {
1105                err = copy_to_user(udata, dataptr, count);
1106                if (err) {
1107                        err = -EFAULT;
1108                        goto free_and_error;
1109                }
1110        }
1111
1112        p9_free_req(clnt, req);
1113        return count;
1114
1115free_and_error:
1116        p9_free_req(clnt, req);
1117error:
1118        return err;
1119}
1120EXPORT_SYMBOL(p9_client_read);
1121
1122int
1123p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1124                                                        u64 offset, u32 count)
1125{
1126        int err, rsize, total;
1127        struct p9_client *clnt;
1128        struct p9_req_t *req;
1129
1130        P9_DPRINTK(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n",
1131                                fid->fid, (long long unsigned) offset, count);
1132        err = 0;
1133        clnt = fid->clnt;
1134        total = 0;
1135
1136        rsize = fid->iounit;
1137        if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1138                rsize = clnt->msize - P9_IOHDRSZ;
1139
1140        if (count < rsize)
1141                rsize = count;
1142        if (data)
1143                req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, offset,
1144                                                                rsize, data);
1145        else
1146                req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, offset,
1147                                                                rsize, udata);
1148        if (IS_ERR(req)) {
1149                err = PTR_ERR(req);
1150                goto error;
1151        }
1152
1153        err = p9pdu_readf(req->rc, clnt->dotu, "d", &count);
1154        if (err) {
1155                p9pdu_dump(1, req->rc);
1156                goto free_and_error;
1157        }
1158
1159        P9_DPRINTK(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
1160
1161        p9_free_req(clnt, req);
1162        return count;
1163
1164free_and_error:
1165        p9_free_req(clnt, req);
1166error:
1167        return err;
1168}
1169EXPORT_SYMBOL(p9_client_write);
1170
1171struct p9_wstat *p9_client_stat(struct p9_fid *fid)
1172{
1173        int err;
1174        struct p9_client *clnt;
1175        struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL);
1176        struct p9_req_t *req;
1177        u16 ignored;
1178
1179        P9_DPRINTK(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid);
1180
1181        if (!ret)
1182                return ERR_PTR(-ENOMEM);
1183
1184        err = 0;
1185        clnt = fid->clnt;
1186
1187        req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid);
1188        if (IS_ERR(req)) {
1189                err = PTR_ERR(req);
1190                goto error;
1191        }
1192
1193        err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret);
1194        if (err) {
1195                ret = ERR_PTR(err);
1196                p9pdu_dump(1, req->rc);
1197                goto free_and_error;
1198        }
1199
1200        P9_DPRINTK(P9_DEBUG_9P,
1201                "<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
1202                "<<<    mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
1203                "<<<    name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
1204                "<<<    uid=%d gid=%d n_muid=%d\n",
1205                ret->size, ret->type, ret->dev, ret->qid.type,
1206                (unsigned long long)ret->qid.path, ret->qid.version, ret->mode,
1207                ret->atime, ret->mtime, (unsigned long long)ret->length,
1208                ret->name, ret->uid, ret->gid, ret->muid, ret->extension,
1209                ret->n_uid, ret->n_gid, ret->n_muid);
1210
1211        p9_free_req(clnt, req);
1212        return ret;
1213
1214free_and_error:
1215        p9_free_req(clnt, req);
1216error:
1217        kfree(ret);
1218        return ERR_PTR(err);
1219}
1220EXPORT_SYMBOL(p9_client_stat);
1221
1222static int p9_client_statsize(struct p9_wstat *wst, int optional)
1223{
1224        int ret;
1225
1226        /* size[2] type[2] dev[4] qid[13] */
1227        /* mode[4] atime[4] mtime[4] length[8]*/
1228        /* name[s] uid[s] gid[s] muid[s] */
1229        ret = 2+2+4+13+4+4+4+8+2+2+2+2;
1230
1231        if (wst->name)
1232                ret += strlen(wst->name);
1233        if (wst->uid)
1234                ret += strlen(wst->uid);
1235        if (wst->gid)
1236                ret += strlen(wst->gid);
1237        if (wst->muid)
1238                ret += strlen(wst->muid);
1239
1240        if (optional) {
1241                ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */
1242                if (wst->extension)
1243                        ret += strlen(wst->extension);
1244        }
1245
1246        return ret;
1247}
1248
1249int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
1250{
1251        int err;
1252        struct p9_req_t *req;
1253        struct p9_client *clnt;
1254
1255        err = 0;
1256        clnt = fid->clnt;
1257        wst->size = p9_client_statsize(wst, clnt->dotu);
1258        P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
1259        P9_DPRINTK(P9_DEBUG_9P,
1260                "     sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
1261                "     mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
1262                "     name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
1263                "     uid=%d gid=%d n_muid=%d\n",
1264                wst->size, wst->type, wst->dev, wst->qid.type,
1265                (unsigned long long)wst->qid.path, wst->qid.version, wst->mode,
1266                wst->atime, wst->mtime, (unsigned long long)wst->length,
1267                wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
1268                wst->n_uid, wst->n_gid, wst->n_muid);
1269
1270        req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size, wst);
1271        if (IS_ERR(req)) {
1272                err = PTR_ERR(req);
1273                goto error;
1274        }
1275
1276        P9_DPRINTK(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid);
1277
1278        p9_free_req(clnt, req);
1279error:
1280        return err;
1281}
1282EXPORT_SYMBOL(p9_client_wstat);
1283