Blame view

net/9p/protocol.c 12.8 KB
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  /*
   * net/9p/protocol.c
   *
   * 9P Protocol Support Code
   *
   *  Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
   *
   *  Base on code from Anthony Liguori <aliguori@us.ibm.com>
   *  Copyright (C) 2008 by IBM, Corp.
   *
   *  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
   *
   */
  
  #include <linux/module.h>
  #include <linux/errno.h>
01b0c5cfb   Thiago Farina   net/9p/protocol.c...
30
  #include <linux/kernel.h>
51a87c552   Eric Van Hensbergen   9p: rework client...
31
  #include <linux/uaccess.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
32
  #include <linux/slab.h>
e7f4b8f1a   Eric Van Hensbergen   9p: Improve debug...
33
  #include <linux/sched.h>
01b0c5cfb   Thiago Farina   net/9p/protocol.c...
34
  #include <linux/stddef.h>
beeebc92e   Eric Van Hensbergen   9p: fix endian is...
35
  #include <linux/types.h>
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
36
37
38
  #include <net/9p/9p.h>
  #include <net/9p/client.h>
  #include "protocol.h"
348b59012   Aneesh Kumar K.V   net/9p: Convert n...
39
  #include <trace/events/9p.h>
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
40
  static int
342fee1d5   Sripathi Kodi   9P2010.L handshak...
41
  p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
42
43
44
45
46
47
48
49
50
51
  
  void p9stat_free(struct p9_wstat *stbuf)
  {
  	kfree(stbuf->name);
  	kfree(stbuf->uid);
  	kfree(stbuf->gid);
  	kfree(stbuf->muid);
  	kfree(stbuf->extension);
  }
  EXPORT_SYMBOL(p9stat_free);
abfa034e4   Aneesh Kumar K.V   fs/9p: Update zer...
52
  size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size)
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
53
  {
01b0c5cfb   Thiago Farina   net/9p/protocol.c...
54
  	size_t len = min(pdu->size - pdu->offset, size);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
55
56
57
58
59
60
61
  	memcpy(data, &pdu->sdata[pdu->offset], len);
  	pdu->offset += len;
  	return size - len;
  }
  
  static size_t pdu_write(struct p9_fcall *pdu, const void *data, size_t size)
  {
01b0c5cfb   Thiago Farina   net/9p/protocol.c...
62
  	size_t len = min(pdu->capacity - pdu->size, size);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
63
64
65
66
  	memcpy(&pdu->sdata[pdu->size], data, len);
  	pdu->size += len;
  	return size - len;
  }
51a87c552   Eric Van Hensbergen   9p: rework client...
67
68
69
  static size_t
  pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size)
  {
01b0c5cfb   Thiago Farina   net/9p/protocol.c...
70
  	size_t len = min(pdu->capacity - pdu->size, size);
7b3bb3fe1   Aneesh Kumar K.V   net/9p: Return er...
71
72
  	if (copy_from_user(&pdu->sdata[pdu->size], udata, len))
  		len = 0;
51a87c552   Eric Van Hensbergen   9p: rework client...
73
74
75
76
  
  	pdu->size += len;
  	return size - len;
  }
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
77
78
79
80
81
82
83
84
85
86
87
  /*
  	b - int8_t
  	w - int16_t
  	d - int32_t
  	q - int64_t
  	s - string
  	S - stat
  	Q - qid
  	D - data blob (int32_t size followed by void *, results are not freed)
  	T - array of strings (int16_t count, followed by strings)
  	R - array of qids (int16_t count, followed by qids)
f08531220   Sripathi Kodi   9p: getattr clien...
88
  	A - stat for 9p2000.L (p9_stat_dotl)
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
89
90
91
92
  	? - if optional = 1, continue parsing
  */
  
  static int
