client.c 51.4 KB
Newer Older
1 2 3 4 5
/*
 * net/9p/clnt.c
 *
 * 9P Client
 *
6
 *  Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2
 *  as published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to:
 *  Free Software Foundation
 *  51 Franklin Street, Fifth Floor
 *  Boston, MA  02111-1301  USA
 *
 */

26 27
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

28 29 30
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fs.h>
31
#include <linux/poll.h>
32 33
#include <linux/idr.h>
#include <linux/mutex.h>
34
#include <linux/slab.h>
35 36 37
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <net/9p/9p.h>
38
#include <linux/parser.h>
39
#include <net/9p/client.h>
40
#include <net/9p/transport.h>
41
#include "protocol.h"
42

43 44 45
#define CREATE_TRACE_POINTS
#include <trace/events/9p.h>

46 47 48 49 50 51 52 53 54
/*
  * Client Option Parsing (code inspired by NFS code)
  *  - a little lazy - parse all client options
  */

enum {
	Opt_msize,
	Opt_trans,
	Opt_legacy,
55
	Opt_version,
56 57 58
	Opt_err,
};

59
static const match_table_t tokens = {
60 61 62
	{Opt_msize, "msize=%u"},
	{Opt_legacy, "noextend"},
	{Opt_trans, "trans=%s"},
63
	{Opt_version, "version=%s"},
64 65 66
	{Opt_err, NULL},
};

67 68
inline int p9_is_proto_dotl(struct p9_client *clnt)
{
E
Eric Dumazet 已提交
69
	return clnt->proto_version == p9_proto_2000L;
70 71 72 73 74
}
EXPORT_SYMBOL(p9_is_proto_dotl);

inline int p9_is_proto_dotu(struct p9_client *clnt)
{
E
Eric Dumazet 已提交
75
	return clnt->proto_version == p9_proto_2000u;
76 77 78
}
EXPORT_SYMBOL(p9_is_proto_dotu);

S
Simon Derr 已提交
79 80 81 82 83 84 85 86 87 88 89 90 91 92
/*
 * Some error codes are taken directly from the server replies,
 * make sure they are valid.
 */
static int safe_errno(int err)
{
	if ((err > 0) || (err < -MAX_ERRNO)) {
		p9_debug(P9_DEBUG_ERROR, "Invalid error code %d\n", err);
		return -EPROTO;
	}
	return err;
}


93
/* Interpret mount option for protocol version */
94
static int get_protocol_version(char *s)
95
{
96 97
	int version = -EINVAL;

98
	if (!strcmp(s, "9p2000")) {
99
		version = p9_proto_legacy;
100
		p9_debug(P9_DEBUG_9P, "Protocol version: Legacy\n");
101
	} else if (!strcmp(s, "9p2000.u")) {
102
		version = p9_proto_2000u;
103
		p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
104
	} else if (!strcmp(s, "9p2000.L")) {
105
		version = p9_proto_2000L;
106
		p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.L\n");
107
	} else
108
		pr_info("Unknown protocol version %s\n", s);
109

110 111 112
	return version;
}

113
/**
A
Abhishek Kulkarni 已提交
114 115 116
 * parse_options - parse mount options into client structure
 * @opts: options string passed from mount
 * @clnt: existing v9fs client information
117
 *
118
 * Return 0 upon success, -ERRNO upon failure
119 120
 */

121
static int parse_opts(char *opts, struct p9_client *clnt)
122
{
E
Eric Van Hensbergen 已提交
123
	char *options, *tmp_options;
124 125 126
	char *p;
	substring_t args[MAX_OPT_ARGS];
	int option;
127
	char *s;
128
	int ret = 0;
129

130
	clnt->proto_version = p9_proto_2000L;
131 132
	clnt->msize = 8192;

133 134 135
	if (!opts)
		return 0;

E
Eric Van Hensbergen 已提交
136 137
	tmp_options = kstrdup(opts, GFP_KERNEL);
	if (!tmp_options) {
138 139
		p9_debug(P9_DEBUG_ERROR,
			 "failed to allocate copy of option string\n");
140 141
		return -ENOMEM;
	}
E
Eric Van Hensbergen 已提交
142
	options = tmp_options;
143 144

	while ((p = strsep(&options, ",")) != NULL) {
145
		int token, r;
146 147 148
		if (!*p)
			continue;
		token = match_token(p, tokens, args);
149 150 151
		switch (token) {
		case Opt_msize:
			r = match_int(&args[0], &option);
152
			if (r < 0) {
153 154
				p9_debug(P9_DEBUG_ERROR,
					 "integer field, but no integer?\n");
155
				ret = r;
156 157 158 159 160
				continue;
			}
			clnt->msize = option;
			break;
		case Opt_trans:
161 162 163
			s = match_strdup(&args[0]);
			if (!s) {
				ret = -ENOMEM;
164 165
				p9_debug(P9_DEBUG_ERROR,
					 "problem allocating copy of trans arg\n");
166 167 168 169
				goto free_and_return;
			 }
			clnt->trans_mod = v9fs_get_trans_by_name(s);
			if (clnt->trans_mod == NULL) {
170 171
				pr_info("Could not find request transport: %s\n",
					s);
172
				ret = -EINVAL;
173
				kfree(s);
174 175
				goto free_and_return;
			}
176
			kfree(s);
177 178
			break;
		case Opt_legacy:
179
			clnt->proto_version = p9_proto_legacy;
180
			break;
181
		case Opt_version:
182 183 184
			s = match_strdup(&args[0]);
			if (!s) {
				ret = -ENOMEM;
185 186
				p9_debug(P9_DEBUG_ERROR,
					 "problem allocating copy of version arg\n");
187
				goto free_and_return;
188 189 190 191 192 193 194
			}
			ret = get_protocol_version(s);
			if (ret == -EINVAL) {
				kfree(s);
				goto free_and_return;
			}
			kfree(s);
195 196
			clnt->proto_version = ret;
			break;
197 198 199 200
		default:
			continue;
		}
	}
201

202
free_and_return:
E
Eric Van Hensbergen 已提交
203
	kfree(tmp_options);
204
	return ret;
205 206
}

207 208 209 210 211 212
/**
 * p9_tag_alloc - lookup/allocate a request by tag
 * @c: client session to lookup tag within
 * @tag: numeric id for transaction
 *
 * this is a simple array lookup, but will grow the
L
Lucas De Marchi 已提交
213
 * request_slots as necessary to accommodate transaction
214 215 216 217 218 219 220 221
 * ids which did not previously have a slot.
 *
 * this code relies on the client spinlock to manage locks, its
 * possible we should switch to something else, but I'd rather
 * stick with something low-overhead for the common case.
 *
 */

222 223
static struct p9_req_t *
p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size)
224 225 226
{
	unsigned long flags;
	int row, col;
227
	struct p9_req_t *req;
228
	int alloc_msize = min(c->msize, max_size);
229 230 231 232 233 234 235 236 237 238 239 240 241 242

	/* This looks up the original request by tag so we know which
	 * buffer to read the data into */
	tag++;

	if (tag >= c->max_tag) {
		spin_lock_irqsave(&c->lock, flags);
		/* check again since original check was outside of lock */
		while (tag >= c->max_tag) {
			row = (tag / P9_ROW_MAXTAG);
			c->reqs[row] = kcalloc(P9_ROW_MAXTAG,
					sizeof(struct p9_req_t), GFP_ATOMIC);

			if (!c->reqs[row]) {
243
				pr_err("Couldn't grow tag array\n");
E
Eric Van Hensbergen 已提交
244
				spin_unlock_irqrestore(&c->lock, flags);
245
				return ERR_PTR(-ENOMEM);
246 247 248
			}
			for (col = 0; col < P9_ROW_MAXTAG; col++) {
				c->reqs[row][col].status = REQ_STATUS_IDLE;
249
				c->reqs[row][col].tc = NULL;
250 251 252 253 254 255 256 257
			}
			c->max_tag += P9_ROW_MAXTAG;
		}
		spin_unlock_irqrestore(&c->lock, flags);
	}
	row = tag / P9_ROW_MAXTAG;
	col = tag % P9_ROW_MAXTAG;

258 259
	req = &c->reqs[row][col];
	if (!req->tc) {
260
		req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS);
S
Simon Derr 已提交
261 262 263
		if (!req->wq)
			goto grow_failed;

264
		init_waitqueue_head(req->wq);
265 266
		req->tc = kmalloc(sizeof(struct p9_fcall) + alloc_msize,
				  GFP_NOFS);
S
Simon Derr 已提交
267 268 269 270 271 272 273
		if (!req->tc)
			goto grow_failed;

		req->tc->capacity = alloc_msize;
		req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall);
	}
	if (!req->rc) {
274 275
		req->rc = kmalloc(sizeof(struct p9_fcall) + alloc_msize,
				  GFP_NOFS);
S
Simon Derr 已提交
276 277 278
		if (!req->rc)
			goto grow_failed;

279
		req->rc->capacity = alloc_msize;
280 281 282 283 284 285 286 287
		req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall);
	}

	p9pdu_reset(req->tc);
	p9pdu_reset(req->rc);

	req->tc->tag = tag-1;
	req->status = REQ_STATUS_ALLOC;
