Initial import of binutils 2.22 on the new vendor branch
[dragonfly.git] / sys / vfs / userfs / userfs_vnops.c
1 /*
2  * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  * 
34  * $DragonFly: src/sys/vfs/userfs/userfs_vnops.c,v 1.4 2007/11/20 21:03:51 dillon Exp $
35  */
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/fcntl.h>
41 #include <sys/namecache.h>
42 #include <sys/vnode.h>
43 #include <sys/lockf.h>
44 #include <sys/event.h>
45 #include <sys/stat.h>
46 #include <sys/syslink.h>
47 #include <sys/syslink_vfs.h>
48 #include <sys/unistd.h>
49 #include <vm/vnode_pager.h>
50
51 #include <sys/buf2.h>
52
53 #include "userfs.h"
54
55 /*
56  * USERFS VNOPS
57  */
58 /*static int user_vop_vnoperate(struct vop_generic_args *);*/
59 static int user_vop_fsync (struct vop_fsync_args *);
60 static int user_vop_read (struct vop_read_args *);
61 static int user_vop_write (struct vop_write_args *);
62 static int user_vop_access (struct vop_access_args *);
63 static int user_vop_advlock (struct vop_advlock_args *);
64 static int user_vop_close (struct vop_close_args *);
65 static int user_vop_ncreate (struct vop_ncreate_args *);
66 static int user_vop_getattr (struct vop_getattr_args *);
67 static int user_vop_nresolve (struct vop_nresolve_args *);
68 static int user_vop_nlookupdotdot (struct vop_nlookupdotdot_args *);
69 static int user_vop_nlink (struct vop_nlink_args *);
70 static int user_vop_nmkdir (struct vop_nmkdir_args *);
71 static int user_vop_nmknod (struct vop_nmknod_args *);
72 static int user_vop_open (struct vop_open_args *);
73 static int user_vop_pathconf (struct vop_pathconf_args *);
74 static int user_vop_print (struct vop_print_args *);
75 static int user_vop_readdir (struct vop_readdir_args *);
76 static int user_vop_readlink (struct vop_readlink_args *);
77 static int user_vop_nremove (struct vop_nremove_args *);
78 static int user_vop_nrename (struct vop_nrename_args *);
79 static int user_vop_nrmdir (struct vop_nrmdir_args *);
80 static int user_vop_setattr (struct vop_setattr_args *);
81 static int user_vop_strategy (struct vop_strategy_args *);
82 static int user_vop_nsymlink (struct vop_nsymlink_args *);
83 static int user_vop_nwhiteout (struct vop_nwhiteout_args *);
84 static int user_vop_bmap (struct vop_bmap_args *);
85
86 struct vop_ops userfs_vnode_vops = {
87         .vop_default =          vop_defaultop,
88         .vop_fsync =            user_vop_fsync,
89         .vop_getpages =         vop_stdgetpages,
90         .vop_putpages =         vop_stdputpages,
91         .vop_read =             user_vop_read,
92         .vop_write =            user_vop_write,
93         .vop_access =           user_vop_access,
94         .vop_advlock =          user_vop_advlock,
95         .vop_close =            user_vop_close,
96         .vop_ncreate =          user_vop_ncreate,
97         .vop_getattr =          user_vop_getattr,
98         .vop_inactive =         user_vop_inactive,
99         .vop_reclaim =          user_vop_reclaim,
100         .vop_nresolve =         user_vop_nresolve,
101         .vop_nlookupdotdot =    user_vop_nlookupdotdot,
102         .vop_nlink =            user_vop_nlink,
103         .vop_nmkdir =           user_vop_nmkdir,
104         .vop_nmknod =           user_vop_nmknod,
105         .vop_open =             user_vop_open,
106         .vop_pathconf =         user_vop_pathconf,
107         .vop_print =            user_vop_print,
108         .vop_readdir =          user_vop_readdir,
109         .vop_readlink =         user_vop_readlink,
110         .vop_nremove =          user_vop_nremove,
111         .vop_nrename =          user_vop_nrename,
112         .vop_nrmdir =           user_vop_nrmdir,
113         .vop_setattr =          user_vop_setattr,
114         .vop_strategy =         user_vop_strategy,
115         .vop_nsymlink =         user_vop_nsymlink,
116         .vop_nwhiteout =        user_vop_nwhiteout,
117         .vop_bmap =             user_vop_bmap
118 };
119
120 #if 0
121 static
122 int
123 user_vop_vnoperate(struct vop_generic_args *)
124 {
125         return (VOCALL(&userfs_vnode_vops, ap));
126 }
127 #endif
128
129 /*
130  * vop_fsync(struct vnode *vp, int waitfor)
131  */
132 static
133 int
134 user_vop_fsync (struct vop_fsync_args *ap)
135 {
136         struct user_mount *ump;
137         struct user_inode *ip;
138         struct vnode *vp;
139         struct slmsg *slmsg;
140         syslink_elm_t par;
141         int error;
142
143         vp = ap->a_vp;
144         ip = vp->v_data;
145         ump = ip->ump;
146
147         slmsg = syslink_kallocmsg();
148         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
149                               SLVFS_CMD_VOP_FSYNC);
150         user_elm_push_vnode(par, ap->a_vp);
151         sl_msg_fini(slmsg->msg);
152
153         kprintf("userfs_fsync\n");
154         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
155                 par = &slmsg->rep->msg->sm_head;
156
157                 if (par->se_cmd == (SLVFS_CMD_VOP_FSYNC|SE_CMDF_REPLY)) {
158                         ;
159                 } else {
160                         error = EBADRPC;
161                 }
162         }
163         syslink_kfreemsg(ump->sldesc, slmsg);
164         kprintf("error %d\n", error);
165         return(error);
166 }
167
168 /*
169  * vop_read(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
170  */
171 static
172 int
173 user_vop_read (struct vop_read_args *ap)
174 {
175         struct user_mount *ump;
176         struct user_inode *ip;
177         struct vnode *vp;
178         struct uio *uio;
179         struct buf *bp;
180         int error;
181         int offset;
182         int n;
183
184         vp = ap->a_vp;
185         ip = vp->v_data;
186         ump = ip->ump;
187         uio = ap->a_uio;
188
189         if (uio->uio_offset < 0)
190                 return (EINVAL);
191         if (vp->v_type != VREG)
192                 return (EINVAL);
193
194         kprintf("userfs_read\n");
195         error = 0;
196         while (uio->uio_resid > 0 && uio->uio_offset < ip->filesize) {
197                 /*
198                  * Use buffer cache I/O (via user_vop_strategy), aligned
199                  * on USERFS_BSIZE boundaries.
200                  */
201                 offset = (int)uio->uio_offset & USERFS_BMASK;
202                 error = bread(vp, uio->uio_offset - offset, USERFS_BSIZE, &bp);
203                 if (error) {
204                         brelse(bp);
205                         break;
206                 }
207
208                 /*
209                  * Figure out how many bytes we can actually copy this loop.
210                  */
211                 n = USERFS_BSIZE - offset;
212                 if (n > uio->uio_resid)
213                         n = uio->uio_resid;
214                 if (n > ip->filesize - uio->uio_offset)
215                         n = (int)(ip->filesize - uio->uio_offset);
216
217                 error = uiomove((char *)bp->b_data + offset, n, uio);
218                 bqrelse(bp);
219                 if (error)
220                         break;
221         }
222         kprintf("userfs_read error %d\n", error);
223         return(error);
224 }
225
226 /*
227  * vop_write(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
228  */
229 static
230 int
231 user_vop_write (struct vop_write_args *ap)
232 {
233         struct user_mount *ump;
234         struct user_inode *ip;
235         struct vnode *vp;
236         struct buf *bp;
237         struct uio *uio;
238         int error;
239         off_t loffset;
240         size_t offset;
241         size_t n;
242
243         vp = ap->a_vp;
244         ip = vp->v_data;
245         ump = ip->ump;
246         uio = ap->a_uio;
247
248         if (vp->v_type != VREG)
249                 return (EINVAL);
250         if (ap->a_ioflag & IO_APPEND)
251                 uio->uio_offset = ip->filesize;
252
253         /*
254          * Check for illegal write offsets.  Valid range is 0...2^63-1
255          */
256         loffset = uio->uio_offset;
257         if (loffset < 0)
258                 return (EFBIG);
259         if (uio->uio_resid) {
260                 /* GCC4 - workaround optimization */
261                 loffset += uio->uio_resid;
262                 if (loffset <= 0)
263                         return (EFBIG);
264         }
265
266         kprintf("userfs_write\n");
267         error = 0;
268         while (uio->uio_resid > 0) {
269                 /*
270                  * Use buffer cache I/O (via user_vop_strategy), aligned
271                  * on USERFS_BSIZE boundaries.
272                  *
273                  * XXX not optimized for complete write-overs or file
274                  * extensions.  Note: must bread on UIO_NOCOPY writes.
275                  *
276                  * XXX No need to read if strictly appending.
277                  */
278                 offset = (size_t)uio->uio_offset & USERFS_BMASK;
279                 /* if offset == ip->filesize use getblk instead */
280                 error = bread(vp, uio->uio_offset - offset, USERFS_BSIZE, &bp);
281                 if (error) {
282                         brelse(bp);
283                         break;
284                 }
285
286                 /*
287                  * Figure out how many bytes we can actually copy this loop.
288                  */
289                 n = USERFS_BSIZE - offset;
290                 if (n > uio->uio_resid)
291                         n = uio->uio_resid;
292                 if (n > ip->filesize - uio->uio_offset)
293                         n = (size_t)(ip->filesize - uio->uio_offset);
294
295                 error = uiomove((char *)bp->b_data + offset, n, uio);
296                 if (error) {
297                         brelse(bp);
298                         break;
299                 }
300
301                 /*
302                  * Extend the file's size if necessary
303                  */
304                 if (ip->filesize < uio->uio_offset)
305                         ip->filesize = uio->uio_offset;
306
307                 /*
308                  * The data has been loaded into the buffer, write it out.
309                  */
310                 if (ap->a_ioflag & IO_SYNC) {
311                         bwrite(bp);
312                 } else if (ap->a_ioflag & IO_DIRECT) {
313                         bp->b_flags |= B_CLUSTEROK;
314                         bawrite(bp);
315                 } else {
316                         bp->b_flags |= B_CLUSTEROK;
317                         bdwrite(bp);
318                 }
319         }
320         kprintf("userfs_write error %d\n", error);
321         return(error);
322 }
323
324 /*
325  * vop_access(struct vnode *vp, int mode, struct ucred *cred)
326  */
327 static
328 int
329 user_vop_access (struct vop_access_args *ap)
330 {
331         struct user_mount *ump;
332         struct user_inode *ip;
333         struct vnode *vp;
334         struct slmsg *slmsg;
335         syslink_elm_t par;
336         int error;
337
338         vp = ap->a_vp;
339         ip = vp->v_data;
340         ump = ip->ump;
341
342         slmsg = syslink_kallocmsg();
343         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
344                               SLVFS_CMD_VOP_ACCESS);
345         user_elm_push_vnode(par, vp);
346         user_elm_push_mode(par, ap->a_mode);
347         user_elm_push_cred(par, ap->a_cred);
348         sl_msg_fini(slmsg->msg);
349
350         /*
351          * Issue the request and do basic validation of the response
352          */
353         kprintf("userfs_access\n");
354         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) != 0)
355                 goto done;
356         par = &slmsg->rep->msg->sm_head;
357         if (par->se_cmd != (SLVFS_CMD_VOP_ACCESS|SE_CMDF_REPLY)) {
358                 error = EBADRPC;
359                 goto done;
360         }
361
362 done:
363         syslink_kfreemsg(ump->sldesc, slmsg);
364         kprintf("error %d\n", error);
365         return(error);
366 }
367
368 /*
369  * vop_advlock(struct vnode *vp, caddr_t id, int op, struct flock *fl,
370  *             int flags)
371  *
372  * This vop is handled directly by the kernel.
373  */
374 static
375 int
376 user_vop_advlock (struct vop_advlock_args *ap)
377 {
378         struct user_inode *ip;
379         struct vnode *vp;
380
381         vp = ap->a_vp;
382         ip = vp->v_data;
383
384         return (lf_advlock(ap, &ip->lockf, ip->filesize));
385 }
386
387 /*
388  * vop_open(struct vnode *vp, int mode, struct ucred *cred, struct file *file)
389  *
390  * This vop is handled directly by the kernel.
391  */
392 static
393 int
394 user_vop_open (struct vop_open_args *ap)
395 {
396         return (vop_stdopen(ap));
397 }
398
399 /*
400  * vop_close(struct vnode *vp, int fflag)
401  *
402  * This vop is handled directly by the kernel.
403  */
404 static
405 int
406 user_vop_close (struct vop_close_args *ap)
407 {
408         return (vop_stdclose(ap));
409 }
410
411 /*
412  * vop_getattr(struct vnode *vp, struct vattr *vap)
413  */
414 static
415 int
416 user_vop_getattr (struct vop_getattr_args *ap)
417 {
418         struct user_mount *ump;
419         struct user_inode *ip;
420         struct vnode *vp;
421         struct slmsg *slmsg;
422         syslink_elm_t par;
423         syslink_elm_t elm;
424         int error;
425
426         vp = ap->a_vp;
427         ip = vp->v_data;
428         ump = ip->ump;
429
430         slmsg = syslink_kallocmsg();
431         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
432                               SLVFS_CMD_VOP_GETATTR);
433         sl_msg_fini(slmsg->msg);
434
435         kprintf("userfs_getattr\n");
436         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) != 0)
437                 goto done;
438         par = &slmsg->rep->msg->sm_head;
439         if (par->se_cmd != (SLVFS_CMD_VOP_GETATTR|SE_CMDF_REPLY)) {
440                 error = EBADRPC;
441                 goto done;
442         }
443
444         /*
445          * Parse reply content
446          */
447         SL_FOREACH_ELEMENT(par, elm) {
448                 switch(elm->se_cmd) {
449                 case SLVFS_ELM_VATTR:
450                         error = user_elm_parse_vattr(elm, ap->a_vap);
451                         break;
452                 default:
453                         break;
454                 }
455                 if (error)
456                         break;
457         }
458 done:
459         syslink_kfreemsg(ump->sldesc, slmsg);
460         kprintf("error %d\n", error);
461         return(error);
462 }
463
464 /*
465  * vop_pathconf(int name, int *retval)
466  *
467  * This vop is handled directly by the kernel.
468  */
469 static
470 int
471 user_vop_pathconf (struct vop_pathconf_args *ap)
472 {
473         int error = 0;
474
475         switch(ap->a_name) {
476         case _PC_LINK_MAX:
477                 *ap->a_retval = LINK_MAX;
478                 break;
479         case _PC_MAX_CANON:
480                 *ap->a_retval = MAX_CANON;
481                 break;
482         case _PC_MAX_INPUT:
483                 *ap->a_retval = MAX_INPUT;
484                 break;
485         case _PC_PIPE_BUF:
486                 *ap->a_retval = PIPE_BUF;
487                 break;
488         case _PC_CHOWN_RESTRICTED:
489                 *ap->a_retval = 1;
490                 break;
491         case _PC_VDISABLE:
492                 *ap->a_retval = _POSIX_VDISABLE;
493                 break;
494         default:
495                 error = EINVAL;
496                 break;
497         }
498         return (error);
499 }
500
501 /*
502  * vop_print(int name, int *retval)
503  *
504  * This vop is handled directly by the kernel.
505  */
506 static
507 int
508 user_vop_print (struct vop_print_args *ap)
509 {
510         return(0);
511 }
512
513 /*
514  * vop_readdir(struct vnode *vp, struct uio *uio, struct ucred *cred,
515  *             int *eofflag, int *ncookies, off_t **a_cookies)
516  */
517 static
518 int
519 user_vop_readdir (struct vop_readdir_args *ap)
520 {
521         struct user_mount *ump;
522         struct user_inode *ip;
523         struct vnode *vp;
524         struct slmsg *slmsg;
525         syslink_elm_t par;
526         int error;
527
528         vp = ap->a_vp;
529         ip = vp->v_data;
530         ump = ip->ump;
531
532         slmsg = syslink_kallocmsg();
533         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
534                               SLVFS_CMD_VOP_READDIR);
535         sl_msg_fini(slmsg->msg);
536
537         kprintf("userfs_readdir\n");
538         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
539                 par = &slmsg->rep->msg->sm_head;
540
541                 if (par->se_cmd == (SLVFS_CMD_VOP_READDIR|SE_CMDF_REPLY)) {
542                         ;
543                 } else {
544                         error = EBADRPC;
545                 }
546         }
547         syslink_kfreemsg(ump->sldesc, slmsg);
548         kprintf("error %d\n", error);
549         return(error);
550 }
551
552 /*
553  * vop_readlink(struct vnode *vp, struct uio *uio, struct ucred *cred)
554  */
555 static
556 int
557 user_vop_readlink (struct vop_readlink_args *ap)
558 {
559         struct user_mount *ump;
560         struct user_inode *ip;
561         struct vnode *vp;
562         struct slmsg *slmsg;
563         syslink_elm_t par;
564         int error;
565
566         vp = ap->a_vp;
567         ip = vp->v_data;
568         ump = ip->ump;
569
570         slmsg = syslink_kallocmsg();
571         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
572                               SLVFS_CMD_VOP_READLINK);
573         sl_msg_fini(slmsg->msg);
574
575         kprintf("userfs_readlink\n");
576         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
577                 par = &slmsg->rep->msg->sm_head;
578
579                 if (par->se_cmd == (SLVFS_CMD_VOP_READLINK|SE_CMDF_REPLY)) {
580                         ;
581                 } else {
582                         error = EBADRPC;
583                 }
584         }
585         syslink_kfreemsg(ump->sldesc, slmsg);
586         kprintf("error %d\n", error);
587         return(error);
588 }
589
590 /*
591  * vop_setattr(struct vnode *vp, struct vattr *vap, struct ucred *cred)
592  */
593 static
594 int
595 user_vop_setattr (struct vop_setattr_args *ap)
596 {
597         struct user_mount *ump;
598         struct user_inode *ip;
599         struct vnode *vp;
600         struct slmsg *slmsg;
601         syslink_elm_t par;
602         int error;
603
604         vp = ap->a_vp;
605         ip = vp->v_data;
606         ump = ip->ump;
607
608         slmsg = syslink_kallocmsg();
609         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
610                               SLVFS_CMD_VOP_SETATTR);
611         sl_msg_fini(slmsg->msg);
612
613         kprintf("userfs_setattr\n");
614         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
615                 par = &slmsg->rep->msg->sm_head;
616
617                 if (par->se_cmd == (SLVFS_CMD_VOP_SETATTR|SE_CMDF_REPLY)) {
618                         ;
619                 } else {
620                         error = EBADRPC;
621                 }
622         }
623         syslink_kfreemsg(ump->sldesc, slmsg);
624         kprintf("error %d\n", error);
625         return(error);
626 }
627
628 /*
629  * user_vop_strategy() - I/O strategy routine.
630  *
631  * Note that userfs interfaces fake-up BMAP so the strategy call just
632  * uses the passed bio instead of pushing a bio to get to the (faked)
633  * device block cache.
634  */
635 static void user_strategy_callback(struct slmsg *msg, void *arg, int error);
636
637 static
638 int
639 user_vop_strategy (struct vop_strategy_args *ap)
640 {
641         struct user_mount *ump;
642         struct user_inode *ip;
643         struct vnode *vp;
644         struct bio *bio;
645         struct buf *bp;
646         struct slmsg *slmsg;
647         syslink_elm_t par;
648         int error;
649
650         vp = ap->a_vp;
651         ip = vp->v_data;
652         ump = ip->ump;
653         bio = ap->a_bio;
654         bp = bio->bio_buf;
655
656         bio->bio_driver_info = ump;
657
658         slmsg = syslink_kallocmsg();
659         switch(bp->b_cmd) {
660         case BUF_CMD_READ:
661                 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
662                                       SLVFS_CMD_VOP_STRATEGY_READ);
663                 break;
664         case BUF_CMD_WRITE:
665                 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
666                                       SLVFS_CMD_VOP_STRATEGY_WRITE);
667                 break;
668         default:
669                 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
670                                       SLVFS_CMD_VOP_STRATEGY_MISC);
671                 break;
672         }
673         user_elm_push_vnode(par, vp);
674         user_elm_push_offset(par, bio->bio_offset);
675         user_elm_push_bio(par, bp->b_cmd, bp->b_bcount);
676         syslink_kdmabuf_data(slmsg, bp->b_data, bp->b_bcount);
677         sl_msg_fini(slmsg->msg);
678
679         kprintf("userfs_strategy\n");
680         error = syslink_ksendmsg(ump->sldesc, slmsg,
681                                  user_strategy_callback, bio);
682         if (error)
683                 syslink_kfreemsg(ump->sldesc, slmsg);
684         kprintf("error %d\n", error);
685         return(error);
686 }
687
688 /*
689  * This callback is made in the context of the responding process which
690  * may or may not be the process the message was sent to.
691  */
692 static void
693 user_strategy_callback(struct slmsg *slmsg, void *arg, int error)
694 {
695         struct bio *bio = arg;
696         struct buf *bp = bio->bio_buf;
697         struct user_mount *ump;
698         syslink_elm_t par;
699
700         kprintf("user_strategy_callback\n");
701         if (error == 0) {
702                 par = &slmsg->rep->msg->sm_head;
703                 if (par->se_cmd != (slmsg->msg->sm_head.se_cmd | SE_CMDF_REPLY)) {
704                         error = EBADRPC;
705                 }
706         }
707         if (error) {
708                 bp->b_error = error;
709                 bp->b_flags |= B_ERROR;
710         }
711         ump = bio->bio_driver_info;
712         syslink_kfreemsg(ump->sldesc, slmsg);
713         biodone(bio);
714 }
715
716 /*
717  * vop_bmap(struct vnode *vp, off_t loffset, off_t *doffsetp,
718  *          int *runp, int *runb)
719  *
720  * Dummy up the bmap op so the kernel will cluster I/Os.  The strategy
721  * code will ignore the dummied up device block translation.
722  */
723 static
724 int
725 user_vop_bmap(struct vop_bmap_args *ap)
726 {
727         int cluster_off;
728
729         *ap->a_doffsetp = ap->a_loffset;
730         cluster_off = (int)(*ap->a_doffsetp & (MAXPHYS - 1));
731
732         if (ap->a_runp)
733                 *ap->a_runp = MAXPHYS - cluster_off;
734         if (ap->a_runb)
735                 *ap->a_runb = cluster_off;
736         return(0);
737 }
738
739
740 /*
741  * vop_ncreate(struct nchandle *nch, struct vnode *dvp, struct vnode **vpp,
742  *             struct ucred *cred, struct vattr *vap)
743  */
744 static
745 int
746 user_vop_ncreate (struct vop_ncreate_args *ap)
747 {
748         struct user_mount *ump;
749         struct user_inode *ip;
750         struct namecache *ncp;
751         struct ucred *cred;
752         struct vnode *dvp;
753         struct slmsg *slmsg;
754         syslink_elm_t par;
755         syslink_elm_t elm;
756         int error;
757
758         cred = ap->a_cred;
759         ncp = ap->a_nch->ncp;
760         dvp = ap->a_dvp;
761
762         if ((error = vget(dvp, LK_SHARED)) != 0)
763                 return (error);
764
765         ip = dvp->v_data;
766         ump = ip->ump;
767
768         slmsg = syslink_kallocmsg();
769         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
770                               SLVFS_CMD_VOP_NCREATE);
771         user_elm_push_nch(par, ap->a_nch);
772         user_elm_push_vnode(par, dvp);
773         user_elm_push_cred(par, ap->a_cred);
774         user_elm_push_vattr(par, ap->a_vap);
775         sl_msg_fini(slmsg->msg);
776
777         kprintf("userfs_ncreate\n");
778         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) != 0)
779                 goto done;
780         par = &slmsg->rep->msg->sm_head;
781         if (par->se_cmd != (SLVFS_CMD_VOP_NCREATE|SE_CMDF_REPLY)) {
782                 error = EBADRPC;
783                 goto done;
784         }
785
786         /*
787          * Parse reply - extract the inode number of the newly created
788          * object and construct a vnode using it.
789          */
790         SL_FOREACH_ELEMENT(par, elm) {
791                 switch(elm->se_cmd) {
792                 case SLVFS_ELM_INUM:
793                         /* XXX */
794                         break;
795                 default:
796                         break;
797                 }
798                 if (error)
799                         break;
800         }
801         /* XXX construct vnode using fileid */
802         error = EINVAL;
803
804 done:
805         syslink_kfreemsg(ump->sldesc, slmsg);
806         kprintf("error %d\n", error);
807         vput(dvp);
808         return(error);
809 }
810
811 /*
812  * vop_nresolve(struct nchandle *nch, struct vnode *dvp, struct ucred *cred)
813  */
814 static
815 int
816 user_vop_nresolve (struct vop_nresolve_args *ap)
817 {
818         struct user_mount *ump;
819         struct user_inode *ip;
820         struct namecache *ncp;
821         struct ucred *cred;
822         struct vnode *dvp;
823         struct slmsg *slmsg;
824         syslink_elm_t par;
825         syslink_elm_t elm;
826         int error;
827         int flags;
828         ino_t inum;
829
830         cred = ap->a_cred;
831         ncp = ap->a_nch->ncp;
832         dvp = ap->a_dvp;
833         if ((error = vget(dvp, LK_SHARED)) != 0)
834                 return (error);
835         vn_unlock(dvp);
836
837         ip = dvp->v_data;
838         ump = ip->ump;
839
840         slmsg = syslink_kallocmsg();
841         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
842                               SLVFS_CMD_VOP_NRESOLVE);
843         user_elm_push_nch(par, ap->a_nch);
844         user_elm_push_vnode(par, dvp);
845         user_elm_push_cred(par, ap->a_cred);
846         sl_msg_fini(slmsg->msg);
847
848         /*
849          * Run the RPC.  The response must still be parsed for a ENOENT
850          * error to extract the whiteout flag.
851          */
852         kprintf("userfs_nresolve\n");
853         error = syslink_kdomsg(ump->sldesc, slmsg);
854         if (error && error != ENOENT)
855                 goto done;
856         par = &slmsg->rep->msg->sm_head;
857         if (par->se_cmd != (SLVFS_CMD_VOP_NRESOLVE|SE_CMDF_REPLY)) {
858                 error = EBADRPC;
859                 goto done;
860         }
861
862         /*
863          * Parse reply - returns inode number of resolved vnode
864          */
865         flags = 0;
866         inum = 0;
867         SL_FOREACH_ELEMENT(par, elm) {
868                 switch(elm->se_cmd) {
869                 case SLVFS_ELM_INUM:
870                         /* XXX */
871                         break;
872                 case SLVFS_ELM_NCPFLAG:
873                         /* flags = & NCF_WHITEOUT */
874                         break;
875                 default:
876                         break;
877                 }
878         }
879
880         if (error == 0) {
881                 error = EINVAL;
882                 /*vp = user_getvp(inum);*/
883                 /* XXX construct vp cache_setvp(nch, vp); */
884         } else {
885                 ncp->nc_flag |= flags;
886                 cache_setvp(ap->a_nch, NULL);
887         }
888 done:
889         syslink_kfreemsg(ump->sldesc, slmsg);
890         vrele(dvp);
891         kprintf("error %d\n", error);
892         return(error);
893 }
894
895 /*
896  * vop_nlookupdotdot(struct vnode *dvp, struct vnode **vpp, struct ucred *cred)
897  *
898  * Lookup the parent of dvp. dvp is ref'd but not locked.  The returned
899  * vnode should be ref'd and locked.
900  */
901 static
902 int
903 user_vop_nlookupdotdot (struct vop_nlookupdotdot_args *ap)
904 {
905         struct user_mount *ump;
906         struct user_inode *ip;
907         struct ucred *cred;
908         struct vnode *dvp;
909         struct vnode *vp;
910         struct slmsg *slmsg;
911         syslink_elm_t par;
912         syslink_elm_t elm;
913         int error;
914         ino_t inum;
915
916         cred = ap->a_cred;
917         dvp = ap->a_dvp;
918         vp = NULL;      /* XXX */
919         ip = vp->v_data;
920         ump = ip->ump;
921
922         slmsg = syslink_kallocmsg();
923         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
924                               SLVFS_CMD_VOP_NLOOKUPDOTDOT);
925         sl_msg_fini(slmsg->msg);
926
927         kprintf("userfs_nlookupdotdot\n");
928         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) != 0)
929                 goto done;
930         par = &slmsg->rep->msg->sm_head;
931
932         if (par->se_cmd != (SLVFS_CMD_VOP_NLOOKUPDOTDOT|SE_CMDF_REPLY)) {
933                 error = EBADRPC;
934                 goto done;
935         }
936
937         /*
938          * Parse reply - inumber of parent directory
939          */
940         inum = 0;
941         SL_FOREACH_ELEMENT(par, elm) {
942                 switch(elm->se_cmd) {
943                 case SLVFS_ELM_INUM:
944                         /* XXX */
945                         break;
946                 case SLVFS_ELM_NCPFLAG:
947                         /* flags = & NCF_WHITEOUT */
948                         break;
949                 default:
950                         break;
951                 }
952         }
953
954         /* construct parent vnode */
955
956 done:
957         syslink_kfreemsg(ump->sldesc, slmsg);
958         kprintf("error %d\n", error);
959         return(error);
960 }
961
962 /*
963  * vop_nlink(struct nchandle *nch, struct vnode *dvp, struct vnode *vp,
964  *           struct ucred *cred)
965  */
966 static
967 int
968 user_vop_nlink (struct vop_nlink_args *ap)
969 {
970         struct user_mount *ump;
971         struct user_inode *ip;
972         struct vnode *vp;
973         struct slmsg *slmsg;
974         syslink_elm_t par;
975         int error;
976
977         vp = ap->a_vp;
978         ip = vp->v_data;
979         ump = ip->ump;
980
981         slmsg = syslink_kallocmsg();
982         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
983                               SLVFS_CMD_VOP_NLINK);
984         sl_msg_fini(slmsg->msg);
985
986         kprintf("userfs_nlink\n");
987         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
988                 par = &slmsg->rep->msg->sm_head;
989
990                 if (par->se_cmd == (SLVFS_CMD_VOP_NLINK|SE_CMDF_REPLY)) {
991                         ;
992                 } else {
993                         error = EBADRPC;
994                 }
995         }
996         syslink_kfreemsg(ump->sldesc, slmsg);
997         kprintf("error %d\n", error);
998         return(error);
999 }
1000
1001 /*
1002  * vop_nmkdir(struct nchandle *nch, struct vnode *dvp, struct vnode **vpp,
1003  *           struct ucred *cred, struct vattr *vap)
1004  */
1005 static
1006 int
1007 user_vop_nmkdir (struct vop_nmkdir_args *ap)
1008 {
1009         struct user_mount *ump;
1010         struct user_inode *ip;
1011         struct namecache *ncp;
1012         struct ucred *cred;
1013         struct vnode *dvp;
1014         struct vnode *vp;
1015         struct slmsg *slmsg;
1016         syslink_elm_t par;
1017         int error;
1018
1019         cred = ap->a_cred;
1020         ncp = ap->a_nch->ncp;
1021         dvp = ap->a_dvp;
1022         if ((error = vget(dvp, LK_SHARED)) != 0)
1023                 return (error);
1024
1025         vp = NULL;      /* XXX */
1026
1027         ip = vp->v_data;
1028         ump = ip->ump;
1029
1030         slmsg = syslink_kallocmsg();
1031         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1032                               SLVFS_CMD_VOP_NMKDIR);
1033         sl_msg_fini(slmsg->msg);
1034
1035         kprintf("userfs_nmkdir\n");
1036         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1037                 par = &slmsg->rep->msg->sm_head;
1038
1039                 if (par->se_cmd == (SLVFS_CMD_VOP_NMKDIR|SE_CMDF_REPLY)) {
1040                         ;
1041                 } else {
1042                         error = EBADRPC;
1043                 }
1044         }
1045         syslink_kfreemsg(ump->sldesc, slmsg);
1046         kprintf("error %d\n", error);
1047         vput(dvp);
1048         return(error);
1049 }
1050
1051 /*
1052  * vop_nmknod(struct nchandle *nch, struct vnode *dvp, struct vnode **vpp,
1053  *           struct ucred *cred, struct vattr *vap)
1054  */
1055 static
1056 int
1057 user_vop_nmknod (struct vop_nmknod_args *ap)
1058 {
1059         struct user_mount *ump;
1060         struct user_inode *ip;
1061         struct namecache *ncp;
1062         struct ucred *cred;
1063         struct vnode *dvp;
1064         struct vnode *vp;
1065         struct slmsg *slmsg;
1066         syslink_elm_t par;
1067         int error;
1068
1069         cred = ap->a_cred;
1070         ncp = ap->a_nch->ncp;
1071         dvp = ncp->nc_parent->nc_vp;    /* needs vget */
1072
1073         vp = NULL;      /* XXX */
1074
1075         ip = vp->v_data;
1076         ump = ip->ump;
1077
1078         slmsg = syslink_kallocmsg();
1079         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1080                               SLVFS_CMD_VOP_NMKNOD);
1081         sl_msg_fini(slmsg->msg);
1082
1083         kprintf("userfs_nmknod\n");
1084         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1085                 par = &slmsg->rep->msg->sm_head;
1086
1087                 if (par->se_cmd == (SLVFS_CMD_VOP_NMKNOD|SE_CMDF_REPLY)) {
1088                         ;
1089                 } else {
1090                         error = EBADRPC;
1091                 }
1092         }
1093         syslink_kfreemsg(ump->sldesc, slmsg);
1094         kprintf("error %d\n", error);
1095         return(error);
1096 }
1097
1098 /*
1099  * vop_nremove(struct nchandle *nch, struct vnode *dvp, struct ucred *cred)
1100  */
1101 static
1102 int
1103 user_vop_nremove (struct vop_nremove_args *ap)
1104 {
1105         struct user_mount *ump;
1106         struct user_inode *ip;
1107         struct namecache *ncp;
1108         struct ucred *cred;
1109         struct vnode *dvp;
1110         struct vnode *vp;
1111         struct slmsg *slmsg;
1112         syslink_elm_t par;
1113         int error;
1114
1115         cred = ap->a_cred;
1116         ncp = ap->a_nch->ncp;
1117         dvp = ncp->nc_parent->nc_vp;    /* needs vget */
1118
1119         vp = NULL;      /* XXX */
1120
1121         ip = vp->v_data;
1122         ump = ip->ump;
1123
1124         slmsg = syslink_kallocmsg();
1125         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1126                               SLVFS_CMD_VOP_NREMOVE);
1127         sl_msg_fini(slmsg->msg);
1128
1129         kprintf("userfs_nremove\n");
1130         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1131                 par = &slmsg->rep->msg->sm_head;
1132
1133                 if (par->se_cmd == (SLVFS_CMD_VOP_NREMOVE|SE_CMDF_REPLY)) {
1134                         ;
1135                 } else {
1136                         error = EBADRPC;
1137                 }
1138         }
1139         syslink_kfreemsg(ump->sldesc, slmsg);
1140         kprintf("error %d\n", error);
1141         return(error);
1142 }
1143
1144 /*
1145  * vop_nrename(struct nchandle *fnch, struct nchandle *tnch,
1146  *             struct vnode *fdvp, struct vnode *tdvp,
1147  *             struct ucred *cred)
1148  */
1149 static
1150 int
1151 user_vop_nrename (struct vop_nrename_args *ap)
1152 {
1153         struct user_mount *ump;
1154         struct user_inode *ip;
1155         struct namecache *fncp;
1156         struct namecache *tncp;
1157         struct ucred *cred;
1158         struct vnode *fdvp;
1159         struct vnode *tdvp;
1160         struct vnode *vp;
1161         struct slmsg *slmsg;
1162         syslink_elm_t par;
1163         int error;
1164
1165         cred = ap->a_cred;
1166         fncp = ap->a_fnch->ncp;
1167         fdvp = ap->a_fdvp;      /* XXX needs vget */
1168         tncp = ap->a_tnch->ncp;
1169         tdvp = ap->a_tdvp;      /* XXX needs vget */
1170
1171         vp = NULL;      /* XXX */
1172
1173         ip = vp->v_data;
1174         ump = ip->ump;
1175
1176         slmsg = syslink_kallocmsg();
1177         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1178                               SLVFS_CMD_VOP_NRENAME);
1179         sl_msg_fini(slmsg->msg);
1180
1181         kprintf("userfs_nrename\n");
1182         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1183                 par = &slmsg->rep->msg->sm_head;
1184
1185                 if (par->se_cmd == (SLVFS_CMD_VOP_NRENAME|SE_CMDF_REPLY)) {
1186                         ;
1187                 } else {
1188                         error = EBADRPC;
1189                 }
1190         }
1191         syslink_kfreemsg(ump->sldesc, slmsg);
1192         kprintf("error %d\n", error);
1193         return(error);
1194 }
1195
1196 /*
1197  * vop_nrmdir(struct nchandle *nch, struct vnode *dvp, struct ucred *cred)
1198  */
1199 static
1200 int
1201 user_vop_nrmdir (struct vop_nrmdir_args *ap)
1202 {
1203         struct user_mount *ump;
1204         struct user_inode *ip;
1205         struct namecache *ncp;
1206         struct ucred *cred;
1207         struct vnode *dvp;
1208         struct vnode *vp;
1209         struct slmsg *slmsg;
1210         syslink_elm_t par;
1211         int error;
1212
1213         cred = ap->a_cred;
1214         ncp = ap->a_nch->ncp;
1215         dvp = ncp->nc_parent->nc_vp;    /* needs vget */
1216
1217         vp = NULL;      /* XXX */
1218
1219         ip = vp->v_data;
1220         ump = ip->ump;
1221
1222         slmsg = syslink_kallocmsg();
1223         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1224                               SLVFS_CMD_VOP_NRMDIR);
1225         sl_msg_fini(slmsg->msg);
1226
1227         kprintf("userfs_nrmdir\n");
1228         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1229                 par = &slmsg->rep->msg->sm_head;
1230
1231                 if (par->se_cmd == (SLVFS_CMD_VOP_NRMDIR|SE_CMDF_REPLY)) {
1232                         ;
1233                 } else {
1234                         error = EBADRPC;
1235                 }
1236         }
1237         syslink_kfreemsg(ump->sldesc, slmsg);
1238         kprintf("error %d\n", error);
1239         return(error);
1240 }
1241
1242 static
1243 int
1244 user_vop_nsymlink (struct vop_nsymlink_args *ap)
1245 {
1246         struct user_mount *ump;
1247         struct user_inode *ip;
1248         struct namecache *ncp;
1249         struct ucred *cred;
1250         struct vnode *dvp;
1251         struct vnode *vp;
1252         struct slmsg *slmsg;
1253         syslink_elm_t par;
1254         int error;
1255
1256         cred = ap->a_cred;
1257         ncp = ap->a_nch->ncp;
1258         dvp = ncp->nc_parent->nc_vp;    /* needs vget */
1259
1260         vp = NULL;      /* XXX */
1261
1262         ip = vp->v_data;
1263         ump = ip->ump;
1264
1265         slmsg = syslink_kallocmsg();
1266         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1267                               SLVFS_CMD_VOP_NSYMLINK);
1268         sl_msg_fini(slmsg->msg);
1269
1270         kprintf("userfs_nsymlink\n");
1271         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1272                 par = &slmsg->rep->msg->sm_head;
1273
1274                 if (par->se_cmd == (SLVFS_CMD_VOP_NSYMLINK|SE_CMDF_REPLY)) {
1275                         ;
1276                 } else {
1277                         error = EBADRPC;
1278                 }
1279         }
1280         syslink_kfreemsg(ump->sldesc, slmsg);
1281         kprintf("error %d\n", error);
1282         return(error);
1283 }
1284
1285 static
1286 int
1287 user_vop_nwhiteout (struct vop_nwhiteout_args *ap)
1288 {
1289         struct user_mount *ump;
1290         struct user_inode *ip;
1291         struct namecache *ncp;
1292         struct ucred *cred;
1293         struct vnode *dvp;
1294         struct vnode *vp;
1295         struct slmsg *slmsg;
1296         syslink_elm_t par;
1297         int error;
1298
1299         cred = ap->a_cred;
1300         ncp = ap->a_nch->ncp;
1301         dvp = ncp->nc_parent->nc_vp;    /* needs vget */
1302
1303         vp = NULL;      /* XXX */
1304
1305         ip = vp->v_data;
1306         ump = ip->ump;
1307
1308         slmsg = syslink_kallocmsg();
1309         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1310                               SLVFS_CMD_VOP_NWHITEOUT);
1311         sl_msg_fini(slmsg->msg);
1312
1313         kprintf("userfs_nwhiteout\n");
1314         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1315                 par = &slmsg->rep->msg->sm_head;
1316
1317                 if (par->se_cmd == (SLVFS_CMD_VOP_NWHITEOUT|SE_CMDF_REPLY)) {
1318                         ;
1319                 } else {
1320                         error = EBADRPC;
1321                 }
1322         }
1323         syslink_kfreemsg(ump->sldesc, slmsg);
1324         kprintf("error %d\n", error);
1325         return(error);
1326 }
1327