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