288

S
Simon Derr 已提交
289 290 291 292 293 294 295 296 297 298
	return req;

grow_failed:
	pr_err("Couldn't grow tag array\n");
	kfree(req->tc);
	kfree(req->rc);
	kfree(req->wq);
	req->tc = req->rc = NULL;
	req->wq = NULL;
	return ERR_PTR(-ENOMEM);
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
}

/**
 * p9_tag_lookup - lookup a request by tag
 * @c: client session to lookup tag within
 * @tag: numeric id for transaction
 *
 */

struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
{
	int row, col;

	/* This looks up the original request by tag so we know which
	 * buffer to read the data into */
	tag++;

316 317
	if(tag >= c->max_tag) 
		return NULL;
318 319 320 321 322 323 324 325 326 327

	row = tag / P9_ROW_MAXTAG;
	col = tag % P9_ROW_MAXTAG;

	return &c->reqs[row][col];
}
EXPORT_SYMBOL(p9_tag_lookup);

/**
 * p9_tag_init - setup tags structure and contents
A
Abhishek Kulkarni 已提交
328
 * @c:  v9fs client struct
329 330 331 332 333 334 335 336 337 338 339 340 341 342
 *
 * This initializes the tags structure for each client instance.
 *
 */

static int p9_tag_init(struct p9_client *c)
{
	int err = 0;

	c->tagpool = p9_idpool_create();
	if (IS_ERR(c->tagpool)) {
		err = PTR_ERR(c->tagpool);
		goto error;
	}
343 344 345 346 347
	err = p9_idpool_get(c->tagpool); /* reserve tag 0 */
	if (err < 0) {
		p9_idpool_destroy(c->tagpool);
		goto error;
	}
348 349 350 351 352 353 354
	c->max_tag = 0;
error:
	return err;
}

/**
 * p9_tag_cleanup - cleans up tags structure and reclaims resources
A
Abhishek Kulkarni 已提交
355
 * @c:  v9fs client struct
356 357 358 359 360 361 362 363 364 365 366 367
 *
 * This frees resources associated with the tags structure
 *
 */
static void p9_tag_cleanup(struct p9_client *c)
{
	int row, col;

	/* check to insure all requests are idle */
	for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
		for (col = 0; col < P9_ROW_MAXTAG; col++) {
			if (c->reqs[row][col].status != REQ_STATUS_IDLE) {
368 369 370
				p9_debug(P9_DEBUG_MUX,
					 "Attempting to cleanup non-free tag %d,%d\n",
					 row, col);
371 372 373 374 375 376
				/* TODO: delay execution of cleanup */
				return;
			}
		}
	}

377 378
	if (c->tagpool) {
		p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */
379
		p9_idpool_destroy(c->tagpool);
380
	}
381 382 383

	/* free requests associated with tags */
	for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
384
		for (col = 0; col < P9_ROW_MAXTAG; col++) {
385
			kfree(c->reqs[row][col].wq);
386 387 388
			kfree(c->reqs[row][col].tc);
			kfree(c->reqs[row][col].rc);
		}
389 390 391 392 393
		kfree(c->reqs[row]);
	}
	c->max_tag = 0;
}

394 395 396 397 398 399 400
/**
 * p9_free_req - free a request and clean-up as necessary
 * c: client state
 * r: request to release
 *
 */

401
static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
402
{
403
	int tag = r->tc->tag;
404
	p9_debug(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
405

406
	r->status = REQ_STATUS_IDLE;
407 408
	if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool))
		p9_idpool_put(tag, c->tagpool);
409 410
}

411 412 413 414 415 416 417 418
/**
 * p9_client_cb - call back from transport to client
 * c: client state
 * req: request received
 *
 */
void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
{
419
	p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
420
	wake_up(req->wq);
421
	p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
422 423 424
}
EXPORT_SYMBOL(p9_client_cb);

425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
/**
 * p9_parse_header - parse header arguments out of a packet
 * @pdu: packet to parse
 * @size: size of packet
 * @type: type of request
 * @tag: tag of packet
 * @rewind: set if we need to rewind offset afterwards
 */

int
p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag,
								int rewind)
{
	int8_t r_type;
	int16_t r_tag;
	int32_t r_size;
	int offset = pdu->offset;
	int err;

	pdu->offset = 0;
	if (pdu->size == 0)
		pdu->size = 7;

	err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag);
	if (err)
		goto rewind_and_exit;

	pdu->size = r_size;
	pdu->id = r_type;
	pdu->tag = r_tag;

456 457
	p9_debug(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n",
		 pdu->size, pdu->id, pdu->tag);
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488

	if (type)
		*type = r_type;
	if (tag)
		*tag = r_tag;
	if (size)
		*size = r_size;


rewind_and_exit:
	if (rewind)
		pdu->offset = offset;
	return err;
}
EXPORT_SYMBOL(p9_parse_header);

/**
 * p9_check_errors - check 9p packet for error return and process it
 * @c: current client instance
 * @req: request to parse and check for error conditions
 *
 * returns error code if one is discovered, otherwise returns 0
 *
 * this will have to be more complicated if we have multiple
 * error packet types
 */

static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
{
	int8_t type;
	int err;
489
	int ecode;
490 491

	err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
492 493 494 495 496
	/*
	 * dump the response from server
	 * This should be after check errors which poplulate pdu_fcall.
	 */
	trace_9p_protocol_dump(c, req->rc);
497
	if (err) {
498
		p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
499 500
		return err;
	}
501 502
	if (type != P9_RERROR && type != P9_RLERROR)
		return 0;
503

504 505 506
	if (!p9_is_proto_dotl(c)) {
		char *ename;
		err = p9pdu_readf(req->rc, c->proto_version, "s?d",
507
				  &ename, &ecode);
508 509
		if (err)
			goto out_err;
510

511 512
		if (p9_is_proto_dotu(c))
			err = -ecode;
513

514 515
		if (!err || !IS_ERR_VALUE(err)) {
			err = p9_errstr2errno(ename, strlen(ename));
516

517 518
			p9_debug(P9_DEBUG_9P, "<<< RERROR (%d) %s\n",
				 -ecode, ename);
519
		}
520
		kfree(ename);
521 522 523 524
	} else {
		err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
		err = -ecode;

525
		p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
526
	}
527 528

	return err;
529 530

out_err:
531
	p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
532 533

	return err;
534 535
}

536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
/**
 * p9_check_zc_errors - check 9p packet for error return and process it
 * @c: current client instance
 * @req: request to parse and check for error conditions
 * @in_hdrlen: Size of response protocol buffer.
 *
 * returns error code if one is discovered, otherwise returns 0
 *
 * this will have to be more complicated if we have multiple
 * error packet types
 */

static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
			      char *uidata, int in_hdrlen, int kern_buf)
{
	int err;
	int ecode;
	int8_t type;
	char *ename = NULL;

	err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
557 558 559 560 561
	/*
	 * dump the response from server
	 * This should be after parse_header which poplulate pdu_fcall.
	 */
	trace_9p_protocol_dump(c, req->rc);
562
	if (err) {
563
		p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
564 565 566 567 568 569 570 571
		return err;
	}

	if (type != P9_RERROR && type != P9_RLERROR)
		return 0;

	if (!p9_is_proto_dotl(c)) {
		/* Error is reported in string format */
572 573 574
		int len;
		/* 7 = header size for RERROR; */
		int inline_len = in_hdrlen - 7;
575

576 577 578
		len =  req->rc->size - req->rc->offset;
		if (len > (P9_ZC_HDR_SZ - 7)) {
			err = -EFAULT;
579 580 581
			goto out_err;
		}

582 583 584
		ename = &req->rc->sdata[req->rc->offset];
		if (len > inline_len) {
			/* We have error in external buffer */
585 586 587 588 589 590 591 592
			if (kern_buf) {
				memcpy(ename + inline_len, uidata,
				       len - inline_len);
			} else {
				err = copy_from_user(ename + inline_len,
						     uidata, len - inline_len);
				if (err) {
					err = -EFAULT;
593
					goto out_err;
594 595 596
				}
			}
		}
597 598 599 600 601 602 603
		ename = NULL;
		err = p9pdu_readf(req->rc, c->proto_version, "s?d",
				  &ename, &ecode);
		if (err)
			goto out_err;

		if (p9_is_proto_dotu(c))
604
			err = -ecode;
605

606 607 608
		if (!err || !IS_ERR_VALUE(err)) {
			err = p9_errstr2errno(ename, strlen(ename));

609 610
			p9_debug(P9_DEBUG_9P, "<<< RERROR (%d) %s\n",
				 -ecode, ename);
611 612 613 614 615 616
		}
		kfree(ename);
	} else {
		err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
		err = -ecode;

617
		p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
618 619 620 621
	}
	return err;

out_err:
622
	p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
623 624 625
	return err;
}

R
Rob Landley 已提交
626 627 628
static struct p9_req_t *
p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);