342fee1d5   Sripathi Kodi   9P2010.L handshak...
93
94
  p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
  	va_list ap)
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  {
  	const char *ptr;
  	int errcode = 0;
  
  	for (ptr = fmt; *ptr; ptr++) {
  		switch (*ptr) {
  		case 'b':{
  				int8_t *val = va_arg(ap, int8_t *);
  				if (pdu_read(pdu, val, sizeof(*val))) {
  					errcode = -EFAULT;
  					break;
  				}
  			}
  			break;
  		case 'w':{
  				int16_t *val = va_arg(ap, int16_t *);
beeebc92e   Eric Van Hensbergen   9p: fix endian is...
111
112
  				__le16 le_val;
  				if (pdu_read(pdu, &le_val, sizeof(le_val))) {
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
113
114
115
  					errcode = -EFAULT;
  					break;
  				}
beeebc92e   Eric Van Hensbergen   9p: fix endian is...
116
  				*val = le16_to_cpu(le_val);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
117
118
119
120
  			}
  			break;
  		case 'd':{
  				int32_t *val = va_arg(ap, int32_t *);
beeebc92e   Eric Van Hensbergen   9p: fix endian is...
121
122
  				__le32 le_val;
  				if (pdu_read(pdu, &le_val, sizeof(le_val))) {
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
123
124
125
  					errcode = -EFAULT;
  					break;
  				}
beeebc92e   Eric Van Hensbergen   9p: fix endian is...
126
  				*val = le32_to_cpu(le_val);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
127
128
129
130
  			}
  			break;
  		case 'q':{
  				int64_t *val = va_arg(ap, int64_t *);
beeebc92e   Eric Van Hensbergen   9p: fix endian is...
131
132
  				__le64 le_val;
  				if (pdu_read(pdu, &le_val, sizeof(le_val))) {
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
133
134
135
  					errcode = -EFAULT;
  					break;
  				}
beeebc92e   Eric Van Hensbergen   9p: fix endian is...
136
  				*val = le64_to_cpu(le_val);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
137
138
139
  			}
  			break;
  		case 's':{
e45c5405e   Eric Van Hensbergen   9p: fix sparse wa...
140
  				char **sptr = va_arg(ap, char **);
219fd58be   M. Mohan Kumar   net/9p: Use prope...
141
  				uint16_t len;
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
142

342fee1d5   Sripathi Kodi   9P2010.L handshak...
143
144
  				errcode = p9pdu_readf(pdu, proto_version,
  								"w", &len);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
145
146
  				if (errcode)
  					break;
eeff66ef6   Aneesh Kumar K.V   net/9p: Convert t...
147
  				*sptr = kmalloc(len + 1, GFP_NOFS);
e45c5405e   Eric Van Hensbergen   9p: fix sparse wa...
148
  				if (*sptr == NULL) {
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
149
150
151
  					errcode = -EFAULT;
  					break;
  				}
219fd58be   M. Mohan Kumar   net/9p: Use prope...
152
  				if (pdu_read(pdu, *sptr, len)) {
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
153
  					errcode = -EFAULT;
e45c5405e   Eric Van Hensbergen   9p: fix sparse wa...
154
155
  					kfree(*sptr);
  					*sptr = NULL;
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
156
  				} else
219fd58be   M. Mohan Kumar   net/9p: Use prope...
157
  					(*sptr)[len] = 0;
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
158
159
160
161
162
  			}
  			break;
  		case 'Q':{
  				struct p9_qid *qid =
  				    va_arg(ap, struct p9_qid *);
342fee1d5   Sripathi Kodi   9P2010.L handshak...
163
  				errcode = p9pdu_readf(pdu, proto_version, "bdq",
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
164
165
166
167
168
169
170
  						      &qid->type, &qid->version,
  						      &qid->path);
  			}
  			break;
  		case 'S':{
  				struct p9_wstat *stbuf =
  				    va_arg(ap, struct p9_wstat *);
f0a0ac2ee   Eric Van Hensbergen   9p: fix oops in p...
171
  				memset(stbuf, 0, sizeof(struct p9_wstat));
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
172
  				stbuf->n_uid = stbuf->n_gid = stbuf->n_muid =
f0a0ac2ee   Eric Van Hensbergen   9p: fix oops in p...
173
  									-1;
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
174
  				errcode =
342fee1d5   Sripathi Kodi   9P2010.L handshak...
175
  				    p9pdu_readf(pdu, proto_version,
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
  						"wwdQdddqssss?sddd",
  						&stbuf->size, &stbuf->type,
  						&stbuf->dev, &stbuf->qid,
  						&stbuf->mode, &stbuf->atime,
  						&stbuf->mtime, &stbuf->length,
  						&stbuf->name, &stbuf->uid,
  						&stbuf->gid, &stbuf->muid,
  						&stbuf->extension,
  						&stbuf->n_uid, &stbuf->n_gid,
  						&stbuf->n_muid);
  				if (errcode)
  					p9stat_free(stbuf);
  			}
  			break;
  		case 'D':{
219fd58be   M. Mohan Kumar   net/9p: Use prope...
191
  				uint32_t *count = va_arg(ap, uint32_t *);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
192
193
194
  				void **data = va_arg(ap, void **);
  
  				errcode =
342fee1d5   Sripathi Kodi   9P2010.L handshak...
195
  				    p9pdu_readf(pdu, proto_version, "d", count);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
196
197
  				if (!errcode) {
  					*count =
219fd58be   M. Mohan Kumar   net/9p: Use prope...
198
  					    min_t(uint32_t, *count,
01b0c5cfb   Thiago Farina   net/9p/protocol.c...
199
  						  pdu->size - pdu->offset);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
200
201
202
203
204
  					*data = &pdu->sdata[pdu->offset];
  				}
  			}
  			break;
  		case 'T':{
b76225e22   Harsh Prateek Bora   net/9p: nwname sh...
205
  				uint16_t *nwname = va_arg(ap, uint16_t *);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
206
  				char ***wnames = va_arg(ap, char ***);
342fee1d5   Sripathi Kodi   9P2010.L handshak...
207
208
  				errcode = p9pdu_readf(pdu, proto_version,
  								"w", nwname);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
209
210
211
  				if (!errcode) {
  					*wnames =
  					    kmalloc(sizeof(char *) * *nwname,
eeff66ef6   Aneesh Kumar K.V   net/9p: Convert t...
212
  						    GFP_NOFS);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
213
214
215
216
217
218
219
220
221
  					if (!*wnames)
  						errcode = -ENOMEM;
  				}
  
  				if (!errcode) {
  					int i;
  
  					for (i = 0; i < *nwname; i++) {
  						errcode =
342fee1d5   Sripathi Kodi   9P2010.L handshak...
222
223
  						    p9pdu_readf(pdu,
  								proto_version,
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
  								"s",
  								&(*wnames)[i]);
  						if (errcode)
  							break;
  					}
  				}
  
  				if (errcode) {
  					if (*wnames) {
  						int i;
  
  						for (i = 0; i < *nwname; i++)
  							kfree((*wnames)[i]);
  					}
  					kfree(*wnames);
  					*wnames = NULL;
  				}
  			}
  			break;
  		case 'R':{
  				int16_t *nwqid = va_arg(ap, int16_t *);
  				struct p9_qid **wqids =
  				    va_arg(ap, struct p9_qid **);
  
  				*wqids = NULL;
  
  				errcode =
342fee1d5   Sripathi Kodi   9P2010.L handshak...
251
  				    p9pdu_readf(pdu, proto_version, "w", nwqid);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
252
253
254
255
  				if (!errcode) {
  					*wqids =
  					    kmalloc(*nwqid *
  						    sizeof(struct p9_qid),
eeff66ef6   Aneesh Kumar K.V   net/9p: Convert t...
256
  						    GFP_NOFS);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
257
258
259
260
261
262
263
264
265
  					if (*wqids == NULL)
  						errcode = -ENOMEM;
  				}
  
  				if (!errcode) {
  					int i;
  
  					for (i = 0; i < *nwqid; i++) {
  						errcode =
342fee1d5   Sripathi Kodi   9P2010.L handshak...
266
267
  						    p9pdu_readf(pdu,
  								proto_version,
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
268
269
270
271
272
273
274
275
276
277
278
279
280
  								"Q",
  								&(*wqids)[i]);
  						if (errcode)
  							break;
  					}
  				}
  
  				if (errcode) {
  					kfree(*wqids);
  					*wqids = NULL;
  				}
  			}
  			break;
f08531220   Sripathi Kodi   9p: getattr clien...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  		case 'A': {
  				struct p9_stat_dotl *stbuf =
  				    va_arg(ap, struct p9_stat_dotl *);
  
  				memset(stbuf, 0, sizeof(struct p9_stat_dotl));
  				errcode =
  				    p9pdu_readf(pdu, proto_version,
  					"qQdddqqqqqqqqqqqqqqq",
  					&stbuf->st_result_mask,
  					&stbuf->qid,
  					&stbuf->st_mode,
  					&stbuf->st_uid, &stbuf->st_gid,
  					&stbuf->st_nlink,
  					&stbuf->st_rdev, &stbuf->st_size,
  					&stbuf->st_blksize, &stbuf->st_blocks,
  					&stbuf->st_atime_sec,
  					&stbuf->st_atime_nsec,
  					&stbuf->st_mtime_sec,
  					&stbuf->st_mtime_nsec,
  					&stbuf->st_ctime_sec,
  					&stbuf->st_ctime_nsec,
  					&stbuf->st_btime_sec,
  					&stbuf->st_btime_nsec,
  					&stbuf->st_gen,
  					&stbuf->st_data_version);
  			}
  			break;
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
308
  		case '?':
c56e4acf5   Sripathi Kodi   9p: VFS switches ...
309
310
  			if ((proto_version != p9_proto_2000u) &&
  				(proto_version != p9_proto_2000L))
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  				return 0;
  			break;
  		default:
  			BUG();
  			break;
  		}
  
  		if (errcode)
  			break;
  	}
  
  	return errcode;
  }
  
  int
