client.c 52.5 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
#include <linux/sched/signal.h>
36
#include <linux/uaccess.h>
37
#include <linux/uio.h>
38
#include <net/9p/9p.h>
39
#include <linux/parser.h>
D
David Howells 已提交
40
#include <linux/seq_file.h>
41
#include <net/9p/client.h>
42
#include <net/9p/transport.h>
43
#include "protocol.h"
44

45 46 47
#define CREATE_TRACE_POINTS
#include <trace/events/9p.h>

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

enum {
	Opt_msize,
	Opt_trans,
	Opt_legacy,
57
	Opt_version,
58 59 60
	Opt_err,
};

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

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

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

D
David Howells 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
int p9_show_client_options(struct seq_file *m, struct p9_client *clnt)
{
	if (clnt->msize != 8192)
		seq_printf(m, ",msize=%u", clnt->msize);
	seq_printf(m, "trans=%s", clnt->trans_mod->name);

	switch (clnt->proto_version) {
	case p9_proto_legacy:
		seq_puts(m, ",noextend");
		break;
	case p9_proto_2000u:
		seq_puts(m, ",version=9p2000.u");
		break;
	case p9_proto_2000L:
		/* Default */
		break;
	}

	if (clnt->trans_mod->show_options)
		return clnt->trans_mod->show_options(m, clnt);
	return 0;
}
EXPORT_SYMBOL(p9_show_client_options);

S
Simon Derr 已提交
105 106 107 108 109 110 111 112 113 114 115 116 117 118
/*
 * 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;
}


119
/* Interpret mount option for protocol version */
120
static int get_protocol_version(char *s)
121
{
122 123
	int version = -EINVAL;

124
	if (!strcmp(s, "9p2000")) {
125
		version = p9_proto_legacy;
126
		p9_debug(P9_DEBUG_9P, "Protocol version: Legacy\n");
127
	} else if (!strcmp(s, "9p2000.u")) {
128
		version = p9_proto_2000u;
129
		p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
130
	} else if (!strcmp(s, "9p2000.L")) {
131
		version = p9_proto_2000L;
132
		p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.L\n");
133
	} else
134
		pr_info("Unknown protocol version %s\n", s);
135

136 137 138
	return version;
}

139
/**
A
Abhishek Kulkarni 已提交
140 141 142
 * parse_options - parse mount options into client structure
 * @opts: options string passed from mount
 * @clnt: existing v9fs client information
143
 *
144
 * Return 0 upon success, -ERRNO upon failure
145 146
 */

147
static int parse_opts(char *opts, struct p9_client *clnt)
148
{
E
Eric Van Hensbergen 已提交
149
	char *options, *tmp_options;
150 151 152
	char *p;
	substring_t args[MAX_OPT_ARGS];
	int option;
153
	char *s;
154
	int ret = 0;
155

156
	clnt->proto_version = p9_proto_2000L;
157 158
	clnt->msize = 8192;

159 160 161
	if (!opts)
		return 0;

E
Eric Van Hensbergen 已提交
162 163
	tmp_options = kstrdup(opts, GFP_KERNEL);
	if (!tmp_options) {
164 165
		p9_debug(P9_DEBUG_ERROR,
			 "failed to allocate copy of option string\n");
166 167
		return -ENOMEM;
	}
E
Eric Van Hensbergen 已提交
168
	options = tmp_options;
169 170

	while ((p = strsep(&options, ",")) != NULL) {
171
		int token, r;
172 173 174
		if (!*p)
			continue;
		token = match_token(p, tokens, args);
175 176 177
		switch (token) {
		case Opt_msize:
			r = match_int(&args[0], &option);
178
			if (r < 0) {
179 180
				p9_debug(P9_DEBUG_ERROR,
					 "integer field, but no integer?\n");
181
				ret = r;
182 183 184 185 186
				continue;
			}
			clnt->msize = option;
			break;
		case Opt_trans:
187 188 189
			s = match_strdup(&args[0]);
			if (!s) {
				ret = -ENOMEM;
190 191
				p9_debug(P9_DEBUG_ERROR,
					 "problem allocating copy of trans arg\n");
192 193 194 195
				goto free_and_return;
			 }
			clnt->trans_mod = v9fs_get_trans_by_name(s);
			if (clnt->trans_mod == NULL) {
196 197
				pr_info("Could not find request transport: %s\n",
					s);
198
				ret = -EINVAL;
199
				kfree(s);
200 201
				goto free_and_return;
			}
202
			kfree(s);
203 204
			break;
		case Opt_legacy:
205
			clnt->proto_version = p9_proto_legacy;
206
			break;
207
		case Opt_version:
208 209 210
			s = match_strdup(&args[0]);
			if (!s) {
				ret = -ENOMEM;
211 212
				p9_debug(P9_DEBUG_ERROR,
					 "problem allocating copy of version arg\n");
213
				goto free_and_return;
214 215 216 217 218 219 220
			}
			ret = get_protocol_version(s);
			if (ret == -EINVAL) {
				kfree(s);
				goto free_and_return;
			}
			kfree(s);
221 222
			clnt->proto_version = ret;
			break;
223 224 225 226
		default:
			continue;
		}
	}
227

228
free_and_return:
E
Eric Van Hensbergen 已提交
229
	kfree(tmp_options);
230
	return ret;
231 232
}

233
static struct p9_fcall *p9_fcall_alloc(int alloc_msize)
234 235 236 237 238 239 240 241 242 243
{
	struct p9_fcall *fc;
	fc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS);
	if (!fc)
		return NULL;
	fc->capacity = alloc_msize;
	fc->sdata = (char *) fc + sizeof(struct p9_fcall);
	return fc;
}

244 245 246 247 248 249
/**
 * 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 已提交
250
 * request_slots as necessary to accommodate transaction
251 252 253 254 255 256 257 258
 * 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.
 *
 */