629 630
/**
 * p9_client_flush - flush (cancel) a request
A
Abhishek Kulkarni 已提交
631 632
 * @c: client state
 * @oldreq: request to cancel
633
 *
R
Rob Landley 已提交
634
 * This sents a flush for a particular request and links
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
 * the flush request to the original request.  The current
 * code only supports a single flush request although the protocol
 * allows for multiple flush requests to be sent for a single request.
 *
 */

static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
{
	struct p9_req_t *req;
	int16_t oldtag;
	int err;

	err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1);
	if (err)
		return err;

651
	p9_debug(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag);
652 653 654 655 656 657

	req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag);
	if (IS_ERR(req))
		return PTR_ERR(req);


658 659 660 661 662 663 664 665
	/* if we haven't received a response for oldreq,
	   remove it from the list. */
	spin_lock(&c->lock);
	if (oldreq->status == REQ_STATUS_FLSH)
		list_del(&oldreq->req_list);
	spin_unlock(&c->lock);

	p9_free_req(c, req);
666 667 668
	return 0;
}

669 670 671
static struct p9_req_t *p9_client_prepare_req(struct p9_client *c,
					      int8_t type, int req_size,
					      const char *fmt, va_list ap)
672
{
673
	int tag, err;
674 675
	struct p9_req_t *req;

676
	p9_debug(P9_DEBUG_MUX, "client %p op %d\n", c, type);
677

678 679 680 681 682 683
	/* we allow for any status other than disconnected */
	if (c->status == Disconnected)
		return ERR_PTR(-EIO);

	/* if status is begin_disconnected we allow only clunk request */
	if ((c->status == BeginDisconnect) && (type != P9_TCLUNK))
684
		return ERR_PTR(-EIO);
685 686

	tag = P9_NOTAG;
687
	if (type != P9_TVERSION) {
688 689
		tag = p9_idpool_get(c->tagpool);
		if (tag < 0)
690
			return ERR_PTR(-ENOMEM);
691 692
	}

693
	req = p9_tag_alloc(c, tag, req_size);
694 695
	if (IS_ERR(req))
		return req;
696

697 698
	/* marshall the data */
	p9pdu_prepare(req->tc, tag, type);
699
	err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap);
700 701
	if (err)
		goto reterr;
702 703
	p9pdu_finalize(c, req->tc);
	trace_9p_client_req(c, type, tag);
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737
	return req;
reterr:
	p9_free_req(c, req);
	return ERR_PTR(err);
}

/**
 * p9_client_rpc - issue a request and wait for a response
 * @c: client session
 * @type: type of request
 * @fmt: protocol format string (see protocol.c)
 *
 * Returns request structure (which client must free using p9_free_req)
 */

static struct p9_req_t *
p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
{
	va_list ap;
	int sigpending, err;
	unsigned long flags;
	struct p9_req_t *req;

	va_start(ap, fmt);
	req = p9_client_prepare_req(c, type, c->msize, fmt, ap);
	va_end(ap);
	if (IS_ERR(req))
		return req;

	if (signal_pending(current)) {
		sigpending = 1;
		clear_thread_flag(TIF_SIGPENDING);
	} else
		sigpending = 0;
738 739 740

	err = c->trans_mod->request(c, req);
	if (err < 0) {
741
		if (err != -ERESTARTSYS && err != -EFAULT)
742
			c->status = Disconnected;
743 744
		goto reterr;
	}
745
again:
746
	/* Wait for the response */
747
	err = wait_event_interruptible(*req->wq,
748
				       req->status >= REQ_STATUS_RCVD);
749

750 751 752 753 754 755 756
	if ((err == -ERESTARTSYS) && (c->status == Connected)
				  && (type == P9_TFLUSH)) {
		sigpending = 1;
		clear_thread_flag(TIF_SIGPENDING);
		goto again;
	}

757
	if (req->status == REQ_STATUS_ERROR) {
758
		p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
759 760
		err = req->t_err;
	}
761
	if ((err == -ERESTARTSYS) && (c->status == Connected)) {
762
		p9_debug(P9_DEBUG_MUX, "flushing\n");
763 764 765
		sigpending = 1;
		clear_thread_flag(TIF_SIGPENDING);

766 767 768 769 770 771
		if (c->trans_mod->cancel(c, req))
			p9_client_flush(c, req);

		/* if we received the response anyway, don't signal error */
		if (req->status == REQ_STATUS_RCVD)
			err = 0;
772 773 774 775 776 777 778 779 780
	}
	if (sigpending) {
		spin_lock_irqsave(&current->sighand->siglock, flags);
		recalc_sigpending();
		spin_unlock_irqrestore(&current->sighand->siglock, flags);
	}
	if (err < 0)
		goto reterr;

781
	err = p9_check_errors(c, req);
782 783
	trace_9p_client_res(c, type, req->rc->tag, err);
	if (!err)
784
		return req;
785 786
reterr:
	p9_free_req(c, req);
S
Simon Derr 已提交
787
	return ERR_PTR(safe_errno(err));
788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
}

/**
 * p9_client_zc_rpc - issue a request and wait for a response
 * @c: client session
 * @type: type of request
 * @uidata: user bffer that should be ued for zero copy read
 * @uodata: user buffer that shoud be user for zero copy write
 * @inlen: read buffer size
 * @olen: write buffer size
 * @hdrlen: reader header size, This is the size of response protocol data
 * @fmt: protocol format string (see protocol.c)
 *
 * Returns request structure (which client must free using p9_free_req)
 */
static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
					 char *uidata, char *uodata,
					 int inlen, int olen, int in_hdrlen,
					 int kern_buf, const char *fmt, ...)
{
	va_list ap;
	int sigpending, err;
	unsigned long flags;
	struct p9_req_t *req;

	va_start(ap, fmt);
	/*
	 * We allocate a inline protocol data of only 4k bytes.
	 * The actual content is passed in zero-copy fashion.
	 */
	req = p9_client_prepare_req(c, type, P9_ZC_HDR_SZ, fmt, ap);
	va_end(ap);
	if (IS_ERR(req))
		return req;

	if (signal_pending(current)) {
		sigpending = 1;
		clear_thread_flag(TIF_SIGPENDING);
	} else
		sigpending = 0;

	/* If we are called with KERNEL_DS force kern_buf */
	if (segment_eq(get_fs(), KERNEL_DS))
		kern_buf = 1;

	err = c->trans_mod->zc_request(c, req, uidata, uodata,
				       inlen, olen, in_hdrlen, kern_buf);
	if (err < 0) {
		if (err == -EIO)
			c->status = Disconnected;
		goto reterr;
	}
	if (req->status == REQ_STATUS_ERROR) {
841
		p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
842 843 844
		err = req->t_err;
	}
	if ((err == -ERESTARTSYS) && (c->status == Connected)) {
845
		p9_debug(P9_DEBUG_MUX, "flushing\n");
846 847
		sigpending = 1;
		clear_thread_flag(TIF_SIGPENDING);
848

849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
		if (c->trans_mod->cancel(c, req))
			p9_client_flush(c, req);

		/* if we received the response anyway, don't signal error */
		if (req->status == REQ_STATUS_RCVD)
			err = 0;
	}
	if (sigpending) {
		spin_lock_irqsave(&current->sighand->siglock, flags);
		recalc_sigpending();
		spin_unlock_irqrestore(&current->sighand->siglock, flags);
	}
	if (err < 0)
		goto reterr;

	err = p9_check_zc_errors(c, req, uidata, in_hdrlen, kern_buf);
865 866
	trace_9p_client_res(c, type, req->rc->tag, err);
	if (!err)
867
		return req;
868 869
reterr:
	p9_free_req(c, req);
S
Simon Derr 已提交
870
	return ERR_PTR(safe_errno(err));
871 872
}

873 874
static struct p9_fid *p9_fid_create(struct p9_client *clnt)
{
R
Roel Kluin 已提交
875
	int ret;
876
	struct p9_fid *fid;
877
	unsigned long flags;
878

879
	p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt);
880 881 882 883
	fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
	if (!fid)
		return ERR_PTR(-ENOMEM);

R
Roel Kluin 已提交
884
	ret = p9_idpool_get(clnt->fidpool);
885
	if (ret < 0) {
R
Roel Kluin 已提交
886
		ret = -ENOSPC;
887 888
		goto error;
	}
R
Roel Kluin 已提交
889
	fid->fid = ret;
890 891 892

	memset(&fid->qid, 0, sizeof(struct p9_qid));
	fid->mode = -1;
893
	fid->uid = current_fsuid();
894
	fid->clnt = clnt;
E
Eric Van Hensbergen 已提交
895
	fid->rdir = NULL;
896
	spin_lock_irqsave(&clnt->lock, flags);
897
	list_add(&fid->flist, &clnt->fidlist);
898
	spin_unlock_irqrestore(&clnt->lock, flags);
899 900 901 902 903

	return fid;

error:
	kfree(fid);
R
Roel Kluin 已提交
904
	return ERR_PTR(ret);
905 906 907 908 909
}

static void p9_fid_destroy(struct p9_fid *fid)
{
	struct p9_client *clnt;
910
	unsigned long flags;
911

912
	p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid);
913 914
	clnt = fid->clnt;
	p9_idpool_put(fid->fid, clnt->fidpool);
