]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/lib9p/request.c
sysctl(9): Fix a few mandoc related issues
[FreeBSD/FreeBSD.git] / contrib / lib9p / request.c
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 #include <stdlib.h>
29 #include <string.h>
30 #include <assert.h>
31 #include <errno.h>
32 #include <sys/param.h>
33 #include <sys/uio.h>
34 #if defined(__FreeBSD__)
35 #include <sys/sbuf.h>
36 #else
37 #include "sbuf/sbuf.h"
38 #endif
39 #include "lib9p.h"
40 #include "lib9p_impl.h"
41 #include "fcall.h"
42 #include "fid.h"
43 #include "hashtable.h"
44 #include "log.h"
45 #include "linux_errno.h"
46 #include "backend/backend.h"
47 #include "threadpool.h"
48
49 #define N(x)    (sizeof(x) / sizeof(x[0]))
50
51 static int l9p_dispatch_tversion(struct l9p_request *req);
52 static int l9p_dispatch_tattach(struct l9p_request *req);
53 static int l9p_dispatch_tclunk(struct l9p_request *req);
54 static int l9p_dispatch_tcreate(struct l9p_request *req);
55 static int l9p_dispatch_topen(struct l9p_request *req);
56 static int l9p_dispatch_tread(struct l9p_request *req);
57 static int l9p_dispatch_tremove(struct l9p_request *req);
58 static int l9p_dispatch_tstat(struct l9p_request *req);
59 static int l9p_dispatch_twalk(struct l9p_request *req);
60 static int l9p_dispatch_twrite(struct l9p_request *req);
61 static int l9p_dispatch_twstat(struct l9p_request *req);
62 static int l9p_dispatch_tstatfs(struct l9p_request *req);
63 static int l9p_dispatch_tlopen(struct l9p_request *req);
64 static int l9p_dispatch_tlcreate(struct l9p_request *req);
65 static int l9p_dispatch_tsymlink(struct l9p_request *req);
66 static int l9p_dispatch_tmknod(struct l9p_request *req);
67 static int l9p_dispatch_trename(struct l9p_request *req);
68 static int l9p_dispatch_treadlink(struct l9p_request *req);
69 static int l9p_dispatch_tgetattr(struct l9p_request *req);
70 static int l9p_dispatch_tsetattr(struct l9p_request *req);
71 static int l9p_dispatch_txattrwalk(struct l9p_request *req);
72 static int l9p_dispatch_txattrcreate(struct l9p_request *req);
73 static int l9p_dispatch_treaddir(struct l9p_request *req);
74 static int l9p_dispatch_tfsync(struct l9p_request *req);
75 static int l9p_dispatch_tlock(struct l9p_request *req);
76 static int l9p_dispatch_tgetlock(struct l9p_request *req);
77 static int l9p_dispatch_tlink(struct l9p_request *req);
78 static int l9p_dispatch_tmkdir(struct l9p_request *req);
79 static int l9p_dispatch_trenameat(struct l9p_request *req);
80 static int l9p_dispatch_tunlinkat(struct l9p_request *req);
81
82 /*
83  * Each Txxx handler has a "must run" flag.  If it is false,
84  * we check for a flush request before calling the handler.
85  * If a flush is already requested we can instantly fail the
86  * request with EINTR.
87  *
88  * Tclunk and Tremove must run because they make their fids
89  * become invalid.  Tversion and Tattach should never get
90  * a flush request applied (it makes no sense as the connection
91  * is not really running yet), so it should be harmless to
92  * set them either way, but for now we have them as must-run.
93  * Flushing a Tflush is not really allowed either so we keep
94  * these as must-run too (although they run without being done
95  * threaded anyway).
96  */
97 struct l9p_handler {
98         enum l9p_ftype type;
99         int (*handler)(struct l9p_request *);
100         bool must_run;
101 };
102
103 static const struct l9p_handler l9p_handlers_no_version[] = {
104         {L9P_TVERSION, l9p_dispatch_tversion, true},
105 };
106
107 static const struct l9p_handler l9p_handlers_base[] = {
108         {L9P_TVERSION, l9p_dispatch_tversion, true},
109         {L9P_TATTACH, l9p_dispatch_tattach, true},
110         {L9P_TCLUNK, l9p_dispatch_tclunk, true},
111         {L9P_TFLUSH, l9p_threadpool_tflush, true},
112         {L9P_TCREATE, l9p_dispatch_tcreate, false},
113         {L9P_TOPEN, l9p_dispatch_topen, false},
114         {L9P_TREAD, l9p_dispatch_tread, false},
115         {L9P_TWRITE, l9p_dispatch_twrite, false},
116         {L9P_TREMOVE, l9p_dispatch_tremove, true},
117         {L9P_TSTAT, l9p_dispatch_tstat, false},
118         {L9P_TWALK, l9p_dispatch_twalk, false},
119         {L9P_TWSTAT, l9p_dispatch_twstat, false}
120 };
121 static const struct l9p_handler l9p_handlers_dotu[] = {
122         {L9P_TVERSION, l9p_dispatch_tversion, true},
123         {L9P_TATTACH, l9p_dispatch_tattach, true},
124         {L9P_TCLUNK, l9p_dispatch_tclunk, true},
125         {L9P_TFLUSH, l9p_threadpool_tflush, true},
126         {L9P_TCREATE, l9p_dispatch_tcreate, false},
127         {L9P_TOPEN, l9p_dispatch_topen, false},
128         {L9P_TREAD, l9p_dispatch_tread, false},
129         {L9P_TWRITE, l9p_dispatch_twrite, false},
130         {L9P_TREMOVE, l9p_dispatch_tremove, true},
131         {L9P_TSTAT, l9p_dispatch_tstat, false},
132         {L9P_TWALK, l9p_dispatch_twalk, false},
133         {L9P_TWSTAT, l9p_dispatch_twstat, false}
134 };
135 static const struct l9p_handler l9p_handlers_dotL[] = {
136         {L9P_TVERSION, l9p_dispatch_tversion, true},
137         {L9P_TATTACH, l9p_dispatch_tattach, true},
138         {L9P_TCLUNK, l9p_dispatch_tclunk, true},
139         {L9P_TFLUSH, l9p_threadpool_tflush, true},
140         {L9P_TCREATE, l9p_dispatch_tcreate, false},
141         {L9P_TOPEN, l9p_dispatch_topen, false},
142         {L9P_TREAD, l9p_dispatch_tread, false},
143         {L9P_TWRITE, l9p_dispatch_twrite, false},
144         {L9P_TREMOVE, l9p_dispatch_tremove, true},
145         {L9P_TSTAT, l9p_dispatch_tstat, false},
146         {L9P_TWALK, l9p_dispatch_twalk, false},
147         {L9P_TWSTAT, l9p_dispatch_twstat, false},
148         {L9P_TSTATFS, l9p_dispatch_tstatfs, false},
149         {L9P_TLOPEN, l9p_dispatch_tlopen, false},
150         {L9P_TLCREATE, l9p_dispatch_tlcreate, false},
151         {L9P_TSYMLINK, l9p_dispatch_tsymlink, false},
152         {L9P_TMKNOD, l9p_dispatch_tmknod, false},
153         {L9P_TRENAME, l9p_dispatch_trename, false},
154         {L9P_TREADLINK, l9p_dispatch_treadlink, false},
155         {L9P_TGETATTR, l9p_dispatch_tgetattr, false},
156         {L9P_TSETATTR, l9p_dispatch_tsetattr, false},
157         {L9P_TXATTRWALK, l9p_dispatch_txattrwalk, false},
158         {L9P_TXATTRCREATE, l9p_dispatch_txattrcreate, false},
159         {L9P_TREADDIR, l9p_dispatch_treaddir, false},
160         {L9P_TFSYNC, l9p_dispatch_tfsync, false},
161         {L9P_TLOCK, l9p_dispatch_tlock, true},
162         {L9P_TGETLOCK, l9p_dispatch_tgetlock, true},
163         {L9P_TLINK, l9p_dispatch_tlink, false},
164         {L9P_TMKDIR, l9p_dispatch_tmkdir, false},
165         {L9P_TRENAMEAT, l9p_dispatch_trenameat, false},
166         {L9P_TUNLINKAT, l9p_dispatch_tunlinkat, false},
167 };
168
169 /*
170  * NB: version index 0 is reserved for new connections, and
171  * is a protocol that handles only L9P_TVERSION.  Once we get a
172  * valid version, we start a new session using its dispatch table.
173  */
174 static const struct {
175         const char *name;
176         const struct l9p_handler *handlers;
177         int n_handlers;
178 } l9p_versions[] = {
179         { "<none>", l9p_handlers_no_version, N(l9p_handlers_no_version) },
180         { "9P2000", l9p_handlers_base, N(l9p_handlers_base) },
181         { "9P2000.u", l9p_handlers_dotu, N(l9p_handlers_dotu), },
182         { "9P2000.L", l9p_handlers_dotL, N(l9p_handlers_dotL), },
183 };
184
185 /*
186  * Run the appropriate handler for this request.
187  * It's our caller's responsibility to respond.
188  */
189 int
190 l9p_dispatch_request(struct l9p_request *req)
191 {
192         struct l9p_connection *conn;
193 #if defined(L9P_DEBUG)
194         struct sbuf *sb;
195 #endif
196         size_t i, n;
197         const struct l9p_handler *handlers, *hp;
198         bool flush_requested;
199
200         conn = req->lr_conn;
201         flush_requested = req->lr_flushstate == L9P_FLUSH_REQUESTED_PRE_START;
202
203         handlers = l9p_versions[conn->lc_version].handlers;
204         n = (size_t)l9p_versions[conn->lc_version].n_handlers;
205         for (hp = handlers, i = 0; i < n; hp++, i++)
206                 if (req->lr_req.hdr.type == hp->type)
207                         goto found;
208         hp = NULL;
209 found:
210
211 #if defined(L9P_DEBUG)
212         sb = sbuf_new_auto();
213         if (flush_requested) {
214                 sbuf_cat(sb, "FLUSH requested pre-dispatch");
215                 if (hp != NULL && hp->must_run)
216                         sbuf_cat(sb, ", but must run");
217                 sbuf_cat(sb, ": ");
218         }
219         l9p_describe_fcall(&req->lr_req, conn->lc_version, sb);
220         sbuf_finish(sb);
221
222         L9P_LOG(L9P_DEBUG, "%s", sbuf_data(sb));
223         sbuf_delete(sb);
224 #endif
225
226         if (hp != NULL) {
227                 if (!flush_requested || hp->must_run)
228                         return (hp->handler(req));
229                 return (EINTR);
230         }
231
232         L9P_LOG(L9P_WARNING, "unknown request of type %d",
233             req->lr_req.hdr.type);
234         return (ENOSYS);
235 }
236
237 /*
238  * Translate BSD errno to 9P2000/9P2000.u errno.
239  */
240 static inline int
241 e29p(int errnum)
242 {
243         static int const table[] = {
244                 [ENOTEMPTY] = EPERM,
245                 [EDQUOT] = EPERM,
246                 [ENOSYS] = EPERM,       /* ??? */
247         };
248
249         if ((size_t)errnum < N(table) && table[errnum] != 0)
250                 return (table[errnum]);
251         if (errnum <= ERANGE)
252                 return (errnum);
253         return (EIO);                   /* ??? */
254 }
255
256 /*
257  * Translate BSD errno to Linux errno.
258  */
259 static inline int
260 e2linux(int errnum)
261 {
262         static int const table[] = {
263                 [EDEADLK] = LINUX_EDEADLK,
264                 [EAGAIN] = LINUX_EAGAIN,
265                 [EINPROGRESS] = LINUX_EINPROGRESS,
266                 [EALREADY] = LINUX_EALREADY,
267                 [ENOTSOCK] = LINUX_ENOTSOCK,
268                 [EDESTADDRREQ] = LINUX_EDESTADDRREQ,
269                 [EMSGSIZE] = LINUX_EMSGSIZE,
270                 [EPROTOTYPE] = LINUX_EPROTOTYPE,
271                 [ENOPROTOOPT] = LINUX_ENOPROTOOPT,
272                 [EPROTONOSUPPORT] = LINUX_EPROTONOSUPPORT,
273                 [ESOCKTNOSUPPORT] = LINUX_ESOCKTNOSUPPORT,
274                 [EOPNOTSUPP] = LINUX_EOPNOTSUPP,
275                 [EPFNOSUPPORT] = LINUX_EPFNOSUPPORT,
276                 [EAFNOSUPPORT] = LINUX_EAFNOSUPPORT,
277                 [EADDRINUSE] = LINUX_EADDRINUSE,
278                 [EADDRNOTAVAIL] = LINUX_EADDRNOTAVAIL,
279                 [ENETDOWN] = LINUX_ENETDOWN,
280                 [ENETUNREACH] = LINUX_ENETUNREACH,
281                 [ENETRESET] = LINUX_ENETRESET,
282                 [ECONNABORTED] = LINUX_ECONNABORTED,
283                 [ECONNRESET] = LINUX_ECONNRESET,
284                 [ENOBUFS] = LINUX_ENOBUFS,
285                 [EISCONN] = LINUX_EISCONN,
286                 [ENOTCONN] = LINUX_ENOTCONN,
287                 [ESHUTDOWN] = LINUX_ESHUTDOWN,
288                 [ETOOMANYREFS] = LINUX_ETOOMANYREFS,
289                 [ETIMEDOUT] = LINUX_ETIMEDOUT,
290                 [ECONNREFUSED] = LINUX_ECONNREFUSED,
291                 [ELOOP] = LINUX_ELOOP,
292                 [ENAMETOOLONG] = LINUX_ENAMETOOLONG,
293                 [EHOSTDOWN] = LINUX_EHOSTDOWN,
294                 [EHOSTUNREACH] = LINUX_EHOSTUNREACH,
295                 [ENOTEMPTY] = LINUX_ENOTEMPTY,
296                 [EPROCLIM] = LINUX_EAGAIN,
297                 [EUSERS] = LINUX_EUSERS,
298                 [EDQUOT] = LINUX_EDQUOT,
299                 [ESTALE] = LINUX_ESTALE,
300                 [EREMOTE] = LINUX_EREMOTE,
301                 /* EBADRPC = unmappable? */
302                 /* ERPCMISMATCH = unmappable? */
303                 /* EPROGUNAVAIL = unmappable? */
304                 /* EPROGMISMATCH = unmappable? */
305                 /* EPROCUNAVAIL = unmappable? */
306                 [ENOLCK] = LINUX_ENOLCK,
307                 [ENOSYS] = LINUX_ENOSYS,
308                 /* EFTYPE = unmappable? */
309                 /* EAUTH = unmappable? */
310                 /* ENEEDAUTH = unmappable? */
311                 [EIDRM] = LINUX_EIDRM,
312                 [ENOMSG] = LINUX_ENOMSG,
313                 [EOVERFLOW] = LINUX_EOVERFLOW,
314                 [ECANCELED] = LINUX_ECANCELED,
315                 [EILSEQ] = LINUX_EILSEQ,
316                 /* EDOOFUS = unmappable? */
317                 [EBADMSG] = LINUX_EBADMSG,
318                 [EMULTIHOP] = LINUX_EMULTIHOP,
319                 [ENOLINK] = LINUX_ENOLINK,
320                 [EPROTO] = LINUX_EPROTO,
321                 /* ENOTCAPABLE = unmappable? */
322 #ifdef ECAPMODE
323                 [ECAPMODE] = EPERM,
324 #endif
325 #ifdef ENOTRECOVERABLE
326                 [ENOTRECOVERABLE] = LINUX_ENOTRECOVERABLE,
327 #endif
328 #ifdef EOWNERDEAD
329                 [EOWNERDEAD] = LINUX_EOWNERDEAD,
330 #endif
331         };
332
333         /*
334          * In case we want to return a raw Linux errno, allow negative
335          * values a la Linux kernel internals.
336          *
337          * Values up to ERANGE are shared across systems (see
338          * linux_errno.h), except for EAGAIN.
339          */
340         if (errnum < 0)
341                 return (-errnum);
342
343         if ((size_t)errnum < N(table) && table[errnum] != 0)
344                 return (table[errnum]);
345
346         if (errnum <= ERANGE)
347                 return (errnum);
348
349         L9P_LOG(L9P_WARNING, "cannot map errno %d to anything reasonable",
350             errnum);
351
352         return (LINUX_ENOTRECOVERABLE); /* ??? */
353 }
354
355 /*
356  * Send response to request, or possibly just drop request.
357  * We also need to know whether to remove the request from
358  * the tag hash table.
359  */
360 void
361 l9p_respond(struct l9p_request *req, bool drop, bool rmtag)
362 {
363         struct l9p_connection *conn = req->lr_conn;
364         size_t iosize;
365 #if defined(L9P_DEBUG)
366         struct sbuf *sb;
367         const char *ftype;
368 #endif
369         int error;
370
371         req->lr_resp.hdr.tag = req->lr_req.hdr.tag;
372
373         error = req->lr_error;
374         if (error == 0)
375                 req->lr_resp.hdr.type = req->lr_req.hdr.type + 1;
376         else {
377                 if (conn->lc_version == L9P_2000L) {
378                         req->lr_resp.hdr.type = L9P_RLERROR;
379                         req->lr_resp.error.errnum = (uint32_t)e2linux(error);
380                 } else {
381                         req->lr_resp.hdr.type = L9P_RERROR;
382                         req->lr_resp.error.ename = strerror(error);
383                         req->lr_resp.error.errnum = (uint32_t)e29p(error);
384                 }
385         }
386
387 #if defined(L9P_DEBUG)
388         sb = sbuf_new_auto();
389         l9p_describe_fcall(&req->lr_resp, conn->lc_version, sb);
390         sbuf_finish(sb);
391
392         switch (req->lr_flushstate) {
393         case L9P_FLUSH_NONE:
394                 ftype = "";
395                 break;
396         case L9P_FLUSH_REQUESTED_PRE_START:
397                 ftype = "FLUSH requested pre-dispatch: ";
398                 break;
399         case L9P_FLUSH_REQUESTED_POST_START:
400                 ftype = "FLUSH requested while running: ";
401                 break;
402         case L9P_FLUSH_TOOLATE:
403                 ftype = "FLUSH requested too late: ";
404                 break;
405         }
406         L9P_LOG(L9P_DEBUG, "%s%s%s",
407             drop ? "DROP: " : "", ftype, sbuf_data(sb));
408         sbuf_delete(sb);
409 #endif
410
411         error = drop ? 0 :
412             l9p_pufcall(&req->lr_resp_msg, &req->lr_resp, conn->lc_version);
413         if (rmtag)
414                 ht_remove(&conn->lc_requests, req->lr_req.hdr.tag);
415         if (error != 0) {
416                 L9P_LOG(L9P_ERROR, "cannot pack response");
417                 drop = true;
418         }
419
420         if (drop) {
421                 conn->lc_lt.lt_drop_response(req,
422                     req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov,
423                     conn->lc_lt.lt_aux);
424         } else {
425                 iosize = req->lr_resp_msg.lm_size;
426
427                 /*
428                  * Include I/O size in calculation for Rread and
429                  * Rreaddir responses.
430                  */
431                 if (req->lr_resp.hdr.type == L9P_RREAD ||
432                     req->lr_resp.hdr.type == L9P_RREADDIR)
433                         iosize += req->lr_resp.io.count;
434
435                 conn->lc_lt.lt_send_response(req,
436                     req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov,
437                     iosize, conn->lc_lt.lt_aux);
438         }
439
440         l9p_freefcall(&req->lr_req);
441         l9p_freefcall(&req->lr_resp);
442
443         free(req);
444 }
445
446 /*
447  * This allows a caller to iterate through the data in a
448  * read or write request (creating the data if packing,
449  * scanning through it if unpacking).  This is used for
450  * writing readdir entries, so mode should be L9P_PACK
451  * (but we allow L9P_UNPACK so that debug code can also scan
452  * through the data later, if desired).
453  *
454  * This relies on the Tread op having positioned the request's
455  * iov to the beginning of the data buffer (note the l9p_seek_iov
456  * in l9p_dispatch_tread).
457  */
458 void
459 l9p_init_msg(struct l9p_message *msg, struct l9p_request *req,
460     enum l9p_pack_mode mode)
461 {
462
463         msg->lm_size = 0;
464         msg->lm_mode = mode;
465         msg->lm_cursor_iov = 0;
466         msg->lm_cursor_offset = 0;
467         msg->lm_niov = req->lr_data_niov;
468         memcpy(msg->lm_iov, req->lr_data_iov,
469             sizeof (struct iovec) * req->lr_data_niov);
470 }
471
472 enum fid_lookup_flags {
473         F_REQUIRE_OPEN = 0x01,  /* require that the file be marked OPEN */
474         F_REQUIRE_DIR = 0x02,   /* require that the file be marked ISDIR */
475         F_REQUIRE_XATTR = 0x04, /* require that the file be marked XATTR */
476         F_REQUIRE_AUTH = 0x08,  /* require that the fid be marked AUTH */
477         F_FORBID_OPEN = 0x10,   /* forbid that the file be marked OPEN */
478         F_FORBID_DIR = 0x20,    /* forbid that the file be marked ISDIR */
479         F_FORBID_XATTR = 0x40,  /* forbid that the file be marked XATTR */
480         F_ALLOW_AUTH = 0x80,    /* allow that the fid be marked AUTH */
481 };
482
483 /*
484  * Look up a fid.  It must correspond to a valid file, else we return
485  * the given errno (some "not a valid fid" calls must return EIO and
486  * some must return EINVAL and qemu returns ENOENT in other cases and
487  * so on, so we just provide a general "return this error number").
488  *
489  * Callers may also set constraints: fid must be (or not be) open,
490  * must be (or not be) a directory, must be (or not be) an xattr.
491  *
492  * Only one op has a fid that *must* be an auth fid.  Most ops forbid
493  * auth fids  So instead of FORBID we have ALLOW here and the default
494  * is FORBID.
495  */
496 static inline int
497 fid_lookup(struct l9p_connection *conn, uint32_t fid, int err, int flags,
498     struct l9p_fid **afile)
499 {
500         struct l9p_fid *file;
501
502         file = ht_find(&conn->lc_files, fid);
503         if (file == NULL)
504                 return (err);
505
506         /*
507          * As soon as we go multithreaded / async, this
508          * assert has to become "return EINVAL" or "return err".
509          *
510          * We may also need a way to mark a fid as
511          * "in async op" (valid for some purposes, but cannot be
512          * used elsewhere until async op is completed or aborted).
513          *
514          * For now, this serves for bug-detecting.
515          */
516         assert(l9p_fid_isvalid(file));
517
518         /*
519          * Note that we're inline expanded and flags is constant,
520          * so unnecessary tests just drop out entirely.
521          */
522         if ((flags & F_REQUIRE_OPEN) && !l9p_fid_isopen(file))
523                 return (EINVAL);
524         if ((flags & F_FORBID_OPEN) && l9p_fid_isopen(file))
525                 return (EINVAL);
526         if ((flags & F_REQUIRE_DIR) && !l9p_fid_isdir(file))
527                 return (ENOTDIR);
528         if ((flags & F_FORBID_DIR) && l9p_fid_isdir(file))
529                 return (EISDIR);
530         if ((flags & F_REQUIRE_XATTR) && !l9p_fid_isxattr(file))
531                 return (EINVAL);
532         if ((flags & F_FORBID_XATTR) && l9p_fid_isxattr(file))
533                 return (EINVAL);
534         if (l9p_fid_isauth(file)) {
535                 if ((flags & (F_REQUIRE_AUTH | F_ALLOW_AUTH)) == 0)
536                         return (EINVAL);
537         } else if (flags & F_REQUIRE_AUTH)
538                 return (EINVAL);
539         *afile = file;
540         return (0);
541 }
542
543 /*
544  * Append variable-size stat object and adjust io count.
545  * Returns 0 if the entire stat object was packed, -1 if not.
546  * A fully packed object updates the request's io count.
547  *
548  * Caller must use their own private l9p_message object since
549  * a partially packed object will leave the message object in
550  * a useless state.
551  *
552  * Frees the stat object.
553  */
554 int
555 l9p_pack_stat(struct l9p_message *msg, struct l9p_request *req,
556     struct l9p_stat *st)
557 {
558         struct l9p_connection *conn = req->lr_conn;
559         uint16_t size = l9p_sizeof_stat(st, conn->lc_version);
560         int ret = 0;
561
562         assert(msg->lm_mode == L9P_PACK);
563
564         if (req->lr_resp.io.count + size > req->lr_req.io.count ||
565             l9p_pustat(msg, st, conn->lc_version) < 0)
566                 ret = -1;
567         else
568                 req->lr_resp.io.count += size;
569         l9p_freestat(st);
570         return (ret);
571 }
572
573 static int
574 l9p_dispatch_tversion(struct l9p_request *req)
575 {
576         struct l9p_connection *conn = req->lr_conn;
577         struct l9p_server *server = conn->lc_server;
578         enum l9p_version remote_version = L9P_INVALID_VERSION;
579         size_t i;
580         const char *remote_version_name;
581
582         for (i = 0; i < N(l9p_versions); i++) {
583                 if (strcmp(req->lr_req.version.version,
584                     l9p_versions[i].name) == 0) {
585                         remote_version = (enum l9p_version)i;
586                         break;
587                 }
588         }
589
590         if (remote_version == L9P_INVALID_VERSION) {
591                 L9P_LOG(L9P_ERROR, "unsupported remote version: %s",
592                     req->lr_req.version.version);
593                 return (ENOSYS);
594         }
595
596         remote_version_name = l9p_versions[remote_version].name;
597         L9P_LOG(L9P_INFO, "remote version: %s", remote_version_name);
598         L9P_LOG(L9P_INFO, "local version: %s",
599             l9p_versions[server->ls_max_version].name);
600
601         conn->lc_version = MIN(remote_version, server->ls_max_version);
602         conn->lc_msize = MIN(req->lr_req.version.msize, conn->lc_msize);
603         conn->lc_max_io_size = conn->lc_msize - 24;
604         req->lr_resp.version.version = strdup(remote_version_name);
605         req->lr_resp.version.msize = conn->lc_msize;
606         return (0);
607 }
608
609 static int
610 l9p_dispatch_tattach(struct l9p_request *req)
611 {
612         struct l9p_connection *conn = req->lr_conn;
613         struct l9p_backend *be;
614         struct l9p_fid *fid;
615         int error;
616
617         /*
618          * We still don't have Tauth yet, but let's code this part
619          * anyway.
620          *
621          * Look up the auth fid first since if it fails we can just
622          * return immediately.
623          */
624         if (req->lr_req.tattach.afid != L9P_NOFID) {
625                 error = fid_lookup(conn, req->lr_req.tattach.afid, EINVAL,
626                     F_REQUIRE_AUTH, &req->lr_fid2);
627                 if (error)
628                         return (error);
629         } else
630                 req->lr_fid2 = NULL;
631
632         fid = l9p_connection_alloc_fid(conn, req->lr_req.hdr.fid);
633         if (fid == NULL)
634                 return (EINVAL);
635
636         be = conn->lc_server->ls_backend;
637
638         req->lr_fid = fid;
639
640         /* For backend convenience, set NONUNAME on 9P2000. */
641         if (conn->lc_version == L9P_2000)
642                 req->lr_req.tattach.n_uname = L9P_NONUNAME;
643         error = be->attach(be->softc, req);
644
645         /*
646          * On success, fid becomes valid; on failure, disconnect.
647          * It certainly *should* be a directory here...
648          */
649         if (error == 0) {
650                 l9p_fid_setvalid(fid);
651                 if (req->lr_resp.rattach.qid.type & L9P_QTDIR)
652                         l9p_fid_setdir(fid);
653         } else
654                 l9p_connection_remove_fid(conn, fid);
655         return (error);
656 }
657
658 static int
659 l9p_dispatch_tclunk(struct l9p_request *req)
660 {
661         struct l9p_connection *conn = req->lr_conn;
662         struct l9p_backend *be;
663         struct l9p_fid *fid;
664         int error;
665
666         /* Note that clunk is the only way to dispose of an auth fid. */
667         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
668             F_ALLOW_AUTH, &fid);
669         if (error)
670                 return (error);
671
672         be = conn->lc_server->ls_backend;
673         l9p_fid_unsetvalid(fid);
674
675         /*
676          * If it's an xattr fid there must, by definition, be an
677          * xattrclunk.  The xattrclunk function can only be NULL if
678          * xattrwalk and xattrcreate are NULL or always return error.
679          *
680          * Q: do we want to allow async xattrclunk in case of very
681          * large xattr create?  This will make things difficult,
682          * so probably not.
683          */
684         if (l9p_fid_isxattr(fid))
685                 error = be->xattrclunk(be->softc, fid);
686         else
687                 error = be->clunk(be->softc, fid);
688
689         /* fid is now gone regardless of any error return */
690         l9p_connection_remove_fid(conn, fid);
691         return (error);
692 }
693
694 static int
695 l9p_dispatch_tcreate(struct l9p_request *req)
696 {
697         struct l9p_connection *conn = req->lr_conn;
698         struct l9p_backend *be;
699         uint32_t dmperm;
700         int error;
701
702         /* Incoming fid must represent a directory that has not been opened. */
703         error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL,
704             F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
705         if (error)
706                 return (error);
707
708         be = conn->lc_server->ls_backend;
709         dmperm = req->lr_req.tcreate.perm;
710 #define MKDIR_OR_SIMILAR \
711     (L9P_DMDIR | L9P_DMSYMLINK | L9P_DMNAMEDPIPE | L9P_DMSOCKET | L9P_DMDEVICE)
712
713         /*
714          * TODO:
715          *  - check new file name
716          *  - break out different kinds of create (file vs mkdir etc)
717          *  - add async file-create (leaves req->lr_fid in limbo)
718          *
719          * A successful file-create changes the fid into an open file.
720          */
721         error = be->create(be->softc, req);
722         if (error == 0 && (dmperm & MKDIR_OR_SIMILAR) == 0) {
723                 l9p_fid_unsetdir(req->lr_fid);
724                 l9p_fid_setopen(req->lr_fid);
725         }
726
727         return (error);
728 }
729
730 static int
731 l9p_dispatch_topen(struct l9p_request *req)
732 {
733         struct l9p_connection *conn = req->lr_conn;
734         struct l9p_backend *be;
735         int error;
736
737         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
738             F_FORBID_OPEN | F_FORBID_XATTR, &req->lr_fid);
739         if (error)
740                 return (error);
741
742         be = conn->lc_server->ls_backend;
743
744         /*
745          * TODO:
746          *  - add async open (leaves req->lr_fid in limbo)
747          */
748         error = be->open(be->softc, req);
749         if (error == 0)
750                 l9p_fid_setopen(req->lr_fid);
751         return (error);
752 }
753
754 static int
755 l9p_dispatch_tread(struct l9p_request *req)
756 {
757         struct l9p_connection *conn = req->lr_conn;
758         struct l9p_backend *be;
759         struct l9p_fid *fid;
760         int error;
761
762         /* Xattr fids are not open, so we need our own tests. */
763         error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 0, &req->lr_fid);
764         if (error)
765                 return (error);
766
767         /*
768          * Adjust so that writing messages (packing data) starts
769          * right after the count field in the response.
770          *
771          * size[4] + Rread[1] + tag[2] + count[4] = 11
772          */
773         l9p_seek_iov(req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov,
774             req->lr_data_iov, &req->lr_data_niov, 11);
775
776         /*
777          * If it's an xattr fid there must, by definition, be an
778          * xattrread.  The xattrread function can only be NULL if
779          * xattrwalk and xattrcreate are NULL or always return error.
780          *
781          * TODO:
782          *   separate out directory-read
783          *   allow async read
784          */
785         be = conn->lc_server->ls_backend;
786         fid = req->lr_fid;
787         if (l9p_fid_isxattr(fid)) {
788                 error = be->xattrread(be->softc, req);
789         } else if (l9p_fid_isopen(fid)) {
790                 error = be->read(be->softc, req);
791         } else {
792                 error = EINVAL;
793         }
794
795         return (error);
796 }
797
798 static int
799 l9p_dispatch_tremove(struct l9p_request *req)
800 {
801         struct l9p_connection *conn = req->lr_conn;
802         struct l9p_backend *be;
803         struct l9p_fid *fid;
804         int error;
805
806         /*
807          * ?? Should we allow Tremove on auth fids? If so, do
808          * we pretend it is just a Tclunk?
809          */
810         error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 0, &fid);
811         if (error)
812                 return (error);
813
814         be = conn->lc_server->ls_backend;
815         l9p_fid_unsetvalid(fid);
816
817         error = be->remove(be->softc, fid);
818         /* fid is now gone regardless of any error return */
819         l9p_connection_remove_fid(conn, fid);
820         return (error);
821 }
822
823 static int
824 l9p_dispatch_tstat(struct l9p_request *req)
825 {
826         struct l9p_connection *conn = req->lr_conn;
827         struct l9p_backend *be;
828         struct l9p_fid *fid;
829         int error;
830
831         /* Allow Tstat on auth fid?  Seems harmless enough... */
832         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
833             F_ALLOW_AUTH, &fid);
834         if (error)
835                 return (error);
836
837         be = conn->lc_server->ls_backend;
838         req->lr_fid = fid;
839         error = be->stat(be->softc, req);
840
841         if (error == 0) {
842                 if (l9p_fid_isauth(fid))
843                         req->lr_resp.rstat.stat.qid.type |= L9P_QTAUTH;
844
845                 /* should we check req->lr_resp.rstat.qid.type L9P_QTDIR bit? */
846                 if (req->lr_resp.rstat.stat.qid.type &= L9P_QTDIR)
847                         l9p_fid_setdir(fid);
848                 else
849                         l9p_fid_unsetdir(fid);
850         }
851
852         return (error);
853 }
854
855 static int
856 l9p_dispatch_twalk(struct l9p_request *req)
857 {
858         struct l9p_connection *conn = req->lr_conn;
859         struct l9p_backend *be;
860         struct l9p_fid *fid, *newfid;
861         uint16_t n;
862         int error;
863
864         /* Can forbid XATTR, but cannot require DIR. */
865         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
866             F_FORBID_XATTR, &fid);
867         if (error)
868                 return (error);
869
870         if (req->lr_req.twalk.hdr.fid != req->lr_req.twalk.newfid) {
871                 newfid = l9p_connection_alloc_fid(conn,
872                     req->lr_req.twalk.newfid);
873                 if (newfid == NULL)
874                         return (EINVAL);
875         } else
876                 newfid = fid;
877
878         be = conn->lc_server->ls_backend;
879         req->lr_fid = fid;
880         req->lr_newfid = newfid;
881         error = be->walk(be->softc, req);
882
883         /*
884          * If newfid == fid, then fid itself has (potentially) changed,
885          * but is still valid.  Otherwise set newfid valid on
886          * success, and destroy it on error.
887          */
888         if (newfid != fid) {
889                 if (error == 0)
890                         l9p_fid_setvalid(newfid);
891                 else
892                         l9p_connection_remove_fid(conn, newfid);
893         }
894
895         /*
896          * If we walked any name elements, the last (n-1'th) qid
897          * has the type (dir vs file) for the new fid.  Otherwise
898          * the type of newfid is the same as fid.  Of course, if
899          * n==0 and fid==newfid, fid is already set up correctly
900          * as the whole thing was a big no-op, but it's safe to
901          * copy its dir bit to itself.
902          */
903         if (error == 0) {
904                 n = req->lr_resp.rwalk.nwqid;
905                 if (n > 0) {
906                         if (req->lr_resp.rwalk.wqid[n - 1].type & L9P_QTDIR)
907                                 l9p_fid_setdir(newfid);
908                 } else {
909                         if (l9p_fid_isdir(fid))
910                                 l9p_fid_setdir(newfid);
911                 }
912         }
913         return (error);
914 }
915
916 static int
917 l9p_dispatch_twrite(struct l9p_request *req)
918 {
919         struct l9p_connection *conn = req->lr_conn;
920         struct l9p_backend *be;
921         struct l9p_fid *fid;
922         int error;
923
924         /* Cannot require open due to xattr write, but can forbid dir. */
925         error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL,
926             F_FORBID_DIR, &req->lr_fid);
927         if (error)
928                 return (error);
929
930         /*
931          * Adjust to point to the data to be written (a la
932          * l9p_dispatch_tread, but we're pointing into the request
933          * buffer rather than the response):
934          *
935          * size[4] + Twrite[1] + tag[2] + fid[4] + offset[8] + count[4] = 23
936          */
937         l9p_seek_iov(req->lr_req_msg.lm_iov, req->lr_req_msg.lm_niov,
938             req->lr_data_iov, &req->lr_data_niov, 23);
939
940         /*
941          * Unlike read, write and xattrwrite are optional (for R/O fs).
942          *
943          * TODO:
944          *   allow async write
945          */
946         be = conn->lc_server->ls_backend;
947         fid = req->lr_fid;
948         if (l9p_fid_isxattr(fid)) {
949                 error = be->xattrwrite != NULL ?
950                     be->xattrwrite(be->softc, req) : ENOSYS;
951         } else if (l9p_fid_isopen(fid)) {
952                 error = be->write != NULL ?
953                     be->write(be->softc, req) : ENOSYS;
954         } else {
955                 error = EINVAL;
956         }
957
958         return (error);
959 }
960
961 static int
962 l9p_dispatch_twstat(struct l9p_request *req)
963 {
964         struct l9p_connection *conn = req->lr_conn;
965         struct l9p_backend *be;
966         int error;
967
968         error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL,
969             F_FORBID_XATTR, &req->lr_fid);
970         if (error)
971                 return (error);
972
973         be = conn->lc_server->ls_backend;
974         error = be->wstat != NULL ? be->wstat(be->softc, req) : ENOSYS;
975         return (error);
976 }
977
978 static int
979 l9p_dispatch_tstatfs(struct l9p_request *req)
980 {
981         struct l9p_connection *conn = req->lr_conn;
982         struct l9p_backend *be;
983         int error;
984
985         /* Should we allow statfs on auth fids? */
986         error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 0, &req->lr_fid);
987         if (error)
988                 return (error);
989
990         be = conn->lc_server->ls_backend;
991         error = be->statfs(be->softc, req);
992         return (error);
993 }
994
995 static int
996 l9p_dispatch_tlopen(struct l9p_request *req)
997 {
998         struct l9p_connection *conn = req->lr_conn;
999         struct l9p_backend *be;
1000         int error;
1001
1002         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1003             F_FORBID_OPEN | F_FORBID_XATTR, &req->lr_fid);
1004         if (error)
1005                 return (error);
1006
1007         be = conn->lc_server->ls_backend;
1008
1009         /*
1010          * TODO:
1011          *  - add async open (leaves req->lr_fid in limbo)
1012          */
1013         error = be->lopen != NULL ? be->lopen(be->softc, req) : ENOSYS;
1014         if (error == 0)
1015                 l9p_fid_setopen(req->lr_fid);
1016         return (error);
1017 }
1018
1019 static int
1020 l9p_dispatch_tlcreate(struct l9p_request *req)
1021 {
1022         struct l9p_connection *conn = req->lr_conn;
1023         struct l9p_backend *be;
1024         int error;
1025
1026         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1027             F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
1028         if (error)
1029                 return (error);
1030
1031         be = conn->lc_server->ls_backend;
1032
1033         /*
1034          * TODO:
1035          *  - check new file name
1036          *  - add async create (leaves req->lr_fid in limbo)
1037          */
1038         error = be->lcreate != NULL ? be->lcreate(be->softc, req) : ENOSYS;
1039         if (error == 0) {
1040                 l9p_fid_unsetdir(req->lr_fid);
1041                 l9p_fid_setopen(req->lr_fid);
1042         }
1043         return (error);
1044 }
1045
1046 static int
1047 l9p_dispatch_tsymlink(struct l9p_request *req)
1048 {
1049         struct l9p_connection *conn = req->lr_conn;
1050         struct l9p_backend *be;
1051         int error;
1052
1053         /* This doesn't affect the containing dir; maybe allow OPEN? */
1054         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1055             F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
1056         if (error)
1057                 return (error);
1058
1059         be = conn->lc_server->ls_backend;
1060
1061         /*
1062          * TODO:
1063          *  - check new file name
1064          */
1065         error = be->symlink != NULL ? be->symlink(be->softc, req) : ENOSYS;
1066         return (error);
1067 }
1068
1069 static int
1070 l9p_dispatch_tmknod(struct l9p_request *req)
1071 {
1072         struct l9p_connection *conn = req->lr_conn;
1073         struct l9p_backend *be;
1074         int error;
1075
1076         /* This doesn't affect the containing dir; maybe allow OPEN? */
1077         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1078             F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
1079         if (error)
1080                 return (error);
1081
1082         be = conn->lc_server->ls_backend;
1083
1084         /*
1085          * TODO:
1086          *  - check new file name
1087          */
1088         error = be->mknod != NULL ? be->mknod(be->softc, req) : ENOSYS;
1089         return (error);
1090 }
1091
1092 static int
1093 l9p_dispatch_trename(struct l9p_request *req)
1094 {
1095         struct l9p_connection *conn = req->lr_conn;
1096         struct l9p_backend *be;
1097         int error;
1098
1099         /* Rename directory or file (including symlink etc). */
1100         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1101             F_FORBID_XATTR, &req->lr_fid);
1102         if (error)
1103                 return (error);
1104
1105         /* Doesn't affect new dir fid; maybe allow OPEN? */
1106         error = fid_lookup(conn, req->lr_req.trename.dfid, ENOENT,
1107             F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid2);
1108         if (error)
1109                 return (error);
1110
1111         be = conn->lc_server->ls_backend;
1112
1113         /*
1114          * TODO:
1115          *  - check new file name (trename.name)
1116          */
1117         error = be->rename != NULL ? be->rename(be->softc, req) : ENOSYS;
1118         return (error);
1119 }
1120
1121 static int
1122 l9p_dispatch_treadlink(struct l9p_request *req)
1123 {
1124         struct l9p_connection *conn = req->lr_conn;
1125         struct l9p_backend *be;
1126         int error;
1127
1128         /*
1129          * The underlying readlink will fail unless it's a symlink,
1130          * and the back end has to check, but we might as well forbid
1131          * directories and open files here since it's cheap.
1132          */
1133         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1134             F_FORBID_DIR | F_FORBID_OPEN, &req->lr_fid);
1135         if (error)
1136                 return (error);
1137
1138         be = conn->lc_server->ls_backend;
1139
1140         error = be->readlink != NULL ? be->readlink(be->softc, req) : ENOSYS;
1141         return (error);
1142 }
1143
1144 static int
1145 l9p_dispatch_tgetattr(struct l9p_request *req)
1146 {
1147         struct l9p_connection *conn = req->lr_conn;
1148         struct l9p_backend *be;
1149         int error;
1150
1151         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1152             F_FORBID_XATTR, &req->lr_fid);
1153         if (error)
1154                 return (error);
1155
1156         be = conn->lc_server->ls_backend;
1157
1158         error = be->getattr != NULL ? be->getattr(be->softc, req) : ENOSYS;
1159         return (error);
1160 }
1161
1162 static int
1163 l9p_dispatch_tsetattr(struct l9p_request *req)
1164 {
1165         struct l9p_connection *conn = req->lr_conn;
1166         struct l9p_backend *be;
1167         int error;
1168
1169         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1170             F_FORBID_XATTR, &req->lr_fid);
1171         if (error)
1172                 return (error);
1173
1174         be = conn->lc_server->ls_backend;
1175
1176         error = be->setattr != NULL ? be->setattr(be->softc, req) : ENOSYS;
1177         return (error);
1178 }
1179
1180 static int
1181 l9p_dispatch_txattrwalk(struct l9p_request *req)
1182 {
1183         struct l9p_connection *conn = req->lr_conn;
1184         struct l9p_backend *be;
1185         struct l9p_fid *fid, *newfid;
1186         int error;
1187
1188         /*
1189          * Not sure if we care if file-or-dir is open or not.
1190          * However, the fid argument should always be a file or
1191          * dir and the newfid argument must be supplied, must
1192          * be different, and always becomes a new xattr,
1193          * so this is not very much like Twalk.
1194          */
1195         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1196             F_FORBID_XATTR, &fid);
1197         if (error)
1198                 return (error);
1199
1200         newfid = l9p_connection_alloc_fid(conn, req->lr_req.txattrwalk.newfid);
1201         if (newfid == NULL)
1202                 return (EINVAL);
1203
1204         be = conn->lc_server->ls_backend;
1205
1206         req->lr_fid = fid;
1207         req->lr_newfid = newfid;
1208         error = be->xattrwalk != NULL ? be->xattrwalk(be->softc, req) : ENOSYS;
1209
1210         /*
1211          * Success/fail is similar to Twalk, except that we need
1212          * to set the xattr type bit in the new fid.  It's also
1213          * much simpler since newfid is always a new fid.
1214          */
1215         if (error == 0) {
1216                 l9p_fid_setvalid(newfid);
1217                 l9p_fid_setxattr(newfid);
1218         } else {
1219                 l9p_connection_remove_fid(conn, newfid);
1220         }
1221         return (error);
1222 }
1223
1224 static int
1225 l9p_dispatch_txattrcreate(struct l9p_request *req)
1226 {
1227         struct l9p_connection *conn = req->lr_conn;
1228         struct l9p_backend *be;
1229         struct l9p_fid *fid;
1230         int error;
1231
1232         /*
1233          * Forbid incoming open fid since it's going to become an
1234          * xattr fid instead.  If it turns out we need to allow
1235          * it, fs code will need to handle this.
1236          *
1237          * Curiously, qemu 9pfs uses ENOENT for a bad txattrwalk
1238          * fid, but EINVAL for txattrcreate (so we do too).
1239          */
1240         error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL,
1241             F_FORBID_XATTR | F_FORBID_OPEN, &fid);
1242         if (error)
1243                 return (error);
1244
1245         be = conn->lc_server->ls_backend;
1246
1247         req->lr_fid = fid;
1248         error = be->xattrcreate != NULL ? be->xattrcreate(be->softc, req) :
1249             ENOSYS;
1250
1251         /*
1252          * On success, fid has changed from a regular (file or dir)
1253          * fid to an xattr fid.
1254          */
1255         if (error == 0) {
1256                 l9p_fid_unsetdir(fid);
1257                 l9p_fid_setxattr(fid);
1258         }
1259         return (error);
1260 }
1261
1262 static int
1263 l9p_dispatch_treaddir(struct l9p_request *req)
1264 {
1265         struct l9p_connection *conn = req->lr_conn;
1266         struct l9p_backend *be;
1267         int error;
1268
1269         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1270             F_REQUIRE_DIR | F_REQUIRE_OPEN, &req->lr_fid);
1271         if (error)
1272                 return (error);
1273
1274         /*
1275          * Adjust so that writing messages (packing data) starts
1276          * right after the count field in the response.
1277          *
1278          * size[4] + Rreaddir[1] + tag[2] + count[4] = 11
1279          */
1280         l9p_seek_iov(req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov,
1281             req->lr_data_iov, &req->lr_data_niov, 11);
1282
1283         be = conn->lc_server->ls_backend;
1284
1285         error = be->readdir != NULL ? be->readdir(be->softc, req) : ENOSYS;
1286         return (error);
1287 }
1288
1289 static int
1290 l9p_dispatch_tfsync(struct l9p_request *req)
1291 {
1292         struct l9p_connection *conn = req->lr_conn;
1293         struct l9p_backend *be;
1294         int error;
1295
1296         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1297             F_REQUIRE_OPEN, &req->lr_fid);
1298         if (error)
1299                 return (error);
1300
1301         be = conn->lc_server->ls_backend;
1302
1303         error = be->fsync != NULL ? be->fsync(be->softc, req) : ENOSYS;
1304         return (error);
1305 }
1306
1307 static int
1308 l9p_dispatch_tlock(struct l9p_request *req)
1309 {
1310         struct l9p_connection *conn = req->lr_conn;
1311         struct l9p_backend *be;
1312         int error;
1313
1314         /* Forbid directories? */
1315         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1316             F_REQUIRE_OPEN, &req->lr_fid);
1317         if (error)
1318                 return (error);
1319
1320         be = conn->lc_server->ls_backend;
1321
1322         /*
1323          * TODO: multiple client handling; perhaps async locking.
1324          */
1325         error = be->lock != NULL ? be->lock(be->softc, req) : ENOSYS;
1326         return (error);
1327 }
1328
1329 static int
1330 l9p_dispatch_tgetlock(struct l9p_request *req)
1331 {
1332         struct l9p_connection *conn = req->lr_conn;
1333         struct l9p_backend *be;
1334         int error;
1335
1336         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1337             F_REQUIRE_OPEN, &req->lr_fid);
1338         if (error)
1339                 return (error);
1340
1341         be = conn->lc_server->ls_backend;
1342
1343         /*
1344          * TODO: multiple client handling; perhaps async locking.
1345          */
1346         error = be->getlock != NULL ? be->getlock(be->softc, req) : ENOSYS;
1347         return (error);
1348 }
1349
1350 static int
1351 l9p_dispatch_tlink(struct l9p_request *req)
1352 {
1353         struct l9p_connection *conn = req->lr_conn;
1354         struct l9p_backend *be;
1355         int error;
1356
1357         /*
1358          * Note, dfid goes into fid2 in current scheme.
1359          *
1360          * Allow open dir?  Target dir fid is not modified...
1361          */
1362         error = fid_lookup(conn, req->lr_req.tlink.dfid, ENOENT,
1363             F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid2);
1364         if (error)
1365                 return (error);
1366
1367         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1368             F_FORBID_DIR | F_FORBID_XATTR, &req->lr_fid);
1369         if (error)
1370                 return (error);
1371
1372         be = conn->lc_server->ls_backend;
1373
1374         error = be->link != NULL ? be->link(be->softc, req) : ENOSYS;
1375         return (error);
1376 }
1377
1378 static int
1379 l9p_dispatch_tmkdir(struct l9p_request *req)
1380 {
1381         struct l9p_connection *conn = req->lr_conn;
1382         struct l9p_backend *be;
1383         int error;
1384
1385         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1386             F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
1387         if (error)
1388                 return (error);
1389
1390         /* Slashes embedded in the name are not allowed */
1391         if (strchr(req->lr_req.tlcreate.name, '/') != NULL)
1392                 return (EINVAL);
1393
1394         be = conn->lc_server->ls_backend;
1395         error = be->mkdir != NULL ? be->mkdir(be->softc, req) : ENOSYS;
1396         return (error);
1397 }
1398
1399 static int
1400 l9p_dispatch_trenameat(struct l9p_request *req)
1401 {
1402         struct l9p_connection *conn = req->lr_conn;
1403         struct l9p_backend *be;
1404         int error;
1405
1406         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1407             F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
1408         if (error)
1409                 return (error);
1410
1411         error = fid_lookup(conn, req->lr_req.trenameat.newdirfid, ENOENT,
1412             F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid2);
1413         if (error)
1414                 return (error);
1415
1416         be = conn->lc_server->ls_backend;
1417
1418         /* TODO: check old and new names */
1419         error = be->renameat != NULL ? be->renameat(be->softc, req) : ENOSYS;
1420         return (error);
1421 }
1422
1423 static int
1424 l9p_dispatch_tunlinkat(struct l9p_request *req)
1425 {
1426         struct l9p_connection *conn = req->lr_conn;
1427         struct l9p_backend *be;
1428         int error;
1429
1430         error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1431             F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
1432         if (error)
1433                 return (error);
1434
1435         be = conn->lc_server->ls_backend;
1436
1437         /* TODO: check dir-or-file name */
1438         error = be->unlinkat != NULL ? be->unlinkat(be->softc, req) : ENOSYS;
1439         return (error);
1440 }