342fee1d5   Sripathi Kodi   9P2010.L handshak...
326
327
  p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
  	va_list ap)
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
328
329
330
331
332
333
334
335
336
337
338
339
340
  {
  	const char *ptr;
  	int errcode = 0;
  
  	for (ptr = fmt; *ptr; ptr++) {
  		switch (*ptr) {
  		case 'b':{
  				int8_t val = va_arg(ap, int);
  				if (pdu_write(pdu, &val, sizeof(val)))
  					errcode = -EFAULT;
  			}
  			break;
  		case 'w':{
beeebc92e   Eric Van Hensbergen   9p: fix endian is...
341
  				__le16 val = cpu_to_le16(va_arg(ap, int));
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
342
343
344
345
346
  				if (pdu_write(pdu, &val, sizeof(val)))
  					errcode = -EFAULT;
  			}
  			break;
  		case 'd':{
beeebc92e   Eric Van Hensbergen   9p: fix endian is...
347
  				__le32 val = cpu_to_le32(va_arg(ap, int32_t));
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
348
349
350
351
352
  				if (pdu_write(pdu, &val, sizeof(val)))
  					errcode = -EFAULT;
  			}
  			break;
  		case 'q':{
beeebc92e   Eric Van Hensbergen   9p: fix endian is...
353
  				__le64 val = cpu_to_le64(va_arg(ap, int64_t));
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
354
355
356
357
358
  				if (pdu_write(pdu, &val, sizeof(val)))
  					errcode = -EFAULT;
  			}
  			break;
  		case 's':{
e45c5405e   Eric Van Hensbergen   9p: fix sparse wa...
359
  				const char *sptr = va_arg(ap, const char *);
219fd58be   M. Mohan Kumar   net/9p: Use prope...
360
  				uint16_t len = 0;
e45c5405e   Eric Van Hensbergen   9p: fix sparse wa...
361
  				if (sptr)
219fd58be   M. Mohan Kumar   net/9p: Use prope...
362
363
  					len = min_t(uint16_t, strlen(sptr),
  								USHRT_MAX);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
364

342fee1d5   Sripathi Kodi   9P2010.L handshak...
365
366
  				errcode = p9pdu_writef(pdu, proto_version,
  								"w", len);
e45c5405e   Eric Van Hensbergen   9p: fix sparse wa...
367
  				if (!errcode && pdu_write(pdu, sptr, len))
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
368
369
370
371
372
373
374
  					errcode = -EFAULT;
  			}
  			break;
  		case 'Q':{
  				const struct p9_qid *qid =
  				    va_arg(ap, const struct p9_qid *);
  				errcode =
342fee1d5   Sripathi Kodi   9P2010.L handshak...
375
  				    p9pdu_writef(pdu, proto_version, "bdq",
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
376
377
378
379
380
381
382
  						 qid->type, qid->version,
  						 qid->path);
  			} break;
  		case 'S':{
  				const struct p9_wstat *stbuf =
  				    va_arg(ap, const struct p9_wstat *);
  				errcode =
342fee1d5   Sripathi Kodi   9P2010.L handshak...
383
  				    p9pdu_writef(pdu, proto_version,
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
384
385
  						 "wwdQdddqssss?sddd",
  						 stbuf->size, stbuf->type,
51a87c552   Eric Van Hensbergen   9p: rework client...
386
  						 stbuf->dev, &stbuf->qid,
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
387
388
389
390
391
392
393
394
  						 stbuf->mode, stbuf->atime,
  						 stbuf->mtime, stbuf->length,
  						 stbuf->name, stbuf->uid,
  						 stbuf->gid, stbuf->muid,
  						 stbuf->extension, stbuf->n_uid,
  						 stbuf->n_gid, stbuf->n_muid);
  			} break;
  		case 'D':{
219fd58be   M. Mohan Kumar   net/9p: Use prope...
395
  				uint32_t count = va_arg(ap, uint32_t);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
396
  				const void *data = va_arg(ap, const void *);
342fee1d5   Sripathi Kodi   9P2010.L handshak...
397
398
  				errcode = p9pdu_writef(pdu, proto_version, "d",
  									count);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
399
400
401
402
  				if (!errcode && pdu_write(pdu, data, count))
  					errcode = -EFAULT;
  			}
  			break;
51a87c552   Eric Van Hensbergen   9p: rework client...
403
404
405
  		case 'U':{
  				int32_t count = va_arg(ap, int32_t);
  				const char __user *udata =
e45c5405e   Eric Van Hensbergen   9p: fix sparse wa...
406
  						va_arg(ap, const void __user *);
342fee1d5   Sripathi Kodi   9P2010.L handshak...
407
408
  				errcode = p9pdu_writef(pdu, proto_version, "d",
  									count);
51a87c552   Eric Van Hensbergen   9p: rework client...
409
410
411
412
  				if (!errcode && pdu_write_u(pdu, udata, count))
  					errcode = -EFAULT;
  			}
  			break;
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
413
  		case 'T':{
b76225e22   Harsh Prateek Bora   net/9p: nwname sh...
414
  				uint16_t nwname = va_arg(ap, int);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
415
  				const char **wnames = va_arg(ap, const char **);
342fee1d5   Sripathi Kodi   9P2010.L handshak...
416
417
  				errcode = p9pdu_writef(pdu, proto_version, "w",
  									nwname);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
418
419
420
421
422
  				if (!errcode) {
  					int i;
  
  					for (i = 0; i < nwname; i++) {
  						errcode =
342fee1d5   Sripathi Kodi   9P2010.L handshak...
423
424
  						    p9pdu_writef(pdu,
  								proto_version,
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
425
426
427
428
429
430
431
432
433
434
435
436
  								 "s",
  								 wnames[i]);
  						if (errcode)
  							break;
  					}
  				}
  			}
  			break;
  		case 'R':{
  				int16_t nwqid = va_arg(ap, int);
  				struct p9_qid *wqids =
  				    va_arg(ap, struct p9_qid *);
342fee1d5   Sripathi Kodi   9P2010.L handshak...
437
438
  				errcode = p9pdu_writef(pdu, proto_version, "w",
  									nwqid);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
439
440
441
442
443
  				if (!errcode) {
  					int i;
  
  					for (i = 0; i < nwqid; i++) {
  						errcode =
342fee1d5   Sripathi Kodi   9P2010.L handshak...
444
445
  						    p9pdu_writef(pdu,
  								proto_version,
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
446
447
448
449
450
451
452
453
  								 "Q",
  								 &wqids[i]);
  						if (errcode)
  							break;
  					}
  				}
  			}
  			break;
87d7845aa   Sripathi Kodi   9p: Implement cli...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
  		case 'I':{
  				struct p9_iattr_dotl *p9attr = va_arg(ap,
  							struct p9_iattr_dotl *);
  
  				errcode = p9pdu_writef(pdu, proto_version,
  							"ddddqqqqq",
  							p9attr->valid,
  							p9attr->mode,
  							p9attr->uid,
  							p9attr->gid,
  							p9attr->size,
  							p9attr->atime_sec,
  							p9attr->atime_nsec,
  							p9attr->mtime_sec,
  							p9attr->mtime_nsec);
  			}
  			break;
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
471
  		case '?':
c56e4acf5   Sripathi Kodi   9p: VFS switches ...
472
473
  			if ((proto_version != p9_proto_2000u) &&
  				(proto_version != p9_proto_2000L))
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
474
475
476
477
478
479
480
481
482
483
484
485
486
  				return 0;
  			break;
  		default:
  			BUG();
  			break;
  		}
  
  		if (errcode)
  			break;
  	}
  
  	return errcode;
  }