915
	spin_lock_irqsave(&clnt->lock, flags);
916
	list_del(&fid->flist);
917
	spin_unlock_irqrestore(&clnt->lock, flags);
E
Eric Van Hensbergen 已提交
918
	kfree(fid->rdir);
919 920
	kfree(fid);
}
921

S
stephen hemminger 已提交
922
static int p9_client_version(struct p9_client *c)
923
{
924
	int err = 0;
925 926 927
	struct p9_req_t *req;
	char *version;
	int msize;
928

929 930
	p9_debug(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n",
		 c->msize, c->proto_version);
931 932

	switch (c->proto_version) {
933
	case p9_proto_2000L:
934
		req = p9_client_rpc(c, P9_TVERSION, "ds",
935
					c->msize, "9P2000.L");
936 937 938 939 940 941 942 943 944 945 946 947 948 949
		break;
	case p9_proto_2000u:
		req = p9_client_rpc(c, P9_TVERSION, "ds",
					c->msize, "9P2000.u");
		break;
	case p9_proto_legacy:
		req = p9_client_rpc(c, P9_TVERSION, "ds",
					c->msize, "9P2000");
		break;
	default:
		return -EINVAL;
		break;
	}

950 951
	if (IS_ERR(req))
		return PTR_ERR(req);
952

953
	err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version);
954
	if (err) {
955
		p9_debug(P9_DEBUG_9P, "version error %d\n", err);
956
		trace_9p_protocol_dump(c, req->rc);
957
		goto error;
958
	}
959

960
	p9_debug(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
961 962
	if (!strncmp(version, "9P2000.L", 8))
		c->proto_version = p9_proto_2000L;
963
	else if (!strncmp(version, "9P2000.u", 8))
964 965 966
		c->proto_version = p9_proto_2000u;
	else if (!strncmp(version, "9P2000", 6))
		c->proto_version = p9_proto_legacy;
967 968 969 970 971
	else {
		err = -EREMOTEIO;
		goto error;
	}

972 973
	if (msize < c->msize)
		c->msize = msize;
974 975

error:
976 977
	kfree(version);
	p9_free_req(c, req);
978 979 980 981 982 983 984 985 986 987

	return err;
}

struct p9_client *p9_client_create(const char *dev_name, char *options)
{
	int err;
	struct p9_client *clnt;

	err = 0;
988 989 990 991
	clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL);
	if (!clnt)
		return ERR_PTR(-ENOMEM);

992
	clnt->trans_mod = NULL;
993
	clnt->trans = NULL;
994 995 996
	spin_lock_init(&clnt->lock);
	INIT_LIST_HEAD(&clnt->fidlist);

997 998 999
	err = p9_tag_init(clnt);
	if (err < 0)
		goto free_client;
1000

1001 1002
	err = parse_opts(options, clnt);
	if (err < 0)
1003
		goto destroy_tagpool;
1004

1005 1006 1007
	if (!clnt->trans_mod)
		clnt->trans_mod = v9fs_get_trans_by_name("virtio");

1008 1009 1010
	if (!clnt->trans_mod)
		clnt->trans_mod = v9fs_get_default_trans();

1011 1012
	if (clnt->trans_mod == NULL) {
		err = -EPROTONOSUPPORT;
1013 1014
		p9_debug(P9_DEBUG_ERROR,
			 "No transport defined or default transport\n");
1015
		goto destroy_tagpool;
1016 1017 1018 1019 1020 1021
	}

	clnt->fidpool = p9_idpool_create();
	if (IS_ERR(clnt->fidpool)) {
		err = PTR_ERR(clnt->fidpool);
		goto put_trans;
1022 1023
	}

1024 1025
	p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n",
		 clnt, clnt->trans_mod, clnt->msize, clnt->proto_version);
1026

1027 1028
	err = clnt->trans_mod->create(clnt, dev_name, options);
	if (err)
1029
		goto destroy_fidpool;
1030

1031 1032
	if (clnt->msize > clnt->trans_mod->maxsize)
		clnt->msize = clnt->trans_mod->maxsize;
1033

1034
	err = p9_client_version(clnt);
1035
	if (err)
1036
		goto close_trans;
1037 1038 1039

	return clnt;

1040 1041 1042 1043 1044 1045
close_trans:
	clnt->trans_mod->close(clnt);
destroy_fidpool:
	p9_idpool_destroy(clnt->fidpool);
put_trans:
	v9fs_put_trans(clnt->trans_mod);
1046 1047
destroy_tagpool:
	p9_idpool_destroy(clnt->tagpool);
1048 1049
free_client:
	kfree(clnt);
1050 1051 1052 1053 1054 1055 1056 1057
	return ERR_PTR(err);
}
EXPORT_SYMBOL(p9_client_create);

void p9_client_destroy(struct p9_client *clnt)
{
	struct p9_fid *fid, *fidptr;

1058
	p9_debug(P9_DEBUG_MUX, "clnt %p\n", clnt);
1059

1060 1061
	if (clnt->trans_mod)
		clnt->trans_mod->close(clnt);
1062

1063 1064
	v9fs_put_trans(clnt->trans_mod);

1065
	list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) {
1066
		pr_info("Found fid %d not clunked\n", fid->fid);
1067
		p9_fid_destroy(fid);
1068
	}
1069

1070 1071 1072
	if (clnt->fidpool)
		p9_idpool_destroy(clnt->fidpool);

1073 1074
	p9_tag_cleanup(clnt);

1075 1076 1077 1078 1079 1080
	kfree(clnt);
}
EXPORT_SYMBOL(p9_client_destroy);

void p9_client_disconnect(struct p9_client *clnt)
{
1081
	p9_debug(P9_DEBUG_9P, "clnt %p\n", clnt);
1082
	clnt->status = Disconnected;
1083 1084 1085
}
EXPORT_SYMBOL(p9_client_disconnect);

1086 1087
void p9_client_begin_disconnect(struct p9_client *clnt)
{
1088
	p9_debug(P9_DEBUG_9P, "clnt %p\n", clnt);
1089 1090 1091 1092
	clnt->status = BeginDisconnect;
}
EXPORT_SYMBOL(p9_client_begin_disconnect);

1093
struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
1094
	char *uname, kuid_t n_uname, char *aname)
1095
{
1096
	int err = 0;
1097
	struct p9_req_t *req;
1098
	struct p9_fid *fid;
1099
	struct p9_qid qid;
1100 1101


1102 1103
	p9_debug(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
		 afid ? afid->fid : -1, uname, aname);
1104 1105 1106 1107 1108 1109 1110
	fid = p9_fid_create(clnt);
	if (IS_ERR(fid)) {
		err = PTR_ERR(fid);
		fid = NULL;
		goto error;
	}

1111
	req = p9_client_rpc(clnt, P9_TATTACH, "ddss?u", fid->fid,
1112 1113 1114
			afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
1115 1116 1117
		goto error;
	}

1118
	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
1119
	if (err) {
1120
		trace_9p_protocol_dump(clnt, req->rc);
1121
		p9_free_req(clnt, req);
1122
		goto error;
1123
	}
1124

1125 1126
	p9_debug(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n",
		 qid.type, (unsigned long long)qid.path, qid.version);
1127 1128 1129 1130

	memmove(&fid->qid, &qid, sizeof(struct p9_qid));

	p9_free_req(clnt, req);
1131 1132 1133 1134 1135 1136 1137 1138 1139
	return fid;

error:
	if (fid)
		p9_fid_destroy(fid);
	return ERR_PTR(err);
}
EXPORT_SYMBOL(p9_client_attach);

1140 1141
struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
		char **wnames, int clone)
1142 1143 1144 1145
{
	int err;
	struct p9_client *clnt;
	struct p9_fid *fid;
1146 1147
	struct p9_qid *wqids;
	struct p9_req_t *req;
1148
	uint16_t nwqids, count;
1149 1150

	err = 0;
1151
	wqids = NULL;
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
	clnt = oldfid->clnt;
	if (clone) {
		fid = p9_fid_create(clnt);
		if (IS_ERR(fid)) {
			err = PTR_ERR(fid);
			fid = NULL;
			goto error;
		}

		fid->uid = oldfid->uid;
	} else
		fid = oldfid;

1165

1166 1167
	p9_debug(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %ud wname[0] %s\n",
		 oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
1168 1169 1170 1171 1172

	req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
								nwname, wnames);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
1173 1174 1175
		goto error;
	}

1176
	err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids);
E
Eric Van Hensbergen 已提交
1177
	if (err) {
1178
		trace_9p_protocol_dump(clnt, req->rc);
E
Eric Van Hensbergen 已提交
1179
		p9_free_req(clnt, req);
1180
		goto clunk_fid;
E
Eric Van Hensbergen 已提交
1181 1182
	}
	p9_free_req(clnt, req);
1183

1184
	p9_debug(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);
1185 1186

	if (nwqids != nwname) {
1187 1188 1189 1190
		err = -ENOENT;
		goto clunk_fid;
	}

1191
	for (count = 0; count < nwqids; count++)
