Add tunable to enable/disable PBCC support in acx(4) and it is enabled
[dragonfly.git] / sys / vfs / userfs / userfs_vnops.c
blobc898b10aa094d51ab1675dac6016160d62ab268b
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:
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.
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.
34 * $DragonFly: src/sys/vfs/userfs/userfs_vnops.c,v 1.4 2007/11/20 21:03:51 dillon Exp $
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"
53 * USERFS VNOPS
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 *);
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
117 #if 0
118 static
120 user_vop_vnoperate(struct vop_generic_args *)
122 return (VOCALL(&userfs_vnode_vops, ap));
124 #endif
127 * vop_fsync(struct vnode *vp, int waitfor)
129 static
131 user_vop_fsync (struct vop_fsync_args *ap)
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;
140 vp = ap->a_vp;
141 ip = vp->v_data;
142 ump = ip->ump;
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);
150 kprintf("userfs_fsync\n");
151 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
152 par = &slmsg->rep->msg->sm_head;
154 if (par->se_cmd == (SLVFS_CMD_VOP_FSYNC|SE_CMDF_REPLY)) {
156 } else {
157 error = EBADRPC;
160 syslink_kfreemsg(ump->sldesc, slmsg);
161 kprintf("error %d\n", error);
162 return(error);
166 * vop_read(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
168 static
170 user_vop_read (struct vop_read_args *ap)
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;
181 vp = ap->a_vp;
182 ip = vp->v_data;
183 ump = ip->ump;
184 uio = ap->a_uio;
186 if (uio->uio_offset < 0)
187 return (EINVAL);
188 if (vp->v_type != VREG)
189 return (EINVAL);
191 kprintf("userfs_read\n");
192 error = 0;
193 while (uio->uio_resid > 0 && uio->uio_offset < ip->filesize) {
195 * Use buffer cache I/O (via user_vop_strategy), aligned
196 * on USERFS_BSIZE boundaries.
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;
206 * Figure out how many bytes we can actually copy this loop.
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);
214 error = uiomove((char *)bp->b_data + offset, n, uio);
215 bqrelse(bp);
216 if (error)
217 break;
219 kprintf("userfs_read error %d\n", error);
220 return(error);
224 * vop_write(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
226 static
228 user_vop_write (struct vop_write_args *ap)
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;
239 vp = ap->a_vp;
240 ip = vp->v_data;
241 ump = ip->ump;
242 uio = ap->a_uio;
244 if (vp->v_type != VREG)
245 return (EINVAL);
246 if (ap->a_ioflag & IO_APPEND)
247 uio->uio_offset = ip->filesize;
250 * Check for illegal write offsets. Valid range is 0...2^63-1
252 if (uio->uio_offset < 0 || uio->uio_offset + uio->uio_resid <= 0)
253 return (EFBIG);
255 kprintf("userfs_write\n");
256 error = 0;
257 while (uio->uio_resid > 0) {
259 * Use buffer cache I/O (via user_vop_strategy), aligned
260 * on USERFS_BSIZE boundaries.
262 * XXX not optimized for complete write-overs or file
263 * extensions. Note: must bread on UIO_NOCOPY writes.
265 * XXX No need to read if strictly appending.
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;
276 * Figure out how many bytes we can actually copy this loop.
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);
284 error = uiomove((char *)bp->b_data + offset, n, uio);
285 if (error) {
286 brelse(bp);
287 break;
291 * Extend the file's size if necessary
293 if (ip->filesize < uio->uio_offset)
294 ip->filesize = uio->uio_offset;
297 * The data has been loaded into the buffer, write it out.
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);
309 kprintf("userfs_write error %d\n", error);
310 return(error);
314 * vop_access(struct vnode *vp, int mode, struct ucred *cred)
316 static
318 user_vop_access (struct vop_access_args *ap)
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;
327 vp = ap->a_vp;
328 ip = vp->v_data;
329 ump = ip->ump;
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);
340 * Issue the request and do basic validation of the response
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;
351 done:
352 syslink_kfreemsg(ump->sldesc, slmsg);
353 kprintf("error %d\n", error);
354 return(error);
358 * vop_advlock(struct vnode *vp, caddr_t id, int op, struct flock *fl,
359 * int flags)
361 * This vop is handled directly by the kernel.
363 static
365 user_vop_advlock (struct vop_advlock_args *ap)
367 struct user_inode *ip;
368 struct vnode *vp;
370 vp = ap->a_vp;
371 ip = vp->v_data;
373 return (lf_advlock(ap, &ip->lockf, ip->filesize));
377 * vop_open(struct vnode *vp, int mode, struct ucred *cred, struct file *file)
379 * This vop is handled directly by the kernel.
381 static
383 user_vop_open (struct vop_open_args *ap)
385 return (vop_stdopen(ap));
389 * vop_close(struct vnode *vp, int fflag)
391 * This vop is handled directly by the kernel.
393 static
395 user_vop_close (struct vop_close_args *ap)
397 return (vop_stdclose(ap));
401 * vop_getattr(struct vnode *vp, struct vattr *vap)
403 static
405 user_vop_getattr (struct vop_getattr_args *ap)
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;
415 vp = ap->a_vp;
416 ip = vp->v_data;
417 ump = ip->ump;
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);
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;
434 * Parse reply content
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;
444 if (error)
445 break;
447 done:
448 syslink_kfreemsg(ump->sldesc, slmsg);
449 kprintf("error %d\n", error);
450 return(error);
454 * vop_pathconf(int name, int *retval)
456 * This vop is handled directly by the kernel.
458 static
460 user_vop_pathconf (struct vop_pathconf_args *ap)
462 int error = 0;
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;
487 return (error);
491 * vop_print(int name, int *retval)
493 * This vop is handled directly by the kernel.
495 static
497 user_vop_print (struct vop_print_args *ap)
499 return(0);
503 * vop_readdir(struct vnode *vp, struct uio *uio, struct ucred *cred,
504 * int *eofflag, int *ncookies, off_t **a_cookies)
506 static
508 user_vop_readdir (struct vop_readdir_args *ap)
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;
517 vp = ap->a_vp;
518 ip = vp->v_data;
519 ump = ip->ump;
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);
526 kprintf("userfs_readdir\n");
527 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
528 par = &slmsg->rep->msg->sm_head;
530 if (par->se_cmd == (SLVFS_CMD_VOP_READDIR|SE_CMDF_REPLY)) {
532 } else {
533 error = EBADRPC;
536 syslink_kfreemsg(ump->sldesc, slmsg);
537 kprintf("error %d\n", error);
538 return(error);
542 * vop_readlink(struct vnode *vp, struct uio *uio, struct ucred *cred)
544 static
546 user_vop_readlink (struct vop_readlink_args *ap)
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;
555 vp = ap->a_vp;
556 ip = vp->v_data;
557 ump = ip->ump;
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);
564 kprintf("userfs_readlink\n");
565 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
566 par = &slmsg->rep->msg->sm_head;
568 if (par->se_cmd == (SLVFS_CMD_VOP_READLINK|SE_CMDF_REPLY)) {
570 } else {
571 error = EBADRPC;
574 syslink_kfreemsg(ump->sldesc, slmsg);
575 kprintf("error %d\n", error);
576 return(error);
580 * vop_setattr(struct vnode *vp, struct vattr *vap, struct ucred *cred)
582 static
584 user_vop_setattr (struct vop_setattr_args *ap)
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;
593 vp = ap->a_vp;
594 ip = vp->v_data;
595 ump = ip->ump;
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);
602 kprintf("userfs_setattr\n");
603 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
604 par = &slmsg->rep->msg->sm_head;
606 if (par->se_cmd == (SLVFS_CMD_VOP_SETATTR|SE_CMDF_REPLY)) {
608 } else {
609 error = EBADRPC;
612 syslink_kfreemsg(ump->sldesc, slmsg);
613 kprintf("error %d\n", error);
614 return(error);
618 * user_vop_strategy() - I/O strategy routine.
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.
624 static void user_strategy_callback(struct slmsg *msg, void *arg, int error);
626 static
628 user_vop_strategy (struct vop_strategy_args *ap)
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;
639 vp = ap->a_vp;
640 ip = vp->v_data;
641 ump = ip->ump;
642 bio = ap->a_bio;
643 bp = bio->bio_buf;
645 bio->bio_driver_info = ump;
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;
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);
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);
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.
681 static void
682 user_strategy_callback(struct slmsg *slmsg, void *arg, int error)
684 struct bio *bio = arg;
685 struct buf *bp = bio->bio_buf;
686 struct user_mount *ump;
687 syslink_elm_t par;
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;
696 if (error) {
697 bp->b_error = error;
698 bp->b_flags |= B_ERROR;
700 ump = bio->bio_driver_info;
701 syslink_kfreemsg(ump->sldesc, slmsg);
702 biodone(bio);
706 * vop_bmap(struct vnode *vp, off_t loffset, off_t *doffsetp,
707 * int *runp, int *runb)
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.
712 static
714 user_vop_bmap(struct vop_bmap_args *ap)
716 int cluster_off;
718 *ap->a_doffsetp = ap->a_loffset;
719 cluster_off = (int)(*ap->a_doffsetp & (MAXPHYS - 1));
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);
730 * vop_ncreate(struct nchandle *nch, struct vnode *dvp, struct vnode **vpp,
731 * struct ucred *cred, struct vattr *vap)
733 static
735 user_vop_ncreate (struct vop_ncreate_args *ap)
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;
747 cred = ap->a_cred;
748 ncp = ap->a_nch->ncp;
749 dvp = ap->a_dvp;
751 if ((error = vget(dvp, LK_SHARED)) != 0)
752 return (error);
754 ip = dvp->v_data;
755 ump = ip->ump;
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);
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;
776 * Parse reply - extract the inode number of the newly created
777 * object and construct a vnode using it.
779 SL_FOREACH_ELEMENT(par, elm) {
780 switch(elm->se_cmd) {
781 case SLVFS_ELM_INUM:
782 /* XXX */
783 break;
784 default:
785 break;
787 if (error)
788 break;
790 /* XXX construct vnode using fileid */
791 error = EINVAL;
793 done:
794 syslink_kfreemsg(ump->sldesc, slmsg);
795 kprintf("error %d\n", error);
796 vput(dvp);
797 return(error);
801 * vop_nresolve(struct nchandle *nch, struct vnode *dvp, struct ucred *cred)
803 static
805 user_vop_nresolve (struct vop_nresolve_args *ap)
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;
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);
826 ip = dvp->v_data;
827 ump = ip->ump;
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);
838 * Run the RPC. The response must still be parsed for a ENOENT
839 * error to extract the whiteout flag.
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;
852 * Parse reply - returns inode number of resolved vnode
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;
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);
877 done:
878 syslink_kfreemsg(ump->sldesc, slmsg);
879 vrele(dvp);
880 kprintf("error %d\n", error);
881 return(error);
885 * vop_nlookupdotdot(struct vnode *dvp, struct vnode **vpp, struct ucred *cred)
887 * Lookup the parent of dvp. dvp is ref'd but not locked. The returned
888 * vnode should be ref'd and locked.
890 static
892 user_vop_nlookupdotdot (struct vop_nlookupdotdot_args *ap)
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;
905 cred = ap->a_cred;
906 dvp = ap->a_dvp;
907 vp = NULL; /* XXX */
908 ip = vp->v_data;
909 ump = ip->ump;
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);
916 kprintf("userfs_nlookupdotdot\n");
917 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) != 0)
918 goto done;
919 par = &slmsg->rep->msg->sm_head;
921 if (par->se_cmd != (SLVFS_CMD_VOP_NLOOKUPDOTDOT|SE_CMDF_REPLY)) {
922 error = EBADRPC;
923 goto done;
927 * Parse reply - inumber of parent directory
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;
943 /* construct parent vnode */
945 done:
946 syslink_kfreemsg(ump->sldesc, slmsg);
947 kprintf("error %d\n", error);
948 return(error);
952 * vop_nlink(struct nchandle *nch, struct vnode *dvp, struct vnode *vp,
953 * struct ucred *cred)
955 static
957 user_vop_nlink (struct vop_nlink_args *ap)
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;
966 vp = ap->a_vp;
967 ip = vp->v_data;
968 ump = ip->ump;
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);
975 kprintf("userfs_nlink\n");
976 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
977 par = &slmsg->rep->msg->sm_head;
979 if (par->se_cmd == (SLVFS_CMD_VOP_NLINK|SE_CMDF_REPLY)) {
981 } else {
982 error = EBADRPC;
985 syslink_kfreemsg(ump->sldesc, slmsg);
986 kprintf("error %d\n", error);
987 return(error);
991 * vop_nmkdir(struct nchandle *nch, struct vnode *dvp, struct vnode **vpp,
992 * struct ucred *cred, struct vattr *vap)
994 static
996 user_vop_nmkdir (struct vop_nmkdir_args *ap)
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;
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);
1014 vp = NULL; /* XXX */
1016 ip = vp->v_data;
1017 ump = ip->ump;
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);
1024 kprintf("userfs_nmkdir\n");
1025 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1026 par = &slmsg->rep->msg->sm_head;
1028 if (par->se_cmd == (SLVFS_CMD_VOP_NMKDIR|SE_CMDF_REPLY)) {
1030 } else {
1031 error = EBADRPC;
1034 syslink_kfreemsg(ump->sldesc, slmsg);
1035 kprintf("error %d\n", error);
1036 vput(dvp);
1037 return(error);
1041 * vop_nmknod(struct nchandle *nch, struct vnode *dvp, struct vnode **vpp,
1042 * struct ucred *cred, struct vattr *vap)
1044 static
1046 user_vop_nmknod (struct vop_nmknod_args *ap)
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;
1058 cred = ap->a_cred;
1059 ncp = ap->a_nch->ncp;
1060 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1062 vp = NULL; /* XXX */
1064 ip = vp->v_data;
1065 ump = ip->ump;
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);
1072 kprintf("userfs_nmknod\n");
1073 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1074 par = &slmsg->rep->msg->sm_head;
1076 if (par->se_cmd == (SLVFS_CMD_VOP_NMKNOD|SE_CMDF_REPLY)) {
1078 } else {
1079 error = EBADRPC;
1082 syslink_kfreemsg(ump->sldesc, slmsg);
1083 kprintf("error %d\n", error);
1084 return(error);
1088 * vop_nremove(struct nchandle *nch, struct vnode *dvp, struct ucred *cred)
1090 static
1092 user_vop_nremove (struct vop_nremove_args *ap)
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;
1104 cred = ap->a_cred;
1105 ncp = ap->a_nch->ncp;
1106 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1108 vp = NULL; /* XXX */
1110 ip = vp->v_data;
1111 ump = ip->ump;
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);
1118 kprintf("userfs_nremove\n");
1119 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1120 par = &slmsg->rep->msg->sm_head;
1122 if (par->se_cmd == (SLVFS_CMD_VOP_NREMOVE|SE_CMDF_REPLY)) {
1124 } else {
1125 error = EBADRPC;
1128 syslink_kfreemsg(ump->sldesc, slmsg);
1129 kprintf("error %d\n", error);
1130 return(error);
1134 * vop_nrename(struct nchandle *fnch, struct nchandle *tnch,
1135 * struct vnode *fdvp, struct vnode *tdvp,
1136 * struct ucred *cred)
1138 static
1140 user_vop_nrename (struct vop_nrename_args *ap)
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;
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 */
1160 vp = NULL; /* XXX */
1162 ip = vp->v_data;
1163 ump = ip->ump;
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);
1170 kprintf("userfs_nrename\n");
1171 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1172 par = &slmsg->rep->msg->sm_head;
1174 if (par->se_cmd == (SLVFS_CMD_VOP_NRENAME|SE_CMDF_REPLY)) {
1176 } else {
1177 error = EBADRPC;
1180 syslink_kfreemsg(ump->sldesc, slmsg);
1181 kprintf("error %d\n", error);
1182 return(error);
1186 * vop_nrmdir(struct nchandle *nch, struct vnode *dvp, struct ucred *cred)
1188 static
1190 user_vop_nrmdir (struct vop_nrmdir_args *ap)
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;
1202 cred = ap->a_cred;
1203 ncp = ap->a_nch->ncp;
1204 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1206 vp = NULL; /* XXX */
1208 ip = vp->v_data;
1209 ump = ip->ump;
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);
1216 kprintf("userfs_nrmdir\n");
1217 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1218 par = &slmsg->rep->msg->sm_head;
1220 if (par->se_cmd == (SLVFS_CMD_VOP_NRMDIR|SE_CMDF_REPLY)) {
1222 } else {
1223 error = EBADRPC;
1226 syslink_kfreemsg(ump->sldesc, slmsg);
1227 kprintf("error %d\n", error);
1228 return(error);
1231 static
1233 user_vop_nsymlink (struct vop_nsymlink_args *ap)
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;
1245 cred = ap->a_cred;
1246 ncp = ap->a_nch->ncp;
1247 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1249 vp = NULL; /* XXX */
1251 ip = vp->v_data;
1252 ump = ip->ump;
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);
1259 kprintf("userfs_nsymlink\n");
1260 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1261 par = &slmsg->rep->msg->sm_head;
1263 if (par->se_cmd == (SLVFS_CMD_VOP_NSYMLINK|SE_CMDF_REPLY)) {
1265 } else {
1266 error = EBADRPC;
1269 syslink_kfreemsg(ump->sldesc, slmsg);
1270 kprintf("error %d\n", error);
1271 return(error);
1274 static
1276 user_vop_nwhiteout (struct vop_nwhiteout_args *ap)
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;
1288 cred = ap->a_cred;
1289 ncp = ap->a_nch->ncp;
1290 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1292 vp = NULL; /* XXX */
1294 ip = vp->v_data;
1295 ump = ip->ump;
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);
1302 kprintf("userfs_nwhiteout\n");
1303 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1304 par = &slmsg->rep->msg->sm_head;
1306 if (par->se_cmd == (SLVFS_CMD_VOP_NWHITEOUT|SE_CMDF_REPLY)) {
1308 } else {
1309 error = EBADRPC;
1312 syslink_kfreemsg(ump->sldesc, slmsg);
1313 kprintf("error %d\n", error);
1314 return(error);