342fee1d5   Sripathi Kodi   9P2010.L handshak...
487
  int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...)
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
488
489
490
491
492
  {
  	va_list ap;
  	int ret;
  
  	va_start(ap, fmt);
342fee1d5   Sripathi Kodi   9P2010.L handshak...
493
  	ret = p9pdu_vreadf(pdu, proto_version, fmt, ap);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
494
495
496
497
498
499
  	va_end(ap);
  
  	return ret;
  }
  
  static int
342fee1d5   Sripathi Kodi   9P2010.L handshak...
500
  p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...)
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
501
502
503
504
505
  {
  	va_list ap;
  	int ret;
  
  	va_start(ap, fmt);
342fee1d5   Sripathi Kodi   9P2010.L handshak...
506
  	ret = p9pdu_vwritef(pdu, proto_version, fmt, ap);
ace51c4dd   Eric Van Hensbergen   9p: add new proto...
507
508
509
510
  	va_end(ap);
  
  	return ret;
  }
51a87c552   Eric Van Hensbergen   9p: rework client...
511

348b59012   Aneesh Kumar K.V   net/9p: Convert n...
512
  int p9stat_read(struct p9_client *clnt, char *buf, int len, struct p9_wstat *st)
02da398b9   Eric Van Hensbergen   9p: eliminate dep...
513
514
  {
  	struct p9_fcall fake_pdu;
e7f4b8f1a   Eric Van Hensbergen   9p: Improve debug...
515
  	int ret;
02da398b9   Eric Van Hensbergen   9p: eliminate dep...
516
517
518
519
520
  
  	fake_pdu.size = len;
  	fake_pdu.capacity = len;
  	fake_pdu.sdata = buf;
  	fake_pdu.offset = 0;
348b59012   Aneesh Kumar K.V   net/9p: Convert n...
521
  	ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "S", st);
