2 * Copyright (c) 1995 - 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
34 #include <nnpfs/nnpfs_locl.h>
35 #include <nnpfs/nnpfs_common.h>
36 #include <nnpfs/nnpfs_fs.h>
37 #include <nnpfs/nnpfs_dev.h>
38 #include <nnpfs/nnpfs_deb.h>
39 #include <nnpfs/nnpfs_vnodeops.h>
40 #include <nnpfs/nnpfs_node.h>
44 extern vop_t
**nnpfs_vnodeop_p
;
51 * Allocate a new vnode with handle `handle' in `mp' and return it in
52 * `vpp'. Return 0 or error.
56 nnpfs_getnewvnode(struct nnpfs
*nnpfsp
,
58 struct nnpfs_handle
*handle
,
59 struct nnpfs_msg_node
*node
,
63 struct nnpfs_node
*result
, *check
;
66 result
= nnpfs_alloc(sizeof(*result
), M_NNPFS_NODE
);
67 bzero(result
, sizeof(*result
));
71 struct vnode_fsparam p
;
73 if (!XA_VALID_TYPE(&node
->attr
)) {
74 nnpfs_free(result
, sizeof(*result
), M_NNPFS_NODE
);
78 memset(&p
, 0, sizeof(p
));
79 p
.vnfs_mp
= NNPFS_TO_VFS(nnpfsp
);
80 switch (node
->attr
.xa_type
) {
100 p
.vnfs_vtype
= VSOCK
;
102 case NNPFS_FILE_FIFO
:
103 p
.vnfs_vtype
= VFIFO
;
109 printf("nnpfs_getnewnvode: bad value");
110 nnpfs_free(result
, sizeof(*result
), M_NNPFS_NODE
);
114 p
.vnfs_dvp
= NULL
; /* parent vnode */
115 p
.vnfs_fsnode
= result
;
116 p
.vnfs_vops
= nnpfs_vnodeop_p
;
117 p
.vnfs_markroot
= isrootp
;
118 p
.vnfs_marksystem
= 0;
120 if (XA_VALID_SIZE(&node
->attr
))
121 p
.vnfs_filesize
= node
->attr
.xa_size
;
125 p
.vnfs_flags
= 0; /* XXX VNFS_CANTCACHE? */
127 error
= vnode_create(VNCREATE_FLAVOR
, VCREATESIZE
, &p
, vpp
);
130 error
= getnewvnode(VT_AFS
, NNPFS_TO_VFS(nnpfsp
), nnpfs_vnodeop_p
, vpp
);
132 (*vpp
)->v_data
= result
;
139 result
->handle
= *handle
;
143 #if (defined(HAVE_KERNEL_LOCKMGR) || defined(HAVE_KERNEL_DEBUGLOCKMGR)) && !defined(__APPLE__)
144 lockinit (&result
->lock
, PVFS
, "nnpfs_lock", 0, LK_NOPAUSE
);
153 result
->anonrights
= 0;
154 nnpfs_setcred(&result
->rd_cred
, NOCRED
);
155 nnpfs_setcred(&result
->wr_cred
, NOCRED
);
157 #if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105280000
158 genfs_node_init(*vpp
, &nnpfs_genfsops
);
162 error
= nnpfs_node_find(nnpfsp
, handle
, &check
);
163 if (error
== ENOENT
) {
164 nnpfs_insert(&nnpfsp
->nodehead
, result
);
168 if (nnpfs_do_vget(XNODE_TO_VNODE(check
), 0, p
))
174 if (error
== EISDIR
) {
175 nnpfs_vletgo(XNODE_TO_VNODE(check
));
185 * Create a new nnpfs_node and make a vget
187 * Also prevents creation of duplicates. This happens
188 * whenever there are more than one name to a file,
189 * "." and ".." are common cases. */
192 nnpfs_new_node(struct nnpfs
*nnpfsp
,
193 struct nnpfs_msg_node
*node
,
195 struct nnpfs_node
**xpp
,
199 struct nnpfs_node
*result
;
202 NNPFSDEB(XDEBNODE
, ("nnpfs_new_node (%d,%d,%d,%d)\n",
209 /* Does not allow duplicates */
210 error
= nnpfs_node_find(nnpfsp
, &node
->handle
, &result
);
211 if (error
== ENOENT
) {
214 error
= nnpfs_getnewvnode(nnpfsp
, &v
, &node
->handle
, node
, p
, isrootp
);
218 result
= VNODE_TO_XNODE(v
);
219 result
->anonrights
= node
->anonrights
;
220 nnpfs_store_attr(&node
->attr
, result
, 1);
223 result
->vn
->v_type
= result
->attr
.va_type
;
225 NNPFS_MAKE_VROOT(result
->vn
);
227 } else if (error
== EISDIR
) {
228 /* node is about to be deleted */
229 NNPFSDEB(XDEBNODE
, ("nnpfs_new_node: node deleted\n"));
232 /* Node is already cached */
233 if (nnpfs_do_vget(XNODE_TO_VNODE(result
), 0, p
))
236 if (result
->flags
& NNPFS_DATA_DIRTY
)
237 XA_CLEAR_SIZE(&node
->attr
);
238 nnpfs_store_attr(&node
->attr
, result
, 0);
241 result
->tokens
|= node
->tokens
; /* XXX correct? */
242 if ((result
->tokens
& NNPFS_DATA_MASK
) && result
->index
== NNPFS_NO_INDEX
) {
243 printf("nnpfs_new_node: tokens and no data (%d,%d,%d,%d) \n",
244 node
->handle
.a
, node
->handle
.b
, node
->handle
.c
, node
->handle
.d
);
245 result
->tokens
&= ~NNPFS_DATA_MASK
;
248 /* XXX scary -- could this remove creator's privileges for existing node? */
249 bcopy(node
->id
, result
->id
, sizeof(result
->id
));
250 bcopy(node
->rights
, result
->rights
, sizeof(result
->rights
));
253 NNPFSDEB(XDEBNODE
, ("return: nnpfs_new_node\n"));
260 * this should always be called with dev lock held
263 nnpfs_free_node(struct nnpfs
*nnpfsp
, struct nnpfs_node
*node
)
265 NNPFSDEB(XDEBNODE
, ("nnpfs_free_node(%lx) (%d,%d,%d,%d)\n",
272 NNPQUEUE_REMOVE(node
, &nnpfsp
->freehead
, nn_free
);
273 nnpfs_remove_node(&nnpfsp
->nodehead
, node
);
275 if (node
->index
!= NNPFS_NO_INDEX
) {
276 node
->index
= NNPFS_NO_INDEX
;
277 nnpfs_block_free_all(node
);
280 nnpfs_free(node
, sizeof(*node
), M_NNPFS_NODE
);
282 NNPFSDEB(XDEBNODE
, ("nnpfs_free_node done\n"));
286 * FreeBSD 4.4 and newer changed to API to vflush around June 2001
287 * FreeBSD 5.2-CURRENT and newer changed to API to vflush
291 nnpfs_vflush(struct mount
*mp
, int flags
, d_thread_t
*td
)
293 #if defined(__FreeBSD__) && __FreeBSD_version > 502123
294 return vflush(mp
, 0, flags
, td
);
295 #elif (__FreeBSD__ && __FreeBSD_version > 430000) || __DragonFly__
296 return vflush(mp
, 0, flags
);
298 return vflush(mp
, NULL
, flags
);
303 nnpfs_free_all_nodes(struct nnpfs
*nnpfsp
, int flags
, int unmountp
)
306 struct mount
*mp
= NNPFS_TO_VFS(nnpfsp
);
309 NNPFSDEB(XDEBNODE
, ("nnpfs_free_all_nodes already freed\n"));
313 NNPFSDEB(XDEBNODE
, ("nnpfs_free_all_nodes starting\n"));
315 nnpfs_dnlc_purge_mp(mp
);
318 struct nnpfs_node
*root
= nnpfsp
->root
;
319 NNPFSDEB(XDEBNODE
, ("nnpfs_free_all_nodes now removing root\n"));
323 vgone(XNODE_TO_VNODE(root
));
325 nnpfs_vletgo(XNODE_TO_VNODE(root
)); /* XXX ? */
329 NNPFSDEB(XDEBNODE
, ("nnpfs_free_all_nodes root removed\n"));
330 NNPFSDEB(XDEBNODE
, ("nnpfs_free_all_nodes now killing all remaining nodes\n"));
333 * If we have a syncer vnode, release it (to emulate dounmount)
334 * and the create it again when if we are going to need it.
337 #ifdef HAVE_STRUCT_MOUNT_MNT_SYNCER
339 if (mp
->mnt_syncer
!= NULL
) {
340 #ifdef HAVE_KERNEL_VFS_DEALLOCATE_SYNCVNODE
341 vfs_deallocate_syncvnode(mp
);
344 * FreeBSD and OpenBSD uses different semantics,
345 * FreeBSD does vrele, and OpenBSD does vgone.
347 #if defined(__OpenBSD__)
348 vgone(mp
->mnt_syncer
);
349 #elif defined(__FreeBSD__) || defined(__DragonFly__)
350 vrele(mp
->mnt_syncer
);
352 #error what os do you use ?
354 mp
->mnt_syncer
= NULL
;
360 error
= nnpfs_vflush(mp
, flags
, nnpfsp
->proc
);
361 #ifdef HAVE_STRUCT_MOUNT_MNT_SYNCER
363 NNPFSDEB(XDEBNODE
, ("nnpfs_free_all_nodes not flushing syncer vnode\n"));
364 if (mp
->mnt_syncer
== NULL
)
365 if (vfs_allocate_syncvnode(mp
))
366 panic("failed to allocate syncer node when nnpfs daemon died");
371 NNPFSDEB(XDEBNODE
, ("nnpfs_free_all_nodes: vflush() error == %d\n",
376 NNPFSDEB(XDEBNODE
, ("nnpfs_free_all_nodes done\n"));
381 #define LIST_FOREACH(var, head, field) \
382 for ((var) = ((head)->lh_first); \
384 (var) = ((var)->field.le_next))
389 vattr2nnpfs_attr(const struct nnpfs_vfs_vattr
*va
, struct nnpfs_attr
*xa
)
391 /* XXX macos bitmask handling */
392 bzero(xa
, sizeof(*xa
));
393 if (VATTR_IS_ACTIVE(va
, va_mode
))
394 XA_SET_MODE(xa
, va
->va_mode
);
395 if (VATTR_IS_ACTIVE(va
, va_nlink
))
396 XA_SET_NLINK(xa
, va
->va_nlink
);
397 if (VATTR_IS_ACTIVE(va
, va_data_size
))
398 XA_SET_SIZE(xa
, nnpfs_vattr_get_size(va
));
399 if (VATTR_IS_ACTIVE(va
, va_uid
))
400 XA_SET_UID(xa
, va
->va_uid
);
401 if (VATTR_IS_ACTIVE(va
, va_gid
))
402 XA_SET_GID(xa
, va
->va_gid
);
403 if (VATTR_IS_ACTIVE(va
, va_access_time
))
404 XA_SET_ATIME(xa
, nnpfs_vattr_get_atime_sec(va
));
405 if (VATTR_IS_ACTIVE(va
, va_modify_time
))
406 XA_SET_MTIME(xa
, nnpfs_vattr_get_mtime_sec(va
));
407 if (VATTR_IS_ACTIVE(va
, va_create_time
))
408 XA_SET_CTIME(xa
, nnpfs_vattr_get_ctime_sec(va
));
409 if (VATTR_IS_ACTIVE(va
, va_fileid
))
410 XA_SET_FILEID(xa
, va
->va_fileid
);
412 if (VATTR_IS_ACTIVE(va
, va_type
)) {
413 switch (va
->va_type
) {
415 xa
->xa_type
= NNPFS_FILE_NON
;
418 xa
->xa_type
= NNPFS_FILE_REG
;
421 xa
->xa_type
= NNPFS_FILE_DIR
;
424 xa
->xa_type
= NNPFS_FILE_BLK
;
427 xa
->xa_type
= NNPFS_FILE_CHR
;
430 xa
->xa_type
= NNPFS_FILE_LNK
;
433 xa
->xa_type
= NNPFS_FILE_SOCK
;
436 xa
->xa_type
= NNPFS_FILE_FIFO
;
439 xa
->xa_type
= NNPFS_FILE_BAD
;
442 panic("vattr2nnpfs_attr: bad value");
450 vattr2nnpfs_attr(const struct nnpfs_vfs_vattr
*va
, struct nnpfs_attr
*xa
)
452 bzero(xa
, sizeof(*xa
));
453 if (va
->va_mode
!= (mode_t
)VNOVAL
)
454 XA_SET_MODE(xa
, va
->va_mode
);
455 if (va
->va_nlink
!= VNOVAL
)
456 XA_SET_NLINK(xa
, va
->va_nlink
);
457 if (nnpfs_vattr_get_size(va
) != VNOVAL
)
458 XA_SET_SIZE(xa
, nnpfs_vattr_get_size(va
));
459 if (va
->va_uid
!= VNOVAL
)
460 XA_SET_UID(xa
, va
->va_uid
);
461 if (va
->va_gid
!= VNOVAL
)
462 XA_SET_GID(xa
, va
->va_gid
);
463 if (nnpfs_vattr_get_atime_sec(va
) != VNOVAL
)
464 XA_SET_ATIME(xa
, nnpfs_vattr_get_atime_sec(va
));
465 if (nnpfs_vattr_get_mtime_sec(va
) != VNOVAL
)
466 XA_SET_MTIME(xa
, nnpfs_vattr_get_mtime_sec(va
));
467 if (nnpfs_vattr_get_ctime_sec(va
) != VNOVAL
)
468 XA_SET_CTIME(xa
, nnpfs_vattr_get_ctime_sec(va
));
469 if (va
->va_fileid
!= VNOVAL
)
470 XA_SET_FILEID(xa
, va
->va_fileid
);
472 switch (va
->va_type
) {
474 xa
->xa_type
= NNPFS_FILE_NON
;
477 xa
->xa_type
= NNPFS_FILE_REG
;
480 xa
->xa_type
= NNPFS_FILE_DIR
;
483 xa
->xa_type
= NNPFS_FILE_BLK
;
486 xa
->xa_type
= NNPFS_FILE_CHR
;
489 xa
->xa_type
= NNPFS_FILE_LNK
;
492 xa
->xa_type
= NNPFS_FILE_SOCK
;
495 xa
->xa_type
= NNPFS_FILE_FIFO
;
498 xa
->xa_type
= NNPFS_FILE_BAD
;
501 panic("vattr2nnpfs_attr: bad value");
507 * Take care of updating the node's size
511 nnpfs_setsize(struct nnpfs_node
*xn
, uint64_t size
)
513 struct vnode
*vp
= XNODE_TO_VNODE(xn
);
514 nnpfs_block_truncate(xn
, size
);
515 nnpfs_set_vp_size(vp
, size
);
519 nnpfs_store_attr(const struct nnpfs_attr
*xa
, struct nnpfs_node
*node
, int clear_node
)
521 struct nnpfs_vfs_vattr
*va
= &node
->attr
;
523 /* XXX proper macos bitmask handling */
531 if (XA_VALID_MODE(xa
))
532 nnpfs_vattr_set(va
, va_mode
, xa
->xa_mode
);
533 if (XA_VALID_NLINK(xa
))
534 nnpfs_vattr_set(va
, va_nlink
, xa
->xa_nlink
);
535 if (XA_VALID_SIZE(xa
)) {
536 nnpfs_vattr_set_size(va
, xa
->xa_size
);
537 nnpfs_vattr_set_bytes(va
, xa
->xa_size
);
538 node
->daemon_length
= xa
->xa_size
;
540 if (XA_VALID_UID(xa
))
541 nnpfs_vattr_set(va
, va_uid
, xa
->xa_uid
);
542 if (XA_VALID_GID(xa
))
543 nnpfs_vattr_set(va
, va_gid
, xa
->xa_gid
);
544 if (XA_VALID_ATIME(xa
)) {
545 nnpfs_vattr_set_atime(va
, xa
->xa_atime
, 0);
547 if (XA_VALID_MTIME(xa
)) {
548 nnpfs_vattr_set_mtime(va
, xa
->xa_mtime
, 0);
550 if (XA_VALID_CTIME(xa
)) {
551 nnpfs_vattr_set_ctime(va
, xa
->xa_ctime
, 0);
553 if (XA_VALID_FILEID(xa
)) {
554 nnpfs_vattr_set(va
, va_fileid
, xa
->xa_fileid
);
556 if (XA_VALID_TYPE(xa
)) {
557 switch (xa
->xa_type
) {
559 nnpfs_vattr_set(va
, va_type
, VNON
);
562 nnpfs_vattr_set(va
, va_type
, VREG
);
565 nnpfs_vattr_set(va
, va_type
, VDIR
);
568 nnpfs_vattr_set(va
, va_type
, VBLK
);
571 nnpfs_vattr_set(va
, va_type
, VCHR
);
574 nnpfs_vattr_set(va
, va_type
, VLNK
);
576 case NNPFS_FILE_SOCK
:
577 nnpfs_vattr_set(va
, va_type
, VSOCK
);
579 case NNPFS_FILE_FIFO
:
580 nnpfs_vattr_set(va
, va_type
, VFIFO
);
583 nnpfs_vattr_set(va
, va_type
, VBAD
);
586 panic("nnpfs_attr2vattr: bad value");
589 nnpfs_vattr_set(va
, va_flags
, 0);
592 VATTR_RETURN(va
, va_iosize
, 8192);
593 va
->va_active
= va
->va_supported
;
595 nnpfs_vattr_set(va
, va_blocksize
, 8192);
600 * A single entry DNLC for systems for handling long names that don't
601 * get put into the system DNLC.
605 struct vnode
*dvp
, *vp
;
606 char name
[MAXNAMLEN
+ 1];
608 #ifdef HAVE_STRUCT_VNODE_V_ID
613 static struct long_entry tbl
;
622 tbl
.dvp
= tbl
.vp
= NULL
;
625 #ifdef HAVE_STRUCT_VNODE_V_ID
626 tbl
.dvpid
= tbl
.vpid
= 0;
631 * Set the entry in the `tbl'
635 tbl_enter (size_t len
, const char *name
, struct vnode
*dvp
, struct vnode
*vp
)
638 bcopy(name
, tbl
.name
, len
);
641 #ifdef HAVE_STRUCT_VNODE_V_ID
642 tbl
.dvpid
= dvp
->v_id
;
648 * Lookup in tbl (`dvp', `name', `len') and return result in `res'.
649 * Return -1 if succesful, otherwise 0.
653 tbl_lookup (struct componentname
*cnp
,
658 #ifdef HAVE_STRUCT_VNODE_V_ID
659 && tbl
.dvpid
== tbl
.dvp
->v_id
660 && tbl
.vpid
== tbl
.vp
->v_id
662 && tbl
.len
== cnp
->cn_namelen
663 && strncmp(tbl
.name
, cnp
->cn_nameptr
, tbl
.len
) == 0) {
668 /* darwin's cache_lookup gives us ref:ed nodes, imitate */
669 nnpfs_do_vget(*res
, 0, NULL
);
678 * Store a componentname in the DNLC
682 nnpfs_dnlc_enter(struct vnode
*dvp
,
683 nnpfs_componentname
*cnp
,
686 NNPFSDEB(XDEBDNLC
, ("nnpfs_dnlc_enter_cnp(%lx, %lx, %lx)\n",
690 #ifdef HAVE_STRUCT_VNODE_V_ID
691 NNPFSDEB(XDEBDNLC
, ("nnpfs_dnlc_enter: v_id = %lu\n", (u_long
)dvp
->v_id
));
694 NNPFSDEB(XDEBDNLC
, ("nnpfs_dnlc_enter: calling cache_enter:"
695 "dvp = %lx, vp = %lx, cnp = (%s, %ld), "
696 "nameiop = %lu, flags = %lx\n",
699 cnp
->cn_nameptr
, cnp
->cn_namelen
,
700 cnp
->cn_nameiop
, cnp
->cn_flags
));
703 if (cnp
->cn_namelen
<= NCHNAMLEN
)
707 * This is to make sure there's no negative entry already in the dnlc
713 save_nameiop
= cnp
->cn_nameiop
;
714 save_flags
= cnp
->cn_flags
;
715 cnp
->cn_nameiop
= CREATE
;
716 cnp
->cn_flags
&= ~MAKEENTRY
;
719 * The version number here is not entirely correct, but it's conservative.
720 * The real change is sys/kern/vfs_cache:1.20
723 #if __NetBSD_Version__ >= 104120000 || OpenBSD > 200211
724 if (cache_lookup(dvp
, &dummy
, cnp
) != -1) {
725 nnpfs_vfs_unlock(dummy
, nnpfs_cnp_to_proc(cnp
));
726 printf ("NNPFS PANIC WARNING! nnpfs_dnlc_enter: %s already in cache\n",
729 #elif defined(__DragonFly__)
730 if (cache_lookup(dvp
, NCPNULL
, &dummy
, NCPPNULL
, cnp
) != 0) {
731 printf ("NNPFS PANIC WARNING! nnpfs_dnlc_enter: %s already in cache\n",
734 #elif !defined(__APPLE__)
735 if (cache_lookup(dvp
, &dummy
, cnp
) != 0) {
736 printf ("NNPFS PANIC WARNING! nnpfs_dnlc_enter: %s already in cache\n",
742 cnp
->cn_nameiop
= save_nameiop
;
743 cnp
->cn_flags
= save_flags
;
745 cache_enter(dvp
, NCPNULL
, vp
, cnp
);
747 cache_enter(dvp
, vp
, cnp
);
752 tbl_enter (cnp
->cn_namelen
, cnp
->cn_nameptr
, dvp
, vp
);
759 nnpfs_cnp_init (struct componentname
*cn
,
761 d_thread_t
*proc
, nnpfs_kernel_cred cred
,
764 bzero(cn
, sizeof(*cn
));
765 cn
->cn_nameptr
= (char *)name
;
766 cn
->cn_namelen
= strlen(name
);
769 cn
->cn_hash
= 0; /* Let the vfs compute the hash */
770 #elif defined(HAVE_KERNEL_NAMEI_HASH)
772 const char *cp
= name
+ cn
->cn_namelen
;
773 cn
->cn_hash
= namei_hash(name
, &cp
);
775 #elif defined(HAVE_STRUCT_COMPONENTNAME_CN_HASH)
777 const unsigned char *p
;
780 for (p
= cn
->cn_nameptr
; *p
; ++p
)
784 cn
->cn_nameiop
= nameiop
;
785 #if defined(__APPLE__)
786 /* apple have not proc */
787 #elif defined(__DragonFly__)
789 #elif defined(HAVE_FREEBSD_THREAD)
790 cn
->cn_thread
= proc
;
792 #if defined(__NetBSD__) && __NetBSD_Version__ >= 399001400 /* 3.99.14 */
799 #if !defined(__APPLE__)
806 * Store (dvp, name, vp) in the DNLC
810 nnpfs_dnlc_enter_name(struct vnode
*dvp
,
814 struct componentname cn
;
816 NNPFSDEB(XDEBDNLC
, ("nnpfs_dnlc_enter_name(%lx, \"%s\", %lx)\n",
821 nnpfs_cnp_init (&cn
, name
, NULL
, NULL
, LOOKUP
);
822 return nnpfs_dnlc_enter (dvp
, &cn
, vp
);
826 * Lookup (dvp, cnp) in the DNLC and return the result in `res'.
827 * Return the result from cache_lookup.
831 nnpfs_dnlc_lookup_int(struct vnode
*dvp
,
832 nnpfs_componentname
*cnp
,
838 NNPFSDEB(XDEBDNLC
, ("nnpfs_dnlc_lookup(%lx, \"%s\")\n",
839 (unsigned long)dvp
, cnp
->cn_nameptr
));
841 #ifdef HAVE_STRUCT_VNODE_V_ID
842 NNPFSDEB(XDEBDNLC
, ("nnpfs_dnlc_lookup: v_id = %lu\n", (u_long
)dvp
->v_id
));
845 NNPFSDEB(XDEBDNLC
, ("nnpfs_dnlc_lookup: calling cache_lookup:"
846 "dvp = %lx, cnp = (%s, %ld), flags = %lx\n",
848 cnp
->cn_nameptr
, cnp
->cn_namelen
,
851 saved_flags
= cnp
->cn_flags
;
852 cnp
->cn_flags
|= MAKEENTRY
| LOCKPARENT
| ISLASTCN
;
855 error
= cache_lookup(dvp
, NCPNULL
, res
, NCPPNULL
, cnp
);
857 error
= cache_lookup(dvp
, res
, cnp
);
860 cnp
->cn_flags
= saved_flags
;
862 NNPFSDEB(XDEBDNLC
, ("nnpfs_dnlc_lookup: cache_lookup returned. "
863 "error = %d, *res = %lx\n", error
,
864 (unsigned long)*res
));
869 * do the last (and locking protocol) portion of xnlc_lookup
877 nnpfs_dnlc_lock(struct vnode
*dvp
,
878 nnpfs_componentname
*cnp
,
884 * Try to handle the (complex) BSD locking protocol.
887 if (*res
== dvp
) { /* "." */
889 } else if (cnp
->cn_flags
& ISDOTDOT
) { /* ".." */
890 #ifdef HAVE_STRUCT_VNODE_V_ID
891 u_long vpid
= dvp
->v_id
;
894 nnpfs_vfs_unlock(dvp
, nnpfs_cnp_to_proc(cnp
));
896 error
= nnpfs_do_vget(*res
, LK_EXCLUSIVE
, nnpfs_cnp_to_proc(cnp
));
897 nnpfs_vfs_writelock(dvp
, nnpfs_cnp_to_proc(cnp
));
900 #ifdef HAVE_STRUCT_VNODE_V_ID
901 if (error
== 0 && dvp
->v_id
!= vpid
) {
908 error
= nnpfs_do_vget(*res
, LK_EXCLUSIVE
, nnpfs_cnp_to_proc(cnp
));
919 * Lookup (`dvp', `cnp') in the DNLC (and the local cache).
921 * Return -1 if succesful, 0 if not and ENOENT if the entry is known
924 * On modern NetBSD, cache_lookup has been changed to return 0 for
925 * succesful and -1 for not.
926 * (see the comment above for version information).
929 #if __NetBSD_Version__ >= 104120000 || OpenBSD > 200211
932 nnpfs_dnlc_lookup(struct vnode
*dvp
,
933 nnpfs_componentname
*cnp
,
936 int error
= nnpfs_dnlc_lookup_int (dvp
, cnp
, res
);
940 else if (error
== ENOENT
)
943 error
= tbl_lookup (cnp
, dvp
, res
);
948 return nnpfs_dnlc_lock (dvp
, cnp
, res
);
951 #else /* ! __NetBSD_Version__ >= 104120000 && ! OpenBSD > 200211 */
954 nnpfs_dnlc_lookup(struct vnode
*dvp
,
955 nnpfs_componentname
*cnp
,
958 int error
= nnpfs_dnlc_lookup_int (dvp
, cnp
, res
);
961 error
= tbl_lookup (cnp
, dvp
, res
);
966 return nnpfs_dnlc_lock (dvp
, cnp
, res
);
969 #endif /* __NetBSD_Version__ >= 104120000 || OpenBSD > 200211 */
972 * Remove one entry from the DNLC
976 nnpfs_dnlc_purge (struct vnode
*vp
)
978 NNPFSDEB(XDEBDNLC
, ("nnpfs_dnlc_purge\n"));
980 if (tbl
.dvp
== vp
|| tbl
.vp
== vp
)
987 * Remove all entries belong to `mp' from the DNLC
991 nnpfs_dnlc_purge_mp(struct mount
*mp
)
993 NNPFSDEB(XDEBDNLC
, ("nnpfs_dnlc_purge_mp()\n"));
1002 * Returns 1 if pag has any rights set in the node
1006 nnpfs_has_pag(const struct nnpfs_node
*xn
, nnpfs_pag_t pag
)
1010 for (i
= 0; i
< NNPFS_MAXRIGHTS
; i
++)
1011 if (xn
->id
[i
] == pag
)
1018 nnpfs_setcred(nnpfs_cred
*ncred
, nnpfs_kernel_cred cred
)
1020 if (cred
== NOCRED
) {
1022 ncred
->pag
= NNPFS_ANONYMOUSID
;
1024 ncred
->uid
= nnpfs_cred_get_uid(cred
);
1025 ncred
->pag
= nnpfs_get_pag(cred
);