1192
		p9_debug(P9_DEBUG_9P, "<<<     [%d] %x.%llx.%x\n",
R
Randy Dunlap 已提交
1193 1194
			count, wqids[count].type,
			(unsigned long long)wqids[count].path,
1195 1196
			wqids[count].version);

1197
	if (nwname)
1198
		memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid));
1199 1200 1201
	else
		fid->qid = oldfid->qid;

1202
	kfree(wqids);
1203 1204 1205
	return fid;

clunk_fid:
1206
	kfree(wqids);
1207 1208
	p9_client_clunk(fid);
	fid = NULL;
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221

error:
	if (fid && (fid != oldfid))
		p9_fid_destroy(fid);

	return ERR_PTR(err);
}
EXPORT_SYMBOL(p9_client_walk);

int p9_client_open(struct p9_fid *fid, int mode)
{
	int err;
	struct p9_client *clnt;
1222 1223 1224
	struct p9_req_t *req;
	struct p9_qid qid;
	int iounit;
1225 1226

	clnt = fid->clnt;
1227
	p9_debug(P9_DEBUG_9P, ">>> %s fid %d mode %d\n",
M
M. Mohan Kumar 已提交
1228 1229
		p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN", fid->fid, mode);
	err = 0;
1230 1231 1232 1233

	if (fid->mode != -1)
		return -EINVAL;

M
M. Mohan Kumar 已提交
1234 1235 1236 1237
	if (p9_is_proto_dotl(clnt))
		req = p9_client_rpc(clnt, P9_TLOPEN, "dd", fid->fid, mode);
	else
		req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode);
1238 1239 1240
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
1241 1242
	}

1243
	err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
E
Eric Van Hensbergen 已提交
1244
	if (err) {
1245
		trace_9p_protocol_dump(clnt, req->rc);
E
Eric Van Hensbergen 已提交
1246 1247
		goto free_and_error;
	}
1248

1249
	p9_debug(P9_DEBUG_9P, "<<< %s qid %x.%llx.%x iounit %x\n",
M
M. Mohan Kumar 已提交
1250 1251
		p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN",  qid.type,
		(unsigned long long)qid.path, qid.version, iounit);
1252 1253

	fid->mode = mode;
1254
	fid->iounit = iounit;
1255

E
Eric Van Hensbergen 已提交
1256 1257
free_and_error:
	p9_free_req(clnt, req);
1258
error:
1259 1260 1261 1262
	return err;
}
EXPORT_SYMBOL(p9_client_open);

1263
int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
1264
		kgid_t gid, struct p9_qid *qid)
1265 1266 1267 1268 1269 1270
{
	int err = 0;
	struct p9_client *clnt;
	struct p9_req_t *req;
	int iounit;

1271
	p9_debug(P9_DEBUG_9P,
1272
			">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n",
1273 1274
			ofid->fid, name, flags, mode,
		 	from_kgid(&init_user_ns, gid));
1275 1276 1277 1278 1279
	clnt = ofid->clnt;

	if (ofid->mode != -1)
		return -EINVAL;

1280
	req = p9_client_rpc(clnt, P9_TLCREATE, "dsddg", ofid->fid, name, flags,
1281 1282 1283 1284 1285 1286 1287 1288
			mode, gid);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", qid, &iounit);
	if (err) {
1289
		trace_9p_protocol_dump(clnt, req->rc);
1290 1291 1292
		goto free_and_error;
	}

1293
	p9_debug(P9_DEBUG_9P, "<<< RLCREATE qid %x.%llx.%x iounit %x\n",
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307
			qid->type,
			(unsigned long long)qid->path,
			qid->version, iounit);

	ofid->mode = mode;
	ofid->iounit = iounit;

free_and_error:
	p9_free_req(clnt, req);
error:
	return err;
}
EXPORT_SYMBOL(p9_client_create_dotl);

1308 1309 1310 1311 1312
int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
		     char *extension)
{
	int err;
	struct p9_client *clnt;
1313 1314 1315
	struct p9_req_t *req;
	struct p9_qid qid;
	int iounit;
1316

1317
	p9_debug(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n",
1318
						fid->fid, name, perm, mode);
1319 1320 1321 1322 1323 1324
	err = 0;
	clnt = fid->clnt;

	if (fid->mode != -1)
		return -EINVAL;

1325 1326 1327 1328 1329
	req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm,
				mode, extension);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
1330 1331
	}

1332
	err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
E
Eric Van Hensbergen 已提交
1333
	if (err) {
1334
		trace_9p_protocol_dump(clnt, req->rc);
E
Eric Van Hensbergen 已提交
1335 1336
		goto free_and_error;
	}
1337

1338
	p9_debug(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
R
Randy Dunlap 已提交
1339 1340 1341
				qid.type,
				(unsigned long long)qid.path,
				qid.version, iounit);
1342 1343

	fid->mode = mode;
1344
	fid->iounit = iounit;
1345

E
Eric Van Hensbergen 已提交
1346 1347
free_and_error:
	p9_free_req(clnt, req);
1348
error:
1349 1350 1351 1352
	return err;
}
EXPORT_SYMBOL(p9_client_fcreate);

1353
int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, kgid_t gid,
1354 1355 1356 1357 1358 1359
		struct p9_qid *qid)
{
	int err = 0;
	struct p9_client *clnt;
	struct p9_req_t *req;

1360
	p9_debug(P9_DEBUG_9P, ">>> TSYMLINK dfid %d name %s  symtgt %s\n",
1361 1362 1363
			dfid->fid, name, symtgt);
	clnt = dfid->clnt;

1364
	req = p9_client_rpc(clnt, P9_TSYMLINK, "dssg", dfid->fid, name, symtgt,
1365 1366 1367 1368 1369 1370 1371 1372
			gid);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
	if (err) {
1373
		trace_9p_protocol_dump(clnt, req->rc);
1374 1375 1376
		goto free_and_error;
	}

1377
	p9_debug(P9_DEBUG_9P, "<<< RSYMLINK qid %x.%llx.%x\n",
1378 1379 1380 1381 1382 1383 1384 1385 1386
			qid->type, (unsigned long long)qid->path, qid->version);

free_and_error:
	p9_free_req(clnt, req);
error:
	return err;
}
EXPORT_SYMBOL(p9_client_symlink);

1387 1388 1389 1390 1391
int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname)
{
	struct p9_client *clnt;
	struct p9_req_t *req;

1392
	p9_debug(P9_DEBUG_9P, ">>> TLINK dfid %d oldfid %d newname %s\n",
1393 1394 1395 1396 1397 1398 1399
			dfid->fid, oldfid->fid, newname);
	clnt = dfid->clnt;
	req = p9_client_rpc(clnt, P9_TLINK, "dds", dfid->fid, oldfid->fid,
			newname);
	if (IS_ERR(req))
		return PTR_ERR(req);

1400
	p9_debug(P9_DEBUG_9P, "<<< RLINK\n");
1401 1402 1403 1404 1405
	p9_free_req(clnt, req);
	return 0;
}
EXPORT_SYMBOL(p9_client_link);

1406
int p9_client_fsync(struct p9_fid *fid, int datasync)
1407 1408 1409 1410 1411
{
	int err;
	struct p9_client *clnt;
	struct p9_req_t *req;

1412
	p9_debug(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n",
1413
			fid->fid, datasync);
1414 1415 1416
	err = 0;
	clnt = fid->clnt;

1417
	req = p9_client_rpc(clnt, P9_TFSYNC, "dd", fid->fid, datasync);
1418 1419 1420 1421 1422
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

1423
	p9_debug(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid);
1424 1425 1426 1427 1428 1429 1430 1431

	p9_free_req(clnt, req);

error:
	return err;
}
EXPORT_SYMBOL(p9_client_fsync);

1432 1433 1434 1435
int p9_client_clunk(struct p9_fid *fid)
{
	int err;
	struct p9_client *clnt;
1436
	struct p9_req_t *req;
1437
	int retries = 0;
1438

1439
	if (!fid) {
1440 1441
		pr_warn("%s (%d): Trying to clunk with NULL fid\n",
			__func__, task_pid_nr(current));
1442 1443 1444 1445
		dump_stack();
		return 0;
	}

1446 1447 1448
again:
	p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n", fid->fid,
								retries);
1449 1450 1451
	err = 0;
	clnt = fid->clnt;

1452 1453 1454 1455
	req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
1456 1457
	}

1458
	p9_debug(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
1459

1460 1461
	p9_free_req(clnt, req);
error:
1462 1463
	/*
	 * Fid is not valid even after a failed clunk
1464 1465
	 * If interrupted, retry once then give up and
	 * leak fid until umount.
1466
	 */
1467 1468 1469 1470 1471
	if (err == -ERESTARTSYS) {
		if (retries++ == 0)
			goto again;
	} else
		p9_fid_destroy(fid);
1472 1473 1474 1475 1476 1477 1478 1479
	return err;
}
EXPORT_SYMBOL(p9_client_clunk);

int p9_client_remove(struct p9_fid *fid)
{
	int err;
	struct p9_client *clnt;
1480
	struct p9_req_t *req;
1481

1482
	p9_debug(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid);
1483 1484 1485
	err = 0;
	clnt = fid->clnt;

1486 1487 1488 1489
	req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
1490 1491
	}

