2 * Copyright (c) 1995 - 2002, 2004 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * 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 the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include <nnpfs/nnpfs_locl.h>
39 #include <nnpfs/nnpfs_message.h>
40 #include <nnpfs/nnpfs_common.h>
41 #include <nnpfs/nnpfs_fs.h>
42 #include <nnpfs/nnpfs_dev.h>
43 #include <nnpfs/nnpfs_deb.h>
44 #include <nnpfs/nnpfs_syscalls.h>
45 #include <nnpfs/nnpfs_vnodeops.h>
46 #include <sys/param.h>
51 nnpfs_handle_stale(struct nnpfs_node
*xn
)
54 struct vnode
*vp
= XNODE_TO_VNODE(xn
);
57 if ((xn
->flags
& NNPFS_STALE
) == 0)
61 if (UBCISVALID(vp
) && !ubc_isinuse(vp
, 1)) {
62 xn
->flags
&= ~NNPFS_STALE
;
64 NNPFS_TOKEN_CLEAR(xn
, ~0,
65 NNPFS_OPEN_MASK
| NNPFS_ATTR_MASK
|
66 NNPFS_DATA_MASK
| NNPFS_LOCK_MASK
);
72 nnpfs_open_valid(struct vnode
*vp
, nnpfs_vfs_context ctx
, u_int tok
)
74 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
75 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
76 nnpfs_kernel_cred cred
= nnpfs_vfs_context_ucred(ctx
);
79 NNPFSDEB(XDEBVFOPS
, ("nnpfs_open_valid\n"));
81 nnpfs_handle_stale(xn
);
84 if (!NNPFS_TOKEN_GOT(xn
, tok
)) {
85 struct nnpfs_message_open msg
;
87 msg
.header
.opcode
= NNPFS_MSG_OPEN
;
88 msg
.cred
.uid
= nnpfs_cred_get_uid(cred
);
89 msg
.cred
.pag
= nnpfs_get_pag(cred
);
90 msg
.handle
= xn
->handle
;
93 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
,
94 sizeof(msg
), nnpfs_vfs_context_proc(ctx
));
96 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
101 } while (error
== 0);
104 NNPFSDEB(XDEBVFOPS
, ("nnpfs_open_valid: error = %d\n", error
));
110 nnpfs_attr_valid(struct vnode
*vp
, nnpfs_kernel_cred cred
, d_thread_t
*p
,
113 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
114 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
116 nnpfs_pag_t pag
= nnpfs_get_pag(cred
);
119 if (!NNPFS_TOKEN_GOT(xn
, tok
) || !nnpfs_has_pag(xn
, pag
)) {
120 struct nnpfs_message_getattr msg
;
122 msg
.header
.opcode
= NNPFS_MSG_GETATTR
;
123 msg
.cred
.uid
= nnpfs_cred_get_uid(cred
);
125 msg
.handle
= xn
->handle
;
126 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
128 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
132 } while (error
== 0);
139 nnpfs_do_getdata(struct nnpfs_node
*xn
, nnpfs_cred
*cred
, u_int tok
,
140 off_t offset
, off_t end
)
142 struct nnpfs_message_getdata msg
;
145 msg
.header
.opcode
= NNPFS_MSG_GETDATA
;
147 msg
.handle
= xn
->handle
;
150 msg
.len
= end
- offset
;
152 error
= nnpfs_message_rpc(NNPFS_FROM_XNODE(xn
), &msg
.header
, sizeof(msg
),
155 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
161 update_end(struct nnpfs_node
*xn
, off_t
*end
, int writep
)
163 if (NNPFS_TOKEN_GOT(xn
, NNPFS_ATTR_R
)) {
164 off_t size
= nnpfs_vattr_get_size(&xn
->attr
);
166 if (*end
> size
&& !writep
)
172 nnpfs_data_valid(struct vnode
*vp
, nnpfs_cred
*cred
,
173 u_int tok
, off_t want_offset
, off_t want_end
)
175 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
177 int writep
= ((tok
& NNPFS_DATA_W
) == NNPFS_DATA_W
);
179 off_t offset
= nnpfs_offset(want_offset
);
182 if (!NNPFS_TOKEN_GOT(xn
, NNPFS_ATTR_R
))
183 printf("NNPFS PANIC WARNING! data_valid w/o tokens!\n");
185 if (nnpfs_vnode_isdir(vp
)) {
186 /* hack, entire dir goes in 'first block' */
195 update_end(xn
, &end
, writep
);
197 NNPFSDEB(XDEBVNOPS
, ("nnpfs_data_valid: want %lld - %lld, "
198 "tokens: want %lx has %lx length: %lld\n",
199 (long long) offset
, (long long) end
,
200 (long) tok
, (long) xn
->tokens
,
201 (long long) nnpfs_vattr_get_size(&xn
->attr
)));
203 /* use find_first_block() ? */
207 if (!nnpfs_block_have_p(xn
, off
)) {
208 off_t size
= nnpfs_vattr_get_size(&xn
->attr
);
211 * For append beyond what daemon knows, just go ahead.
212 * Offset zero is special in that the block always exists;
213 * we need it "installed" to be safe against gc.
216 /* XXX can length be less than end after rpc or schedule? */
217 if (off
>= xn
->daemon_length
&& off
> 0
218 && NNPFS_TOKEN_GOT_ALL(xn
, tok
|NNPFS_ATTR_R
)
219 && (writep
|| off
< nnpfs_end_offset(size
))) {
220 error
= nnpfs_block_create(xn
, off
);
224 update_end(xn
, &end
, writep
);
230 error
= nnpfs_do_getdata(xn
, cred
, tok
, off
, end
);
234 update_end(xn
, &end
, writep
);
236 off
+= nnpfs_blocksize
;
242 if (!NNPFS_TOKEN_GOT_ALL(xn
, tok
|NNPFS_ATTR_R
)) {
243 error
= nnpfs_do_getdata(xn
, cred
, tok
, offset
, end
);
247 } while (error
== 0 && did_rpc
);
253 nnpfs_open_common(struct vnode
*vp
,
255 nnpfs_vfs_context ctx
)
257 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
258 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
259 nnpfs_kernel_cred cred
= nnpfs_vfs_context_ucred(ctx
);
262 nnpfs_dev_lock(nnpfsp
);
263 NNPFSDEB(XDEBVNOPS
, ("nnpfs_open(%p)\n", vp
));
266 ret
= nnpfs_open_valid(vp
, ctx
, NNPFS_OPEN_NW
);
272 nnpfs_setcred(&xn
->wr_cred
, cred
);
275 ret
= nnpfs_open_valid(vp
, ctx
, NNPFS_OPEN_NR
);
278 /* always update the read cred */
280 nnpfs_setcred(&xn
->rd_cred
, cred
);
282 nnpfs_dev_unlock(nnpfsp
);
288 * find first block in given range with validity according to 'validp'
290 * returns offset of first such block, or NNPFS_NO_OFFSET if none
294 find_first_block(struct nnpfs_node
*node
, uint64_t offset
,
295 uint64_t end
, int validp
)
297 off_t eof
= nnpfs_vattr_get_size(&node
->attr
);
300 if (nnpfs_block_empty(node
)
302 return NNPFS_NO_OFFSET
;
304 /* get some batch search perhaps? */
306 nnpfs_assert(nnpfs_offset(offset
) == offset
);
311 for (off
= offset
; off
< end
; off
+= nnpfs_blocksize
) {
312 int validity
= nnpfs_block_have_p(node
, off
);
322 return NNPFS_NO_OFFSET
;
326 * store data for entire node
329 do_fsync(struct nnpfs
*nnpfsp
,
330 struct nnpfs_node
*xn
,
331 nnpfs_kernel_cred cred
,
336 off_t len
= nnpfs_vattr_get_size(&xn
->attr
); /* XXX may change on rpc */
337 struct nnpfs_message_putdata msg
;
343 NNPFSDEB(XDEBVNOPS
, ("nnpfs_fsync: len 0x%llx, mask0=0x%lx\n",
344 (unsigned long long)len
,
345 (unsigned long)(xn
->data
.nmasks
> 1
346 ? xn
->data
.masks
.list
[0]
347 : xn
->data
.masks
.first
)));
350 /* get first valid block */
351 off
= find_first_block(xn
, off
, len
, TRUE
);
352 if (off
>= len
|| off
== NNPFS_NO_OFFSET
)
353 break; /* no more blocks installed */
355 /* find the end of this range of valid blocks */
356 end
= find_first_block(xn
, off
+ nnpfs_blocksize
, len
, FALSE
);
357 if (end
> len
|| off
== NNPFS_NO_OFFSET
)
360 vattr2nnpfs_attr(&xn
->attr
, &msg
.attr
);
365 nnpfs_setcred(&msg
.cred
, cred
);
367 msg
.header
.opcode
= NNPFS_MSG_PUTDATA
;
368 msg
.handle
= xn
->handle
;
373 xn
->pending_writes
++; /* XXX lock */
376 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
378 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
380 /* XXX locking, rpc may fail */
381 xn
->daemon_length
= nnpfs_vattr_get_size(&xn
->attr
);
383 xn
->pending_writes
--; /* XXX lock */
384 nnpfs_assert(xn
->pending_writes
>= 0);
387 } while (!error
&& end
< len
);
390 xn
->flags
&= ~NNPFS_DATA_DIRTY
;
392 NNPFSDEB(XDEBVNOPS
, ("nnpfs_fsync: nrpcs %d -> %d\n", nrpcs
, error
));
398 nnpfs_fsync_common(struct vnode
*vp
, nnpfs_kernel_cred cred
, nnpfs_cred
*ncred
,
399 int waitfor
, d_thread_t
*proc
)
401 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
402 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
405 NNPFSDEB(XDEBVNOPS
, ("nnpfs_fsync: %lx\n", (unsigned long)vp
));
408 * It seems that fsync is sometimes called after reclaiming a node.
409 * In that case we just look happy.
413 printf("NNPFS PANIC WARNING! nnpfs_fsync called after reclaiming!\n");
419 nnpfs_dev_lock(nnpfsp
);
420 if (xn
->flags
& NNPFS_DATA_DIRTY
) {
421 NNPFSDEB(XDEBVNOPS
, ("nnpfs_fsync: dirty\n"));
423 /* writing back the data from this vnode failed */
424 if (waitfor
& FSYNC_RECLAIM
) {
425 printf("nnpfs_fsync: data lost, failed to write back\n");
426 xn
->flags
&= ~NNPFS_DATA_DIRTY
;
430 error
= do_fsync(nnpfsp
, xn
, cred
, ncred
, proc
, NNPFS_WRITE
| NNPFS_FSYNC
);
432 nnpfs_dev_unlock(nnpfsp
);
434 NNPFSDEB(XDEBVNOPS
, ("nnpfs_fsync: return %d\n", error
));
440 nnpfs_close_common(struct vnode
*vp
, int fflag
,
441 d_thread_t
*proc
, nnpfs_kernel_cred cred
)
443 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
444 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
448 ("nnpfs_close(%p) cred = %lx, fflag = %x, xn->flags = %x\n",
449 vp
, (unsigned long)cred
, fflag
, xn
->flags
));
451 if (nnpfs_vnode_isreg(vp
))
454 nnpfs_dev_lock(nnpfsp
);
456 if (fflag
& FWRITE
) {
457 if (xn
->async_error
== 0 && xn
->flags
& NNPFS_DATA_DIRTY
) {
458 NNPFSDEB(XDEBVNOPS
, ("nnpfs_close: fsync\n"));
460 error
= do_fsync(nnpfsp
, xn
, cred
, NULL
, proc
, NNPFS_WRITE
);
462 /* XXX DATA_DIRTY on async_error? */
465 if (--xn
->writers
< 0)
466 panic("xn -ve writers");
470 if (xn
->async_error
) {
475 nnpfs_dev_unlock(nnpfsp
);
477 NNPFSDEB(XDEBVNOPS
, ("nnpfs_close -> %d\n", error
));
483 * return offset + resid
487 nnpfs_uio_end_length (struct uio
*uio
)
489 #if defined(DIAGNOSTIC) && !defined(__APPLE__)
493 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
494 sz
+= uio
->uio_iov
[i
].iov_len
;
495 if (sz
!= uio
->uio_resid
)
496 panic("nnpfs_uio_end_length");
498 return nnpfs_uio_offset(uio
) + nnpfs_uio_resid(uio
);
502 nnpfs_read_common(struct vnode
*vp
, struct uio
*uio
, int ioflag
, nnpfs_kernel_cred cred
)
505 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
506 struct nnpfs_node
*node
= VNODE_TO_XNODE(vp
);
507 off_t offset
= nnpfs_uio_offset(uio
);
508 off_t length
= nnpfs_uio_end_length(uio
);
512 NNPFSDEB(XDEBVNOPS
, ("nnpfs_read\n"));
515 * Currently, directories are handled in a different way than
516 * ordinary files, so we refuse to read them. Very un-BSD-ish.
518 if (nnpfs_vnode_isdir(vp
))
521 nnpfs_dev_lock(nnpfsp
);
523 nnpfs_setcred(&node
->rd_cred
, cred
);
525 error
= nnpfs_data_valid(vp
, &node
->rd_cred
, NNPFS_DATA_R
,
529 eof
= nnpfs_vattr_get_size(&node
->attr
);
531 if (error
== 0 && offset
< eof
) {
533 resid_add
= length
- eof
;
534 nnpfs_uio_setresid(uio
, eof
- offset
);
538 while (offset
< length
) {
540 off_t off
= offset
& (nnpfs_blocksize
- 1);
543 error
= nnpfs_block_open(node
,
544 nnpfs_offset(offset
),
549 nnpfs_uio_setoffset(uio
, off
);
551 #if defined(__APPLE__)
552 nnpfs_vop_read(t
, uio
, ioflag
, NULL
, error
);
554 nnpfs_vfs_readlock(t
, nnpfs_uio_to_proc(uio
));
555 nnpfs_vop_read(t
, uio
, ioflag
,
556 nnpfs_vfs_context_ucred(nnpfsp
->ctx
), error
);
557 nnpfs_vfs_unlock(t
, nnpfs_uio_to_proc(uio
));
559 nnpfs_block_close(node
, t
, 0);
564 nbytes
= nnpfs_uio_offset(uio
) - off
;
566 error
= EIO
; /* XXX maybe should be no error? */
567 printf("nnpfs_read: nbytes is %lld @0x%llx, index 0x%x\n",
568 (long long)nbytes
, (unsigned long long)offset
,
576 nnpfs_uio_setoffset(uio
, offset
);
578 nnpfs_uio_setresid(uio
, nnpfs_uio_resid(uio
) + resid_add
);
581 NNPFSDEB(XDEBVNOPS
, ("nnpfs_read offset: %lu resid: %lu\n",
582 (unsigned long)nnpfs_uio_offset(uio
),
583 (unsigned long)nnpfs_uio_resid(uio
)));
584 NNPFSDEB(XDEBVNOPS
, ("nnpfs_read error: %d\n", error
));
586 nnpfs_dev_unlock(nnpfsp
);
592 * update node attributes after write, using cache file 't' as time
597 nnpfs_update_write_attr(struct vnode
*vp
, struct nnpfs_node
*xn
,
598 struct vnode
*t
, off_t length
,
599 nnpfs_vfs_context ctx
)
601 off_t eof
= nnpfs_vattr_get_size(&xn
->attr
);
602 struct nnpfs_vfs_vattr sub_attr
;
606 VATTR_INIT(&sub_attr
);
607 VATTR_WANTED(&sub_attr
, va_modify_time
);
611 nnpfs_vattr_set_size(&xn
->attr
, length
);
612 nnpfs_vattr_set_bytes(&xn
->attr
, length
);
614 nnpfs_set_vp_size(vp
, length
);
619 nnpfs_vop_getattr(t
, &sub_attr
, ctx
, error2
);
621 nnpfs_vattr_set_mtime(&xn
->attr
,
622 nnpfs_vattr_get_mtime_sec(&sub_attr
),
623 nnpfs_vattr_get_mtime_nsec(&sub_attr
));
625 printf("nnpfs_update_write_attr: "
626 "getattr failed for len 0x%llx\n",
627 (unsigned long long)length
);
633 nnpfs_write_common(struct vnode
*vp
, struct uio
*uiop
, int ioflag
,
634 nnpfs_vfs_context ctx
)
636 nnpfs_kernel_cred cred
= nnpfs_vfs_context_ucred(ctx
);
637 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
638 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
639 nnpfs_vfs_context daemon_ctx
= NNPFS_FROM_VNODE(vp
)->ctx
;
640 off_t eof
= nnpfs_vattr_get_size(&xn
->attr
);
641 int error
= xn
->async_error
;
645 nnpfs_dev_lock(nnpfsp
);
646 NNPFSDEB(XDEBVNOPS
, ("nnpfs_write(%p)\n", vp
));
648 nnpfs_assert(!nnpfs_vnode_isdir(vp
));
650 nnpfs_setcred(&xn
->wr_cred
, cred
);
654 nnpfs_dev_unlock(nnpfsp
);
658 if (ioflag
& IO_APPEND
)
659 nnpfs_uio_setoffset(uiop
, eof
);
661 offset
= nnpfs_uio_offset(uiop
);
662 length
= nnpfs_uio_end_length(uiop
);
664 error
= nnpfs_data_valid(vp
, &xn
->wr_cred
, NNPFS_DATA_W
, offset
, length
);
666 nnpfs_dev_unlock(nnpfsp
);
670 while (offset
< length
) {
671 off_t off
= offset
& (nnpfs_blocksize
- 1);
682 flags
= FWRITE
| O_CREAT
;
684 error
= nnpfs_block_open(xn
, nnpfs_offset(offset
), flags
, &t
);
690 resid
= nnpfs_blocksize
- off
;
691 if (offset
+ resid
> length
)
692 resid
= length
- offset
;
694 nnpfs_uio_setoffset(uiop
, off
);
695 nnpfs_uio_setresid(uiop
, resid
);
698 nnpfs_vop_write(t
, uiop
, ioflag
, daemon_ctx
, error
);
702 (void)vn_start_write(t
, &mp
, V_WAIT
);
704 nnpfs_vfs_writelock(t
, nnpfs_vfs_context_proc(ctx
));
705 (void)VOP_LEASE(t
, nnpfs_vfs_context_proc(ctx
), cred
, LEASE_WRITE
);
707 nnpfs_vop_write(t
, uiop
, ioflag
, cred
, error
);
711 nbytes
= nnpfs_uio_offset(uiop
) - off
;
716 printf("nnpfs_write: nbytes is %lld!\n",
721 /* get time stamp etc from the last cache file */
722 if (offset
>= length
)
723 nnpfs_update_write_attr(vp
, xn
, t
, offset
, daemon_ctx
);
724 #endif /* !__NetBSD__ */
727 nnpfs_vfs_unlock(t
, nnpfs_vfs_context_proc(ctx
));
730 vn_finished_write(mp
);
733 nnpfs_block_close(xn
, t
, 1);
739 xn
->flags
|= NNPFS_DATA_DIRTY
;
740 nnpfs_uio_setoffset(uiop
, offset
);
741 nnpfs_uio_setresid(uiop
, length
- offset
);
743 nnpfs_dev_unlock(nnpfsp
);
745 NNPFSDEB(XDEBVNOPS
, ("nnpfs_write -> %d\n", error
));
751 nnpfs_getattr_common(struct vnode
*vp
, struct nnpfs_vfs_vattr
*vap
,
752 nnpfs_kernel_cred cred
, d_thread_t
*p
)
754 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
755 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
758 nnpfs_dev_lock(nnpfsp
);
759 NNPFSDEB(XDEBVNOPS
, ("nnpfs_getattr\n"));
761 error
= nnpfs_attr_valid(vp
, cred
, p
, NNPFS_ATTR_R
);
765 nnpfs_dev_unlock(nnpfsp
);
771 setattr_is_noop(struct nnpfs_node
*xn
, struct nnpfs_vfs_vattr
*vap
)
775 #define CHECK_NNPFSATTR(A) (!VATTR_IS_ACTIVE(vap, A) || vap->A == xn->attr.A)
776 if (CHECK_NNPFSATTR(va_mode
) &&
777 CHECK_NNPFSATTR(va_nlink
) &&
778 CHECK_NNPFSATTR(va_data_size
) &&
779 CHECK_NNPFSATTR(va_uid
) &&
780 CHECK_NNPFSATTR(va_gid
) &&
781 CHECK_NNPFSATTR(va_fileid
) && /* we ignore va_type */
782 (!VATTR_IS_ACTIVE(vap
, va_modify_time
)
783 || vap
->va_modify_time
.tv_sec
== xn
->attr
.va_modify_time
.tv_sec
))
785 #undef CHECK_NNPFSATTR
789 #define CHECK_NNPFSATTR(A, cast) (vap->A == cast VNOVAL || vap->A == xn->attr.A)
790 if (CHECK_NNPFSATTR(va_mode
,(mode_t
)) &&
791 CHECK_NNPFSATTR(va_nlink
,(short)) &&
792 CHECK_NNPFSATTR(va_size
,(va_size_t
)) &&
793 CHECK_NNPFSATTR(va_uid
,(uid_t
)) &&
794 CHECK_NNPFSATTR(va_gid
,(gid_t
)) &&
795 CHECK_NNPFSATTR(va_mtime
.tv_sec
,(time_t)) &&
796 CHECK_NNPFSATTR(va_fileid
,(long)) &&
797 CHECK_NNPFSATTR(va_type
,(enum vtype
)))
799 #undef CHECK_NNPFSATTR
801 #endif /* ! __APPLE__ */
807 nnpfs_setattr_common(struct vnode
*vp
, struct nnpfs_vfs_vattr
*vap
,
808 nnpfs_kernel_cred cred
, d_thread_t
*p
)
810 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
811 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
814 nnpfs_dev_lock(nnpfsp
);
815 NNPFSDEB(XDEBVNOPS
, ("nnpfs_setattr\n"));
817 if (setattr_is_noop(xn
, vap
)) {
818 nnpfs_dev_unlock(nnpfsp
);
819 return 0; /* nothing to do */
822 if (NNPFS_TOKEN_GOT(xn
, NNPFS_ATTR_W
)) {
823 /* Update attributes and mark them dirty. */
824 VNODE_TO_XNODE(vp
)->flags
|= NNPFS_ATTR_DIRTY
;
825 error
= EINVAL
; /* XXX not yet implemented */
828 struct nnpfs_message_putattr msg
;
829 uint64_t old_length
, new_length
;
831 msg
.header
.opcode
= NNPFS_MSG_PUTATTR
;
832 nnpfs_setcred(&msg
.cred
, cred
);
833 msg
.handle
= xn
->handle
;
834 vattr2nnpfs_attr(vap
, &msg
.attr
);
836 if (NNPFS_TOKEN_GOT(xn
, NNPFS_DATA_R
)) {
837 if (nnpfs_vnode_isreg(vp
)) {
838 old_length
= nnpfs_vattr_get_size(&xn
->attr
);
840 if (nnpfs_vattr_size_isactive(vap
)) {
841 new_length
= nnpfs_vattr_get_size(vap
);
843 XA_SET_SIZE(&msg
.attr
, new_length
);
845 XA_SET_SIZE(&msg
.attr
, old_length
);
849 if (nnpfs_vattr_mtime_isactive(vap
))
850 XA_SET_MTIME(&msg
.attr
, nnpfs_vattr_get_mtime_sec(vap
));
852 XA_SET_MTIME(&msg
.attr
, nnpfs_vattr_get_mtime_sec(&xn
->attr
));
855 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
857 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
859 #if 0 /* assume length is always in (loose) sync with daemon nowadays */
860 if (error
== 0 && do_fixup
)
861 truncate_block_fixup(xn
, old_length
, new_length
);
866 nnpfs_dev_unlock(nnpfsp
);
867 NNPFS_VN_KNOTE(vp
, NOTE_ATTRIB
);
873 check_rights (nnpfs_rights rights
, int mode
, int dirp
)
878 /* VNOP_ACCESS passes a kauth action instead of ordinary unix mode */
881 if (mode
& (KAUTH_VNODE_LIST_DIRECTORY
| KAUTH_VNODE_SEARCH
))
882 if ((rights
& NNPFS_RIGHT_X
) == 0)
884 if (mode
& KAUTH_VNODE_DELETE_CHILD
)
885 if ((rights
& NNPFS_RIGHT_AD
) == 0)
887 if (mode
& (KAUTH_VNODE_ADD_FILE
| KAUTH_VNODE_ADD_SUBDIRECTORY
))
888 if ((rights
& NNPFS_RIGHT_AI
) == 0)
891 /* XXX can't check KAUTH_VNODE_DELETE, have no info */
894 if (mode
& (KAUTH_VNODE_READ_DATA
| KAUTH_VNODE_READ_ATTRIBUTES
))
895 if ((rights
& NNPFS_RIGHT_AR
) == 0)
897 if (mode
& (KAUTH_VNODE_WRITE_DATA
| KAUTH_VNODE_APPEND_DATA
| KAUTH_VNODE_WRITE_ATTRIBUTES
| KAUTH_VNODE_TAKE_OWNERSHIP
))
898 if ((rights
& NNPFS_RIGHT_W
) == 0)
900 if (mode
& KAUTH_VNODE_EXECUTE
)
901 if ((rights
& NNPFS_RIGHT_X
) == 0)
903 if (mode
& KAUTH_VNODE_DELETE
)
904 if ((rights
& NNPFS_RIGHT_AD
) == 0)
909 KAUTH_VNODE_READ_EXTATTRIBUTES
910 KAUTH_VNODE_WRITE_EXTATTRIBUTES
911 KAUTH_VNODE_READ_SECURITY
912 KAUTH_VNODE_WRITE_SECURITY
913 KAUTH_VNODE_SYNCHRONIZE notused
914 KAUTH_VNODE_LINKTARGET like insert
, but
for target
???
915 KAUTH_VNODE_CHECKIMMUTABLE always ok
916 KAUTH_VNODE_ACCESS (advisory
)
917 KAUTH_VNODE_NOIMMUTABLE
?
920 #else /* !__APPLE__ */
923 if ((rights
& NNPFS_RIGHT_R
) == 0)
926 if ((rights
& NNPFS_RIGHT_W
) == 0)
929 if ((rights
& NNPFS_RIGHT_X
) == 0)
932 #endif /* !__APPLE__ */
938 nnpfs_access_common(struct vnode
*vp
, int mode
, nnpfs_kernel_cred cred
,
941 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
942 int dirp
= nnpfs_vnode_isdir(vp
);
946 nnpfs_dev_lock(nnpfsp
);
947 NNPFSDEB(XDEBVNOPS
, ("nnpfs_access mode = 0%o\n", mode
));
949 pag
= nnpfs_get_pag(cred
);
951 error
= nnpfs_attr_valid(vp
, cred
, p
, NNPFS_ATTR_R
);
953 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
956 error
= check_rights(xn
->anonrights
, mode
, dirp
);
961 NNPFSDEB(XDEBVNOPS
, ("nnpfs_access anonaccess failed\n"));
963 error
= EACCES
; /* default to EACCES if pag isn't in xn->id */
965 for (i
= 0; i
< NNPFS_MAXRIGHTS
; i
++)
966 if (xn
->id
[i
] == pag
) {
967 error
= check_rights(xn
->rights
[i
], mode
, dirp
);
973 NNPFSDEB(XDEBVNOPS
, ("nnpfs_access(0%o) = %d\n", mode
, error
));
974 nnpfs_dev_unlock(nnpfsp
);
980 nnpfs_lookup_common(struct vnode
*dvp
,
981 nnpfs_componentname
*cnp
,
983 nnpfs_vfs_context ctx
)
985 struct nnpfs_message_getnode msg
;
986 nnpfs_kernel_cred cred
= nnpfs_vfs_context_ucred(ctx
);
987 d_thread_t
*p
= nnpfs_vfs_context_proc(ctx
);
988 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
989 struct nnpfs_node
*d
= VNODE_TO_XNODE(dvp
);
992 NNPFSDEB(XDEBVNOPS
, ("nnpfs_lookup_common: enter\n"));
996 if (cnp
->cn_namelen
>= NNPFS_MAX_NAME
)
999 if (!nnpfs_vnode_isdir(dvp
))
1002 if (cnp
->cn_namelen
== 1 && cnp
->cn_nameptr
[0] == '.') {
1005 nnpfs_do_vget(*vpp
, 0 /* XXX flag */, NULL
/*proc */);
1012 nnpfs_dev_lock(nnpfsp
);
1014 nnpfs_lookup_access(dvp
, ctx
, p
, error
);
1018 NNPFSDEB(XDEBVNOPS
, ("nnpfs_lookup_common: dvp = %lx\n",
1019 (unsigned long) dvp
));
1020 NNPFSDEB(XDEBVNOPS
, ("nnpfs_lookup_common: cnp = %lx, "
1021 "cnp->cn_nameiop = %d\n",
1022 (unsigned long) cnp
, (int)cnp
->cn_nameiop
));
1024 error
= nnpfs_dnlc_lookup(dvp
, cnp
, vpp
);
1025 if (error
== 0) { /* not cached */
1028 * Doesn't quite work.
1032 if ((cnp
->cn_nameiop
== CREATE
|| cnp
->cn_nameiop
== RENAME
)
1033 && (cnp
->cn_flags
& ISLASTCN
)) {
1034 error
= EJUSTRETURN
;
1039 msg
.header
.opcode
= NNPFS_MSG_GETNODE
;
1040 nnpfs_setcred(&msg
.cred
, cred
);
1041 msg
.parent_handle
= d
->handle
;
1042 memcpy(msg
.name
, cnp
->cn_nameptr
, cnp
->cn_namelen
);
1043 msg
.name
[cnp
->cn_namelen
] = '\0';
1044 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1046 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1047 if(error
== ENOENT
&& cnp
->cn_nameiop
!= CREATE
) {
1048 NNPFSDEB(XDEBVNOPS
, ("nnpfs_lookup: neg cache %lx (%s, %ld)\n",
1050 cnp
->cn_nameptr
, cnp
->cn_namelen
));
1051 nnpfs_dnlc_enter (dvp
, cnp
, NULL
);
1053 } else if (error
== -1) { /* found */
1057 } while (error
== 0);
1060 nnpfs_dev_unlock(nnpfsp
);
1061 NNPFS_VN_KNOTE(dvp
, NOTE_WRITE
);
1063 NNPFSDEB(XDEBVNOPS
, ("nnpfs_lookup_common: return %d, vn %p\n",
1069 nnpfs_create_common(struct vnode
*dvp
,
1071 struct nnpfs_vfs_vattr
*vap
,
1072 nnpfs_kernel_cred cred
,
1075 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1076 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1079 nnpfs_dev_lock(nnpfsp
);
1080 NNPFSDEB(XDEBVNOPS
, ("nnpfs_create: (%lx, %s)\n",
1081 (unsigned long)dvp
, name
));
1083 struct nnpfs_message_create msg
;
1085 msg
.header
.opcode
= NNPFS_MSG_CREATE
;
1086 msg
.parent_handle
= xn
->handle
;
1087 if (strlcpy(msg
.name
, name
, sizeof(msg
.name
)) >= NNPFS_MAX_NAME
)
1088 return ENAMETOOLONG
;
1089 vattr2nnpfs_attr(vap
, &msg
.attr
);
1091 msg
.mode
= 0; /* XXX - mode */
1092 nnpfs_setcred(&msg
.cred
, cred
);
1095 /* needed for subsequent writes to succeed with n */
1096 msg
.attr
.valid
&= ~XA_V_UID
;
1099 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1101 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1105 if (error
== EEXIST
)
1109 nnpfs_dev_unlock(nnpfsp
);
1111 NNPFSDEB(XDEBVNOPS
, ("nnpfs_create -> %d\n", error
));
1117 nnpfs_remove_common(struct vnode
*dvp
,
1120 nnpfs_kernel_cred cred
,
1123 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1124 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1125 struct nnpfs_message_remove msg
;
1128 nnpfs_dev_lock(nnpfsp
);
1129 NNPFSDEB(XDEBVNOPS
, ("nnpfs_remove(%p): %s\n", dvp
, name
));
1131 msg
.header
.opcode
= NNPFS_MSG_REMOVE
;
1132 msg
.parent_handle
= xn
->handle
;
1133 msg
.cred
.uid
= nnpfs_cred_get_uid(cred
);
1134 msg
.cred
.pag
= nnpfs_get_pag(cred
);
1136 if (strlcpy(msg
.name
, name
, sizeof(msg
.name
)) >= NNPFS_MAX_NAME
)
1137 error
= ENAMETOOLONG
;
1139 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1141 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1144 nnpfs_dnlc_purge (vp
);
1146 nnpfs_dev_unlock(nnpfsp
);
1149 NNPFS_VN_KNOTE(vp
, NOTE_DELETE
);
1150 NNPFS_VN_KNOTE(dvp
, NOTE_WRITE
);
1153 NNPFSDEB(XDEBVNOPS
, ("nnpfs_remove -> %d\n", error
));
1159 nnpfs_rename_common(struct vnode
*fdvp
,
1165 nnpfs_kernel_cred cred
,
1168 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(fdvp
);
1171 nnpfs_dev_lock(nnpfsp
);
1172 NNPFSDEB(XDEBVNOPS
, ("nnpfs_rename: %s %s\n", fname
, tname
));
1175 if ((fvp
->v_mount
!= tdvp
->v_mount
)
1176 || (tvp
&& (fvp
->v_mount
!= tvp
->v_mount
))) {
1182 struct nnpfs_message_rename msg
;
1184 msg
.header
.opcode
= NNPFS_MSG_RENAME
;
1185 msg
.old_parent_handle
= VNODE_TO_XNODE(fdvp
)->handle
;
1186 if (strlcpy(msg
.old_name
, fname
, sizeof(msg
.old_name
)) >= NNPFS_MAX_NAME
) {
1187 nnpfs_dev_unlock(nnpfsp
);
1188 return ENAMETOOLONG
;
1191 msg
.new_parent_handle
= VNODE_TO_XNODE(tdvp
)->handle
;
1192 if (strlcpy(msg
.new_name
, tname
, sizeof(msg
.new_name
)) >= NNPFS_MAX_NAME
) {
1193 nnpfs_dev_unlock(nnpfsp
);
1194 return ENAMETOOLONG
;
1197 msg
.cred
.uid
= nnpfs_cred_get_uid(cred
);
1198 msg
.cred
.pag
= nnpfs_get_pag(cred
);
1199 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1201 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1205 nnpfs_dev_unlock(nnpfsp
);
1206 NNPFS_VN_KNOTE(fdvp
, NOTE_WRITE
);
1207 NNPFS_VN_KNOTE(fvp
, NOTE_WRITE
);
1209 NNPFSDEB(XDEBVNOPS
, ("nnpfs_rename: error = %d\n", error
));
1215 nnpfs_mkdir_common(struct vnode
*dvp
,
1217 struct nnpfs_vfs_vattr
*vap
,
1218 nnpfs_kernel_cred cred
,
1221 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1222 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1225 nnpfs_dev_lock(nnpfsp
);
1226 NNPFSDEB(XDEBVNOPS
, ("nnpfs_mkdir(%p): %s\n", dvp
, name
));
1228 struct nnpfs_message_mkdir msg
;
1230 msg
.header
.opcode
= NNPFS_MSG_MKDIR
;
1231 msg
.parent_handle
= xn
->handle
;
1232 if (strlcpy(msg
.name
, name
, sizeof(msg
.name
)) >= NNPFS_MAX_NAME
) {
1233 nnpfs_dev_unlock(nnpfsp
);
1234 return ENAMETOOLONG
;
1237 vattr2nnpfs_attr(vap
, &msg
.attr
);
1238 nnpfs_setcred(&msg
.cred
, cred
);
1239 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1241 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1244 nnpfs_dev_unlock(nnpfsp
);
1247 NNPFS_VN_KNOTE(dvp
, NOTE_WRITE
| NOTE_LINK
);
1249 NNPFSDEB(XDEBVNOPS
, ("nnpfs_mkdir -> %d\n", error
));
1254 nnpfs_rmdir_common(struct vnode
*dvp
,
1257 nnpfs_kernel_cred cred
,
1260 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1261 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1262 struct nnpfs_message_rmdir msg
;
1265 nnpfs_dev_lock(nnpfsp
);
1266 NNPFSDEB(XDEBVNOPS
, ("nnpfs_rmdir: %s\n", name
));
1268 msg
.header
.opcode
= NNPFS_MSG_RMDIR
;
1269 msg
.parent_handle
= xn
->handle
;
1270 msg
.cred
.uid
= nnpfs_cred_get_uid(cred
);
1271 msg
.cred
.pag
= nnpfs_get_pag(cred
);
1272 if (strlcpy(msg
.name
, name
, sizeof(msg
.name
)) >= NNPFS_MAX_NAME
)
1273 error
= ENAMETOOLONG
;
1275 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1277 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1280 nnpfs_dnlc_purge (vp
);
1282 /* XXX knote even on error? */
1283 NNPFS_VN_KNOTE(dvp
, NOTE_WRITE
| NOTE_LINK
);
1284 NNPFS_VN_KNOTE(vp
, NOTE_DELETE
);
1287 nnpfs_dev_unlock(nnpfsp
);
1289 NNPFSDEB(XDEBVNOPS
, ("nnpfs_rmdir error: %d\n", error
));
1295 nnpfs_readdir_common(struct vnode
*vp
,
1298 nnpfs_vfs_context ctx
)
1300 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
1301 struct vnode
*t
= NULL
;
1302 struct nnpfs_node
*node
;
1306 nnpfs_dev_lock(nnpfsp
);
1307 NNPFSDEB(XDEBVNOPS
, ("nnpfs_readdir(%p)\n", vp
));
1312 nnpfs_assert(nnpfs_vnode_isdir(vp
));
1314 nnpfs_setcred(&cred
, nnpfs_vfs_context_ucred(ctx
));
1316 /* XXX dir can be removed at any moment, but this is ridiculous. */
1318 error
= nnpfs_data_valid(vp
, &cred
, NNPFS_DATA_R
,
1319 nnpfs_uio_offset(uiop
),
1320 nnpfs_uio_end_length(uiop
));
1322 nnpfs_dev_unlock(nnpfsp
);
1325 node
= VNODE_TO_XNODE(vp
);
1326 error
= nnpfs_block_open(node
, 0, FREAD
, &t
);
1331 nnpfs_vfs_readlock(t
, nnpfs_uio_to_proc(uiop
));
1332 nnpfs_vop_read(t
, uiop
, 0, NULL
, error
);
1334 struct nnpfs_vfs_vattr t_attr
;
1338 VATTR_INIT(&t_attr
);
1339 VATTR_WANTED(&t_attr
, va_data_size
);
1341 nnpfs_vop_getattr(t
, &t_attr
, ctx
, error2
); /* XXX check bitmask */
1343 *eofflag
= nnpfs_vattr_get_size(&t_attr
) <= nnpfs_uio_offset(uiop
);
1345 nnpfs_vfs_unlock(t
, nnpfs_uio_to_proc(uiop
));
1346 nnpfs_block_close(node
, t
, 0);
1348 nnpfs_dev_unlock(nnpfsp
);
1350 NNPFSDEB(XDEBVNOPS
, ("nnpfs_readdir -> %d\n", error
));
1356 nnpfs_link_common(struct vnode
*dvp
,
1359 nnpfs_kernel_cred cred
,
1362 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1363 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1364 struct nnpfs_node
*xn2
= VNODE_TO_XNODE(vp
);
1365 struct nnpfs_message_link msg
;
1368 nnpfs_dev_lock(nnpfsp
);
1369 NNPFSDEB(XDEBVNOPS
, ("nnpfs_link: %s\n", name
));
1371 msg
.header
.opcode
= NNPFS_MSG_LINK
;
1372 msg
.parent_handle
= xn
->handle
;
1373 msg
.from_handle
= xn2
->handle
;
1374 if (strlcpy(msg
.name
, name
, sizeof(msg
.name
)) >= NNPFS_MAX_NAME
) {
1375 nnpfs_dev_unlock(nnpfsp
);
1376 return ENAMETOOLONG
;
1379 msg
.cred
.uid
= nnpfs_cred_get_uid(cred
);
1380 msg
.cred
.pag
= nnpfs_get_pag(cred
);
1382 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1384 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1386 nnpfs_dev_unlock(nnpfsp
);
1387 NNPFS_VN_KNOTE(vp
, NOTE_LINK
);
1393 nnpfs_symlink_common(struct vnode
*dvp
,
1395 nnpfs_componentname
*cnp
,
1396 struct nnpfs_vfs_vattr
*vap
,
1398 nnpfs_vfs_context ctx
)
1400 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1401 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1402 nnpfs_kernel_cred cred
= nnpfs_vfs_context_ucred(ctx
);
1403 struct nnpfs_message_symlink msg
;
1404 const char *name
= cnp
->cn_nameptr
;
1407 nnpfs_dev_lock(nnpfsp
);
1408 NNPFSDEB(XDEBVNOPS
, ("nnpfs_symlink: %s\n", name
));
1410 msg
.header
.opcode
= NNPFS_MSG_SYMLINK
;
1411 msg
.parent_handle
= xn
->handle
;
1412 vattr2nnpfs_attr(vap
, &msg
.attr
);
1413 msg
.cred
.uid
= nnpfs_cred_get_uid(cred
);
1414 msg
.cred
.pag
= nnpfs_get_pag(cred
);
1415 if (strlcpy (msg
.contents
, target
, sizeof(msg
.contents
)) >= NNPFS_MAX_SYMLINK_CONTENT
) {
1416 error
= ENAMETOOLONG
;
1419 if (strlcpy(msg
.name
, name
, sizeof(msg
.name
)) >= NNPFS_MAX_NAME
) {
1420 error
= ENAMETOOLONG
;
1423 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
),
1424 nnpfs_vfs_context_proc(ctx
));
1426 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1429 nnpfs_dev_unlock(nnpfsp
);
1430 NNPFS_VN_KNOTE(dvp
, NOTE_WRITE
);
1436 nnpfs_readlink_common(struct vnode
*vp
, struct uio
*uiop
, nnpfs_vfs_context ctx
)
1440 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
1441 d_thread_t
*proc
= nnpfs_vfs_context_proc(ctx
);
1443 NNPFSDEB(XDEBVNOPS
, ("nnpfs_readlink\n"));
1445 if (!nnpfs_vnode_islnk(vp
) || (nnpfs_uio_offset(uiop
) != (off_t
)0))
1448 nnpfs_dev_lock(nnpfsp
);
1450 /* XXX check it fits in one block */
1452 nnpfs_setcred(&cred
, nnpfs_vfs_context_ucred(ctx
));
1453 error
= nnpfs_data_valid(vp
, &cred
, NNPFS_DATA_R
,
1454 nnpfs_uio_offset(uiop
),
1455 nnpfs_uio_end_length(uiop
));
1458 struct nnpfs_node
*node
= VNODE_TO_XNODE(vp
);
1462 error
= nnpfs_block_open(node
, 0, FREAD
, &t
);
1466 eof
= nnpfs_vattr_get_size(&node
->attr
);
1467 resid
= nnpfs_uio_resid(uiop
);
1470 nnpfs_uio_setresid(uiop
, eof
);
1472 #if defined(__APPLE__)
1473 nnpfs_vop_read(t
, uiop
, 0, ctx
, error
);
1475 nnpfs_vfs_readlock(t
, proc
);
1476 nnpfs_vop_read(t
, uiop
, 0, nnpfs_vfs_context_ucred(ctx
), error
);
1477 nnpfs_vfs_unlock(t
, proc
);
1479 nnpfs_block_close(node
, t
, 0);
1482 nnpfs_uio_setresid(uiop
, nnpfs_uio_resid(uiop
) + (resid
- eof
));
1486 nnpfs_dev_unlock(nnpfsp
);
1487 NNPFSDEB(XDEBVNOPS
, ("nnpfs_readlink: return %d\n", error
));
1493 nnpfs_inactive_common(struct vnode
*vp
, d_thread_t
*proc
)
1495 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
1496 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
1500 NNPFSDEB(XDEBVNOPS
, ("nnpfs_inactive(%lx)\n", (unsigned long)vp
));
1503 * This seems rather bogus, but sometimes we get an already
1504 * cleaned node to be made inactive. Just ignoring it seems safe.
1508 NNPFSDEB(XDEBVNOPS
, ("nnpfs_inactive: clean node\n"));
1512 /* xn->wr_cred not set -> NOCRED */
1514 if (nnpfs_vnode_isreg(vp
))
1515 nnpfs_pushdirty(vp
);
1517 nnpfs_dev_lock(nnpfsp
);
1519 error
= nnpfs_fsync_common(vp
, NULL
, &xn
->wr_cred
, 0, proc
);
1521 printf ("nnpfs_inactive: failed writing back data: %d\n", error
);
1522 xn
->flags
&= ~NNPFS_DATA_DIRTY
;
1525 /* If this node is no longer valid, recycle immediately. */
1526 recyclep
= (!NNPFS_TOKEN_GOT(xn
, NNPFS_ATTR_R
| NNPFS_ATTR_W
)
1527 || (xn
->flags
& NNPFS_STALE
) == NNPFS_STALE
);
1530 nnpfs_vfs_unlock(vp
, proc
);
1534 NNPFSDEB(XDEBVNOPS
, ("nnpfs_inactive: vrecycle\n"));
1535 nnpfs_vrecycle(vp
, 0, proc
);
1538 NNPFSDEB(XDEBVNOPS
, ("return: nnpfs_inactive done\n"));
1540 nnpfs_dev_unlock(nnpfsp
);
1545 nnpfs_reclaim_common(struct vnode
*vp
)
1547 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
1548 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
1550 NNPFSDEB(XDEBVNOPS
, ("nnpfs_reclaim(%lx)\n", (unsigned long)vp
));
1552 nnpfs_dev_lock(nnpfsp
);
1554 xn
->flags
|= NNPFS_LIMBO
;
1556 nnpfs_release_data(xn
);
1558 nnpfs_dnlc_purge(vp
);
1560 NNPQUEUE_INSERT_HEAD(&nnpfsp
->freehead
, xn
, nn_free
);
1562 if (nnpfsp
->status
& CHANNEL_OPENED
) {
1563 struct nnpfs_message_inactivenode msg
;
1565 msg
.header
.opcode
= NNPFS_MSG_INACTIVENODE
;
1566 msg
.handle
= xn
->handle
;
1567 msg
.flag
= NNPFS_NOREFS
| NNPFS_DELETE
;
1568 nnpfs_message_send(nnpfsp
, &msg
.header
, sizeof(msg
));
1570 nnpfs_free_node(nnpfsp
, xn
);
1573 nnpfs_dev_unlock(nnpfsp
);
1574 NNPFSDEB(XDEBVNOPS
, ("nnpfs_reclaim done\n"));
1586 nnpfs_advlock_common(struct vnode
*dvp
,
1588 unsigned long lockid
, /* XXX this good ? */
1589 nnpfs_kernel_cred cred
)
1591 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1592 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1595 nnpfs_dev_lock(nnpfsp
);
1596 NNPFSDEB(XDEBVNOPS
, ("nnpfs_advlock\n"));
1598 struct nnpfs_message_advlock msg
;
1600 msg
.header
.opcode
= NNPFS_MSG_ADVLOCK
;
1601 msg
.handle
= xn
->handle
;
1602 msg
.locktype
= locktype
;
1603 msg
.lockid
= lockid
;
1605 nnpfs_setcred(&msg
.cred
, cred
);
1606 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
),
1607 nnpfs_vfs_context_proc(ctx
));
1609 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1614 /* sleep until woken */
1621 nnpfs_dev_unlock(nnpfsp
);
1632 nnpfs_printnode_common (struct vnode
*vp
)
1634 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
1636 printf ("xnode: fid: %d.%d.%d.%d\n",
1637 xn
->handle
.a
, xn
->handle
.b
, xn
->handle
.c
, xn
->handle
.d
);
1638 printf ("\tattr: %svalid\n",
1639 NNPFS_TOKEN_GOT(xn
, NNPFS_ATTR_VALID
) ? "": "in");
1640 printf ("\tdata: %svalid\n",
1641 NNPFS_TOKEN_GOT(xn
, NNPFS_DATA_VALID
) ? "": "in");
1642 printf ("\tflags: 0x%x\n", xn
->flags
);