e7f4b8f1a   Eric Van Hensbergen   9p: Improve debug...
522
  	if (ret) {
5d3851530   Joe Perches   9p: Reduce object...
523
524
  		p9_debug(P9_DEBUG_9P, "<<< p9stat_read failed: %d
  ", ret);
348b59012   Aneesh Kumar K.V   net/9p: Convert n...
525
  		trace_9p_protocol_dump(clnt, &fake_pdu);
e7f4b8f1a   Eric Van Hensbergen   9p: Improve debug...
526
527
528
  	}
  
  	return ret;
02da398b9   Eric Van Hensbergen   9p: eliminate dep...
529
530
  }
  EXPORT_SYMBOL(p9stat_read);
51a87c552   Eric Van Hensbergen   9p: rework client...
531
532
  int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type)
  {
9bb6c10a4   Venkateswararao Jujjuri (JV)   [net/9p] Assign t...
533
  	pdu->id = type;
51a87c552   Eric Van Hensbergen   9p: rework client...
534
535
  	return p9pdu_writef(pdu, 0, "dbw", 0, type, tag);
  }
348b59012   Aneesh Kumar K.V   net/9p: Convert n...
536
  int p9pdu_finalize(struct p9_client *clnt, struct p9_fcall *pdu)
51a87c552   Eric Van Hensbergen   9p: rework client...
537
538
539
540
541
542
543
  {
  	int size = pdu->size;
  	int err;
  
  	pdu->size = 0;
  	err = p9pdu_writef(pdu, 0, "d", size);
  	pdu->size = size;
348b59012   Aneesh Kumar K.V   net/9p: Convert n...
544
  	trace_9p_protocol_dump(clnt, pdu);
5d3851530   Joe Perches   9p: Reduce object...
545
546
547
  	p9_debug(P9_DEBUG_9P, ">>> size=%d type: %d tag: %d
  ",
  		 pdu->size, pdu->id, pdu->tag);
e7f4b8f1a   Eric Van Hensbergen   9p: Improve debug...
548

51a87c552   Eric Van Hensbergen   9p: rework client...
549
550
551
552
553
554
555
556
  	return err;
  }
  
  void p9pdu_reset(struct p9_fcall *pdu)
  {
  	pdu->offset = 0;
  	pdu->size = 0;
  }