1492
	p9_debug(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid);
1493

1494 1495
	p9_free_req(clnt, req);
error:
1496 1497 1498 1499
	if (err == -ERESTARTSYS)
		p9_client_clunk(fid);
	else
		p9_fid_destroy(fid);
1500 1501 1502 1503
	return err;
}
EXPORT_SYMBOL(p9_client_remove);

1504 1505 1506 1507 1508 1509
int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags)
{
	int err = 0;
	struct p9_req_t *req;
	struct p9_client *clnt;

1510
	p9_debug(P9_DEBUG_9P, ">>> TUNLINKAT fid %d %s %d\n",
1511 1512 1513 1514 1515 1516 1517 1518
		   dfid->fid, name, flags);

	clnt = dfid->clnt;
	req = p9_client_rpc(clnt, P9_TUNLINKAT, "dsd", dfid->fid, name, flags);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}
1519
	p9_debug(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name);
1520 1521 1522 1523 1524 1525 1526

	p9_free_req(clnt, req);
error:
	return err;
}
EXPORT_SYMBOL(p9_client_unlinkat);

1527 1528 1529
int
p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
								u32 count)
1530
{
1531
	char *dataptr;
1532 1533 1534 1535 1536
	int kernel_buf = 0;
	struct p9_req_t *req;
	struct p9_client *clnt;
	int err, rsize, non_zc = 0;

1537

1538
	p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n",
1539
		   fid->fid, (unsigned long long) offset, count);
1540 1541 1542 1543 1544 1545 1546
	err = 0;
	clnt = fid->clnt;

	rsize = fid->iounit;
	if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
		rsize = clnt->msize - P9_IOHDRSZ;

1547 1548
	if (count < rsize)
		rsize = count;
1549

R
Rob Landley 已提交
1550
	/* Don't bother zerocopy for small IO (< 1024) */
1551 1552 1553 1554 1555 1556
	if (clnt->trans_mod->zc_request && rsize > 1024) {
		char *indata;
		if (data) {
			kernel_buf = 1;
			indata = data;
		} else
1557
			indata = (__force char *)udata;
1558 1559 1560 1561 1562 1563 1564
		/*
		 * response header len is 11
		 * PDU Header(7) + IO Size (4)
		 */
		req = p9_client_zc_rpc(clnt, P9_TREAD, indata, NULL, rsize, 0,
				       11, kernel_buf, "dqd", fid->fid,
				       offset, rsize);
1565
	} else {
1566
		non_zc = 1;
1567
		req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
1568
				    rsize);
1569
	}
1570 1571 1572 1573
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}
1574

1575
	err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
E
Eric Van Hensbergen 已提交
1576
	if (err) {
1577
		trace_9p_protocol_dump(clnt, req->rc);
1578
		goto free_and_error;
E
Eric Van Hensbergen 已提交
1579
	}
1580

1581
	p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
1582

1583
	if (non_zc) {
1584 1585 1586 1587 1588 1589 1590 1591
		if (data) {
			memmove(data, dataptr, count);
		} else {
			err = copy_to_user(udata, dataptr, count);
			if (err) {
				err = -EFAULT;
				goto free_and_error;
			}
1592
		}
1593 1594 1595
	}
	p9_free_req(clnt, req);
	return count;
1596

1597 1598
free_and_error:
	p9_free_req(clnt, req);
1599 1600 1601
error:
	return err;
}
1602
EXPORT_SYMBOL(p9_client_read);
1603 1604

int
1605 1606
p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
							u64 offset, u32 count)
1607
{
1608
	int err, rsize;
1609
	int kernel_buf = 0;
1610
	struct p9_client *clnt;
1611
	struct p9_req_t *req;
1612

1613
	p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n",
1614
				fid->fid, (unsigned long long) offset, count);
1615 1616 1617 1618 1619 1620 1621
	err = 0;
	clnt = fid->clnt;

	rsize = fid->iounit;
	if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
		rsize = clnt->msize - P9_IOHDRSZ;

1622 1623
	if (count < rsize)
		rsize = count;
1624

1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635
	/* Don't bother zerocopy for small IO (< 1024) */
	if (clnt->trans_mod->zc_request && rsize > 1024) {
		char *odata;
		if (data) {
			kernel_buf = 1;
			odata = data;
		} else
			odata = (char *)udata;
		req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, odata, 0, rsize,
				       P9_ZC_HDR_SZ, kernel_buf, "dqd",
				       fid->fid, offset, rsize);
1636 1637 1638
	} else {
		if (data)
			req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid,
1639
					    offset, rsize, data);
1640 1641
		else
			req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid,
1642
					    offset, rsize, udata);
1643
	}
1644 1645 1646 1647
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}
1648

1649
	err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count);
E
Eric Van Hensbergen 已提交
1650
	if (err) {
1651
		trace_9p_protocol_dump(clnt, req->rc);
1652
		goto free_and_error;
E
Eric Van Hensbergen 已提交
1653 1654
	}

1655
	p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
1656

1657 1658
	p9_free_req(clnt, req);
	return count;
1659

1660 1661
free_and_error:
	p9_free_req(clnt, req);
1662 1663 1664
error:
	return err;
}
1665
EXPORT_SYMBOL(p9_client_write);
1666

1667
struct p9_wstat *p9_client_stat(struct p9_fid *fid)
1668
{
1669 1670 1671 1672 1673
	int err;
	struct p9_client *clnt;
	struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL);
	struct p9_req_t *req;
	u16 ignored;
1674

1675
	p9_debug(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid);
1676 1677 1678 1679

	if (!ret)
		return ERR_PTR(-ENOMEM);

1680 1681 1682
	err = 0;
	clnt = fid->clnt;

1683 1684 1685
	req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
1686 1687 1688
		goto error;
	}

1689
	err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret);
E
Eric Van Hensbergen 已提交
1690
	if (err) {
1691
		trace_9p_protocol_dump(clnt, req->rc);
1692 1693
		p9_free_req(clnt, req);
		goto error;
E
Eric Van Hensbergen 已提交
1694
	}
1695

1696
	p9_debug(P9_DEBUG_9P,
E
Eric Van Hensbergen 已提交
1697 1698 1699 1700
		"<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
		"<<<    mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
		"<<<    name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
		"<<<    uid=%d gid=%d n_muid=%d\n",
1701
		ret->size, ret->type, ret->dev, ret->qid.type,
R
Randy Dunlap 已提交
1702 1703 1704
		(unsigned long long)ret->qid.path, ret->qid.version, ret->mode,
		ret->atime, ret->mtime, (unsigned long long)ret->length,
		ret->name, ret->uid, ret->gid, ret->muid, ret->extension,
1705 1706 1707
		from_kuid(&init_user_ns, ret->n_uid),
		from_kgid(&init_user_ns, ret->n_gid),
		from_kuid(&init_user_ns, ret->n_muid));
1708

1709 1710 1711
	p9_free_req(clnt, req);
	return ret;

1712
error:
1713 1714
	kfree(ret);
	return ERR_PTR(err);
1715 1716 1717
}
EXPORT_SYMBOL(p9_client_stat);

1718 1719 1720 1721 1722 1723 1724 1725 1726
struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
							u64 request_mask)
{
	int err;
	struct p9_client *clnt;
	struct p9_stat_dotl *ret = kmalloc(sizeof(struct p9_stat_dotl),
								GFP_KERNEL);
	struct p9_req_t *req;

1727
	p9_debug(P9_DEBUG_9P, ">>> TGETATTR fid %d, request_mask %lld\n",
1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743
							fid->fid, request_mask);

	if (!ret)
		return ERR_PTR(-ENOMEM);

	err = 0;
	clnt = fid->clnt;

	req = p9_client_rpc(clnt, P9_TGETATTR, "dq", fid->fid, request_mask);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->proto_version, "A", ret);
	if (err) {
1744
		trace_9p_protocol_dump(clnt, req->rc);
1745 1746 1747 1748
		p9_free_req(clnt, req);
		goto error;
	}

1749
	p9_debug(P9_DEBUG_9P,
1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760
		"<<< RGETATTR st_result_mask=%lld\n"
		"<<< qid=%x.%llx.%x\n"
		"<<< st_mode=%8.8x st_nlink=%llu\n"
		"<<< st_uid=%d st_gid=%d\n"
		"<<< st_rdev=%llx st_size=%llx st_blksize=%llu st_blocks=%llu\n"
		"<<< st_atime_sec=%lld st_atime_nsec=%lld\n"
		"<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n"
		"<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n"
		"<<< st_btime_sec=%lld st_btime_nsec=%lld\n"
		"<<< st_gen=%lld st_data_version=%lld",
		ret->st_result_mask, ret->qid.type, ret->qid.path,
1761 1762 1763 1764
		ret->qid.version, ret->st_mode, ret->st_nlink,
		from_kuid(&init_user_ns, ret->st_uid),
		from_kgid(&init_user_ns, ret->st_gid),
		ret->st_rdev, ret->st_size, ret->st_blksize,
1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778
		ret->st_blocks, ret->st_atime_sec, ret->st_atime_nsec,
		ret->st_mtime_sec, ret->st_mtime_nsec, ret->st_ctime_sec,
		ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec,
		ret->st_gen, ret->st_data_version);

	p9_free_req(clnt, req);
	return ret;