259 260
static struct p9_req_t *
p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size)
261 262 263
{
	unsigned long flags;
	int row, col;
264
	struct p9_req_t *req;
265
	int alloc_msize = min(c->msize, max_size);
266 267 268 269 270 271 272 273 274 275 276 277 278 279

	/* 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]) {
280
				pr_err("Couldn't grow tag array\n");
E
Eric Van Hensbergen 已提交
281
				spin_unlock_irqrestore(&c->lock, flags);
282
				return ERR_PTR(-ENOMEM);
283 284 285
			}
			for (col = 0; col < P9_ROW_MAXTAG; col++) {
				c->reqs[row][col].status = REQ_STATUS_IDLE;
286
				c->reqs[row][col].tc = NULL;
287 288 289 290 291 292 293 294
			}
			c->max_tag += P9_ROW_MAXTAG;
		}
		spin_unlock_irqrestore(&c->lock, flags);
	}
	row = tag / P9_ROW_MAXTAG;
	col = tag % P9_ROW_MAXTAG;

295
	req = &c->reqs[row][col];
296
	if (!req->wq) {
297
		req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS);
S
Simon Derr 已提交
298 299
		if (!req->wq)
			goto grow_failed;
300
		init_waitqueue_head(req->wq);
S
Simon Derr 已提交
301 302
	}

303 304 305 306 307 308
	if (!req->tc)
		req->tc = p9_fcall_alloc(alloc_msize);
	if (!req->rc)
		req->rc = p9_fcall_alloc(alloc_msize);
	if (!req->tc || !req->rc)
		goto grow_failed;
309 310 311 312 313 314

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

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

S
Simon Derr 已提交
316 317 318 319 320 321 322 323 324 325
	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);
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
}

/**
 * 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++;

343 344
	if(tag >= c->max_tag) 
		return NULL;
345 346 347 348 349 350 351 352 353 354

	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 已提交
355
 * @c:  v9fs client struct
356 357 358 359 360 361 362 363 364 365 366 367 368 369
 *
 * 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;
	}
370 371 372 373 374
	err = p9_idpool_get(c->tagpool); /* reserve tag 0 */
	if (err < 0) {
		p9_idpool_destroy(c->tagpool);
		goto error;
	}
375 376 377 378 379 380 381
	c->max_tag = 0;
error:
	return err;
}

/**
 * p9_tag_cleanup - cleans up tags structure and reclaims resources
A
Abhishek Kulkarni 已提交
382
 * @c:  v9fs client struct
383 384 385 386 387 388 389 390 391 392 393 394
 *
 * 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) {
395 396 397
				p9_debug(P9_DEBUG_MUX,
					 "Attempting to cleanup non-free tag %d,%d\n",
					 row, col);
398 399 400 401 402 403
				/* TODO: delay execution of cleanup */
				return;
			}
		}
	}

404 405
	if (c->tagpool) {
		p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */
406
		p9_idpool_destroy(c->tagpool);
407
	}
408 409 410

	/* free requests associated with tags */
	for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
411
		for (col = 0; col < P9_ROW_MAXTAG; col++) {
412
			kfree(c->reqs[row][col].wq);
413 414 415
			kfree(c->reqs[row][col].tc);
			kfree(c->reqs[row][col].rc);
		}
416 417 418 419 420
		kfree(c->reqs[row]);
	}
	c->max_tag = 0;
}

421 422 423 424 425 426 427
/**
 * p9_free_req - free a request and clean-up as necessary
 * c: client state
 * r: request to release
 *
 */

428
static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
429
{
430
	int tag = r->tc->tag;
431
	p9_debug(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
432

433
	r->status = REQ_STATUS_IDLE;
434 435
	if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool))
		p9_idpool_put(tag, c->tagpool);
436 437
}

438 439 440 441 442 443
/**
 * p9_client_cb - call back from transport to client
 * c: client state
 * req: request received
 *
 */
444
void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status)
445
{
446
	p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
447 448 449 450 451 452 453 454

	/*
	 * This barrier is needed to make sure any change made to req before
	 * the other thread wakes up will indeed be seen by the waiting side.
	 */
	smp_wmb();
	req->status = status;

455
	wake_up(req->wq);
456
	p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
457 458 459
}
EXPORT_SYMBOL(p9_client_cb);

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 489 490
/**
 * 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;

491 492
	p9_debug(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n",
		 pdu->size, pdu->id, pdu->tag);
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523

	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;
524
	int ecode;
525 526

	err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
527 528 529 530 531
	/*
	 * dump the response from server
	 * This should be after check errors which poplulate pdu_fcall.
	 */
	trace_9p_protocol_dump(c, req->rc);
532
	if (err) {
533
		p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
534 535
		return err;
	}
536 537
	if (type != P9_RERROR && type != P9_RLERROR)
		return 0;
538

539 540 541
	if (!p9_is_proto_dotl(c)) {
		char *ename;
		err = p9pdu_readf(req->rc, c->proto_version, "s?d",
542
				  &ename, &ecode);
543 544
		if (err)
			goto out_err;
545

546
		if (p9_is_proto_dotu(c) && ecode < 512)
547
			err = -ecode;
548

549
		if (!err) {
550
			err = p9_errstr2errno(ename, strlen(ename));
551

552 553
			p9_debug(P9_DEBUG_9P, "<<< RERROR (%d) %s\n",
				 -ecode, ename);
554
		}
555
		kfree(ename);
556 557 558 559
	} else {
		err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
		err = -ecode;

560
		p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
561
	}
562 563

	return err;
564 565

out_err:
566
	p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
567 568

	return err;
569 570
}

571 572 573 574 575 576 577 578 579 580 581 582 583
/**
 * 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,
584
			      struct iov_iter *uidata, int in_hdrlen)
585 586 587 588 589 590 591
{
	int err;
	int ecode;
	int8_t type;
	char *ename = NULL;

	err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
592 593 594 595 596
	/*
	 * dump the response from server
	 * This should be after parse_header which poplulate pdu_fcall.
	 */
	trace_9p_protocol_dump(c, req->rc);
597
	if (err) {
598
		p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
599 600 601 602 603 604 605 606
		return err;
	}

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

	if (!p9_is_proto_dotl(c)) {
		/* Error is reported in string format */
607 608 609
		int len;
		/* 7 = header size for RERROR; */
		int inline_len = in_hdrlen - 7;
610

611 612 613
		len =  req->rc->size - req->rc->offset;
		if (len > (P9_ZC_HDR_SZ - 7)) {
			err = -EFAULT;
614 615 616
			goto out_err;
		}

617 618 619
		ename = &req->rc->sdata[req->rc->offset];
		if (len > inline_len) {
			/* We have error in external buffer */
620 621
			if (!copy_from_iter_full(ename + inline_len,
					     len - inline_len, uidata)) {
622 623
				err = -EFAULT;
				goto out_err;
624 625
			}
		}
626 627 628 629 630 631
		ename = NULL;
		err = p9pdu_readf(req->rc, c->proto_version, "s?d",
				  &ename, &ecode);
		if (err)
			goto out_err;

632
		if (p9_is_proto_dotu(c) && ecode < 512)
633
			err = -ecode;
634

635
		if (!err) {
636 637
			err = p9_errstr2errno(ename, strlen(ename));

638 639
			p9_debug(P9_DEBUG_9P, "<<< RERROR (%d) %s\n",
				 -ecode, ename);
640 641 642 643 644 645
		}
		kfree(ename);
	} else {
		err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
		err = -ecode;

646
		p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
647 648 649 650
	}
	return err;

