HAMMER VFS - Fix serious bug when downgrading (and later upgrading) a PFS
[dragonfly.git] / sys / vfs / userfs / userfs_vnops.c
blobfcfe81b03cbd61e142f0e602981490a19675dedd
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 off_t loffset;
237 size_t offset;
238 size_t n;
240 vp = ap->a_vp;
241 ip = vp->v_data;
242 ump = ip->ump;
243 uio = ap->a_uio;
245 if (vp->v_type != VREG)
246 return (EINVAL);
247 if (ap->a_ioflag & IO_APPEND)
248 uio->uio_offset = ip->filesize;
251 * Check for illegal write offsets. Valid range is 0...2^63-1
253 loffset = uio->uio_offset;
254 if (loffset < 0)
255 return (EFBIG);
256 if (uio->uio_resid) {
257 /* GCC4 - workaround optimization */
258 loffset += uio->uio_resid;
259 if (loffset <= 0)
260 return (EFBIG);
263 kprintf("userfs_write\n");
264 error = 0;
265 while (uio->uio_resid > 0) {
267 * Use buffer cache I/O (via user_vop_strategy), aligned
268 * on USERFS_BSIZE boundaries.
270 * XXX not optimized for complete write-overs or file
271 * extensions. Note: must bread on UIO_NOCOPY writes.
273 * XXX No need to read if strictly appending.
275 offset = (size_t)uio->uio_offset & USERFS_BMASK;
276 /* if offset == ip->filesize use getblk instead */
277 error = bread(vp, uio->uio_offset - offset, USERFS_BSIZE, &bp);
278 if (error) {
279 brelse(bp);
280 break;
284 * Figure out how many bytes we can actually copy this loop.
286 n = USERFS_BSIZE - offset;
287 if (n > uio->uio_resid)
288 n = uio->uio_resid;
289 if (n > ip->filesize - uio->uio_offset)
290 n = (size_t)(ip->filesize - uio->uio_offset);
292 error = uiomove((char *)bp->b_data + offset, n, uio);
293 if (error) {
294 brelse(bp);
295 break;
299 * Extend the file's size if necessary
301 if (ip->filesize < uio->uio_offset)
302 ip->filesize = uio->uio_offset;
305 * The data has been loaded into the buffer, write it out.
307 if (ap->a_ioflag & IO_SYNC) {
308 bwrite(bp);
309 } else if (ap->a_ioflag & IO_DIRECT) {
310 bp->b_flags |= B_CLUSTEROK;
311 bawrite(bp);
312 } else {
313 bp->b_flags |= B_CLUSTEROK;
314 bdwrite(bp);
317 kprintf("userfs_write error %d\n", error);
318 return(error);
322 * vop_access(struct vnode *vp, int mode, struct ucred *cred)
324 static
326 user_vop_access (struct vop_access_args *ap)
328 struct user_mount *ump;
329 struct user_inode *ip;
330 struct vnode *vp;
331 struct slmsg *slmsg;
332 syslink_elm_t par;
333 int error;
335 vp = ap->a_vp;
336 ip = vp->v_data;
337 ump = ip->ump;
339 slmsg = syslink_kallocmsg();
340 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
341 SLVFS_CMD_VOP_ACCESS);
342 user_elm_push_vnode(par, vp);
343 user_elm_push_mode(par, ap->a_mode);
344 user_elm_push_cred(par, ap->a_cred);
345 sl_msg_fini(slmsg->msg);
348 * Issue the request and do basic validation of the response
350 kprintf("userfs_access\n");
351 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) != 0)
352 goto done;
353 par = &slmsg->rep->msg->sm_head;
354 if (par->se_cmd != (SLVFS_CMD_VOP_ACCESS|SE_CMDF_REPLY)) {
355 error = EBADRPC;
356 goto done;
359 done:
360 syslink_kfreemsg(ump->sldesc, slmsg);
361 kprintf("error %d\n", error);
362 return(error);
366 * vop_advlock(struct vnode *vp, caddr_t id, int op, struct flock *fl,
367 * int flags)
369 * This vop is handled directly by the kernel.
371 static
373 user_vop_advlock (struct vop_advlock_args *ap)
375 struct user_inode *ip;
376 struct vnode *vp;
378 vp = ap->a_vp;
379 ip = vp->v_data;
381 return (lf_advlock(ap, &ip->lockf, ip->filesize));
385 * vop_open(struct vnode *vp, int mode, struct ucred *cred, struct file *file)
387 * This vop is handled directly by the kernel.
389 static
391 user_vop_open (struct vop_open_args *ap)
393 return (vop_stdopen(ap));
397 * vop_close(struct vnode *vp, int fflag)
399 * This vop is handled directly by the kernel.
401 static
403 user_vop_close (struct vop_close_args *ap)
405 return (vop_stdclose(ap));
409 * vop_getattr(struct vnode *vp, struct vattr *vap)
411 static
413 user_vop_getattr (struct vop_getattr_args *ap)
415 struct user_mount *ump;
416 struct user_inode *ip;
417 struct vnode *vp;
418 struct slmsg *slmsg;
419 syslink_elm_t par;
420 syslink_elm_t elm;
421 int error;
423 vp = ap->a_vp;
424 ip = vp->v_data;
425 ump = ip->ump;
427 slmsg = syslink_kallocmsg();
428 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
429 SLVFS_CMD_VOP_GETATTR);
430 sl_msg_fini(slmsg->msg);
432 kprintf("userfs_getattr\n");
433 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) != 0)
434 goto done;
435 par = &slmsg->rep->msg->sm_head;
436 if (par->se_cmd != (SLVFS_CMD_VOP_GETATTR|SE_CMDF_REPLY)) {
437 error = EBADRPC;
438 goto done;
442 * Parse reply content
444 SL_FOREACH_ELEMENT(par, elm) {
445 switch(elm->se_cmd) {
446 case SLVFS_ELM_VATTR:
447 error = user_elm_parse_vattr(elm, ap->a_vap);
448 break;
449 default:
450 break;
452 if (error)
453 break;
455 done:
456 syslink_kfreemsg(ump->sldesc, slmsg);
457 kprintf("error %d\n", error);
458 return(error);
462 * vop_pathconf(int name, int *retval)
464 * This vop is handled directly by the kernel.
466 static
468 user_vop_pathconf (struct vop_pathconf_args *ap)
470 int error = 0;
472 switch(ap->a_name) {
473 case _PC_LINK_MAX:
474 *ap->a_retval = LINK_MAX;
475 break;
476 case _PC_MAX_CANON:
477 *ap->a_retval = MAX_CANON;
478 break;
479 case _PC_MAX_INPUT:
480 *ap->a_retval = MAX_INPUT;
481 break;
482 case _PC_PIPE_BUF:
483 *ap->a_retval = PIPE_BUF;
484 break;
485 case _PC_CHOWN_RESTRICTED:
486 *ap->a_retval = 1;
487 break;
488 case _PC_VDISABLE:
489 *ap->a_retval = _POSIX_VDISABLE;
490 break;
491 default:
492 error = EINVAL;
493 break;
495 return (error);
499 * vop_print(int name, int *retval)
501 * This vop is handled directly by the kernel.
503 static
505 user_vop_print (struct vop_print_args *ap)
507 return(0);
511 * vop_readdir(struct vnode *vp, struct uio *uio, struct ucred *cred,
512 * int *eofflag, int *ncookies, off_t **a_cookies)
514 static
516 user_vop_readdir (struct vop_readdir_args *ap)
518 struct user_mount *ump;
519 struct user_inode *ip;
520 struct vnode *vp;
521 struct slmsg *slmsg;
522 syslink_elm_t par;
523 int error;
525 vp = ap->a_vp;
526 ip = vp->v_data;
527 ump = ip->ump;
529 slmsg = syslink_kallocmsg();
530 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
531 SLVFS_CMD_VOP_READDIR);
532 sl_msg_fini(slmsg->msg);
534 kprintf("userfs_readdir\n");
535 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
536 par = &slmsg->rep->msg->sm_head;
538 if (par->se_cmd == (SLVFS_CMD_VOP_READDIR|SE_CMDF_REPLY)) {
540 } else {
541 error = EBADRPC;
544 syslink_kfreemsg(ump->sldesc, slmsg);
545 kprintf("error %d\n", error);
546 return(error);
550 * vop_readlink(struct vnode *vp, struct uio *uio, struct ucred *cred)
552 static
554 user_vop_readlink (struct vop_readlink_args *ap)
556 struct user_mount *ump;
557 struct user_inode *ip;
558 struct vnode *vp;
559 struct slmsg *slmsg;
560 syslink_elm_t par;
561 int error;
563 vp = ap->a_vp;
564 ip = vp->v_data;
565 ump = ip->ump;
567 slmsg = syslink_kallocmsg();
568 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
569 SLVFS_CMD_VOP_READLINK);
570 sl_msg_fini(slmsg->msg);
572 kprintf("userfs_readlink\n");
573 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
574 par = &slmsg->rep->msg->sm_head;
576 if (par->se_cmd == (SLVFS_CMD_VOP_READLINK|SE_CMDF_REPLY)) {
578 } else {
579 error = EBADRPC;
582 syslink_kfreemsg(ump->sldesc, slmsg);
583 kprintf("error %d\n", error);
584 return(error);
588 * vop_setattr(struct vnode *vp, struct vattr *vap, struct ucred *cred)
590 static
592 user_vop_setattr (struct vop_setattr_args *ap)
594 struct user_mount *ump;
595 struct user_inode *ip;
596 struct vnode *vp;
597 struct slmsg *slmsg;
598 syslink_elm_t par;
599 int error;
601 vp = ap->a_vp;
602 ip = vp->v_data;
603 ump = ip->ump;
605 slmsg = syslink_kallocmsg();
606 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
607 SLVFS_CMD_VOP_SETATTR);
608 sl_msg_fini(slmsg->msg);
610 kprintf("userfs_setattr\n");
611 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
612 par = &slmsg->rep->msg->sm_head;
614 if (par->se_cmd == (SLVFS_CMD_VOP_SETATTR|SE_CMDF_REPLY)) {
616 } else {
617 error = EBADRPC;
620 syslink_kfreemsg(ump->sldesc, slmsg);
621 kprintf("error %d\n", error);
622 return(error);
626 * user_vop_strategy() - I/O strategy routine.
628 * Note that userfs interfaces fake-up BMAP so the strategy call just
629 * uses the passed bio instead of pushing a bio to get to the (faked)
630 * device block cache.
632 static void user_strategy_callback(struct slmsg *msg, void *arg, int error);
634 static
636 user_vop_strategy (struct vop_strategy_args *ap)
638 struct user_mount *ump;
639 struct user_inode *ip;
640 struct vnode *vp;
641 struct bio *bio;
642 struct buf *bp;
643 struct slmsg *slmsg;
644 syslink_elm_t par;
645 int error;
647 vp = ap->a_vp;
648 ip = vp->v_data;
649 ump = ip->ump;
650 bio = ap->a_bio;
651 bp = bio->bio_buf;
653 bio->bio_driver_info = ump;
655 slmsg = syslink_kallocmsg();
656 switch(bp->b_cmd) {
657 case BUF_CMD_READ:
658 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
659 SLVFS_CMD_VOP_STRATEGY_READ);
660 break;
661 case BUF_CMD_WRITE:
662 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
663 SLVFS_CMD_VOP_STRATEGY_WRITE);
664 break;
665 default:
666 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
667 SLVFS_CMD_VOP_STRATEGY_MISC);
668 break;
670 user_elm_push_vnode(par, vp);
671 user_elm_push_offset(par, bio->bio_offset);
672 user_elm_push_bio(par, bp->b_cmd, bp->b_bcount);
673 syslink_kdmabuf_data(slmsg, bp->b_data, bp->b_bcount);
674 sl_msg_fini(slmsg->msg);
676 kprintf("userfs_strategy\n");
677 error = syslink_ksendmsg(ump->sldesc, slmsg,
678 user_strategy_callback, bio);
679 if (error)
680 syslink_kfreemsg(ump->sldesc, slmsg);
681 kprintf("error %d\n", error);
682 return(error);
686 * This callback is made in the context of the responding process which
687 * may or may not be the process the message was sent to.
689 static void
690 user_strategy_callback(struct slmsg *slmsg, void *arg, int error)
692 struct bio *bio = arg;
693 struct buf *bp = bio->bio_buf;
694 struct user_mount *ump;
695 syslink_elm_t par;
697 kprintf("user_strategy_callback\n");
698 if (error == 0) {
699 par = &slmsg->rep->msg->sm_head;
700 if (par->se_cmd != (slmsg->msg->sm_head.se_cmd | SE_CMDF_REPLY)) {
701 error = EBADRPC;
704 if (error) {
705 bp->b_error = error;
706 bp->b_flags |= B_ERROR;
708 ump = bio->bio_driver_info;
709 syslink_kfreemsg(ump->sldesc, slmsg);
710 biodone(bio);
714 * vop_bmap(struct vnode *vp, off_t loffset, off_t *doffsetp,
715 * int *runp, int *runb)
717 * Dummy up the bmap op so the kernel will cluster I/Os. The strategy
718 * code will ignore the dummied up device block translation.
720 static
722 user_vop_bmap(struct vop_bmap_args *ap)
724 int cluster_off;
726 *ap->a_doffsetp = ap->a_loffset;
727 cluster_off = (int)(*ap->a_doffsetp & (MAXPHYS - 1));
729 if (ap->a_runp)
730 *ap->a_runp = MAXPHYS - cluster_off;
731 if (ap->a_runb)
732 *ap->a_runb = cluster_off;
733 return(0);
738 * vop_ncreate(struct nchandle *nch, struct vnode *dvp, struct vnode **vpp,
739 * struct ucred *cred, struct vattr *vap)
741 static
743 user_vop_ncreate (struct vop_ncreate_args *ap)
745 struct user_mount *ump;
746 struct user_inode *ip;
747 struct namecache *ncp;
748 struct ucred *cred;
749 struct vnode *dvp;
750 struct slmsg *slmsg;
751 syslink_elm_t par;
752 syslink_elm_t elm;
753 int error;
755 cred = ap->a_cred;
756 ncp = ap->a_nch->ncp;
757 dvp = ap->a_dvp;
759 if ((error = vget(dvp, LK_SHARED)) != 0)
760 return (error);
762 ip = dvp->v_data;
763 ump = ip->ump;
765 slmsg = syslink_kallocmsg();
766 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
767 SLVFS_CMD_VOP_NCREATE);
768 user_elm_push_nch(par, ap->a_nch);
769 user_elm_push_vnode(par, dvp);
770 user_elm_push_cred(par, ap->a_cred);
771 user_elm_push_vattr(par, ap->a_vap);
772 sl_msg_fini(slmsg->msg);
774 kprintf("userfs_ncreate\n");
775 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) != 0)
776 goto done;
777 par = &slmsg->rep->msg->sm_head;
778 if (par->se_cmd != (SLVFS_CMD_VOP_NCREATE|SE_CMDF_REPLY)) {
779 error = EBADRPC;
780 goto done;
784 * Parse reply - extract the inode number of the newly created
785 * object and construct a vnode using it.
787 SL_FOREACH_ELEMENT(par, elm) {
788 switch(elm->se_cmd) {
789 case SLVFS_ELM_INUM:
790 /* XXX */
791 break;
792 default:
793 break;
795 if (error)
796 break;
798 /* XXX construct vnode using fileid */
799 error = EINVAL;
801 done:
802 syslink_kfreemsg(ump->sldesc, slmsg);
803 kprintf("error %d\n", error);
804 vput(dvp);
805 return(error);
809 * vop_nresolve(struct nchandle *nch, struct vnode *dvp, struct ucred *cred)
811 static
813 user_vop_nresolve (struct vop_nresolve_args *ap)
815 struct user_mount *ump;
816 struct user_inode *ip;
817 struct namecache *ncp;
818 struct ucred *cred;
819 struct vnode *dvp;
820 struct slmsg *slmsg;
821 syslink_elm_t par;
822 syslink_elm_t elm;
823 int error;
824 int flags;
825 ino_t inum;
827 cred = ap->a_cred;
828 ncp = ap->a_nch->ncp;
829 dvp = ap->a_dvp;
830 if ((error = vget(dvp, LK_SHARED)) != 0)
831 return (error);
832 vn_unlock(dvp);
834 ip = dvp->v_data;
835 ump = ip->ump;
837 slmsg = syslink_kallocmsg();
838 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
839 SLVFS_CMD_VOP_NRESOLVE);
840 user_elm_push_nch(par, ap->a_nch);
841 user_elm_push_vnode(par, dvp);
842 user_elm_push_cred(par, ap->a_cred);
843 sl_msg_fini(slmsg->msg);
846 * Run the RPC. The response must still be parsed for a ENOENT
847 * error to extract the whiteout flag.
849 kprintf("userfs_nresolve\n");
850 error = syslink_kdomsg(ump->sldesc, slmsg);
851 if (error && error != ENOENT)
852 goto done;
853 par = &slmsg->rep->msg->sm_head;
854 if (par->se_cmd != (SLVFS_CMD_VOP_NRESOLVE|SE_CMDF_REPLY)) {
855 error = EBADRPC;
856 goto done;
860 * Parse reply - returns inode number of resolved vnode
862 flags = 0;
863 inum = 0;
864 SL_FOREACH_ELEMENT(par, elm) {
865 switch(elm->se_cmd) {
866 case SLVFS_ELM_INUM:
867 /* XXX */
868 break;
869 case SLVFS_ELM_NCPFLAG:
870 /* flags = & NCF_WHITEOUT */
871 break;
872 default:
873 break;
877 if (error == 0) {
878 error = EINVAL;
879 /*vp = user_getvp(inum);*/
880 /* XXX construct vp cache_setvp(nch, vp); */
881 } else {
882 ncp->nc_flag |= flags;
883 cache_setvp(ap->a_nch, NULL);
885 done:
886 syslink_kfreemsg(ump->sldesc, slmsg);
887 vrele(dvp);
888 kprintf("error %d\n", error);
889 return(error);
893 * vop_nlookupdotdot(struct vnode *dvp, struct vnode **vpp, struct ucred *cred)
895 * Lookup the parent of dvp. dvp is ref'd but not locked. The returned
896 * vnode should be ref'd and locked.
898 static
900 user_vop_nlookupdotdot (struct vop_nlookupdotdot_args *ap)
902 struct user_mount *ump;
903 struct user_inode *ip;
904 struct ucred *cred;
905 struct vnode *dvp;
906 struct vnode *vp;
907 struct slmsg *slmsg;
908 syslink_elm_t par;
909 syslink_elm_t elm;
910 int error;
911 ino_t inum;
913 cred = ap->a_cred;
914 dvp = ap->a_dvp;
915 vp = NULL; /* XXX */
916 ip = vp->v_data;
917 ump = ip->ump;
919 slmsg = syslink_kallocmsg();
920 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
921 SLVFS_CMD_VOP_NLOOKUPDOTDOT);
922 sl_msg_fini(slmsg->msg);
924 kprintf("userfs_nlookupdotdot\n");
925 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) != 0)
926 goto done;
927 par = &slmsg->rep->msg->sm_head;
929 if (par->se_cmd != (SLVFS_CMD_VOP_NLOOKUPDOTDOT|SE_CMDF_REPLY)) {
930 error = EBADRPC;
931 goto done;
935 * Parse reply - inumber of parent directory
937 inum = 0;
938 SL_FOREACH_ELEMENT(par, elm) {
939 switch(elm->se_cmd) {
940 case SLVFS_ELM_INUM:
941 /* XXX */
942 break;
943 case SLVFS_ELM_NCPFLAG:
944 /* flags = & NCF_WHITEOUT */
945 break;
946 default:
947 break;
951 /* construct parent vnode */
953 done:
954 syslink_kfreemsg(ump->sldesc, slmsg);
955 kprintf("error %d\n", error);
956 return(error);
960 * vop_nlink(struct nchandle *nch, struct vnode *dvp, struct vnode *vp,
961 * struct ucred *cred)
963 static
965 user_vop_nlink (struct vop_nlink_args *ap)
967 struct user_mount *ump;
968 struct user_inode *ip;
969 struct vnode *vp;
970 struct slmsg *slmsg;
971 syslink_elm_t par;
972 int error;
974 vp = ap->a_vp;
975 ip = vp->v_data;
976 ump = ip->ump;
978 slmsg = syslink_kallocmsg();
979 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
980 SLVFS_CMD_VOP_NLINK);
981 sl_msg_fini(slmsg->msg);
983 kprintf("userfs_nlink\n");
984 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
985 par = &slmsg->rep->msg->sm_head;
987 if (par->se_cmd == (SLVFS_CMD_VOP_NLINK|SE_CMDF_REPLY)) {
989 } else {
990 error = EBADRPC;
993 syslink_kfreemsg(ump->sldesc, slmsg);
994 kprintf("error %d\n", error);
995 return(error);
999 * vop_nmkdir(struct nchandle *nch, struct vnode *dvp, struct vnode **vpp,
1000 * struct ucred *cred, struct vattr *vap)
1002 static
1004 user_vop_nmkdir (struct vop_nmkdir_args *ap)
1006 struct user_mount *ump;
1007 struct user_inode *ip;
1008 struct namecache *ncp;
1009 struct ucred *cred;
1010 struct vnode *dvp;
1011 struct vnode *vp;
1012 struct slmsg *slmsg;
1013 syslink_elm_t par;
1014 int error;
1016 cred = ap->a_cred;
1017 ncp = ap->a_nch->ncp;
1018 dvp = ap->a_dvp;
1019 if ((error = vget(dvp, LK_SHARED)) != 0)
1020 return (error);
1022 vp = NULL; /* XXX */
1024 ip = vp->v_data;
1025 ump = ip->ump;
1027 slmsg = syslink_kallocmsg();
1028 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1029 SLVFS_CMD_VOP_NMKDIR);
1030 sl_msg_fini(slmsg->msg);
1032 kprintf("userfs_nmkdir\n");
1033 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1034 par = &slmsg->rep->msg->sm_head;
1036 if (par->se_cmd == (SLVFS_CMD_VOP_NMKDIR|SE_CMDF_REPLY)) {
1038 } else {
1039 error = EBADRPC;
1042 syslink_kfreemsg(ump->sldesc, slmsg);
1043 kprintf("error %d\n", error);
1044 vput(dvp);
1045 return(error);
1049 * vop_nmknod(struct nchandle *nch, struct vnode *dvp, struct vnode **vpp,
1050 * struct ucred *cred, struct vattr *vap)
1052 static
1054 user_vop_nmknod (struct vop_nmknod_args *ap)
1056 struct user_mount *ump;
1057 struct user_inode *ip;
1058 struct namecache *ncp;
1059 struct ucred *cred;
1060 struct vnode *dvp;
1061 struct vnode *vp;
1062 struct slmsg *slmsg;
1063 syslink_elm_t par;
1064 int error;
1066 cred = ap->a_cred;
1067 ncp = ap->a_nch->ncp;
1068 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1070 vp = NULL; /* XXX */
1072 ip = vp->v_data;
1073 ump = ip->ump;
1075 slmsg = syslink_kallocmsg();
1076 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1077 SLVFS_CMD_VOP_NMKNOD);
1078 sl_msg_fini(slmsg->msg);
1080 kprintf("userfs_nmknod\n");
1081 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1082 par = &slmsg->rep->msg->sm_head;
1084 if (par->se_cmd == (SLVFS_CMD_VOP_NMKNOD|SE_CMDF_REPLY)) {
1086 } else {
1087 error = EBADRPC;
1090 syslink_kfreemsg(ump->sldesc, slmsg);
1091 kprintf("error %d\n", error);
1092 return(error);
1096 * vop_nremove(struct nchandle *nch, struct vnode *dvp, struct ucred *cred)
1098 static
1100 user_vop_nremove (struct vop_nremove_args *ap)
1102 struct user_mount *ump;
1103 struct user_inode *ip;
1104 struct namecache *ncp;
1105 struct ucred *cred;
1106 struct vnode *dvp;
1107 struct vnode *vp;
1108 struct slmsg *slmsg;
1109 syslink_elm_t par;
1110 int error;
1112 cred = ap->a_cred;
1113 ncp = ap->a_nch->ncp;
1114 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1116 vp = NULL; /* XXX */
1118 ip = vp->v_data;
1119 ump = ip->ump;
1121 slmsg = syslink_kallocmsg();
1122 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1123 SLVFS_CMD_VOP_NREMOVE);
1124 sl_msg_fini(slmsg->msg);
1126 kprintf("userfs_nremove\n");
1127 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1128 par = &slmsg->rep->msg->sm_head;
1130 if (par->se_cmd == (SLVFS_CMD_VOP_NREMOVE|SE_CMDF_REPLY)) {
1132 } else {
1133 error = EBADRPC;
1136 syslink_kfreemsg(ump->sldesc, slmsg);
1137 kprintf("error %d\n", error);
1138 return(error);
1142 * vop_nrename(struct nchandle *fnch, struct nchandle *tnch,
1143 * struct vnode *fdvp, struct vnode *tdvp,
1144 * struct ucred *cred)
1146 static
1148 user_vop_nrename (struct vop_nrename_args *ap)
1150 struct user_mount *ump;
1151 struct user_inode *ip;
1152 struct namecache *fncp;
1153 struct namecache *tncp;
1154 struct ucred *cred;
1155 struct vnode *fdvp;
1156 struct vnode *tdvp;
1157 struct vnode *vp;
1158 struct slmsg *slmsg;
1159 syslink_elm_t par;
1160 int error;
1162 cred = ap->a_cred;
1163 fncp = ap->a_fnch->ncp;
1164 fdvp = ap->a_fdvp; /* XXX needs vget */
1165 tncp = ap->a_tnch->ncp;
1166 tdvp = ap->a_tdvp; /* XXX needs vget */
1168 vp = NULL; /* XXX */
1170 ip = vp->v_data;
1171 ump = ip->ump;
1173 slmsg = syslink_kallocmsg();
1174 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1175 SLVFS_CMD_VOP_NRENAME);
1176 sl_msg_fini(slmsg->msg);
1178 kprintf("userfs_nrename\n");
1179 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1180 par = &slmsg->rep->msg->sm_head;
1182 if (par->se_cmd == (SLVFS_CMD_VOP_NRENAME|SE_CMDF_REPLY)) {
1184 } else {
1185 error = EBADRPC;
1188 syslink_kfreemsg(ump->sldesc, slmsg);
1189 kprintf("error %d\n", error);
1190 return(error);
1194 * vop_nrmdir(struct nchandle *nch, struct vnode *dvp, struct ucred *cred)
1196 static
1198 user_vop_nrmdir (struct vop_nrmdir_args *ap)
1200 struct user_mount *ump;
1201 struct user_inode *ip;
1202 struct namecache *ncp;
1203 struct ucred *cred;
1204 struct vnode *dvp;
1205 struct vnode *vp;
1206 struct slmsg *slmsg;
1207 syslink_elm_t par;
1208 int error;
1210 cred = ap->a_cred;
1211 ncp = ap->a_nch->ncp;
1212 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1214 vp = NULL; /* XXX */
1216 ip = vp->v_data;
1217 ump = ip->ump;
1219 slmsg = syslink_kallocmsg();
1220 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1221 SLVFS_CMD_VOP_NRMDIR);
1222 sl_msg_fini(slmsg->msg);
1224 kprintf("userfs_nrmdir\n");
1225 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1226 par = &slmsg->rep->msg->sm_head;
1228 if (par->se_cmd == (SLVFS_CMD_VOP_NRMDIR|SE_CMDF_REPLY)) {
1230 } else {
1231 error = EBADRPC;
1234 syslink_kfreemsg(ump->sldesc, slmsg);
1235 kprintf("error %d\n", error);
1236 return(error);
1239 static
1241 user_vop_nsymlink (struct vop_nsymlink_args *ap)
1243 struct user_mount *ump;
1244 struct user_inode *ip;
1245 struct namecache *ncp;
1246 struct ucred *cred;
1247 struct vnode *dvp;
1248 struct vnode *vp;
1249 struct slmsg *slmsg;
1250 syslink_elm_t par;
1251 int error;
1253 cred = ap->a_cred;
1254 ncp = ap->a_nch->ncp;
1255 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1257 vp = NULL; /* XXX */
1259 ip = vp->v_data;
1260 ump = ip->ump;
1262 slmsg = syslink_kallocmsg();
1263 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1264 SLVFS_CMD_VOP_NSYMLINK);
1265 sl_msg_fini(slmsg->msg);
1267 kprintf("userfs_nsymlink\n");
1268 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1269 par = &slmsg->rep->msg->sm_head;
1271 if (par->se_cmd == (SLVFS_CMD_VOP_NSYMLINK|SE_CMDF_REPLY)) {
1273 } else {
1274 error = EBADRPC;
1277 syslink_kfreemsg(ump->sldesc, slmsg);
1278 kprintf("error %d\n", error);
1279 return(error);
1282 static
1284 user_vop_nwhiteout (struct vop_nwhiteout_args *ap)
1286 struct user_mount *ump;
1287 struct user_inode *ip;
1288 struct namecache *ncp;
1289 struct ucred *cred;
1290 struct vnode *dvp;
1291 struct vnode *vp;
1292 struct slmsg *slmsg;
1293 syslink_elm_t par;
1294 int error;
1296 cred = ap->a_cred;
1297 ncp = ap->a_nch->ncp;
1298 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1300 vp = NULL; /* XXX */
1302 ip = vp->v_data;
1303 ump = ip->ump;
1305 slmsg = syslink_kallocmsg();
1306 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
1307 SLVFS_CMD_VOP_NWHITEOUT);
1308 sl_msg_fini(slmsg->msg);
1310 kprintf("userfs_nwhiteout\n");
1311 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1312 par = &slmsg->rep->msg->sm_head;
1314 if (par->se_cmd == (SLVFS_CMD_VOP_NWHITEOUT|SE_CMDF_REPLY)) {
1316 } else {
1317 error = EBADRPC;
1320 syslink_kfreemsg(ump->sldesc, slmsg);
1321 kprintf("error %d\n", error);
1322 return(error);