error:
	kfree(ret);
	return ERR_PTR(err);
}
EXPORT_SYMBOL(p9_client_getattr_dotl);

1779
static int p9_client_statsize(struct p9_wstat *wst, int proto_version)
1780 1781 1782
{
	int ret;

1783
	/* NOTE: size shouldn't include its own length */
1784 1785 1786
	/* size[2] type[2] dev[4] qid[13] */
	/* mode[4] atime[4] mtime[4] length[8]*/
	/* name[s] uid[s] gid[s] muid[s] */
1787
	ret = 2+4+13+4+4+4+8+2+2+2+2;
1788 1789 1790 1791 1792 1793 1794 1795 1796 1797

	if (wst->name)
		ret += strlen(wst->name);
	if (wst->uid)
		ret += strlen(wst->uid);
	if (wst->gid)
		ret += strlen(wst->gid);
	if (wst->muid)
		ret += strlen(wst->muid);

1798 1799
	if ((proto_version == p9_proto_2000u) ||
		(proto_version == p9_proto_2000L)) {
1800 1801 1802 1803 1804 1805 1806 1807
		ret += 2+4+4+4;	/* extension[s] n_uid[4] n_gid[4] n_muid[4] */
		if (wst->extension)
			ret += strlen(wst->extension);
	}

	return ret;
}

1808 1809 1810
int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
{
	int err;
1811
	struct p9_req_t *req;
1812 1813
	struct p9_client *clnt;

1814 1815
	err = 0;
	clnt = fid->clnt;
1816
	wst->size = p9_client_statsize(wst, clnt->proto_version);
1817 1818
	p9_debug(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
	p9_debug(P9_DEBUG_9P,
E
Eric Van Hensbergen 已提交
1819 1820 1821 1822 1823
		"     sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
		"     mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
		"     name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
		"     uid=%d gid=%d n_muid=%d\n",
		wst->size, wst->type, wst->dev, wst->qid.type,
R
Randy Dunlap 已提交
1824 1825 1826
		(unsigned long long)wst->qid.path, wst->qid.version, wst->mode,
		wst->atime, wst->mtime, (unsigned long long)wst->length,
		wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
1827 1828 1829
		from_kuid(&init_user_ns, wst->n_uid),
		from_kgid(&init_user_ns, wst->n_gid),
		from_kuid(&init_user_ns, wst->n_muid));
1830

1831
	req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst);
1832 1833 1834
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
1835 1836
	}

1837
	p9_debug(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid);
1838

1839 1840
	p9_free_req(clnt, req);
error:
1841 1842 1843
	return err;
}
EXPORT_SYMBOL(p9_client_wstat);
1844

1845 1846 1847 1848 1849 1850 1851 1852
int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr)
{
	int err;
	struct p9_req_t *req;
	struct p9_client *clnt;

	err = 0;
	clnt = fid->clnt;
1853 1854
	p9_debug(P9_DEBUG_9P, ">>> TSETATTR fid %d\n", fid->fid);
	p9_debug(P9_DEBUG_9P,
1855 1856 1857
		"    valid=%x mode=%x uid=%d gid=%d size=%lld\n"
		"    atime_sec=%lld atime_nsec=%lld\n"
		"    mtime_sec=%lld mtime_nsec=%lld\n",
1858 1859 1860
		p9attr->valid, p9attr->mode,
		from_kuid(&init_user_ns, p9attr->uid),
		from_kgid(&init_user_ns, p9attr->gid),
1861 1862 1863 1864 1865 1866 1867 1868 1869
		p9attr->size, p9attr->atime_sec, p9attr->atime_nsec,
		p9attr->mtime_sec, p9attr->mtime_nsec);

	req = p9_client_rpc(clnt, P9_TSETATTR, "dI", fid->fid, p9attr);

	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}
1870
	p9_debug(P9_DEBUG_9P, "<<< RSETATTR fid %d\n", fid->fid);
1871 1872 1873 1874 1875 1876
	p9_free_req(clnt, req);
error:
	return err;
}
EXPORT_SYMBOL(p9_client_setattr);

1877 1878 1879 1880 1881 1882 1883 1884 1885
int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb)
{
	int err;
	struct p9_req_t *req;
	struct p9_client *clnt;

	err = 0;
	clnt = fid->clnt;

1886
	p9_debug(P9_DEBUG_9P, ">>> TSTATFS fid %d\n", fid->fid);
1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897

	req = p9_client_rpc(clnt, P9_TSTATFS, "d", fid->fid);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type,
		&sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail,
		&sb->files, &sb->ffree, &sb->fsid, &sb->namelen);
	if (err) {
1898
		trace_9p_protocol_dump(clnt, req->rc);
1899 1900 1901 1902
		p9_free_req(clnt, req);
		goto error;
	}

1903
	p9_debug(P9_DEBUG_9P, "<<< RSTATFS fid %d type 0x%lx bsize %ld "
1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914
		"blocks %llu bfree %llu bavail %llu files %llu ffree %llu "
		"fsid %llu namelen %ld\n",
		fid->fid, (long unsigned int)sb->type, (long int)sb->bsize,
		sb->blocks, sb->bfree, sb->bavail, sb->files,  sb->ffree,
		sb->fsid, (long int)sb->namelen);

	p9_free_req(clnt, req);
error:
	return err;
}
EXPORT_SYMBOL(p9_client_statfs);
1915

1916 1917
int p9_client_rename(struct p9_fid *fid,
		     struct p9_fid *newdirfid, const char *name)
1918 1919 1920 1921 1922 1923 1924 1925
{
	int err;
	struct p9_req_t *req;
	struct p9_client *clnt;

	err = 0;
	clnt = fid->clnt;

1926
	p9_debug(P9_DEBUG_9P, ">>> TRENAME fid %d newdirfid %d name %s\n",
1927 1928 1929 1930 1931 1932 1933 1934 1935
			fid->fid, newdirfid->fid, name);

	req = p9_client_rpc(clnt, P9_TRENAME, "dds", fid->fid,
			newdirfid->fid, name);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

1936
	p9_debug(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid);
1937 1938 1939 1940 1941 1942 1943

	p9_free_req(clnt, req);
error:
	return err;
}
EXPORT_SYMBOL(p9_client_rename);

1944 1945 1946 1947 1948 1949 1950 1951 1952 1953
int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
		       struct p9_fid *newdirfid, const char *new_name)
{
	int err;
	struct p9_req_t *req;
	struct p9_client *clnt;

	err = 0;
	clnt = olddirfid->clnt;

1954
	p9_debug(P9_DEBUG_9P, ">>> TRENAMEAT olddirfid %d old name %s"
1955 1956 1957 1958 1959 1960 1961 1962 1963 1964
		   " newdirfid %d new name %s\n", olddirfid->fid, old_name,
		   newdirfid->fid, new_name);

	req = p9_client_rpc(clnt, P9_TRENAMEAT, "dsds", olddirfid->fid,
			    old_name, newdirfid->fid, new_name);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

1965
	p9_debug(P9_DEBUG_9P, "<<< RRENAMEAT newdirfid %d new name %s\n",
1966 1967 1968 1969 1970 1971 1972 1973
		   newdirfid->fid, new_name);

	p9_free_req(clnt, req);
error:
	return err;
}
EXPORT_SYMBOL(p9_client_renameat);

1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992
/*
 * An xattrwalk without @attr_name gives the fid for the lisxattr namespace
 */
struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
				const char *attr_name, u64 *attr_size)
{
	int err;
	struct p9_req_t *req;
	struct p9_client *clnt;
	struct p9_fid *attr_fid;

	err = 0;
	clnt = file_fid->clnt;
	attr_fid = p9_fid_create(clnt);
	if (IS_ERR(attr_fid)) {
		err = PTR_ERR(attr_fid);
		attr_fid = NULL;
		goto error;
	}
1993
	p9_debug(P9_DEBUG_9P,
1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004
		">>> TXATTRWALK file_fid %d, attr_fid %d name %s\n",
		file_fid->fid, attr_fid->fid, attr_name);

	req = p9_client_rpc(clnt, P9_TXATTRWALK, "dds",
			file_fid->fid, attr_fid->fid, attr_name);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}
	err = p9pdu_readf(req->rc, clnt->proto_version, "q", attr_size);
	if (err) {
2005
		trace_9p_protocol_dump(clnt, req->rc);
2006 2007 2008 2009
		p9_free_req(clnt, req);
		goto clunk_fid;
	}
	p9_free_req(clnt, req);
2010
	p9_debug(P9_DEBUG_9P, "<<<  RXATTRWALK fid %d size %llu\n",
2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023
		attr_fid->fid, *attr_size);
	return attr_fid;
clunk_fid:
	p9_client_clunk(attr_fid);
	attr_fid = NULL;
error:
	if (attr_fid && (attr_fid != file_fid))
		p9_fid_destroy(attr_fid);

	return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(p9_client_xattrwalk);

