xref: /illumos-gate/usr/src/lib/lib9p/common/fcall.h (revision 9b9d39d2a32ff806d2431dbcc50968ef1e6d46b2)
1 /*
2  * Copyright 2016 Jakub Klama <jceel@FreeBSD.org>
3  * All rights reserved
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted providing that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 /*
29  * Based on libixp code: ©2007-2010 Kris Maglione <maglione.k at Gmail>
30  */
31 
32 #ifndef LIB9P_FCALL_H
33 #define LIB9P_FCALL_H
34 
35 #include <stdint.h>
36 
37 #define L9P_MAX_WELEM   256
38 
39 /*
40  * Function call/reply (Tfoo/Rfoo) numbers.
41  *
42  * These are protocol code numbers, so the exact values
43  * matter.  However, __FIRST and __LAST_PLUS_ONE are for
44  * debug code, and just need to encompass the entire range.
45  *
46  * Note that we rely (in the debug code) on Rfoo == Tfoo+1.
47  */
48 enum l9p_ftype {
49 	L9P__FIRST = 6,		/* NB: must be <= all legal values */
50 	L9P_TLERROR = 6,	/* illegal; exists for parity with Rlerror */
51 	L9P_RLERROR,
52 	L9P_TSTATFS = 8,
53 	L9P_RSTATFS,
54 	L9P_TLOPEN = 12,
55 	L9P_RLOPEN,
56 	L9P_TLCREATE = 14,
57 	L9P_RLCREATE,
58 	L9P_TSYMLINK = 16,
59 	L9P_RSYMLINK,
60 	L9P_TMKNOD = 18,
61 	L9P_RMKNOD,
62 	L9P_TRENAME = 20,
63 	L9P_RRENAME,
64 	L9P_TREADLINK = 22,
65 	L9P_RREADLINK,
66 	L9P_TGETATTR = 24,
67 	L9P_RGETATTR,
68 	L9P_TSETATTR = 26,
69 	L9P_RSETATTR,
70 	L9P_TXATTRWALK = 30,
71 	L9P_RXATTRWALK,
72 	L9P_TXATTRCREATE = 32,
73 	L9P_RXATTRCREATE,
74 	L9P_TREADDIR = 40,
75 	L9P_RREADDIR,
76 	L9P_TFSYNC = 50,
77 	L9P_RFSYNC,
78 	L9P_TLOCK = 52,
79 	L9P_RLOCK,
80 	L9P_TGETLOCK = 54,
81 	L9P_RGETLOCK,
82 	L9P_TLINK = 70,
83 	L9P_RLINK,
84 	L9P_TMKDIR = 72,
85 	L9P_RMKDIR,
86 	L9P_TRENAMEAT = 74,
87 	L9P_RRENAMEAT,
88 	L9P_TUNLINKAT = 76,
89 	L9P_RUNLINKAT,
90 	L9P_TVERSION = 100,
91 	L9P_RVERSION,
92 	L9P_TAUTH = 102,
93 	L9P_RAUTH,
94 	L9P_TATTACH = 104,
95 	L9P_RATTACH,
96 	L9P_TERROR = 106, 	/* illegal */
97 	L9P_RERROR,
98 	L9P_TFLUSH = 108,
99 	L9P_RFLUSH,
100 	L9P_TWALK = 110,
101 	L9P_RWALK,
102 	L9P_TOPEN = 112,
103 	L9P_ROPEN,
104 	L9P_TCREATE = 114,
105 	L9P_RCREATE,
106 	L9P_TREAD = 116,
107 	L9P_RREAD,
108 	L9P_TWRITE = 118,
109 	L9P_RWRITE,
110 	L9P_TCLUNK = 120,
111 	L9P_RCLUNK,
112 	L9P_TREMOVE = 122,
113 	L9P_RREMOVE,
114 	L9P_TSTAT = 124,
115 	L9P_RSTAT,
116 	L9P_TWSTAT = 126,
117 	L9P_RWSTAT,
118 	L9P__LAST_PLUS_1,	/* NB: must be last */
119 };
120 
121 /*
122  * When a Tfoo request comes over the wire, we decode it
123  * (pack.c) from wire format into a request laid out in
124  * a "union l9p_fcall" object.  This object is not in wire
125  * format, but rather in something more convenient for us
126  * to operate on.
127  *
128  * We then dispatch the request (request.c, backend/fs.c) and
129  * use another "union l9p_fcall" object to build a reply.
130  * The reply is converted to wire format on the way back out
131  * (pack.c again).
132  *
133  * All sub-objects start with a header containing the request
134  * or reply type code and two-byte tag, and whether or not it
135  * is needed, a four-byte fid.
136  *
137  * What this means here is that the data structures within
138  * the union can be shared across various requests and replies.
139  * For instance, replies to OPEN, CREATE, LCREATE, LOPEN, MKDIR, and
140  * SYMLINK are all fairly similar (providing a qid and sometimes
141  * an iounit) and hence can all use the l9p_f_ropen structure.
142  * Which structures are used for which operations is somewhat
143  * arbitrary; for programming ease, if an operation shares a
144  * data structure, it still has its own name: there are union
145  * members named ropen, rcreate, rlcreate, rlopen, rmkdir, and
146  * rsymlink, even though all use struct l9p_f_ropen.
147  *
148  * The big exception to the above rule is struct l9p_f_io, which
149  * is used as both request and reply for all of READ, WRITE, and
150  * READDIR.  Moreover, the READDIR reply must be pre-packed into
151  * wire format (it is handled like raw data a la READ).
152  *
153  * Some request messages (e.g., TREADLINK) fit in a header, having
154  * just type code, tag, and fid.  These have no separate data
155  * structure, nor union member name.  Similarly, some reply
156  * messages (e.g., RCLUNK, RREMOVE, RRENAME) have just the type
157  * code and tag.
158  */
159 
160 /*
161  * Type code bits in (the first byte of) a qid.
162  */
163 enum l9p_qid_type {
164 	L9P_QTDIR = 0x80, /* type bit for directories */
165 	L9P_QTAPPEND = 0x40, /* type bit for append only files */
166 	L9P_QTEXCL = 0x20, /* type bit for exclusive use files */
167 	L9P_QTMOUNT = 0x10, /* type bit for mounted channel */
168 	L9P_QTAUTH = 0x08, /* type bit for authentication file */
169 	L9P_QTTMP = 0x04, /* type bit for non-backed-up file */
170 	L9P_QTSYMLINK = 0x02, /* type bit for symbolic link */
171 	L9P_QTFILE = 0x00 /* type bits for plain file */
172 };
173 
174 /*
175  * Extra permission bits in create and file modes (stat).
176  */
177 #define L9P_DMDIR 0x80000000
178 enum {
179 	L9P_DMAPPEND = 0x40000000,
180 	L9P_DMEXCL = 0x20000000,
181 	L9P_DMMOUNT = 0x10000000,
182 	L9P_DMAUTH = 0x08000000,
183 	L9P_DMTMP = 0x04000000,
184 	L9P_DMSYMLINK = 0x02000000,
185 	/* 9P2000.u extensions */
186 	L9P_DMDEVICE = 0x00800000,
187 	L9P_DMNAMEDPIPE = 0x00200000,
188 	L9P_DMSOCKET = 0x00100000,
189 	L9P_DMSETUID = 0x00080000,
190 	L9P_DMSETGID = 0x00040000,
191 };
192 
193 /*
194  * Open/create mode bits in 9P2000 and 9P2000.u operations
195  * (not Linux lopen and lcreate flags, which are different).
196  * Note that the mode field is only one byte wide.
197  */
198 enum l9p_omode {
199 	L9P_OREAD = 0,	/* open for read */
200 	L9P_OWRITE = 1,	/* write */
201 	L9P_ORDWR = 2,	/* read and write */
202 	L9P_OEXEC = 3,	/* execute, == read but check execute permission */
203 	L9P_OACCMODE = 3, /* mask for the above access-mode bits */
204 	L9P_OTRUNC = 16,	/* or'ed in (except for exec), truncate file first */
205 	L9P_OCEXEC = 32,	/* or'ed in, close on exec */
206 	L9P_ORCLOSE = 64,	/* or'ed in, remove on close */
207 	L9P_ODIRECT = 128,	/* or'ed in, direct access */
208 };
209 
210 /*
211  * Flag bits in 9P2000.L operations (Tlopen, Tlcreate).  These are
212  * basically just the Linux L_* flags.  The bottom 3 bits are the
213  * same as for l9p_omode, although open-for-exec is not used:
214  * instead, the client does a Tgetattr and checks the mode for
215  * execute bits, then just opens for reading.
216  *
217  * Each L_O_xxx is just value O_xxx has on Linux in <fcntl.h>;
218  * not all are necessarily used.  From observation, we do get
219  * L_O_CREAT and L_O_EXCL when creating with exclusive, and always
220  * get L_O_LARGEFILE.  We do get L_O_APPEND when opening for
221  * append.  We also get both L_O_DIRECT and L_O_DIRECTORY set
222  * when opening directories.
223  *
224  * We probably never get L_O_NOCTTY which makes no sense, and
225  * some of the other options may need to be handled on the client.
226  */
227 enum l9p_l_o_flags {
228 	L9P_L_O_CREAT =		000000100U,
229 	L9P_L_O_EXCL =		000000200U,
230 	L9P_L_O_NOCTTY =	000000400U,
231 	L9P_L_O_TRUNC =		000001000U,
232 	L9P_L_O_APPEND =	000002000U,
233 	L9P_L_O_NONBLOCK =	000004000U,
234 	L9P_L_O_DSYNC =		000010000U,
235 	L9P_L_O_FASYNC =	000020000U,
236 	L9P_L_O_DIRECT =	000040000U,
237 	L9P_L_O_LARGEFILE =	000100000U,
238 	L9P_L_O_DIRECTORY =	000200000U,
239 	L9P_L_O_NOFOLLOW =	000400000U,
240 	L9P_L_O_NOATIME =	001000000U,
241 	L9P_L_O_CLOEXEC =	002000000U,
242 	L9P_L_O_SYNC =		004000000U,
243 	L9P_L_O_PATH =		010000000U,
244 	L9P_L_O_TMPFILE =	020000000U,
245 };
246 
247 struct l9p_hdr {
248 	uint8_t type;
249 	uint16_t tag;
250 	uint32_t fid;
251 };
252 
253 struct l9p_qid {
254 	uint8_t  type;
255 	uint32_t version;
256 	uint64_t path;
257 };
258 
259 struct l9p_stat {
260 	uint16_t type;
261 	uint32_t dev;
262 	struct l9p_qid qid;
263 	uint32_t mode;
264 	uint32_t atime;
265 	uint32_t mtime;
266 	uint64_t length;
267 	char *name;
268 	char *uid;
269 	char *gid;
270 	char *muid;
271 	char *extension;
272 	uint32_t n_uid;
273 	uint32_t n_gid;
274 	uint32_t n_muid;
275 };
276 
277 #define	L9P_FSTYPE	 0x01021997
278 
279 struct l9p_statfs {
280 	uint32_t type;		/* file system type */
281 	uint32_t bsize;		/* block size for I/O */
282 	uint64_t blocks;	/* file system size (bsize-byte blocks) */
283 	uint64_t bfree;		/* free blocks in fs */
284 	uint64_t bavail;	/* free blocks avail to non-superuser*/
285 	uint64_t files;		/* file nodes in file system (# inodes) */
286 	uint64_t ffree;		/* free file nodes in fs */
287 	uint64_t fsid;		/* file system identifier */
288 	uint32_t namelen;	/* maximum length of filenames */
289 };
290 
291 struct l9p_f_version {
292 	struct l9p_hdr hdr;
293 	uint32_t msize;
294 	char *version;
295 };
296 
297 struct l9p_f_tflush {
298 	struct l9p_hdr hdr;
299 	uint16_t oldtag;
300 };
301 
302 struct l9p_f_error {
303 	struct l9p_hdr hdr;
304 	char *ename;
305 	uint32_t errnum;
306 };
307 
308 struct l9p_f_ropen {
309 	struct l9p_hdr hdr;
310 	struct l9p_qid qid;
311 	uint32_t iounit;
312 };
313 
314 struct l9p_f_rauth {
315 	struct l9p_hdr hdr;
316 	struct l9p_qid aqid;
317 };
318 
319 struct l9p_f_attach {
320 	struct l9p_hdr hdr;
321 	uint32_t afid;
322 	char *uname;
323 	char *aname;
324 	uint32_t n_uname;
325 };
326 #define	L9P_NOFID ((uint32_t)-1)	/* in Tattach, no auth fid */
327 #define	L9P_NONUNAME ((uint32_t)-1)	/* in Tattach, no n_uname */
328 
329 struct l9p_f_tcreate {
330 	struct l9p_hdr hdr;
331 	uint32_t perm;
332 	char *name;
333 	uint8_t mode; /* +Topen */
334 	char *extension;
335 };
336 
337 struct l9p_f_twalk {
338 	struct l9p_hdr hdr;
339 	uint32_t newfid;
340 	uint16_t nwname;
341 	char *wname[L9P_MAX_WELEM];
342 };
343 
344 struct l9p_f_rwalk {
345 	struct l9p_hdr hdr;
346 	uint16_t nwqid;
347 	struct l9p_qid wqid[L9P_MAX_WELEM];
348 };
349 
350 struct l9p_f_io {
351 	struct l9p_hdr hdr;
352 	uint64_t offset; /* Tread, Twrite, Treaddir */
353 	uint32_t count; /* Tread, Twrite, Rread, Treaddir, Rreaddir */
354 };
355 
356 struct l9p_f_rstat {
357 	struct l9p_hdr hdr;
358 	struct l9p_stat stat;
359 };
360 
361 struct l9p_f_twstat {
362 	struct l9p_hdr hdr;
363 	struct l9p_stat stat;
364 };
365 
366 struct l9p_f_rstatfs {
367 	struct l9p_hdr hdr;
368 	struct l9p_statfs statfs;
369 };
370 
371 /* Used for Tlcreate, Tlopen, Tmkdir, Tunlinkat. */
372 struct l9p_f_tlcreate {
373 	struct l9p_hdr hdr;
374 	char *name;		/* Tlcreate, Tmkdir, Tunlinkat */
375 	uint32_t flags;		/* Tlcreate, Tlopen, Tmkdir, Tunlinkat */
376 	uint32_t mode;		/* Tlcreate, Tmkdir */
377 	uint32_t gid;		/* Tlcreate, Tmkdir */
378 };
379 
380 struct l9p_f_tsymlink {
381 	struct l9p_hdr hdr;
382 	char *name;
383 	char *symtgt;
384 	uint32_t gid;
385 };
386 
387 struct l9p_f_tmknod {
388 	struct l9p_hdr hdr;
389 	char *name;
390 	uint32_t mode;
391 	uint32_t major;
392 	uint32_t minor;
393 	uint32_t gid;
394 };
395 
396 struct l9p_f_trename {
397 	struct l9p_hdr hdr;
398 	uint32_t dfid;
399 	char *name;
400 };
401 
402 struct l9p_f_rreadlink {
403 	struct l9p_hdr hdr;
404 	char *target;
405 };
406 
407 struct l9p_f_tgetattr {
408 	struct l9p_hdr hdr;
409 	uint64_t request_mask;
410 };
411 
412 struct l9p_f_rgetattr {
413 	struct l9p_hdr hdr;
414 	uint64_t valid;
415 	struct l9p_qid qid;
416 	uint32_t mode;
417 	uint32_t uid;
418 	uint32_t gid;
419 	uint64_t nlink;
420 	uint64_t rdev;
421 	uint64_t size;
422 	uint64_t blksize;
423 	uint64_t blocks;
424 	uint64_t atime_sec;
425 	uint64_t atime_nsec;
426 	uint64_t mtime_sec;
427 	uint64_t mtime_nsec;
428 	uint64_t ctime_sec;
429 	uint64_t ctime_nsec;
430 	uint64_t btime_sec;
431 	uint64_t btime_nsec;
432 	uint64_t gen;
433 	uint64_t data_version;
434 };
435 
436 /* Fields in req->request_mask and reply->valid for Tgetattr, Rgetattr. */
437 enum l9pl_getattr_flags {
438 	L9PL_GETATTR_MODE = 0x00000001,
439 	L9PL_GETATTR_NLINK = 0x00000002,
440 	L9PL_GETATTR_UID = 0x00000004,
441 	L9PL_GETATTR_GID = 0x00000008,
442 	L9PL_GETATTR_RDEV = 0x00000010,
443 	L9PL_GETATTR_ATIME = 0x00000020,
444 	L9PL_GETATTR_MTIME = 0x00000040,
445 	L9PL_GETATTR_CTIME = 0x00000080,
446 	L9PL_GETATTR_INO = 0x00000100,
447 	L9PL_GETATTR_SIZE = 0x00000200,
448 	L9PL_GETATTR_BLOCKS = 0x00000400,
449 	/* everything up to and including BLOCKS is BASIC */
450 	L9PL_GETATTR_BASIC = L9PL_GETATTR_MODE |
451 		L9PL_GETATTR_NLINK |
452 		L9PL_GETATTR_UID |
453 		L9PL_GETATTR_GID |
454 		L9PL_GETATTR_RDEV |
455 		L9PL_GETATTR_ATIME |
456 		L9PL_GETATTR_MTIME |
457 		L9PL_GETATTR_CTIME |
458 		L9PL_GETATTR_INO |
459 		L9PL_GETATTR_SIZE |
460 		L9PL_GETATTR_BLOCKS,
461 	L9PL_GETATTR_BTIME = 0x00000800,
462 	L9PL_GETATTR_GEN = 0x00001000,
463 	L9PL_GETATTR_DATA_VERSION = 0x00002000,
464 	/* BASIC + birthtime + gen + data-version = ALL */
465 	L9PL_GETATTR_ALL = L9PL_GETATTR_BASIC |
466 		L9PL_GETATTR_BTIME |
467 		L9PL_GETATTR_GEN |
468 		L9PL_GETATTR_DATA_VERSION,
469 };
470 
471 struct l9p_f_tsetattr {
472 	struct l9p_hdr hdr;
473 	uint32_t valid;
474 	uint32_t mode;
475 	uint32_t uid;
476 	uint32_t gid;
477 	uint64_t size;
478 	uint64_t atime_sec;	/* if valid & L9PL_SETATTR_ATIME_SET */
479 	uint64_t atime_nsec;	/* (else use on-server time) */
480 	uint64_t mtime_sec;	/* if valid & L9PL_SETATTR_MTIME_SET */
481 	uint64_t mtime_nsec;	/* (else use on-server time) */
482 };
483 
484 /* Fields in req->valid for Tsetattr. */
485 enum l9pl_setattr_flags {
486 	L9PL_SETATTR_MODE = 0x00000001,
487 	L9PL_SETATTR_UID = 0x00000002,
488 	L9PL_SETATTR_GID = 0x00000004,
489 	L9PL_SETATTR_SIZE = 0x00000008,
490 	L9PL_SETATTR_ATIME = 0x00000010,
491 	L9PL_SETATTR_MTIME = 0x00000020,
492 	L9PL_SETATTR_CTIME = 0x00000040,
493 	L9PL_SETATTR_ATIME_SET = 0x00000080,
494 	L9PL_SETATTR_MTIME_SET = 0x00000100,
495 };
496 
497 struct l9p_f_txattrwalk {
498 	struct l9p_hdr hdr;
499 	uint32_t newfid;
500 	char *name;
501 };
502 
503 struct l9p_f_rxattrwalk {
504 	struct l9p_hdr hdr;
505 	uint64_t size;
506 };
507 
508 struct l9p_f_txattrcreate {
509 	struct l9p_hdr hdr;
510 	char *name;
511 	uint64_t attr_size;
512 	uint32_t flags;
513 };
514 
515 struct l9p_f_tlock {
516 	struct l9p_hdr hdr;
517 	uint8_t type;		/* from l9pl_lock_type */
518 	uint32_t flags;		/* from l9pl_lock_flags */
519 	uint64_t start;
520 	uint64_t length;
521 	uint32_t proc_id;
522 	char *client_id;
523 };
524 
525 enum l9pl_lock_type {
526 	L9PL_LOCK_TYPE_RDLOCK =	0,
527 	L9PL_LOCK_TYPE_WRLOCK =	1,
528 	L9PL_LOCK_TYPE_UNLOCK =	2,
529 };
530 
531 enum l9pl_lock_flags {
532 	L9PL_LOCK_TYPE_BLOCK = 1,
533 	L9PL_LOCK_TYPE_RECLAIM = 2,
534 };
535 
536 struct l9p_f_rlock {
537 	struct l9p_hdr hdr;
538 	uint8_t status;		/* from l9pl_lock_status */
539 };
540 
541 enum l9pl_lock_status {
542 	L9PL_LOCK_SUCCESS = 0,
543 	L9PL_LOCK_BLOCKED = 1,
544 	L9PL_LOCK_ERROR = 2,
545 	L9PL_LOCK_GRACE = 3,
546 };
547 
548 struct l9p_f_getlock {
549 	struct l9p_hdr hdr;
550 	uint8_t type;		/* from l9pl_lock_type */
551 	uint64_t start;
552 	uint64_t length;
553 	uint32_t proc_id;
554 	char *client_id;
555 };
556 
557 struct l9p_f_tlink {
558 	struct l9p_hdr hdr;
559 	uint32_t dfid;
560 	char *name;
561 };
562 
563 struct l9p_f_trenameat {
564 	struct l9p_hdr hdr;
565 	char *oldname;
566 	uint32_t newdirfid;
567 	char *newname;
568 };
569 
570 /*
571  * Flags in Tunlinkat (which re-uses f_tlcreate data structure but
572  * with different meaning).
573  */
574 enum l9p_l_unlinkat_flags {
575 	/* not sure if any other AT_* flags are passed through */
576 	L9PL_AT_REMOVEDIR =	0x0200,
577 };
578 
579 union l9p_fcall {
580 	struct l9p_hdr hdr;
581 	struct l9p_f_version version;
582 	struct l9p_f_tflush tflush;
583 	struct l9p_f_ropen ropen;
584 	struct l9p_f_ropen rcreate;
585 	struct l9p_f_ropen rattach;
586 	struct l9p_f_error error;
587 	struct l9p_f_rauth rauth;
588 	struct l9p_f_attach tattach;
589 	struct l9p_f_attach tauth;
590 	struct l9p_f_tcreate tcreate;
591 	struct l9p_f_tcreate topen;
592 	struct l9p_f_twalk twalk;
593 	struct l9p_f_rwalk rwalk;
594 	struct l9p_f_twstat twstat;
595 	struct l9p_f_rstat rstat;
596 	struct l9p_f_rstatfs rstatfs;
597 	struct l9p_f_tlcreate tlopen;
598 	struct l9p_f_ropen rlopen;
599 	struct l9p_f_tlcreate tlcreate;
600 	struct l9p_f_ropen rlcreate;
601 	struct l9p_f_tsymlink tsymlink;
602 	struct l9p_f_ropen rsymlink;
603 	struct l9p_f_tmknod tmknod;
604 	struct l9p_f_ropen rmknod;
605 	struct l9p_f_trename trename;
606 	struct l9p_f_rreadlink rreadlink;
607 	struct l9p_f_tgetattr tgetattr;
608 	struct l9p_f_rgetattr rgetattr;
609 	struct l9p_f_tsetattr tsetattr;
610 	struct l9p_f_txattrwalk txattrwalk;
611 	struct l9p_f_rxattrwalk rxattrwalk;
612 	struct l9p_f_txattrcreate txattrcreate;
613 	struct l9p_f_tlock tlock;
614 	struct l9p_f_rlock rlock;
615 	struct l9p_f_getlock getlock;
616 	struct l9p_f_tlink tlink;
617 	struct l9p_f_tlcreate tmkdir;
618 	struct l9p_f_ropen rmkdir;
619 	struct l9p_f_trenameat trenameat;
620 	struct l9p_f_tlcreate tunlinkat;
621 	struct l9p_f_io io;
622 };
623 
624 #endif  /* LIB9P_FCALL_H */
625