out_err:
651
	p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
652 653 654
	return err;
}

R
Rob Landley 已提交
655 656 657
static struct p9_req_t *
p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);

658 659
/**
 * p9_client_flush - flush (cancel) a request
A
Abhishek Kulkarni 已提交
660 661
 * @c: client state
 * @oldreq: request to cancel
662
 *
R
Rob Landley 已提交
663
 * This sents a flush for a particular request and links
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
 * 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;

680
	p9_debug(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag);
681 682 683 684 685

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

686 687
	/*
	 * if we haven't received a response for oldreq,
688
	 * remove it from the list
689
	 */
S
Simon Derr 已提交
690
	if (oldreq->status == REQ_STATUS_SENT)
691 692
		if (c->trans_mod->cancelled)
			c->trans_mod->cancelled(c, oldreq);
693 694

	p9_free_req(c, req);
695 696 697
	return 0;
}

698 699 700
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)
701
{
702
	int tag, err;
703 704
	struct p9_req_t *req;

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

707 708 709 710 711 712
	/* 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))
713
		return ERR_PTR(-EIO);
714 715

	tag = P9_NOTAG;
716
	if (type != P9_TVERSION) {
717 718
		tag = p9_idpool_get(c->tagpool);
		if (tag < 0)
719
			return ERR_PTR(-ENOMEM);
720 721
	}

722
	req = p9_tag_alloc(c, tag, req_size);
723 724
	if (IS_ERR(req))
		return req;
725

726 727
	/* marshall the data */
	p9pdu_prepare(req->tc, tag, type);
728
	err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap);
729 730
	if (err)
		goto reterr;
731 732
	p9pdu_finalize(c, req->tc);
	trace_9p_client_req(c, type, tag);
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
	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;
767 768 769

	err = c->trans_mod->request(c, req);
	if (err < 0) {
770
		if (err != -ERESTARTSYS && err != -EFAULT)
771
			c->status = Disconnected;
772 773
		goto reterr;
	}
774
again:
775
	/* Wait for the response */
776
	err = wait_event_killable(*req->wq, req->status >= REQ_STATUS_RCVD);
777

778 779 780 781 782 783
	/*
	 * Make sure our req is coherent with regard to updates in other
	 * threads - echoes to wmb() in the callback
	 */
	smp_rmb();

784 785 786 787 788 789 790
	if ((err == -ERESTARTSYS) && (c->status == Connected)
				  && (type == P9_TFLUSH)) {
		sigpending = 1;
		clear_thread_flag(TIF_SIGPENDING);
		goto again;
	}

791
	if (req->status == REQ_STATUS_ERROR) {
792
		p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
793 794
		err = req->t_err;
	}
795
	if ((err == -ERESTARTSYS) && (c->status == Connected)) {
796
		p9_debug(P9_DEBUG_MUX, "flushing\n");
797 798 799
		sigpending = 1;
		clear_thread_flag(TIF_SIGPENDING);

800 801 802 803 804 805
		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;
806 807 808 809 810 811 812 813 814
	}
	if (sigpending) {
		spin_lock_irqsave(&current->sighand->siglock, flags);
		recalc_sigpending();
		spin_unlock_irqrestore(&current->sighand->siglock, flags);
	}
	if (err < 0)
		goto reterr;

815
	err = p9_check_errors(c, req);
816 817
	trace_9p_client_res(c, type, req->rc->tag, err);
	if (!err)
818
		return req;
819 820
reterr:
	p9_free_req(c, req);
S
Simon Derr 已提交
821
	return ERR_PTR(safe_errno(err));
822 823 824 825 826 827
}

