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
);
703 nnpfs_vfs_writelock(t
, nnpfs_vfs_context_proc(ctx
));
704 (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",
720 /* #ifndef __NetBSD__ */
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__ */
728 nnpfs_vfs_unlock(t
, nnpfs_vfs_context_proc(ctx
));
732 vn_finished_write(mp
);
735 nnpfs_block_close(xn
, t
, 1);
741 xn
->flags
|= NNPFS_DATA_DIRTY
;
742 nnpfs_uio_setoffset(uiop
, offset
);
743 nnpfs_uio_setresid(uiop
, length
- offset
);
745 nnpfs_dev_unlock(nnpfsp
);
747 NNPFSDEB(XDEBVNOPS
, ("nnpfs_write -> %d\n", error
));
753 nnpfs_getattr_common(struct vnode
*vp
, struct nnpfs_vfs_vattr
*vap
,
754 nnpfs_kernel_cred cred
, d_thread_t
*p
)
756 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
757 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
760 nnpfs_dev_lock(nnpfsp
);
761 NNPFSDEB(XDEBVNOPS
, ("nnpfs_getattr\n"));
763 error
= nnpfs_attr_valid(vp
, cred
, p
, NNPFS_ATTR_R
);
767 nnpfs_dev_unlock(nnpfsp
);
773 setattr_is_noop(struct nnpfs_node
*xn
, struct nnpfs_vfs_vattr
*vap
)
777 #define CHECK_NNPFSATTR(A) (!VATTR_IS_ACTIVE(vap, A) || vap->A == xn->attr.A)
778 if (CHECK_NNPFSATTR(va_mode
) &&
779 CHECK_NNPFSATTR(va_nlink
) &&
780 CHECK_NNPFSATTR(va_data_size
) &&
781 CHECK_NNPFSATTR(va_uid
) &&
782 CHECK_NNPFSATTR(va_gid
) &&
783 CHECK_NNPFSATTR(va_fileid
) && /* we ignore va_type */
784 (!VATTR_IS_ACTIVE(vap
, va_modify_time
)
785 || vap
->va_modify_time
.tv_sec
== xn
->attr
.va_modify_time
.tv_sec
))
787 #undef CHECK_NNPFSATTR
791 #define CHECK_NNPFSATTR(A, cast) (vap->A == cast VNOVAL || vap->A == xn->attr.A)
792 if (CHECK_NNPFSATTR(va_mode
,(mode_t
)) &&
793 CHECK_NNPFSATTR(va_nlink
,(short)) &&
794 CHECK_NNPFSATTR(va_size
,(va_size_t
)) &&
795 CHECK_NNPFSATTR(va_uid
,(uid_t
)) &&
796 CHECK_NNPFSATTR(va_gid
,(gid_t
)) &&
797 CHECK_NNPFSATTR(va_mtime
.tv_sec
,(time_t)) &&
798 CHECK_NNPFSATTR(va_fileid
,(long)) &&
799 CHECK_NNPFSATTR(va_type
,(enum vtype
)))
801 #undef CHECK_NNPFSATTR
803 #endif /* ! __APPLE__ */
809 nnpfs_setattr_common(struct vnode
*vp
, struct nnpfs_vfs_vattr
*vap
,
810 nnpfs_kernel_cred cred
, d_thread_t
*p
)
812 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
813 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
816 nnpfs_dev_lock(nnpfsp
);
817 NNPFSDEB(XDEBVNOPS
, ("nnpfs_setattr\n"));
819 if (setattr_is_noop(xn
, vap
)) {
820 nnpfs_dev_unlock(nnpfsp
);
821 return 0; /* nothing to do */
824 if (NNPFS_TOKEN_GOT(xn
, NNPFS_ATTR_W
)) {
825 /* Update attributes and mark them dirty. */
826 VNODE_TO_XNODE(vp
)->flags
|= NNPFS_ATTR_DIRTY
;
827 error
= EINVAL
; /* XXX not yet implemented */
830 struct nnpfs_message_putattr msg
;
831 uint64_t old_length
, new_length
;
833 msg
.header
.opcode
= NNPFS_MSG_PUTATTR
;
834 nnpfs_setcred(&msg
.cred
, cred
);
835 msg
.handle
= xn
->handle
;
836 vattr2nnpfs_attr(vap
, &msg
.attr
);
838 if (NNPFS_TOKEN_GOT(xn
, NNPFS_DATA_R
)) {
839 if (nnpfs_vnode_isreg(vp
)) {
840 old_length
= nnpfs_vattr_get_size(&xn
->attr
);
842 if (nnpfs_vattr_size_isactive(vap
)) {
843 new_length
= nnpfs_vattr_get_size(vap
);
845 XA_SET_SIZE(&msg
.attr
, new_length
);
847 XA_SET_SIZE(&msg
.attr
, old_length
);
851 if (nnpfs_vattr_mtime_isactive(vap
))
852 XA_SET_MTIME(&msg
.attr
, nnpfs_vattr_get_mtime_sec(vap
));
854 XA_SET_MTIME(&msg
.attr
, nnpfs_vattr_get_mtime_sec(&xn
->attr
));
857 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
859 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
861 #if 0 /* assume length is always in (loose) sync with daemon nowadays */
862 if (error
== 0 && do_fixup
)
863 truncate_block_fixup(xn
, old_length
, new_length
);
868 nnpfs_dev_unlock(nnpfsp
);
869 NNPFS_VN_KNOTE(vp
, NOTE_ATTRIB
);
875 check_rights (nnpfs_rights rights
, int mode
, int dirp
)
880 /* VNOP_ACCESS passes a kauth action instead of ordinary unix mode */
883 if (mode
& (KAUTH_VNODE_LIST_DIRECTORY
| KAUTH_VNODE_SEARCH
))
884 if ((rights
& NNPFS_RIGHT_X
) == 0)
886 if (mode
& KAUTH_VNODE_DELETE_CHILD
)
887 if ((rights
& NNPFS_RIGHT_AD
) == 0)
889 if (mode
& (KAUTH_VNODE_ADD_FILE
| KAUTH_VNODE_ADD_SUBDIRECTORY
))
890 if ((rights
& NNPFS_RIGHT_AI
) == 0)
893 /* XXX can't check KAUTH_VNODE_DELETE, have no info */
896 if (mode
& (KAUTH_VNODE_READ_DATA
| KAUTH_VNODE_READ_ATTRIBUTES
))
897 if ((rights
& NNPFS_RIGHT_AR
) == 0)
899 if (mode
& (KAUTH_VNODE_WRITE_DATA
| KAUTH_VNODE_APPEND_DATA
| KAUTH_VNODE_WRITE_ATTRIBUTES
| KAUTH_VNODE_TAKE_OWNERSHIP
))
900 if ((rights
& NNPFS_RIGHT_W
) == 0)
902 if (mode
& KAUTH_VNODE_EXECUTE
)
903 if ((rights
& NNPFS_RIGHT_X
) == 0)
905 if (mode
& KAUTH_VNODE_DELETE
)
906 if ((rights
& NNPFS_RIGHT_AD
) == 0)
911 KAUTH_VNODE_READ_EXTATTRIBUTES
912 KAUTH_VNODE_WRITE_EXTATTRIBUTES
913 KAUTH_VNODE_READ_SECURITY
914 KAUTH_VNODE_WRITE_SECURITY
915 KAUTH_VNODE_SYNCHRONIZE notused
916 KAUTH_VNODE_LINKTARGET like insert
, but
for target
???
917 KAUTH_VNODE_CHECKIMMUTABLE always ok
918 KAUTH_VNODE_ACCESS (advisory
)
919 KAUTH_VNODE_NOIMMUTABLE
?
922 #else /* !__APPLE__ */
925 if ((rights
& NNPFS_RIGHT_R
) == 0)
928 if ((rights
& NNPFS_RIGHT_W
) == 0)
931 if ((rights
& NNPFS_RIGHT_X
) == 0)
934 #endif /* !__APPLE__ */
940 nnpfs_access_common(struct vnode
*vp
, int mode
, nnpfs_kernel_cred cred
,
943 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
944 int dirp
= nnpfs_vnode_isdir(vp
);
948 nnpfs_dev_lock(nnpfsp
);
949 NNPFSDEB(XDEBVNOPS
, ("nnpfs_access mode = 0%o\n", mode
));
951 pag
= nnpfs_get_pag(cred
);
953 error
= nnpfs_attr_valid(vp
, cred
, p
, NNPFS_ATTR_R
);
955 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
958 error
= check_rights(xn
->anonrights
, mode
, dirp
);
963 NNPFSDEB(XDEBVNOPS
, ("nnpfs_access anonaccess failed\n"));
965 error
= EACCES
; /* default to EACCES if pag isn't in xn->id */
967 for (i
= 0; i
< NNPFS_MAXRIGHTS
; i
++)
968 if (xn
->id
[i
] == pag
) {
969 error
= check_rights(xn
->rights
[i
], mode
, dirp
);
975 NNPFSDEB(XDEBVNOPS
, ("nnpfs_access(0%o) = %d\n", mode
, error
));
976 nnpfs_dev_unlock(nnpfsp
);
982 nnpfs_lookup_common(struct vnode
*dvp
,
983 nnpfs_componentname
*cnp
,
985 nnpfs_vfs_context ctx
)
987 struct nnpfs_message_getnode msg
;
988 nnpfs_kernel_cred cred
= nnpfs_vfs_context_ucred(ctx
);
989 d_thread_t
*p
= nnpfs_vfs_context_proc(ctx
);
990 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
991 struct nnpfs_node
*d
= VNODE_TO_XNODE(dvp
);
994 NNPFSDEB(XDEBVNOPS
, ("nnpfs_lookup_common: enter\n"));
998 if (cnp
->cn_namelen
>= NNPFS_MAX_NAME
)
1001 if (!nnpfs_vnode_isdir(dvp
))
1004 if (cnp
->cn_namelen
== 1 && cnp
->cn_nameptr
[0] == '.') {
1007 nnpfs_do_vget(*vpp
, 0 /* XXX flag */, NULL
/*proc */);
1014 nnpfs_dev_lock(nnpfsp
);
1016 nnpfs_lookup_access(dvp
, ctx
, p
, error
);
1020 NNPFSDEB(XDEBVNOPS
, ("nnpfs_lookup_common: dvp = %lx\n",
1021 (unsigned long) dvp
));
1022 NNPFSDEB(XDEBVNOPS
, ("nnpfs_lookup_common: cnp = %lx, "
1023 "cnp->cn_nameiop = %d\n",
1024 (unsigned long) cnp
, (int)cnp
->cn_nameiop
));
1026 error
= nnpfs_dnlc_lookup(dvp
, cnp
, vpp
);
1027 if (error
== 0) { /* not cached */
1030 * Doesn't quite work.
1034 if ((cnp
->cn_nameiop
== CREATE
|| cnp
->cn_nameiop
== RENAME
)
1035 && (cnp
->cn_flags
& ISLASTCN
)) {
1036 error
= EJUSTRETURN
;
1041 msg
.header
.opcode
= NNPFS_MSG_GETNODE
;
1042 nnpfs_setcred(&msg
.cred
, cred
);
1043 msg
.parent_handle
= d
->handle
;
1044 memcpy(msg
.name
, cnp
->cn_nameptr
, cnp
->cn_namelen
);
1045 msg
.name
[cnp
->cn_namelen
] = '\0';
1046 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1048 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1049 if(error
== ENOENT
&& cnp
->cn_nameiop
!= CREATE
) {
1050 NNPFSDEB(XDEBVNOPS
, ("nnpfs_lookup: neg cache %lx (%s, %ld)\n",
1052 cnp
->cn_nameptr
, cnp
->cn_namelen
));
1053 nnpfs_dnlc_enter (dvp
, cnp
, NULL
);
1055 } else if (error
== -1) { /* found */
1059 } while (error
== 0);
1062 nnpfs_dev_unlock(nnpfsp
);
1063 NNPFS_VN_KNOTE(dvp
, NOTE_WRITE
);
1065 NNPFSDEB(XDEBVNOPS
, ("nnpfs_lookup_common: return %d, vn %p\n",
1071 nnpfs_create_common(struct vnode
*dvp
,
1073 struct nnpfs_vfs_vattr
*vap
,
1074 nnpfs_kernel_cred cred
,
1077 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1078 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1081 nnpfs_dev_lock(nnpfsp
);
1082 NNPFSDEB(XDEBVNOPS
, ("nnpfs_create: (%lx, %s)\n",
1083 (unsigned long)dvp
, name
));
1085 struct nnpfs_message_create msg
;
1087 msg
.header
.opcode
= NNPFS_MSG_CREATE
;
1088 msg
.parent_handle
= xn
->handle
;
1089 if (strlcpy(msg
.name
, name
, sizeof(msg
.name
)) >= NNPFS_MAX_NAME
)
1090 return ENAMETOOLONG
;
1091 vattr2nnpfs_attr(vap
, &msg
.attr
);
1093 msg
.mode
= 0; /* XXX - mode */
1094 nnpfs_setcred(&msg
.cred
, cred
);
1097 /* needed for subsequent writes to succeed with n */
1098 msg
.attr
.valid
&= ~XA_V_UID
;
1101 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1103 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1107 if (error
== EEXIST
)
1111 nnpfs_dev_unlock(nnpfsp
);
1113 NNPFSDEB(XDEBVNOPS
, ("nnpfs_create -> %d\n", error
));
1119 nnpfs_remove_common(struct vnode
*dvp
,
1122 nnpfs_kernel_cred cred
,
1125 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1126 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1127 struct nnpfs_message_remove msg
;
1130 nnpfs_dev_lock(nnpfsp
);
1131 NNPFSDEB(XDEBVNOPS
, ("nnpfs_remove(%p): %s\n", dvp
, name
));
1133 msg
.header
.opcode
= NNPFS_MSG_REMOVE
;
1134 msg
.parent_handle
= xn
->handle
;
1135 msg
.cred
.uid
= nnpfs_cred_get_uid(cred
);
1136 msg
.cred
.pag
= nnpfs_get_pag(cred
);
1138 if (strlcpy(msg
.name
, name
, sizeof(msg
.name
)) >= NNPFS_MAX_NAME
)
1139 error
= ENAMETOOLONG
;
1141 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1143 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1146 nnpfs_dnlc_purge (vp
);
1148 nnpfs_dev_unlock(nnpfsp
);
1151 NNPFS_VN_KNOTE(vp
, NOTE_DELETE
);
1152 NNPFS_VN_KNOTE(dvp
, NOTE_WRITE
);
1155 NNPFSDEB(XDEBVNOPS
, ("nnpfs_remove -> %d\n", error
));
1161 nnpfs_rename_common(struct vnode
*fdvp
,
1167 nnpfs_kernel_cred cred
,
1170 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(fdvp
);
1173 nnpfs_dev_lock(nnpfsp
);
1174 NNPFSDEB(XDEBVNOPS
, ("nnpfs_rename: %s %s\n", fname
, tname
));
1177 if ((fvp
->v_mount
!= tdvp
->v_mount
)
1178 || (tvp
&& (fvp
->v_mount
!= tvp
->v_mount
))) {
1184 struct nnpfs_message_rename msg
;
1186 msg
.header
.opcode
= NNPFS_MSG_RENAME
;
1187 msg
.old_parent_handle
= VNODE_TO_XNODE(fdvp
)->handle
;
1188 if (strlcpy(msg
.old_name
, fname
, sizeof(msg
.old_name
)) >= NNPFS_MAX_NAME
) {
1189 nnpfs_dev_unlock(nnpfsp
);
1190 return ENAMETOOLONG
;
1193 msg
.new_parent_handle
= VNODE_TO_XNODE(tdvp
)->handle
;
1194 if (strlcpy(msg
.new_name
, tname
, sizeof(msg
.new_name
)) >= NNPFS_MAX_NAME
) {
1195 nnpfs_dev_unlock(nnpfsp
);
1196 return ENAMETOOLONG
;
1199 msg
.cred
.uid
= nnpfs_cred_get_uid(cred
);
1200 msg
.cred
.pag
= nnpfs_get_pag(cred
);
1201 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1203 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1207 nnpfs_dev_unlock(nnpfsp
);
1208 NNPFS_VN_KNOTE(fdvp
, NOTE_WRITE
);
1209 NNPFS_VN_KNOTE(fvp
, NOTE_WRITE
);
1211 NNPFSDEB(XDEBVNOPS
, ("nnpfs_rename: error = %d\n", error
));
1217 nnpfs_mkdir_common(struct vnode
*dvp
,
1219 struct nnpfs_vfs_vattr
*vap
,
1220 nnpfs_kernel_cred cred
,
1223 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1224 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1227 nnpfs_dev_lock(nnpfsp
);
1228 NNPFSDEB(XDEBVNOPS
, ("nnpfs_mkdir(%p): %s\n", dvp
, name
));
1230 struct nnpfs_message_mkdir msg
;
1232 msg
.header
.opcode
= NNPFS_MSG_MKDIR
;
1233 msg
.parent_handle
= xn
->handle
;
1234 if (strlcpy(msg
.name
, name
, sizeof(msg
.name
)) >= NNPFS_MAX_NAME
) {
1235 nnpfs_dev_unlock(nnpfsp
);
1236 return ENAMETOOLONG
;
1239 vattr2nnpfs_attr(vap
, &msg
.attr
);
1240 nnpfs_setcred(&msg
.cred
, cred
);
1241 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1243 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1246 nnpfs_dev_unlock(nnpfsp
);
1249 NNPFS_VN_KNOTE(dvp
, NOTE_WRITE
| NOTE_LINK
);
1251 NNPFSDEB(XDEBVNOPS
, ("nnpfs_mkdir -> %d\n", error
));
1256 nnpfs_rmdir_common(struct vnode
*dvp
,
1259 nnpfs_kernel_cred cred
,
1262 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1263 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1264 struct nnpfs_message_rmdir msg
;
1267 nnpfs_dev_lock(nnpfsp
);
1268 NNPFSDEB(XDEBVNOPS
, ("nnpfs_rmdir: %s\n", name
));
1270 msg
.header
.opcode
= NNPFS_MSG_RMDIR
;
1271 msg
.parent_handle
= xn
->handle
;
1272 msg
.cred
.uid
= nnpfs_cred_get_uid(cred
);
1273 msg
.cred
.pag
= nnpfs_get_pag(cred
);
1274 if (strlcpy(msg
.name
, name
, sizeof(msg
.name
)) >= NNPFS_MAX_NAME
)
1275 error
= ENAMETOOLONG
;
1277 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1279 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1282 nnpfs_dnlc_purge (vp
);
1284 /* XXX knote even on error? */
1285 NNPFS_VN_KNOTE(dvp
, NOTE_WRITE
| NOTE_LINK
);
1286 NNPFS_VN_KNOTE(vp
, NOTE_DELETE
);
1289 nnpfs_dev_unlock(nnpfsp
);
1291 NNPFSDEB(XDEBVNOPS
, ("nnpfs_rmdir error: %d\n", error
));
1297 nnpfs_readdir_common(struct vnode
*vp
,
1300 nnpfs_vfs_context ctx
)
1302 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
1303 struct vnode
*t
= NULL
;
1304 struct nnpfs_node
*node
;
1308 nnpfs_dev_lock(nnpfsp
);
1309 NNPFSDEB(XDEBVNOPS
, ("nnpfs_readdir(%p)\n", vp
));
1314 nnpfs_assert(nnpfs_vnode_isdir(vp
));
1316 nnpfs_setcred(&cred
, nnpfs_vfs_context_ucred(ctx
));
1318 /* XXX dir can be removed at any moment, but this is ridiculous. */
1320 error
= nnpfs_data_valid(vp
, &cred
, NNPFS_DATA_R
,
1321 nnpfs_uio_offset(uiop
),
1322 nnpfs_uio_end_length(uiop
));
1324 nnpfs_dev_unlock(nnpfsp
);
1327 node
= VNODE_TO_XNODE(vp
);
1328 error
= nnpfs_block_open(node
, 0, FREAD
, &t
);
1333 nnpfs_vfs_readlock(t
, nnpfs_uio_to_proc(uiop
));
1334 nnpfs_vop_read(t
, uiop
, 0, NULL
, error
);
1336 struct nnpfs_vfs_vattr t_attr
;
1340 VATTR_INIT(&t_attr
);
1341 VATTR_WANTED(&t_attr
, va_data_size
);
1343 nnpfs_vop_getattr(t
, &t_attr
, ctx
, error2
); /* XXX check bitmask */
1345 *eofflag
= nnpfs_vattr_get_size(&t_attr
) <= nnpfs_uio_offset(uiop
);
1347 nnpfs_vfs_unlock(t
, nnpfs_uio_to_proc(uiop
));
1348 nnpfs_block_close(node
, t
, 0);
1350 nnpfs_dev_unlock(nnpfsp
);
1352 NNPFSDEB(XDEBVNOPS
, ("nnpfs_readdir -> %d\n", error
));
1358 nnpfs_link_common(struct vnode
*dvp
,
1361 nnpfs_kernel_cred cred
,
1364 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1365 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1366 struct nnpfs_node
*xn2
= VNODE_TO_XNODE(vp
);
1367 struct nnpfs_message_link msg
;
1370 nnpfs_dev_lock(nnpfsp
);
1371 NNPFSDEB(XDEBVNOPS
, ("nnpfs_link: %s\n", name
));
1373 msg
.header
.opcode
= NNPFS_MSG_LINK
;
1374 msg
.parent_handle
= xn
->handle
;
1375 msg
.from_handle
= xn2
->handle
;
1376 if (strlcpy(msg
.name
, name
, sizeof(msg
.name
)) >= NNPFS_MAX_NAME
) {
1377 nnpfs_dev_unlock(nnpfsp
);
1378 return ENAMETOOLONG
;
1381 msg
.cred
.uid
= nnpfs_cred_get_uid(cred
);
1382 msg
.cred
.pag
= nnpfs_get_pag(cred
);
1384 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
), p
);
1386 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1388 nnpfs_dev_unlock(nnpfsp
);
1389 NNPFS_VN_KNOTE(vp
, NOTE_LINK
);
1395 nnpfs_symlink_common(struct vnode
*dvp
,
1397 nnpfs_componentname
*cnp
,
1398 struct nnpfs_vfs_vattr
*vap
,
1400 nnpfs_vfs_context ctx
)
1402 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1403 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1404 nnpfs_kernel_cred cred
= nnpfs_vfs_context_ucred(ctx
);
1405 struct nnpfs_message_symlink msg
;
1406 const char *name
= cnp
->cn_nameptr
;
1409 nnpfs_dev_lock(nnpfsp
);
1410 NNPFSDEB(XDEBVNOPS
, ("nnpfs_symlink: %s\n", name
));
1412 msg
.header
.opcode
= NNPFS_MSG_SYMLINK
;
1413 msg
.parent_handle
= xn
->handle
;
1414 vattr2nnpfs_attr(vap
, &msg
.attr
);
1415 msg
.cred
.uid
= nnpfs_cred_get_uid(cred
);
1416 msg
.cred
.pag
= nnpfs_get_pag(cred
);
1417 if (strlcpy (msg
.contents
, target
, sizeof(msg
.contents
)) >= NNPFS_MAX_SYMLINK_CONTENT
) {
1418 error
= ENAMETOOLONG
;
1421 if (strlcpy(msg
.name
, name
, sizeof(msg
.name
)) >= NNPFS_MAX_NAME
) {
1422 error
= ENAMETOOLONG
;
1425 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
),
1426 nnpfs_vfs_context_proc(ctx
));
1428 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1431 nnpfs_dev_unlock(nnpfsp
);
1432 NNPFS_VN_KNOTE(dvp
, NOTE_WRITE
);
1438 nnpfs_readlink_common(struct vnode
*vp
, struct uio
*uiop
, nnpfs_vfs_context ctx
)
1442 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
1443 #ifdef HAVE_THREE_ARGUMENT_VOP_UNLOCK
1444 d_thread_t
*proc
= nnpfs_vfs_context_proc(ctx
);
1447 NNPFSDEB(XDEBVNOPS
, ("nnpfs_readlink\n"));
1449 if (!nnpfs_vnode_islnk(vp
) || (nnpfs_uio_offset(uiop
) != (off_t
)0))
1452 nnpfs_dev_lock(nnpfsp
);
1454 /* XXX check it fits in one block */
1456 nnpfs_setcred(&cred
, nnpfs_vfs_context_ucred(ctx
));
1457 error
= nnpfs_data_valid(vp
, &cred
, NNPFS_DATA_R
,
1458 nnpfs_uio_offset(uiop
),
1459 nnpfs_uio_end_length(uiop
));
1462 struct nnpfs_node
*node
= VNODE_TO_XNODE(vp
);
1466 error
= nnpfs_block_open(node
, 0, FREAD
, &t
);
1470 eof
= nnpfs_vattr_get_size(&node
->attr
);
1471 resid
= nnpfs_uio_resid(uiop
);
1474 nnpfs_uio_setresid(uiop
, eof
);
1476 #if defined(__APPLE__)
1477 nnpfs_vop_read(t
, uiop
, 0, ctx
, error
);
1479 nnpfs_vfs_readlock(t
, proc
);
1480 nnpfs_vop_read(t
, uiop
, 0, nnpfs_vfs_context_ucred(ctx
), error
);
1481 nnpfs_vfs_unlock(t
, proc
);
1483 nnpfs_block_close(node
, t
, 0);
1486 nnpfs_uio_setresid(uiop
, nnpfs_uio_resid(uiop
) + (resid
- eof
));
1490 nnpfs_dev_unlock(nnpfsp
);
1491 NNPFSDEB(XDEBVNOPS
, ("nnpfs_readlink: return %d\n", error
));
1497 nnpfs_inactive_common(struct vnode
*vp
, d_thread_t
*proc
)
1499 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
1500 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
1504 NNPFSDEB(XDEBVNOPS
, ("nnpfs_inactive(%lx)\n", (unsigned long)vp
));
1507 * This seems rather bogus, but sometimes we get an already
1508 * cleaned node to be made inactive. Just ignoring it seems safe.
1512 NNPFSDEB(XDEBVNOPS
, ("nnpfs_inactive: clean node\n"));
1516 /* xn->wr_cred not set -> NOCRED */
1518 if (nnpfs_vnode_isreg(vp
))
1519 nnpfs_pushdirty(vp
);
1521 nnpfs_dev_lock(nnpfsp
);
1523 error
= nnpfs_fsync_common(vp
, NULL
, &xn
->wr_cred
, 0, proc
);
1525 printf ("nnpfs_inactive: failed writing back data: %d\n", error
);
1526 xn
->flags
&= ~NNPFS_DATA_DIRTY
;
1529 /* If this node is no longer valid, recycle immediately. */
1530 recyclep
= (!NNPFS_TOKEN_GOT(xn
, NNPFS_ATTR_R
| NNPFS_ATTR_W
)
1531 || (xn
->flags
& NNPFS_STALE
) == NNPFS_STALE
);
1534 nnpfs_vfs_unlock(vp
, proc
);
1538 NNPFSDEB(XDEBVNOPS
, ("nnpfs_inactive: vrecycle\n"));
1539 nnpfs_vrecycle(vp
, 0, proc
);
1542 NNPFSDEB(XDEBVNOPS
, ("return: nnpfs_inactive done\n"));
1544 nnpfs_dev_unlock(nnpfsp
);
1549 nnpfs_reclaim_common(struct vnode
*vp
)
1551 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(vp
);
1552 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
1554 NNPFSDEB(XDEBVNOPS
, ("nnpfs_reclaim(%lx)\n", (unsigned long)vp
));
1556 nnpfs_dev_lock(nnpfsp
);
1558 xn
->flags
|= NNPFS_LIMBO
;
1560 nnpfs_release_data(xn
);
1562 nnpfs_dnlc_purge(vp
);
1564 NNPQUEUE_INSERT_HEAD(&nnpfsp
->freehead
, xn
, nn_free
);
1566 if (nnpfsp
->status
& CHANNEL_OPENED
) {
1567 struct nnpfs_message_inactivenode msg
;
1569 msg
.header
.opcode
= NNPFS_MSG_INACTIVENODE
;
1570 msg
.handle
= xn
->handle
;
1571 msg
.flag
= NNPFS_NOREFS
| NNPFS_DELETE
;
1572 nnpfs_message_send(nnpfsp
, &msg
.header
, sizeof(msg
));
1574 nnpfs_free_node(nnpfsp
, xn
);
1577 nnpfs_dev_unlock(nnpfsp
);
1578 NNPFSDEB(XDEBVNOPS
, ("nnpfs_reclaim done\n"));
1590 nnpfs_advlock_common(struct vnode
*dvp
,
1592 unsigned long lockid
, /* XXX this good ? */
1593 nnpfs_kernel_cred cred
)
1595 struct nnpfs
*nnpfsp
= NNPFS_FROM_VNODE(dvp
);
1596 struct nnpfs_node
*xn
= VNODE_TO_XNODE(dvp
);
1599 nnpfs_dev_lock(nnpfsp
);
1600 NNPFSDEB(XDEBVNOPS
, ("nnpfs_advlock\n"));
1602 struct nnpfs_message_advlock msg
;
1604 msg
.header
.opcode
= NNPFS_MSG_ADVLOCK
;
1605 msg
.handle
= xn
->handle
;
1606 msg
.locktype
= locktype
;
1607 msg
.lockid
= lockid
;
1609 nnpfs_setcred(&msg
.cred
, cred
);
1610 error
= nnpfs_message_rpc(nnpfsp
, &msg
.header
, sizeof(msg
),
1611 nnpfs_vfs_context_proc(ctx
));
1613 error
= NNPFS_MSG_WAKEUP_ERROR(&msg
);
1618 /* sleep until woken */
1625 nnpfs_dev_unlock(nnpfsp
);
1636 nnpfs_printnode_common (struct vnode
*vp
)
1638 struct nnpfs_node
*xn
= VNODE_TO_XNODE(vp
);
1640 printf ("xnode: fid: %d.%d.%d.%d\n",
1641 xn
->handle
.a
, xn
->handle
.b
, xn
->handle
.c
, xn
->handle
.d
);
1642 printf ("\tattr: %svalid\n",
1643 NNPFS_TOKEN_GOT(xn
, NNPFS_ATTR_VALID
) ? "": "in");
1644 printf ("\tdata: %svalid\n",
1645 NNPFS_TOKEN_GOT(xn
, NNPFS_DATA_VALID
) ? "": "in");
1646 printf ("\tflags: 0x%x\n", xn
->flags
);