7751bdb3a   Sripathi Kodi   9p: readdir imple...
557

348b59012   Aneesh Kumar K.V   net/9p: Convert n...
558
559
  int p9dirent_read(struct p9_client *clnt, char *buf, int len,
  		  struct p9_dirent *dirent)
7751bdb3a   Sripathi Kodi   9p: readdir imple...
560
561
562
563
564
565
566
567
568
  {
  	struct p9_fcall fake_pdu;
  	int ret;
  	char *nameptr;
  
  	fake_pdu.size = len;
  	fake_pdu.capacity = len;
  	fake_pdu.sdata = buf;
  	fake_pdu.offset = 0;
348b59012   Aneesh Kumar K.V   net/9p: Convert n...
569
570
  	ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "Qqbs", &dirent->qid,
  			  &dirent->d_off, &dirent->d_type, &nameptr);
7751bdb3a   Sripathi Kodi   9p: readdir imple...
571
  	if (ret) {
5d3851530   Joe Perches   9p: Reduce object...
572
573
  		p9_debug(P9_DEBUG_9P, "<<< p9dirent_read failed: %d
  ", ret);
348b59012   Aneesh Kumar K.V   net/9p: Convert n...
574
  		trace_9p_protocol_dump(clnt, &fake_pdu);
7751bdb3a   Sripathi Kodi   9p: readdir imple...
575
576
577
578
  		goto out;
  	}
  
  	strcpy(dirent->d_name, nameptr);
1b0bcbcf6   Pedro Scarapicchia Junior   net/9p/protocol.c...
579
  	kfree(nameptr);
7751bdb3a   Sripathi Kodi   9p: readdir imple...
580
581
582
583
584
  
  out:
  	return fake_pdu.offset;
  }
  EXPORT_SYMBOL(p9dirent_read);