/**
 * p9_client_zc_rpc - issue a request and wait for a response
 * @c: client session
 * @type: type of request
828 829
 * @uidata: destination for zero copy read
 * @uodata: source for zero copy write
830 831 832 833 834 835 836 837
 * @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,
838 839
					 struct iov_iter *uidata,
					 struct iov_iter *uodata,
840
					 int inlen, int olen, int in_hdrlen,
841
					 const char *fmt, ...)
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
{
	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;

	err = c->trans_mod->zc_request(c, req, uidata, uodata,
865
				       inlen, olen, in_hdrlen);
866 867 868
	if (err < 0) {
		if (err == -EIO)
			c->status = Disconnected;
869 870
		if (err != -ERESTARTSYS)
			goto reterr;
871 872
	}
	if (req->status == REQ_STATUS_ERROR) {
873
		p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
874 875 876
		err = req->t_err;
	}
	if ((err == -ERESTARTSYS) && (c->status == Connected)) {
877
		p9_debug(P9_DEBUG_MUX, "flushing\n");
878 879
		sigpending = 1;
		clear_thread_flag(TIF_SIGPENDING);
880

881 882 883 884 885 886 887 888 889 890 891 892 893 894 895
		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;

896
	err = p9_check_zc_errors(c, req, uidata, in_hdrlen);
897 898
	trace_9p_client_res(c, type, req->rc->tag, err);
	if (!err)
899
		return req;
900 901
reterr:
	p9_free_req(c, req);
S
Simon Derr 已提交
902
	return ERR_PTR(safe_errno(err));
903 904
}

905 906
static struct p9_fid *p9_fid_create(struct p9_client *clnt)
{
R
Roel Kluin 已提交
907
	int ret;
908
	struct p9_fid *fid;
909
	unsigned long flags;
910

911
	p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt);
912 913 914 915
	fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
	if (!fid)
		return ERR_PTR(-ENOMEM);

R
Roel Kluin 已提交
916
	ret = p9_idpool_get(clnt->fidpool);
917
	if (ret < 0) {
R
Roel Kluin 已提交
918
		ret = -ENOSPC;
919 920
		goto error;
	}
R
Roel Kluin 已提交
921
	fid->fid = ret;
922 923 924

	memset(&fid->qid, 0, sizeof(struct p9_qid));
	fid->mode = -1;
925
	fid->uid = current_fsuid();
926
	fid->clnt = clnt;
E
Eric Van Hensbergen 已提交
927
	fid->rdir = NULL;
928
	spin_lock_irqsave(&clnt->lock, flags);
929
	list_add(&fid->flist, &clnt->fidlist);
930
	spin_unlock_irqrestore(&clnt->lock, flags);
931 932 933 934 935

	return fid;

error:
	kfree(fid);
R
Roel Kluin 已提交
936
	return ERR_PTR(ret);
937 938 939 940 941
}

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

944
	p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid);
945 946
	clnt = fid->clnt;
	p9_idpool_put(fid->fid, clnt->fidpool);
947
	spin_lock_irqsave(&clnt->lock, flags);
948
	list_del(&fid->flist);
949
	spin_unlock_irqrestore(&clnt->lock, flags);
E
Eric Van Hensbergen 已提交
950
	kfree(fid->rdir);
951 952
	kfree(fid);
}
953

S
stephen hemminger 已提交
954
static int p9_client_version(struct p9_client *c)
955
{
956
	int err = 0;
957 958 959
	struct p9_req_t *req;
	char *version;
	int msize;
960

961 962
	p9_debug(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n",
		 c->msize, c->proto_version);
963 964

	switch (c->proto_version) {
965
	case p9_proto_2000L:
966
		req = p9_client_rpc(c, P9_TVERSION, "ds",
967
					c->msize, "9P2000.L");
968 969 970 971 972 973 974 975 976 977 978 979 980
		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;
	}

981 982
	if (IS_ERR(req))
		return PTR_ERR(req);
983

984
	err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version);
985
	if (err) {
986
		p9_debug(P9_DEBUG_9P, "version error %d\n", err);
987
		trace_9p_protocol_dump(c, req->rc);
988
		goto error;
989
	}
990

991
	p9_debug(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
992 993
	if (!strncmp(version, "9P2000.L", 8))
		c->proto_version = p9_proto_2000L;
994
	else if (!strncmp(version, "9P2000.u", 8))
995 996 997
		c->proto_version = p9_proto_2000u;
	else if (!strncmp(version, "9P2000", 6))
		c->proto_version = p9_proto_legacy;
998 999 1000 1001 1002
	else {
		err = -EREMOTEIO;
		goto error;
	}

1003 1004
	if (msize < c->msize)
		c->msize = msize;
1005 1006

error:
1007 1008
	kfree(version);
	p9_free_req(c, req);
1009 1010 1011 1012 1013 1014 1015 1016

	return err;
}

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

	err = 0;
1020 1021 1022 1023
	clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL);
	if (!clnt)
		return ERR_PTR(-ENOMEM);

1024
	clnt->trans_mod = NULL;
1025
	clnt->trans = NULL;
1026 1027 1028 1029

	client_id = utsname()->nodename;
	memcpy(clnt->name, client_id, strlen(client_id) + 1);

1030 1031 1032
	spin_lock_init(&clnt->lock);
	INIT_LIST_HEAD(&clnt->fidlist);

1033 1034 1035
	err = p9_tag_init(clnt);
	if (err < 0)
		goto free_client;
1036

1037 1038
	err = parse_opts(options, clnt);
	if (err < 0)
1039
		goto destroy_tagpool;
1040

1041 1042 1043
	if (!clnt->trans_mod)
		clnt->trans_mod = v9fs_get_default_trans();

1044 1045
	if (clnt->trans_mod == NULL) {
		err = -EPROTONOSUPPORT;
1046 1047
		p9_debug(P9_DEBUG_ERROR,
			 "No transport defined or default transport\n");
1048
		goto destroy_tagpool;
1049 1050 1051 1052 1053 1054
	}

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

1057 1058
	p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n",
		 clnt, clnt->trans_mod, clnt->msize, clnt->proto_version);
1059

1060 1061
	err = clnt->trans_mod->create(clnt, dev_name, options);
	if (err)
1062
		goto destroy_fidpool;
1063

1064 1065
	if (clnt->msize > clnt->trans_mod->maxsize)
		clnt->msize = clnt->trans_mod->maxsize;
1066

1067
	err = p9_client_version(clnt);
1068
	if (err)
1069
		goto close_trans;
1070 1071 1072

	return clnt;

1073 1074 1075 1076 1077 1078
close_trans:
	clnt->trans_mod->close(clnt);
destroy_fidpool:
	p9_idpool_destroy(clnt->fidpool);
put_trans:
	v9fs_put_trans(clnt->trans_mod);
1079 1080
destroy_tagpool:
	p9_idpool_destroy(clnt->tagpool);
1081 1082
free_client:
	kfree(clnt);
1083 1084 1085 1086 1087 1088 1089 1090
	return ERR_PTR(err);
}
EXPORT_SYMBOL(p9_client_create);

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

1091
	p9_debug(P9_DEBUG_MUX, "clnt %p\n", clnt);
1092

1093 1094
	if (clnt->trans_mod)
		clnt->trans_mod->close(clnt);
1095

1096 1097
	v9fs_put_trans(clnt->trans_mod);

1098
	list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) {
1099
		pr_info("Found fid %d not clunked\n", fid->fid);
1100
		p9_fid_destroy(fid);
1101
	}
1102

1103 1104 1105
	if (clnt->fidpool)
		p9_idpool_destroy(clnt->fidpool);

1106 1107
	p9_tag_cleanup(clnt);

1108 1109 1110 1111 1112 1113
	kfree(clnt);
}
EXPORT_SYMBOL(p9_client_destroy);

void p9_client_disconnect(struct p9_client *clnt)
{
1114
	p9_debug(P9_DEBUG_9P, "clnt %p\n", clnt);
1115
	clnt->status = Disconnected;
1116 1117 1118
}
EXPORT_SYMBOL(p9_client_disconnect);

1119 1120
void p9_client_begin_disconnect(struct p9_client *clnt)
{
1121
	p9_debug(P9_DEBUG_9P, "clnt %p\n", clnt);
1122 1123 1124 1125
	clnt->status = BeginDisconnect;
}
EXPORT_SYMBOL(p9_client_begin_disconnect);

1126
struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
A
Al Viro 已提交
1127
	const char *uname, kuid_t n_uname, const char *aname)
1128
{
1129
	int err = 0;
1130
	struct p9_req_t *req;
1131
	struct p9_fid *fid;
1132
	struct p9_qid qid;
1133 1134


1135 1136
	p9_debug(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
		 afid ? afid->fid : -1, uname, aname);
1137 1138 1139 1140 1141 1142
	fid = p9_fid_create(clnt);
	if (IS_ERR(fid)) {
		err = PTR_ERR(fid);
		fid = NULL;
		goto error;
	}
1143
	fid->uid = n_uname;
1144

1145
	req = p9_client_rpc(clnt, P9_TATTACH, "ddss?u", fid->fid,
1146 1147 1148
			afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
1149 1150 1151
		goto error;
	}

1152
	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
1153
	if (err) {
1154
		trace_9p_protocol_dump(clnt, req->rc);
1155
		p9_free_req(clnt, req);
1156
		goto error;
1157
	}
1158

1159 1160
	p9_debug(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n",
		 qid.type, (unsigned long long)qid.path, qid.version);
1161 1162 1163 1164

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

	p9_free_req(clnt, req);
1165 1166 1167 1168 1169 1170 1171 1172 1173
	return fid;

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

1174
struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
A
Al Viro 已提交
1175
		const unsigned char * const *wnames, int clone)
1176 1177 1178 1179
{
	int err;
	struct p9_client *clnt;
	struct p9_fid *fid;
1180 1181
	struct p9_qid *wqids;
	struct p9_req_t *req;
1182
	uint16_t nwqids, count;
1183 1184

	err = 0;
1185
	wqids = NULL;
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
	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;

1199

1200 1201
	p9_debug(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %ud wname[0] %s\n",
		 oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
1202 1203 1204 1205 1206

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

1210
	err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids);
E
Eric Van Hensbergen 已提交
1211
	if (err) {
1212
		trace_9p_protocol_dump(clnt, req->rc);
E
Eric Van Hensbergen 已提交
1213
		p9_free_req(clnt, req);
1214
		goto clunk_fid;
E
Eric Van Hensbergen 已提交
1215 1216
	}
	p9_free_req(clnt, req);
1217

1218
	p9_debug(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);
1219 1220

	if (nwqids != nwname) {
1221 1222 1223 1224
		err = -ENOENT;
		goto clunk_fid;
	}

1225
	for (count = 0; count < nwqids; count++)
1226
		p9_debug(P9_DEBUG_9P, "<<<     [%d] %x.%llx.%x\n",
R
Randy Dunlap 已提交
1227 1228
			count, wqids[count].type,
			(unsigned long long)wqids[count].path,
1229 1230
			wqids[count].version);

1231
	if (nwname)
1232
		memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid));
1233 1234 1235
	else
		fid->qid = oldfid->qid;

1236
	kfree(wqids);
1237 1238 1239
	return fid;

clunk_fid:
1240
	kfree(wqids);
1241 1242
	p9_client_clunk(fid);
	fid = NULL;
1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255

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;
1256 1257 1258
	struct p9_req_t *req;
	struct p9_qid qid;
	int iounit;
1259 1260

	clnt = fid->clnt;
1261
	p9_debug(P9_DEBUG_9P, ">>> %s fid %d mode %d\n",
M
M. Mohan Kumar 已提交
1262 1263
		p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN", fid->fid, mode);
	err = 0;
1264 1265 1266 1267

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

M
M. Mohan Kumar 已提交
1268 1269 1270 1271
	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);
1272 1273 1274
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
1275 1276
	}

1277
	err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
E
Eric Van Hensbergen 已提交
1278
	if (err) {
1279
		trace_9p_protocol_dump(clnt, req->rc);
E
Eric Van Hensbergen 已提交
1280 1281
		goto free_and_error;
	}
1282

1283
	p9_debug(P9_DEBUG_9P, "<<< %s qid %x.%llx.%x iounit %x\n",
M
M. Mohan Kumar 已提交
1284 1285
		p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN",  qid.type,
		(unsigned long long)qid.path, qid.version, iounit);
1286 1287

	fid->mode = mode;
1288
	fid->iounit = iounit;
1289

E
Eric Van Hensbergen 已提交
1290 1291
free_and_error:
	p9_free_req(clnt, req);
1292
error:
1293 1294 1295 1296
	return err;
}
EXPORT_SYMBOL(p9_client_open);

A
Al Viro 已提交
1297
int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32 mode,
1298
		kgid_t gid, struct p9_qid *qid)
1299 1300 1301 1302 1303 1304
{
	int err = 0;
	struct p9_client *clnt;
	struct p9_req_t *req;
	int iounit;

1305
	p9_debug(P9_DEBUG_9P,
1306
			">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n",
1307 1308
			ofid->fid, name, flags, mode,
		 	from_kgid(&init_user_ns, gid));
1309 1310 1311 1312 1313
	clnt = ofid->clnt;

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

1314
	req = p9_client_rpc(clnt, P9_TLCREATE, "dsddg", ofid->fid, name, flags,
1315 1316 1317 1318 1319 1320 1321 1322
			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) {
1323
		trace_9p_protocol_dump(clnt, req->rc);
1324 1325 1326
		goto free_and_error;
	}

1327
	p9_debug(P9_DEBUG_9P, "<<< RLCREATE qid %x.%llx.%x iounit %x\n",
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341
			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);

A
Al Viro 已提交
1342
int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode,
1343 1344 1345 1346
		     char *extension)
{
	int err;
	struct p9_client *clnt;
1347 1348 1349
	struct p9_req_t *req;
	struct p9_qid qid;
	int iounit;
1350

1351
	p9_debug(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n",
1352
						fid->fid, name, perm, mode);
1353 1354 1355 1356 1357 1358
	err = 0;
	clnt = fid->clnt;

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

1359 1360 1361 1362 1363
	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;
1364 1365
	}

1366
	err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
E
Eric Van Hensbergen 已提交
1367
	if (err) {
1368
		trace_9p_protocol_dump(clnt, req->rc);
E
Eric Van Hensbergen 已提交
1369 1370
		goto free_and_error;
	}
1371

1372
	p9_debug(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
R
Randy Dunlap 已提交
1373 1374 1375
				qid.type,
				(unsigned long long)qid.path,
				qid.version, iounit);
1376 1377

	fid->mode = mode;
1378
	fid->iounit = iounit;
1379

E
Eric Van Hensbergen 已提交
1380 1381
free_and_error:
	p9_free_req(clnt, req);
1382
error:
1383 1384 1385 1386
	return err;
}
EXPORT_SYMBOL(p9_client_fcreate);

A
Al Viro 已提交
1387 1388
int p9_client_symlink(struct p9_fid *dfid, const char *name,
		const char *symtgt, kgid_t gid, struct p9_qid *qid)
1389 1390 1391 1392 1393
{
	int err = 0;
	struct p9_client *clnt;
	struct p9_req_t *req;

1394
	p9_debug(P9_DEBUG_9P, ">>> TSYMLINK dfid %d name %s  symtgt %s\n",
1395 1396 1397
			dfid->fid, name, symtgt);
	clnt = dfid->clnt;

1398
	req = p9_client_rpc(clnt, P9_TSYMLINK, "dssg", dfid->fid, name, symtgt,
1399 1400 1401 1402 1403 1404 1405 1406
			gid);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
	if (err) {
1407
		trace_9p_protocol_dump(clnt, req->rc);
1408 1409 1410
		goto free_and_error;
	}

1411
	p9_debug(P9_DEBUG_9P, "<<< RSYMLINK qid %x.%llx.%x\n",
1412 1413 1414 1415 1416 1417 1418 1419 1420
			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);

A
Al Viro 已提交
1421
int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, const char *newname)
1422 1423 1424 1425
{
	struct p9_client *clnt;
	struct p9_req_t *req;

1426
	p9_debug(P9_DEBUG_9P, ">>> TLINK dfid %d oldfid %d newname %s\n",
1427 1428 1429 1430 1431 1432 1433
			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);

1434
	p9_debug(P9_DEBUG_9P, "<<< RLINK\n");
1435 1436 1437 1438 1439
	p9_free_req(clnt, req);
	return 0;
}
EXPORT_SYMBOL(p9_client_link);

1440
int p9_client_fsync(struct p9_fid *fid, int datasync)
1441 1442 1443 1444 1445
{
	int err;
	struct p9_client *clnt;
	struct p9_req_t *req;

1446
	p9_debug(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n",
1447
			fid->fid, datasync);
1448 1449 1450
	err = 0;
	clnt = fid->clnt;

1451
	req = p9_client_rpc(clnt, P9_TFSYNC, "dd", fid->fid, datasync);
1452 1453 1454 1455 1456
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

1457
	p9_debug(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid);
1458 1459 1460 1461 1462 1463 1464 1465

	p9_free_req(clnt, req);

error:
	return err;
}
EXPORT_SYMBOL(p9_client_fsync);

1466 1467 1468 1469
int p9_client_clunk(struct p9_fid *fid)
{
	int err;
	struct p9_client *clnt;
1470
	struct p9_req_t *req;
1471
	int retries = 0;
1472

1473
	if (!fid) {
1474 1475
		pr_warn("%s (%d): Trying to clunk with NULL fid\n",
			__func__, task_pid_nr(current));
1476 1477 1478 1479
		dump_stack();
		return 0;
	}

1480 1481 1482
again:
	p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n", fid->fid,
								retries);
1483 1484 1485
	err = 0;
	clnt = fid->clnt;

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

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

1494 1495
	p9_free_req(clnt, req);
error:
1496 1497
	/*
	 * Fid is not valid even after a failed clunk
1498 1499
	 * If interrupted, retry once then give up and
	 * leak fid until umount.
1500
	 */