2024 2025 2026 2027 2028 2029 2030
int p9_client_xattrcreate(struct p9_fid *fid, const char *name,
			u64 attr_size, int flags)
{
	int err;
	struct p9_req_t *req;
	struct p9_client *clnt;

2031
	p9_debug(P9_DEBUG_9P,
2032 2033 2034 2035 2036 2037 2038 2039 2040 2041
		">>> TXATTRCREATE fid %d name  %s size %lld flag %d\n",
		fid->fid, name, (long long)attr_size, flags);
	err = 0;
	clnt = fid->clnt;
	req = p9_client_rpc(clnt, P9_TXATTRCREATE, "dsqd",
			fid->fid, name, attr_size, flags);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}
2042
	p9_debug(P9_DEBUG_9P, "<<< RXATTRCREATE fid %d\n", fid->fid);
2043 2044 2045 2046 2047 2048
	p9_free_req(clnt, req);
error:
	return err;
}
EXPORT_SYMBOL_GPL(p9_client_xattrcreate);

2049 2050
int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
{
2051
	int err, rsize, non_zc = 0;
2052 2053 2054 2055
	struct p9_client *clnt;
	struct p9_req_t *req;
	char *dataptr;

2056
	p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n",
2057
				fid->fid, (unsigned long long) offset, count);
2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068

	err = 0;
	clnt = fid->clnt;

	rsize = fid->iounit;
	if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ)
		rsize = clnt->msize - P9_READDIRHDRSZ;

	if (count < rsize)
		rsize = count;

2069 2070 2071 2072 2073 2074 2075 2076
	/* Don't bother zerocopy for small IO (< 1024) */
	if (clnt->trans_mod->zc_request && rsize > 1024) {
		/*
		 * response header len is 11
		 * PDU Header(7) + IO Size (4)
		 */
		req = p9_client_zc_rpc(clnt, P9_TREADDIR, data, NULL, rsize, 0,
				       11, 1, "dqd", fid->fid, offset, rsize);
2077
	} else {
2078
		non_zc = 1;
2079
		req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid,
2080
				    offset, rsize);
2081
	}
2082 2083 2084 2085 2086 2087 2088
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
	if (err) {
2089
		trace_9p_protocol_dump(clnt, req->rc);
2090 2091 2092
		goto free_and_error;
	}

2093
	p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
2094

2095
	if (non_zc)
2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106
		memmove(data, dataptr, count);

	p9_free_req(clnt, req);
	return count;

free_and_error:
	p9_free_req(clnt, req);
error:
	return err;
}
EXPORT_SYMBOL(p9_client_readdir);
M
M. Mohan Kumar 已提交
2107 2108

int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode,
2109
			dev_t rdev, kgid_t gid, struct p9_qid *qid)
M
M. Mohan Kumar 已提交
2110 2111 2112 2113 2114 2115 2116
{
	int err;
	struct p9_client *clnt;
	struct p9_req_t *req;

	err = 0;
	clnt = fid->clnt;
2117
	p9_debug(P9_DEBUG_9P, ">>> TMKNOD fid %d name %s mode %d major %d "
M
M. Mohan Kumar 已提交
2118
		"minor %d\n", fid->fid, name, mode, MAJOR(rdev), MINOR(rdev));
2119
	req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddg", fid->fid, name, mode,
M
M. Mohan Kumar 已提交
2120 2121 2122 2123 2124 2125
		MAJOR(rdev), MINOR(rdev), gid);
	if (IS_ERR(req))
		return PTR_ERR(req);

	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
	if (err) {
2126
		trace_9p_protocol_dump(clnt, req->rc);
M
M. Mohan Kumar 已提交
2127 2128
		goto error;
	}
2129
	p9_debug(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type,
M
M. Mohan Kumar 已提交
2130 2131 2132 2133 2134 2135 2136 2137
				(unsigned long long)qid->path, qid->version);

error:
	p9_free_req(clnt, req);
	return err;

}
EXPORT_SYMBOL(p9_client_mknod_dotl);
M
M. Mohan Kumar 已提交
2138 2139

int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
2140
				kgid_t gid, struct p9_qid *qid)
M
M. Mohan Kumar 已提交
2141 2142 2143 2144 2145 2146 2147
{
	int err;
	struct p9_client *clnt;
	struct p9_req_t *req;

	err = 0;
	clnt = fid->clnt;
2148
	p9_debug(P9_DEBUG_9P, ">>> TMKDIR fid %d name %s mode %d gid %d\n",
2149 2150
		 fid->fid, name, mode, from_kgid(&init_user_ns, gid));
	req = p9_client_rpc(clnt, P9_TMKDIR, "dsdg", fid->fid, name, mode,
M
M. Mohan Kumar 已提交
2151 2152 2153 2154 2155 2156
		gid);
	if (IS_ERR(req))
		return PTR_ERR(req);

	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
	if (err) {
2157
		trace_9p_protocol_dump(clnt, req->rc);
M
M. Mohan Kumar 已提交
2158 2159
		goto error;
	}
2160
	p9_debug(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type,
M
M. Mohan Kumar 已提交
2161 2162 2163 2164 2165 2166 2167 2168
				(unsigned long long)qid->path, qid->version);

error:
	p9_free_req(clnt, req);
	return err;

}
EXPORT_SYMBOL(p9_client_mkdir_dotl);
M
M. Mohan Kumar 已提交
2169 2170 2171 2172 2173 2174 2175 2176 2177

int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status)
{
	int err;
	struct p9_client *clnt;
	struct p9_req_t *req;

	err = 0;
	clnt = fid->clnt;
2178
	p9_debug(P9_DEBUG_9P, ">>> TLOCK fid %d type %i flags %d "
M
M. Mohan Kumar 已提交
2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191
			"start %lld length %lld proc_id %d client_id %s\n",
			fid->fid, flock->type, flock->flags, flock->start,
			flock->length, flock->proc_id, flock->client_id);

	req = p9_client_rpc(clnt, P9_TLOCK, "dbdqqds", fid->fid, flock->type,
				flock->flags, flock->start, flock->length,
					flock->proc_id, flock->client_id);

	if (IS_ERR(req))
		return PTR_ERR(req);

	err = p9pdu_readf(req->rc, clnt->proto_version, "b", status);
	if (err) {
2192
		trace_9p_protocol_dump(clnt, req->rc);
M
M. Mohan Kumar 已提交
2193 2194
		goto error;
	}
2195
	p9_debug(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status);
M
M. Mohan Kumar 已提交
2196 2197 2198 2199 2200 2201
error:
	p9_free_req(clnt, req);
	return err;

}
EXPORT_SYMBOL(p9_client_lock_dotl);
M
M. Mohan Kumar 已提交
2202 2203 2204 2205 2206 2207 2208 2209 2210

int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock)
{
	int err;
	struct p9_client *clnt;
	struct p9_req_t *req;

	err = 0;
	clnt = fid->clnt;
2211
	p9_debug(P9_DEBUG_9P, ">>> TGETLOCK fid %d, type %i start %lld "
M
M. Mohan Kumar 已提交
2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224
		"length %lld proc_id %d client_id %s\n", fid->fid, glock->type,
		glock->start, glock->length, glock->proc_id, glock->client_id);

	req = p9_client_rpc(clnt, P9_TGETLOCK, "dbqqds", fid->fid,  glock->type,
		glock->start, glock->length, glock->proc_id, glock->client_id);

	if (IS_ERR(req))
		return PTR_ERR(req);

	err = p9pdu_readf(req->rc, clnt->proto_version, "bqqds", &glock->type,
			&glock->start, &glock->length, &glock->proc_id,
			&glock->client_id);
	if (err) {
2225
		trace_9p_protocol_dump(clnt, req->rc);
M
M. Mohan Kumar 已提交
2226 2227
		goto error;
	}
2228
	p9_debug(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld "
M
M. Mohan Kumar 已提交
2229 2230 2231 2232 2233 2234 2235
		"proc_id %d client_id %s\n", glock->type, glock->start,
		glock->length, glock->proc_id, glock->client_id);
error:
	p9_free_req(clnt, req);
	return err;
}
EXPORT_SYMBOL(p9_client_getlock_dotl);
2236 2237 2238 2239 2240 2241 2242 2243 2244

int p9_client_readlink(struct p9_fid *fid, char **target)
{
	int err;
	struct p9_client *clnt;
	struct p9_req_t *req;

	err = 0;
	clnt = fid->clnt;
2245
	p9_debug(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid);
2246 2247 2248 2249 2250 2251 2252

	req = p9_client_rpc(clnt, P9_TREADLINK, "d", fid->fid);
	if (IS_ERR(req))
		return PTR_ERR(req);

	err = p9pdu_readf(req->rc, clnt->proto_version, "s", target);
	if (err) {
2253
		trace_9p_protocol_dump(clnt, req->rc);
2254 2255
		goto error;
	}
2256
	p9_debug(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
2257 2258 2259 2260 2261
error:
	p9_free_req(clnt, req);
	return err;
}
EXPORT_SYMBOL(p9_client_readlink);