AMD64 - Refactor uio_resid and size_t assumptions.
[dragonfly.git] / sys / vfs / userfs / userfs_vnops.c
CommitLineData
a92480c3
MD
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 *
84009d92 34 * $DragonFly: src/sys/vfs/userfs/userfs_vnops.c,v 1.4 2007/11/20 21:03:51 dillon Exp $
a92480c3
MD
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>
9b082684 48#include <sys/unistd.h>
a92480c3
MD
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 *);*/
56static int user_vop_fsync (struct vop_fsync_args *);
a92480c3
MD
57static int user_vop_read (struct vop_read_args *);
58static int user_vop_write (struct vop_write_args *);
59static int user_vop_access (struct vop_access_args *);
60static int user_vop_advlock (struct vop_advlock_args *);
61static int user_vop_close (struct vop_close_args *);
62static int user_vop_ncreate (struct vop_ncreate_args *);
63static int user_vop_getattr (struct vop_getattr_args *);
64static int user_vop_nresolve (struct vop_nresolve_args *);
65static int user_vop_nlookupdotdot (struct vop_nlookupdotdot_args *);
66static int user_vop_nlink (struct vop_nlink_args *);
67static int user_vop_nmkdir (struct vop_nmkdir_args *);
68static int user_vop_nmknod (struct vop_nmknod_args *);
69static int user_vop_open (struct vop_open_args *);
70static int user_vop_pathconf (struct vop_pathconf_args *);
71static int user_vop_print (struct vop_print_args *);
72static int user_vop_readdir (struct vop_readdir_args *);
73static int user_vop_readlink (struct vop_readlink_args *);
74static int user_vop_nremove (struct vop_nremove_args *);
75static int user_vop_nrename (struct vop_nrename_args *);
76static int user_vop_nrmdir (struct vop_nrmdir_args *);
77static int user_vop_setattr (struct vop_setattr_args *);
78static int user_vop_strategy (struct vop_strategy_args *);
79static int user_vop_nsymlink (struct vop_nsymlink_args *);
80static int user_vop_nwhiteout (struct vop_nwhiteout_args *);
81static int user_vop_bmap (struct vop_bmap_args *);
82
83struct vop_ops userfs_vnode_vops = {
84 .vop_default = vop_defaultop,
85 .vop_fsync = user_vop_fsync,
9b082684
MD
86 .vop_getpages = vop_stdgetpages,
87 .vop_putpages = vop_stdputpages,
a92480c3
MD
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
118static
119int
120user_vop_vnoperate(struct vop_generic_args *)
121{
122 return (VOCALL(&userfs_vnode_vops, ap));
123}
124#endif
125
9b082684
MD
126/*
127 * vop_fsync(struct vnode *vp, int waitfor)
128 */
a92480c3
MD
129static
130int
131user_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
a92480c3 165/*
9b082684 166 * vop_read(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
a92480c3
MD
167 */
168static
169int
170user_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
9b082684
MD
186 if (uio->uio_offset < 0)
187 return (EINVAL);
188 if (vp->v_type != VREG)
189 return (EINVAL);
190
a92480c3
MD
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
9b082684
MD
223/*
224 * vop_write(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
225 */
a92480c3
MD
226static
227int
228user_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;
e54488bb
MD
236 off_t loffset;
237 size_t offset;
238 size_t n;
a92480c3
MD
239
240 vp = ap->a_vp;
241 ip = vp->v_data;
242 ump = ip->ump;
243 uio = ap->a_uio;
244
9b082684 245 if (vp->v_type != VREG)
a92480c3 246 return (EINVAL);
9b082684
MD
247 if (ap->a_ioflag & IO_APPEND)
248 uio->uio_offset = ip->filesize;
a92480c3
MD
249
250 /*
251 * Check for illegal write offsets. Valid range is 0...2^63-1
252 */
e54488bb
MD
253 loffset = uio->uio_offset;
254 if (loffset < 0)
a92480c3 255 return (EFBIG);
e54488bb
MD
256 if (uio->uio_resid) {
257 /* GCC4 - workaround optimization */
258 loffset += uio->uio_resid;
259 if (loffset <= 0)
260 return (EFBIG);
261 }
a92480c3
MD
262
263 kprintf("userfs_write\n");
264 error = 0;
265 while (uio->uio_resid > 0) {
266 /*
267 * Use buffer cache I/O (via user_vop_strategy), aligned
268 * on USERFS_BSIZE boundaries.
269 *
270 * XXX not optimized for complete write-overs or file
8aa7625b 271 * extensions. Note: must bread on UIO_NOCOPY writes.
9b082684
MD
272 *
273 * XXX No need to read if strictly appending.
a92480c3 274 */
e54488bb 275 offset = (size_t)uio->uio_offset & USERFS_BMASK;
9b082684 276 /* if offset == ip->filesize use getblk instead */
a92480c3
MD
277 error = bread(vp, uio->uio_offset - offset, USERFS_BSIZE, &bp);
278 if (error) {
279 brelse(bp);
280 break;
281 }
282
283 /*
284 * Figure out how many bytes we can actually copy this loop.
285 */
286 n = USERFS_BSIZE - offset;
287 if (n > uio->uio_resid)
288 n = uio->uio_resid;
289 if (n > ip->filesize - uio->uio_offset)
e54488bb 290 n = (size_t)(ip->filesize - uio->uio_offset);
a92480c3
MD
291
292 error = uiomove((char *)bp->b_data + offset, n, uio);
293 if (error) {
294 brelse(bp);
295 break;
296 }
297
298 /*
299 * Extend the file's size if necessary
300 */
301 if (ip->filesize < uio->uio_offset)
302 ip->filesize = uio->uio_offset;
303
304 /*
305 * The data has been loaded into the buffer, write it out.
306 */
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);
315 }
316 }
317 kprintf("userfs_write error %d\n", error);
318 return(error);
319}
320
9b082684
MD
321/*
322 * vop_access(struct vnode *vp, int mode, struct ucred *cred)
323 */
a92480c3
MD
324static
325int
326user_vop_access (struct vop_access_args *ap)
327{
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;
334
335 vp = ap->a_vp;
336 ip = vp->v_data;
337 ump = ip->ump;
338
339 slmsg = syslink_kallocmsg();
340 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
341 SLVFS_CMD_VOP_ACCESS);
9b082684
MD
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);
a92480c3
MD
345 sl_msg_fini(slmsg->msg);
346
9b082684
MD
347 /*
348 * Issue the request and do basic validation of the response
349 */
a92480c3 350 kprintf("userfs_access\n");
9b082684
MD
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;
a92480c3 357 }
9b082684
MD
358
359done:
a92480c3
MD
360 syslink_kfreemsg(ump->sldesc, slmsg);
361 kprintf("error %d\n", error);
362 return(error);
363}
364
9b082684
MD
365/*
366 * vop_advlock(struct vnode *vp, caddr_t id, int op, struct flock *fl,
367 * int flags)
368 *
369 * This vop is handled directly by the kernel.
370 */
a92480c3
MD
371static
372int
373user_vop_advlock (struct vop_advlock_args *ap)
374{
375 struct user_inode *ip;
376 struct vnode *vp;
377
378 vp = ap->a_vp;
379 ip = vp->v_data;
380
381 return (lf_advlock(ap, &ip->lockf, ip->filesize));
382}
383
9b082684
MD
384/*
385 * vop_open(struct vnode *vp, int mode, struct ucred *cred, struct file *file)
386 *
387 * This vop is handled directly by the kernel.
388 */
a92480c3
MD
389static
390int
391user_vop_open (struct vop_open_args *ap)
392{
393 return (vop_stdopen(ap));
394}
395
9b082684
MD
396/*
397 * vop_close(struct vnode *vp, int fflag)
398 *
399 * This vop is handled directly by the kernel.
400 */
a92480c3
MD
401static
402int
403user_vop_close (struct vop_close_args *ap)
404{
405 return (vop_stdclose(ap));
406}
407
9b082684
MD
408/*
409 * vop_getattr(struct vnode *vp, struct vattr *vap)
410 */
a92480c3
MD
411static
412int
9b082684 413user_vop_getattr (struct vop_getattr_args *ap)
a92480c3
MD
414{
415 struct user_mount *ump;
416 struct user_inode *ip;
a92480c3
MD
417 struct vnode *vp;
418 struct slmsg *slmsg;
419 syslink_elm_t par;
9b082684 420 syslink_elm_t elm;
a92480c3
MD
421 int error;
422
9b082684 423 vp = ap->a_vp;
a92480c3
MD
424 ip = vp->v_data;
425 ump = ip->ump;
426
427 slmsg = syslink_kallocmsg();
428 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
9b082684 429 SLVFS_CMD_VOP_GETATTR);
a92480c3
MD
430 sl_msg_fini(slmsg->msg);
431
9b082684
MD
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;
439 }
a92480c3 440
9b082684
MD
441 /*
442 * Parse reply content
443 */
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;
a92480c3 451 }
9b082684
MD
452 if (error)
453 break;
a92480c3 454 }
9b082684 455done:
a92480c3
MD
456 syslink_kfreemsg(ump->sldesc, slmsg);
457 kprintf("error %d\n", error);
a92480c3
MD
458 return(error);
459}
460
9b082684
MD
461/*
462 * vop_pathconf(int name, int *retval)
463 *
464 * This vop is handled directly by the kernel.
465 */
a92480c3
MD
466static
467int
9b082684
MD
468user_vop_pathconf (struct vop_pathconf_args *ap)
469{
470 int error = 0;
471
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;
494 }
495 return (error);
496}
497
498/*
499 * vop_print(int name, int *retval)
500 *
501 * This vop is handled directly by the kernel.
502 */
503static
504int
505user_vop_print (struct vop_print_args *ap)
506{
507 return(0);
508}
509
510/*
511 * vop_readdir(struct vnode *vp, struct uio *uio, struct ucred *cred,
84009d92 512 * int *eofflag, int *ncookies, off_t **a_cookies)
9b082684
MD
513 */
514static
515int
516user_vop_readdir (struct vop_readdir_args *ap)
a92480c3
MD
517{
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;
524
a92480c3 525 vp = ap->a_vp;
a92480c3 526 ip = vp->v_data;
a92480c3 527 ump = ip->ump;
a92480c3
MD
528
529 slmsg = syslink_kallocmsg();
530 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
9b082684 531 SLVFS_CMD_VOP_READDIR);
a92480c3
MD
532 sl_msg_fini(slmsg->msg);
533
9b082684 534 kprintf("userfs_readdir\n");
a92480c3
MD
535 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
536 par = &slmsg->rep->msg->sm_head;
537
9b082684 538 if (par->se_cmd == (SLVFS_CMD_VOP_READDIR|SE_CMDF_REPLY)) {
a92480c3
MD
539 ;
540 } else {
541 error = EBADRPC;
542 }
543 }
544 syslink_kfreemsg(ump->sldesc, slmsg);
545 kprintf("error %d\n", error);
546 return(error);
547}
548
9b082684
MD
549/*
550 * vop_readlink(struct vnode *vp, struct uio *uio, struct ucred *cred)
551 */
a92480c3
MD
552static
553int
9b082684 554user_vop_readlink (struct vop_readlink_args *ap)
a92480c3
MD
555{
556 struct user_mount *ump;
557 struct user_inode *ip;
a92480c3 558 struct vnode *vp;
a92480c3
MD
559 struct slmsg *slmsg;
560 syslink_elm_t par;
561 int error;
562
9b082684 563 vp = ap->a_vp;
a92480c3
MD
564 ip = vp->v_data;
565 ump = ip->ump;
566
a92480c3
MD
567 slmsg = syslink_kallocmsg();
568 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
9b082684 569 SLVFS_CMD_VOP_READLINK);
a92480c3
MD
570 sl_msg_fini(slmsg->msg);
571
9b082684 572 kprintf("userfs_readlink\n");
a92480c3
MD
573 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
574 par = &slmsg->rep->msg->sm_head;
575
9b082684 576 if (par->se_cmd == (SLVFS_CMD_VOP_READLINK|SE_CMDF_REPLY)) {
a92480c3
MD
577 ;
578 } else {
579 error = EBADRPC;
580 }
581 }
582 syslink_kfreemsg(ump->sldesc, slmsg);
a92480c3
MD
583 kprintf("error %d\n", error);
584 return(error);
585}
586
9b082684
MD
587/*
588 * vop_setattr(struct vnode *vp, struct vattr *vap, struct ucred *cred)
589 */
a92480c3
MD
590static
591int
9b082684 592user_vop_setattr (struct vop_setattr_args *ap)
a92480c3
MD
593{
594 struct user_mount *ump;
595 struct user_inode *ip;
a92480c3
MD
596 struct vnode *vp;
597 struct slmsg *slmsg;
598 syslink_elm_t par;
599 int error;
600
9b082684 601 vp = ap->a_vp;
a92480c3
MD
602 ip = vp->v_data;
603 ump = ip->ump;
604
605 slmsg = syslink_kallocmsg();
606 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
9b082684 607 SLVFS_CMD_VOP_SETATTR);
a92480c3
MD
608 sl_msg_fini(slmsg->msg);
609
9b082684 610 kprintf("userfs_setattr\n");
a92480c3
MD
611 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
612 par = &slmsg->rep->msg->sm_head;
613
9b082684 614 if (par->se_cmd == (SLVFS_CMD_VOP_SETATTR|SE_CMDF_REPLY)) {
a92480c3
MD
615 ;
616 } else {
617 error = EBADRPC;
618 }
619 }
620 syslink_kfreemsg(ump->sldesc, slmsg);
621 kprintf("error %d\n", error);
622 return(error);
623}
624
9b082684
MD
625/*
626 * user_vop_strategy() - I/O strategy routine.
627 *
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.
631 */
632static void user_strategy_callback(struct slmsg *msg, void *arg, int error);
633
a92480c3
MD
634static
635int
9b082684 636user_vop_strategy (struct vop_strategy_args *ap)
a92480c3
MD
637{
638 struct user_mount *ump;
639 struct user_inode *ip;
640 struct vnode *vp;
9b082684
MD
641 struct bio *bio;
642 struct buf *bp;
a92480c3
MD
643 struct slmsg *slmsg;
644 syslink_elm_t par;
645 int error;
646
647 vp = ap->a_vp;
648 ip = vp->v_data;
649 ump = ip->ump;
9b082684
MD
650 bio = ap->a_bio;
651 bp = bio->bio_buf;
652
653 bio->bio_driver_info = ump;
a92480c3
MD
654
655 slmsg = syslink_kallocmsg();
9b082684
MD
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;
669 }
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);
a92480c3
MD
674 sl_msg_fini(slmsg->msg);
675
9b082684
MD
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);
a92480c3
MD
681 kprintf("error %d\n", error);
682 return(error);
683}
684
9b082684
MD
685/*
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.
688 */
689static void
690user_strategy_callback(struct slmsg *slmsg, void *arg, int error)
a92480c3 691{
9b082684
MD
692 struct bio *bio = arg;
693 struct buf *bp = bio->bio_buf;
a92480c3 694 struct user_mount *ump;
a92480c3 695 syslink_elm_t par;
a92480c3 696
9b082684
MD
697 kprintf("user_strategy_callback\n");
698 if (error == 0) {
a92480c3 699 par = &slmsg->rep->msg->sm_head;
9b082684 700 if (par->se_cmd != (slmsg->msg->sm_head.se_cmd | SE_CMDF_REPLY)) {
a92480c3
MD
701 error = EBADRPC;
702 }
703 }
9b082684
MD
704 if (error) {
705 bp->b_error = error;
706 bp->b_flags |= B_ERROR;
707 }
708 ump = bio->bio_driver_info;
709 syslink_kfreemsg(ump->sldesc, slmsg);
710 biodone(bio);
711}
712
713/*
714 * vop_bmap(struct vnode *vp, off_t loffset, off_t *doffsetp,
715 * int *runp, int *runb)
716 *
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.
719 */
720static
721int
722user_vop_bmap(struct vop_bmap_args *ap)
723{
724 int cluster_off;
725
726 *ap->a_doffsetp = ap->a_loffset;
727 cluster_off = (int)(*ap->a_doffsetp & (MAXPHYS - 1));
728
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);
734}
735
736
737/*
738 * vop_ncreate(struct nchandle *nch, struct vnode *dvp, struct vnode **vpp,
739 * struct ucred *cred, struct vattr *vap)
740 */
741static
742int
743user_vop_ncreate (struct vop_ncreate_args *ap)
744{
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;
754
755 cred = ap->a_cred;
756 ncp = ap->a_nch->ncp;
757 dvp = ap->a_dvp;
758
759 if ((error = vget(dvp, LK_SHARED)) != 0)
760 return (error);
761
762 ip = dvp->v_data;
763 ump = ip->ump;
764
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);
773
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;
781 }
782
783 /*
784 * Parse reply - extract the inode number of the newly created
785 * object and construct a vnode using it.
786 */
787 SL_FOREACH_ELEMENT(par, elm) {
788 switch(elm->se_cmd) {
789 case SLVFS_ELM_INUM:
790 /* XXX */
791 break;
792 default:
793 break;
794 }
795 if (error)
796 break;
797 }
798 /* XXX construct vnode using fileid */
799 error = EINVAL;
800
801done:
a92480c3
MD
802 syslink_kfreemsg(ump->sldesc, slmsg);
803 kprintf("error %d\n", error);
804 vput(dvp);
805 return(error);
806}
807
9b082684
MD
808/*
809 * vop_nresolve(struct nchandle *nch, struct vnode *dvp, struct ucred *cred)
810 */
a92480c3
MD
811static
812int
9b082684 813user_vop_nresolve (struct vop_nresolve_args *ap)
a92480c3
MD
814{
815 struct user_mount *ump;
816 struct user_inode *ip;
817 struct namecache *ncp;
818 struct ucred *cred;
819 struct vnode *dvp;
a92480c3
MD
820 struct slmsg *slmsg;
821 syslink_elm_t par;
9b082684 822 syslink_elm_t elm;
a92480c3 823 int error;
9b082684
MD
824 int flags;
825 ino_t inum;
a92480c3
MD
826
827 cred = ap->a_cred;
828 ncp = ap->a_nch->ncp;
9b082684
MD
829 dvp = ap->a_dvp;
830 if ((error = vget(dvp, LK_SHARED)) != 0)
831 return (error);
832 vn_unlock(dvp);
a92480c3 833
9b082684 834 ip = dvp->v_data;
a92480c3
MD
835 ump = ip->ump;
836
837 slmsg = syslink_kallocmsg();
838 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
9b082684
MD
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);
a92480c3
MD
843 sl_msg_fini(slmsg->msg);
844
9b082684
MD
845 /*
846 * Run the RPC. The response must still be parsed for a ENOENT
847 * error to extract the whiteout flag.
848 */
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;
857 }
a92480c3 858
9b082684
MD
859 /*
860 * Parse reply - returns inode number of resolved vnode
861 */
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;
a92480c3
MD
874 }
875 }
9b082684
MD
876
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);
884 }
885done:
a92480c3 886 syslink_kfreemsg(ump->sldesc, slmsg);
9b082684 887 vrele(dvp);
a92480c3
MD
888 kprintf("error %d\n", error);
889 return(error);
890}
891
9b082684
MD
892/*
893 * vop_nlookupdotdot(struct vnode *dvp, struct vnode **vpp, struct ucred *cred)
894 *
895 * Lookup the parent of dvp. dvp is ref'd but not locked. The returned
896 * vnode should be ref'd and locked.
897 */
a92480c3
MD
898static
899int
9b082684 900user_vop_nlookupdotdot (struct vop_nlookupdotdot_args *ap)
a92480c3
MD
901{
902 struct user_mount *ump;
903 struct user_inode *ip;
9b082684
MD
904 struct ucred *cred;
905 struct vnode *dvp;
a92480c3
MD
906 struct vnode *vp;
907 struct slmsg *slmsg;
908 syslink_elm_t par;
9b082684 909 syslink_elm_t elm;
a92480c3 910 int error;
9b082684 911 ino_t inum;
a92480c3 912
9b082684
MD
913 cred = ap->a_cred;
914 dvp = ap->a_dvp;
915 vp = NULL; /* XXX */
a92480c3
MD
916 ip = vp->v_data;
917 ump = ip->ump;
918
919 slmsg = syslink_kallocmsg();
920 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
9b082684 921 SLVFS_CMD_VOP_NLOOKUPDOTDOT);
a92480c3
MD
922 sl_msg_fini(slmsg->msg);
923
9b082684
MD
924 kprintf("userfs_nlookupdotdot\n");
925 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) != 0)
926 goto done;
927 par = &slmsg->rep->msg->sm_head;
a92480c3 928
9b082684
MD
929 if (par->se_cmd != (SLVFS_CMD_VOP_NLOOKUPDOTDOT|SE_CMDF_REPLY)) {
930 error = EBADRPC;
931 goto done;
932 }
933
934 /*
935 * Parse reply - inumber of parent directory
936 */
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;
a92480c3
MD
948 }
949 }
9b082684
MD
950
951 /* construct parent vnode */
952
953done:
a92480c3
MD
954 syslink_kfreemsg(ump->sldesc, slmsg);
955 kprintf("error %d\n", error);
956 return(error);
957}
958
9b082684
MD
959/*
960 * vop_nlink(struct nchandle *nch, struct vnode *dvp, struct vnode *vp,
961 * struct ucred *cred)
962 */
a92480c3
MD
963static
964int
9b082684 965user_vop_nlink (struct vop_nlink_args *ap)
a92480c3
MD
966{
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;
973
974 vp = ap->a_vp;
975 ip = vp->v_data;
976 ump = ip->ump;
977
978 slmsg = syslink_kallocmsg();
979 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
9b082684 980 SLVFS_CMD_VOP_NLINK);
a92480c3
MD
981 sl_msg_fini(slmsg->msg);
982
9b082684 983 kprintf("userfs_nlink\n");
a92480c3
MD
984 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
985 par = &slmsg->rep->msg->sm_head;
986
9b082684 987 if (par->se_cmd == (SLVFS_CMD_VOP_NLINK|SE_CMDF_REPLY)) {
a92480c3
MD
988 ;
989 } else {
990 error = EBADRPC;
991 }
992 }
993 syslink_kfreemsg(ump->sldesc, slmsg);
994 kprintf("error %d\n", error);
995 return(error);
996}
997
9b082684
MD
998/*
999 * vop_nmkdir(struct nchandle *nch, struct vnode *dvp, struct vnode **vpp,
1000 * struct ucred *cred, struct vattr *vap)
1001 */
a92480c3
MD
1002static
1003int
9b082684 1004user_vop_nmkdir (struct vop_nmkdir_args *ap)
a92480c3
MD
1005{
1006 struct user_mount *ump;
1007 struct user_inode *ip;
9b082684
MD
1008 struct namecache *ncp;
1009 struct ucred *cred;
1010 struct vnode *dvp;
a92480c3
MD
1011 struct vnode *vp;
1012 struct slmsg *slmsg;
1013 syslink_elm_t par;
1014 int error;
1015
9b082684
MD
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);
1021
1022 vp = NULL; /* XXX */
1023
a92480c3
MD
1024 ip = vp->v_data;
1025 ump = ip->ump;
1026
1027 slmsg = syslink_kallocmsg();
1028 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
9b082684 1029 SLVFS_CMD_VOP_NMKDIR);
a92480c3
MD
1030 sl_msg_fini(slmsg->msg);
1031
9b082684 1032 kprintf("userfs_nmkdir\n");
a92480c3
MD
1033 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1034 par = &slmsg->rep->msg->sm_head;
1035
9b082684 1036 if (par->se_cmd == (SLVFS_CMD_VOP_NMKDIR|SE_CMDF_REPLY)) {
a92480c3
MD
1037 ;
1038 } else {
1039 error = EBADRPC;
1040 }
1041 }
1042 syslink_kfreemsg(ump->sldesc, slmsg);
1043 kprintf("error %d\n", error);
9b082684 1044 vput(dvp);
a92480c3
MD
1045 return(error);
1046}
1047
9b082684
MD
1048/*
1049 * vop_nmknod(struct nchandle *nch, struct vnode *dvp, struct vnode **vpp,
1050 * struct ucred *cred, struct vattr *vap)
1051 */
a92480c3
MD
1052static
1053int
9b082684 1054user_vop_nmknod (struct vop_nmknod_args *ap)
a92480c3
MD
1055{
1056 struct user_mount *ump;
1057 struct user_inode *ip;
9b082684
MD
1058 struct namecache *ncp;
1059 struct ucred *cred;
1060 struct vnode *dvp;
a92480c3
MD
1061 struct vnode *vp;
1062 struct slmsg *slmsg;
1063 syslink_elm_t par;
1064 int error;
1065
9b082684
MD
1066 cred = ap->a_cred;
1067 ncp = ap->a_nch->ncp;
1068 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1069
1070 vp = NULL; /* XXX */
1071
a92480c3
MD
1072 ip = vp->v_data;
1073 ump = ip->ump;
1074
1075 slmsg = syslink_kallocmsg();
1076 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS,
9b082684 1077 SLVFS_CMD_VOP_NMKNOD);
a92480c3
MD
1078 sl_msg_fini(slmsg->msg);
1079
9b082684 1080 kprintf("userfs_nmknod\n");
a92480c3
MD
1081 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1082 par = &slmsg->rep->msg->sm_head;
1083
9b082684 1084 if (par->se_cmd == (SLVFS_CMD_VOP_NMKNOD|SE_CMDF_REPLY)) {
a92480c3
MD
1085 ;
1086 } else {
1087 error = EBADRPC;
1088 }
1089 }
1090 syslink_kfreemsg(ump->sldesc, slmsg);
1091 kprintf("error %d\n", error);
1092 return(error);
1093}
1094
9b082684
MD
1095/*
1096 * vop_nremove(struct nchandle *nch, struct vnode *dvp, struct ucred *cred)
1097 */
a92480c3
MD
1098static
1099int
1100user_vop_nremove (struct vop_nremove_args *ap)
1101{
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;
1111
1112 cred = ap->a_cred;
1113 ncp = ap->a_nch->ncp;
1114 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1115
1116 vp = NULL; /* XXX */
1117
1118 ip = vp->v_data;
1119 ump = ip->ump;
1120
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);
1125
1126 kprintf("userfs_nremove\n");
1127 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1128 par = &slmsg->rep->msg->sm_head;
1129
1130 if (par->se_cmd == (SLVFS_CMD_VOP_NREMOVE|SE_CMDF_REPLY)) {
1131 ;
1132 } else {
1133 error = EBADRPC;
1134 }
1135 }
1136 syslink_kfreemsg(ump->sldesc, slmsg);
1137 kprintf("error %d\n", error);
1138 return(error);
1139}
1140
9b082684
MD
1141/*
1142 * vop_nrename(struct nchandle *fnch, struct nchandle *tnch,
1143 * struct vnode *fdvp, struct vnode *tdvp,
1144 * struct ucred *cred)
1145 */
a92480c3
MD
1146static
1147int
1148user_vop_nrename (struct vop_nrename_args *ap)
1149{
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;
1161
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 */
1167
1168 vp = NULL; /* XXX */
1169
1170 ip = vp->v_data;
1171 ump = ip->ump;
1172
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);
1177
1178 kprintf("userfs_nrename\n");
1179 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1180 par = &slmsg->rep->msg->sm_head;
1181
1182 if (par->se_cmd == (SLVFS_CMD_VOP_NRENAME|SE_CMDF_REPLY)) {
1183 ;
1184 } else {
1185 error = EBADRPC;
1186 }
1187 }
1188 syslink_kfreemsg(ump->sldesc, slmsg);
1189 kprintf("error %d\n", error);
1190 return(error);
1191}
1192
9b082684
MD
1193/*
1194 * vop_nrmdir(struct nchandle *nch, struct vnode *dvp, struct ucred *cred)
1195 */
a92480c3
MD
1196static
1197int
1198user_vop_nrmdir (struct vop_nrmdir_args *ap)
1199{
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;
1209
1210 cred = ap->a_cred;
1211 ncp = ap->a_nch->ncp;
1212 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1213
1214 vp = NULL; /* XXX */
1215
1216 ip = vp->v_data;
1217 ump = ip->ump;
1218
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);
1223
1224 kprintf("userfs_nrmdir\n");
1225 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1226 par = &slmsg->rep->msg->sm_head;
1227
1228 if (par->se_cmd == (SLVFS_CMD_VOP_NRMDIR|SE_CMDF_REPLY)) {
1229 ;
1230 } else {
1231 error = EBADRPC;
1232 }
1233 }
1234 syslink_kfreemsg(ump->sldesc, slmsg);
1235 kprintf("error %d\n", error);
1236 return(error);
1237}
1238
1239static
1240int
a92480c3
MD
1241user_vop_nsymlink (struct vop_nsymlink_args *ap)
1242{
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;
1252
1253 cred = ap->a_cred;
1254 ncp = ap->a_nch->ncp;
1255 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1256
1257 vp = NULL; /* XXX */
1258
1259 ip = vp->v_data;
1260 ump = ip->ump;
1261
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);
1266
1267 kprintf("userfs_nsymlink\n");
1268 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1269 par = &slmsg->rep->msg->sm_head;
1270
1271 if (par->se_cmd == (SLVFS_CMD_VOP_NSYMLINK|SE_CMDF_REPLY)) {
1272 ;
1273 } else {
1274 error = EBADRPC;
1275 }
1276 }
1277 syslink_kfreemsg(ump->sldesc, slmsg);
1278 kprintf("error %d\n", error);
1279 return(error);
1280}
1281
1282static
1283int
1284user_vop_nwhiteout (struct vop_nwhiteout_args *ap)
1285{
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;
1295
1296 cred = ap->a_cred;
1297 ncp = ap->a_nch->ncp;
1298 dvp = ncp->nc_parent->nc_vp; /* needs vget */
1299
1300 vp = NULL; /* XXX */
1301
1302 ip = vp->v_data;
1303 ump = ip->ump;
1304
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);
1309
1310 kprintf("userfs_nwhiteout\n");
1311 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
1312 par = &slmsg->rep->msg->sm_head;
1313
1314 if (par->se_cmd == (SLVFS_CMD_VOP_NWHITEOUT|SE_CMDF_REPLY)) {
1315 ;
1316 } else {
1317 error = EBADRPC;
1318 }
1319 }
1320 syslink_kfreemsg(ump->sldesc, slmsg);
1321 kprintf("error %d\n", error);
1322 return(error);
1323}
1324