1501 1502 1503 1504 1505
	if (err == -ERESTARTSYS) {
		if (retries++ == 0)
			goto again;
	} else
		p9_fid_destroy(fid);
1506 1507 1508 1509 1510 1511 1512 1513
	return err;
}
EXPORT_SYMBOL(p9_client_clunk);

int p9_client_remove(struct p9_fid *fid)
{
	int err;
	struct p9_client *clnt;
1514
	struct p9_req_t *req;
1515

1516
	p9_debug(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid);
1517 1518 1519
	err = 0;
	clnt = fid->clnt;

1520 1521 1522 1523
	req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
1524 1525
	}

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

1528 1529
	p9_free_req(clnt, req);
error:
1530 1531 1532 1533
	if (err == -ERESTARTSYS)
		p9_client_clunk(fid);
	else
		p9_fid_destroy(fid);
1534 1535 1536 1537
	return err;
}
EXPORT_SYMBOL(p9_client_remove);

1538 1539 1540 1541 1542 1543
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;

1544
	p9_debug(P9_DEBUG_9P, ">>> TUNLINKAT fid %d %s %d\n",
1545 1546 1547 1548 1549 1550 1551 1552
		   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;
	}
1553
	p9_debug(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name);
1554 1555 1556 1557 1558 1559 1560

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

1561
int
1562
p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
1563
{
1564
	struct p9_client *clnt = fid->clnt;
1565
	struct p9_req_t *req;
1566
	int total = 0;
1567
	*err = 0;
1568

1569
	p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n",
1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601
		   fid->fid, (unsigned long long) offset, (int)iov_iter_count(to));

	while (iov_iter_count(to)) {
		int count = iov_iter_count(to);
		int rsize, non_zc = 0;
		char *dataptr;
			
		rsize = fid->iounit;
		if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
			rsize = clnt->msize - P9_IOHDRSZ;

		if (count < rsize)
			rsize = count;

		/* 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_TREAD, to, NULL, rsize,
					       0, 11, "dqd", fid->fid,
					       offset, rsize);
		} else {
			non_zc = 1;
			req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
					    rsize);
		}
		if (IS_ERR(req)) {
			*err = PTR_ERR(req);
			break;
		}
1602

1603 1604 1605 1606 1607 1608 1609
		*err = p9pdu_readf(req->rc, clnt->proto_version,
				   "D", &count, &dataptr);
		if (*err) {
			trace_9p_protocol_dump(clnt, req->rc);
			p9_free_req(clnt, req);
			break;
		}
1610 1611 1612 1613
		if (rsize < count) {
			pr_err("bogus RREAD count (%d > %d)\n", count, rsize);
			count = rsize;
		}
1614

1615 1616 1617 1618 1619
		p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
		if (!count) {
			p9_free_req(clnt, req);
			break;
		}
1620

1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635
		if (non_zc) {
			int n = copy_to_iter(dataptr, count, to);
			total += n;
			offset += n;
			if (n != count) {
				*err = -EFAULT;
				p9_free_req(clnt, req);
				break;
			}
		} else {
			iov_iter_advance(to, count);
			total += count;
			offset += count;
		}
		p9_free_req(clnt, req);
1636
	}
1637
	return total;
1638
}
1639
EXPORT_SYMBOL(p9_client_read);
1640 1641

int
1642
p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
1643
{
1644
	struct p9_client *clnt = fid->clnt;
1645
	struct p9_req_t *req;
1646
	int total = 0;
1647
	*err = 0;
1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674

	p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %zd\n",
				fid->fid, (unsigned long long) offset,
				iov_iter_count(from));

	while (iov_iter_count(from)) {
		int count = iov_iter_count(from);
		int rsize = fid->iounit;
		if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
			rsize = clnt->msize - P9_IOHDRSZ;

		if (count < rsize)
			rsize = count;

		/* Don't bother zerocopy for small IO (< 1024) */
		if (clnt->trans_mod->zc_request && rsize > 1024) {
			req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, from, 0,
					       rsize, P9_ZC_HDR_SZ, "dqd",
					       fid->fid, offset, rsize);
		} else {
			req = p9_client_rpc(clnt, P9_TWRITE, "dqV", fid->fid,
						    offset, rsize, from);
		}
		if (IS_ERR(req)) {
			*err = PTR_ERR(req);
			break;
		}
1675

1676 1677 1678 1679
		*err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count);
		if (*err) {
			trace_9p_protocol_dump(clnt, req->rc);
			p9_free_req(clnt, req);
1680
			break;
1681
		}
1682 1683 1684 1685
		if (rsize < count) {
			pr_err("bogus RWRITE count (%d > %d)\n", count, rsize);
			count = rsize;
		}
1686

1687
		p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
1688

1689 1690 1691 1692
		p9_free_req(clnt, req);
		iov_iter_advance(from, count);
		total += count;
		offset += count;
E
Eric Van Hensbergen 已提交
1693
	}
1694
	return total;
1695
}
1696
EXPORT_SYMBOL(p9_client_write);
1697

1698
struct p9_wstat *p9_client_stat(struct p9_fid *fid)
1699
{
1700 1701 1702 1703 1704
	int err;
	struct p9_client *clnt;
	struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL);
	struct p9_req_t *req;
	u16 ignored;
1705

1706
	p9_debug(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid);
1707 1708 1709 1710

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

1711 1712 1713
	err = 0;
	clnt = fid->clnt;

1714 1715 1716
	req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
1717 1718 1719
		goto error;
	}

1720
	err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret);
E
Eric Van Hensbergen 已提交
1721
	if (err) {
1722
		trace_9p_protocol_dump(clnt, req->rc);
1723 1724
		p9_free_req(clnt, req);
		goto error;
E
Eric Van Hensbergen 已提交
1725
	}
1726

1727
	p9_debug(P9_DEBUG_9P,
E
Eric Van Hensbergen 已提交
1728 1729 1730 1731
		"<<< 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",
1732
		ret->size, ret->type, ret->dev, ret->qid.type,
R
Randy Dunlap 已提交
1733 1734 1735
		(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,
1736 1737 1738
		from_kuid(&init_user_ns, ret->n_uid),
		from_kgid(&init_user_ns, ret->n_gid),
		from_kuid(&init_user_ns, ret->n_muid));
1739

1740 1741 1742
	p9_free_req(clnt, req);
	return ret;

1743
error:
1744 1745
	kfree(ret);
	return ERR_PTR(err);
1746 1747 1748
}
EXPORT_SYMBOL(p9_client_stat);

1749 1750 1751 1752 1753 1754 1755 1756 1757
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;

1758
	p9_debug(P9_DEBUG_9P, ">>> TGETATTR fid %d, request_mask %lld\n",
1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774
							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) {
1775
		trace_9p_protocol_dump(clnt, req->rc);
1776 1777 1778 1779
		p9_free_req(clnt, req);
		goto error;
	}

1780
	p9_debug(P9_DEBUG_9P,
1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791
		"<<< 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,
1792 1793 1794 1795
		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,
1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809
		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);

1810
static int p9_client_statsize(struct p9_wstat *wst, int proto_version)
1811 1812 1813
{
	int ret;

1814
	/* NOTE: size shouldn't include its own length */
1815 1816 1817
	/* size[2] type[2] dev[4] qid[13] */
	/* mode[4] atime[4] mtime[4] length[8]*/
	/* name[s] uid[s] gid[s] muid[s] */
1818
	ret = 2+4+13+4+4+4+8+2+2+2+2;
1819 1820 1821 1822 1823 1824 1825 1826 1827 1828

	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);

1829 1830
	if ((proto_version == p9_proto_2000u) ||
		(proto_version == p9_proto_2000L)) {
1831 1832 1833 1834 1835 1836 1837 1838
		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;
}

1839 1840 1841
int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
{
	int err;
1842
	struct p9_req_t *req;
1843 1844
	struct p9_client *clnt;

1845 1846
	err = 0;
	clnt = fid->clnt;
1847
	wst->size = p9_client_statsize(wst, clnt->proto_version);
1848 1849
	p9_debug(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
	p9_debug(P9_DEBUG_9P,
E
Eric Van Hensbergen 已提交
1850 1851 1852 1853 1854
		"     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 已提交
1855 1856 1857
		(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,
1858 1859 1860
		from_kuid(&init_user_ns, wst->n_uid),
		from_kgid(&init_user_ns, wst->n_gid),
		from_kuid(&init_user_ns, wst->n_muid));
1861

1862
	req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst);
1863 1864 1865
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
1866 1867
	}

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

1870 1871
	p9_free_req(clnt, req);
error:
1872 1873 1874
	return err;
}
EXPORT_SYMBOL(p9_client_wstat);
1875

1876 1877 1878 1879 1880 1881 1882 1883
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;
1884 1885
	p9_debug(P9_DEBUG_9P, ">>> TSETATTR fid %d\n", fid->fid);
	p9_debug(P9_DEBUG_9P,
1886 1887 1888
		"    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",
1889 1890 1891
		p9attr->valid, p9attr->mode,
		from_kuid(&init_user_ns, p9attr->uid),
		from_kgid(&init_user_ns, p9attr->gid),
1892 1893 1894 1895 1896 1897 1898 1899 1900
		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;
	}
1901
	p9_debug(P9_DEBUG_9P, "<<< RSETATTR fid %d\n", fid->fid);
1902 1903 1904 1905 1906 1907
	p9_free_req(clnt, req);
error:
	return err;
}
EXPORT_SYMBOL(p9_client_setattr);

1908 1909 1910 1911 1912 1913 1914 1915 1916
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;

1917
	p9_debug(P9_DEBUG_9P, ">>> TSTATFS fid %d\n", fid->fid);
1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928

	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) {
1929
		trace_9p_protocol_dump(clnt, req->rc);
1930 1931 1932 1933
		p9_free_req(clnt, req);
		goto error;
	}

1934
	p9_debug(P9_DEBUG_9P, "<<< RSTATFS fid %d type 0x%lx bsize %ld "
1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
		"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);
1946

1947 1948
int p9_client_rename(struct p9_fid *fid,
		     struct p9_fid *newdirfid, const char *name)
1949 1950 1951 1952 1953 1954 1955 1956
{
	int err;
	struct p9_req_t *req;
	struct p9_client *clnt;

	err = 0;
	clnt = fid->clnt;

1957
	p9_debug(P9_DEBUG_9P, ">>> TRENAME fid %d newdirfid %d name %s\n",
1958 1959 1960 1961 1962 1963 1964 1965 1966
			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;
	}

1967
	p9_debug(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid);
1968 1969 1970 1971 1972 1973 1974

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

1975 1976 1977 1978 1979 1980 1981 1982 1983 1984
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;

1985
	p9_debug(P9_DEBUG_9P, ">>> TRENAMEAT olddirfid %d old name %s"
1986 1987 1988 1989 1990 1991 1992 1993 1994 1995
		   " 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;
	}

1996
	p9_debug(P9_DEBUG_9P, "<<< RRENAMEAT newdirfid %d new name %s\n",
1997 1998 1999 2000 2001 2002 2003 2004
		   newdirfid->fid, new_name);

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

2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023
/*
 * 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;
	}
2024
	p9_debug(P9_DEBUG_9P,
2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035
		">>> 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) {
2036
		trace_9p_protocol_dump(clnt, req->rc);
2037 2038 2039 2040
		p9_free_req(clnt, req);
		goto clunk_fid;
	}
	p9_free_req(clnt, req);
2041
	p9_debug(P9_DEBUG_9P, "<<<  RXATTRWALK fid %d size %llu\n",
2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054
		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);

2055 2056 2057 2058 2059 2060 2061
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;

2062
	p9_debug(P9_DEBUG_9P,
2063 2064 2065 2066 2067 2068 2069 2070 2071 2072
		">>> 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;
	}
2073
	p9_debug(P9_DEBUG_9P, "<<< RXATTRCREATE fid %d\n", fid->fid);
2074 2075 2076 2077 2078 2079
	p9_free_req(clnt, req);
error:
	return err;
}
EXPORT_SYMBOL_GPL(p9_client_xattrcreate);

2080 2081
int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
{
2082
	int err, rsize, non_zc = 0;
2083 2084 2085
	struct p9_client *clnt;
	struct p9_req_t *req;
	char *dataptr;
2086 2087 2088 2089
	struct kvec kv = {.iov_base = data, .iov_len = count};
	struct iov_iter to;

	iov_iter_kvec(&to, READ | ITER_KVEC, &kv, 1, count);
2090

2091
	p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n",
2092
				fid->fid, (unsigned long long) offset, count);
2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103

	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;

2104 2105 2106 2107 2108 2109
	/* 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)
		 */
2110 2111
		req = p9_client_zc_rpc(clnt, P9_TREADDIR, &to, NULL, rsize, 0,
				       11, "dqd", fid->fid, offset, rsize);
2112
	} else {
2113
		non_zc = 1;
2114
		req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid,
2115
				    offset, rsize);
2116
	}
2117 2118 2119 2120 2121 2122 2123
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
	if (err) {
2124
		trace_9p_protocol_dump(clnt, req->rc);
2125 2126
		goto free_and_error;
	}
A
Al Viro 已提交
2127 2128 2129 2130
	if (rsize < count) {
		pr_err("bogus RREADDIR count (%d > %d)\n", count, rsize);
		count = rsize;
	}
2131

2132
	p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
2133

2134
	if (non_zc)
2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145
		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 已提交
2146

A
Al Viro 已提交
2147
int p9_client_mknod_dotl(struct p9_fid *fid, const char *name, int mode,
2148
			dev_t rdev, kgid_t gid, struct p9_qid *qid)
M
M. Mohan Kumar 已提交
2149 2150 2151 2152 2153 2154 2155
{
	int err;
	struct p9_client *clnt;
	struct p9_req_t *req;

	err = 0;
	clnt = fid->clnt;
2156
	p9_debug(P9_DEBUG_9P, ">>> TMKNOD fid %d name %s mode %d major %d "
M
M. Mohan Kumar 已提交
2157
		"minor %d\n", fid->fid, name, mode, MAJOR(rdev), MINOR(rdev));
2158
	req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddg", fid->fid, name, mode,
M
M. Mohan Kumar 已提交
2159 2160 2161 2162 2163 2164
		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) {
2165
		trace_9p_protocol_dump(clnt, req->rc);
M
M. Mohan Kumar 已提交
2166 2167
		goto error;
	}
2168
	p9_debug(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type,
M
M. Mohan Kumar 已提交
2169 2170 2171 2172 2173 2174 2175 2176
				(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 已提交
2177

A
Al Viro 已提交
2178
int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode,
2179
				kgid_t gid, struct p9_qid *qid)
M
M. Mohan Kumar 已提交
2180 2181 2182 2183 2184 2185 2186
{
	int err;
	struct p9_client *clnt;
	struct p9_req_t *req;

	err = 0;
	clnt = fid->clnt;
2187
	p9_debug(P9_DEBUG_9P, ">>> TMKDIR fid %d name %s mode %d gid %d\n",
2188 2189
		 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 已提交
2190 2191 2192 2193 2194 2195
		gid);
	if (IS_ERR(req))
		return PTR_ERR(req);

	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
	if (err) {
2196
		trace_9p_protocol_dump(clnt, req->rc);
M
M. Mohan Kumar 已提交
2197 2198
		goto error;
	}
2199
	p9_debug(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type,
M
M. Mohan Kumar 已提交
2200 2201 2202 2203 2204 2205 2206 2207
				(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 已提交
2208 2209 2210 2211 2212 2213 2214 2215 2216

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;
2217
	p9_debug(P9_DEBUG_9P, ">>> TLOCK fid %d type %i flags %d "
M
M. Mohan Kumar 已提交
2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230
			"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) {
2231
		trace_9p_protocol_dump(clnt, req->rc);
M
M. Mohan Kumar 已提交
2232 2233
		goto error;
	}
2234
	p9_debug(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status);
M
M. Mohan Kumar 已提交
2235 2236 2237 2238 2239 2240
error:
	p9_free_req(clnt, req);
	return err;

}
EXPORT_SYMBOL(p9_client_lock_dotl);
M
M. Mohan Kumar 已提交
2241 2242 2243 2244 2245 2246 2247 2248 2249

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;
2250
	p9_debug(P9_DEBUG_9P, ">>> TGETLOCK fid %d, type %i start %lld "
M
M. Mohan Kumar 已提交
2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263
		"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) {
2264
		trace_9p_protocol_dump(clnt, req->rc);
M
M. Mohan Kumar 已提交
2265 2266
		goto error;
	}
2267
	p9_debug(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld "
M
M. Mohan Kumar 已提交
2268 2269 2270 2271 2272 2273 2274
		"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);
2275 2276 2277 2278 2279 2280 2281 2282 2283

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;
2284
	p9_debug(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid);
2285 2286 2287 2288 2289 2290 2291

	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) {
2292
		trace_9p_protocol_dump(clnt, req->rc);
2293 2294
		goto error;
	}
2295
	p9_debug(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
2296 2297 2298 2299 2300
error:
	p9_free_req(clnt, req);
	return err;
}
EXPORT_SYMBOL(p9_client_readlink);