(nnpfs_new_node): try not to mess up attrs if node already is in cache
[arla.git] / nnpfs / bsd / nnpfs_node-bsd.c
blobedb77b77dc38b4386a85602e168696dbad3deefc
1 /*
2 * Copyright (c) 1995 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
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>
42 RCSID("$Id$");
44 extern vop_t **nnpfs_vnodeop_p;
46 #ifndef LK_NOPAUSE
47 #define LK_NOPAUSE 0
48 #endif
51 * Allocate a new vnode with handle `handle' in `mp' and return it in
52 * `vpp'. Return 0 or error.
55 int
56 nnpfs_getnewvnode(struct nnpfs *nnpfsp,
57 struct vnode **vpp,
58 struct nnpfs_handle *handle,
59 struct nnpfs_msg_node *node,
60 d_thread_t *p,
61 int isrootp)
63 struct nnpfs_node *result, *check;
64 int error;
66 result = nnpfs_alloc(sizeof(*result), M_NNPFS_NODE);
67 bzero(result, sizeof(*result));
69 #ifdef __APPLE__
71 struct vnode_fsparam p;
73 if (!XA_VALID_TYPE(&node->attr)) {
74 nnpfs_free(result, sizeof(*result), M_NNPFS_NODE);
75 return EINVAL;
78 memset(&p, 0, sizeof(p));
79 p.vnfs_mp = NNPFS_TO_VFS(nnpfsp);
80 switch (node->attr.xa_type) {
81 case NNPFS_FILE_NON:
82 p.vnfs_vtype = VNON;
83 break;
84 case NNPFS_FILE_REG:
85 p.vnfs_vtype = VREG;
86 break;
87 case NNPFS_FILE_DIR:
88 p.vnfs_vtype = VDIR;
89 break;
90 case NNPFS_FILE_BLK:
91 p.vnfs_vtype = VBLK;
92 break;
93 case NNPFS_FILE_CHR:
94 p.vnfs_vtype = VCHR;
95 break;
96 case NNPFS_FILE_LNK:
97 p.vnfs_vtype = VLNK;
98 break;
99 case NNPFS_FILE_SOCK:
100 p.vnfs_vtype = VSOCK;
101 break;
102 case NNPFS_FILE_FIFO:
103 p.vnfs_vtype = VFIFO;
104 break;
105 case NNPFS_FILE_BAD:
106 p.vnfs_vtype = VBAD;
107 break;
108 default:
109 printf("nnpfs_getnewnvode: bad value");
110 nnpfs_free(result, sizeof(*result), M_NNPFS_NODE);
111 return EINVAL;
113 p.vnfs_str = "arla";
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;
119 p.vnfs_rdev = 0;
120 if (XA_VALID_SIZE(&node->attr))
121 p.vnfs_filesize = node->attr.xa_size;
122 else
123 p.vnfs_filesize = 0;
124 p.vnfs_cnp = NULL;
125 p.vnfs_flags = 0; /* XXX VNFS_CANTCACHE? */
127 error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &p, vpp);
129 #else
130 error = getnewvnode(VT_AFS, NNPFS_TO_VFS(nnpfsp), nnpfs_vnodeop_p, vpp);
131 if (error == 0)
132 (*vpp)->v_data = result;
133 #endif
134 if (error)
135 return error;
137 result->vn = *vpp;
139 result->handle = *handle;
140 result->flags = 0;
141 result->tokens = 0;
143 #if (defined(HAVE_KERNEL_LOCKMGR) || defined(HAVE_KERNEL_DEBUGLOCKMGR)) && !defined(__APPLE__)
144 lockinit (&result->lock, PVFS, "nnpfs_lock", 0, LK_NOPAUSE);
145 #else
146 result->vnlocks = 0;
147 #endif
149 #ifdef __APPLE__
150 result->writers = 0;
151 #endif
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);
159 #endif
161 retry:
162 error = nnpfs_node_find(nnpfsp, handle, &check);
163 if (error == ENOENT) {
164 nnpfs_insert(&nnpfsp->nodehead, result);
165 return 0;
168 if (nnpfs_do_vget(XNODE_TO_VNODE(check), 0, p))
169 goto retry;
171 nnpfs_vput(*vpp);
172 *vpp = NULL;
174 if (error == EISDIR) {
175 nnpfs_vletgo(XNODE_TO_VNODE(check));
176 return EEXIST;
179 *vpp = check->vn;
181 return 0;
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,
194 char *name,
195 struct nnpfs_node **xpp,
196 d_thread_t *p,
197 int isrootp)
199 struct nnpfs_node *result;
200 int error;
202 NNPFSDEB(XDEBNODE, ("nnpfs_new_node (%d,%d,%d,%d)\n",
203 node->handle.a,
204 node->handle.b,
205 node->handle.c,
206 node->handle.d));
208 retry:
209 /* Does not allow duplicates */
210 error = nnpfs_node_find(nnpfsp, &node->handle, &result);
211 if (error == ENOENT) {
212 struct vnode *v;
214 error = nnpfs_getnewvnode(nnpfsp, &v, &node->handle, node, p, isrootp);
215 if (error)
216 return error;
218 result = VNODE_TO_XNODE(v);
219 result->anonrights = node->anonrights;
220 nnpfs_store_attr(&node->attr, result, 1);
222 #ifndef __APPLE__
223 result->vn->v_type = result->attr.va_type;
224 if (isrootp)
225 NNPFS_MAKE_VROOT(result->vn);
226 #endif
227 } else if (error == EISDIR) {
228 /* node is about to be deleted */
229 NNPFSDEB(XDEBNODE, ("nnpfs_new_node: node deleted\n"));
230 return error;
231 } else {
232 /* Node is already cached */
233 if (nnpfs_do_vget(XNODE_TO_VNODE(result), 0, p))
234 goto retry;
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));
252 *xpp = result;
253 NNPFSDEB(XDEBNODE, ("return: nnpfs_new_node\n"));
254 return 0;
258 * free node.
260 * this should always be called with dev lock held
262 void
263 nnpfs_free_node(struct nnpfs *nnpfsp, struct nnpfs_node *node)
265 NNPFSDEB(XDEBNODE, ("nnpfs_free_node(%lx) (%d,%d,%d,%d)\n",
266 (unsigned long)node,
267 node->handle.a,
268 node->handle.b,
269 node->handle.c,
270 node->handle.d));
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
290 static int
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);
297 #else
298 return vflush(mp, NULL, flags);
299 #endif
303 nnpfs_free_all_nodes(struct nnpfs *nnpfsp, int flags, int unmountp)
305 int error = 0;
306 struct mount *mp = NNPFS_TO_VFS(nnpfsp);
308 if (mp == NULL) {
309 NNPFSDEB(XDEBNODE, ("nnpfs_free_all_nodes already freed\n"));
310 return 0;
313 NNPFSDEB(XDEBNODE, ("nnpfs_free_all_nodes starting\n"));
315 nnpfs_dnlc_purge_mp(mp);
317 if (nnpfsp->root) {
318 struct nnpfs_node *root = nnpfsp->root;
319 NNPFSDEB(XDEBNODE, ("nnpfs_free_all_nodes now removing root\n"));
321 nnpfsp->root = NULL;
322 #if 0
323 vgone(XNODE_TO_VNODE(root));
324 #else
325 nnpfs_vletgo(XNODE_TO_VNODE(root)); /* XXX ? */
326 #endif
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
338 if (!unmountp) {
339 if (mp->mnt_syncer != NULL) {
340 #ifdef HAVE_KERNEL_VFS_DEALLOCATE_SYNCVNODE
341 vfs_deallocate_syncvnode(mp);
342 #else
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);
351 #else
352 #error what os do you use ?
353 #endif
354 mp->mnt_syncer = NULL;
355 #endif
358 #endif
360 error = nnpfs_vflush(mp, flags, nnpfsp->proc);
361 #ifdef HAVE_STRUCT_MOUNT_MNT_SYNCER
362 if (!unmountp) {
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");
368 #endif
370 if (error) {
371 NNPFSDEB(XDEBNODE, ("nnpfs_free_all_nodes: vflush() error == %d\n",
372 error));
373 return error;
376 NNPFSDEB(XDEBNODE, ("nnpfs_free_all_nodes done\n"));
377 return error;
380 #ifndef LIST_FOREACH
381 #define LIST_FOREACH(var, head, field) \
382 for ((var) = ((head)->lh_first); \
383 (var); \
384 (var) = ((var)->field.le_next))
385 #endif
387 #ifdef __APPLE__
388 void
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) {
414 case VNON:
415 xa->xa_type = NNPFS_FILE_NON;
416 break;
417 case VREG:
418 xa->xa_type = NNPFS_FILE_REG;
419 break;
420 case VDIR:
421 xa->xa_type = NNPFS_FILE_DIR;
422 break;
423 case VBLK:
424 xa->xa_type = NNPFS_FILE_BLK;
425 break;
426 case VCHR:
427 xa->xa_type = NNPFS_FILE_CHR;
428 break;
429 case VLNK:
430 xa->xa_type = NNPFS_FILE_LNK;
431 break;
432 case VSOCK:
433 xa->xa_type = NNPFS_FILE_SOCK;
434 break;
435 case VFIFO:
436 xa->xa_type = NNPFS_FILE_FIFO;
437 break;
438 case VBAD:
439 xa->xa_type = NNPFS_FILE_BAD;
440 break;
441 default:
442 panic("vattr2nnpfs_attr: bad value");
447 #else
449 void
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) {
473 case VNON:
474 xa->xa_type = NNPFS_FILE_NON;
475 break;
476 case VREG:
477 xa->xa_type = NNPFS_FILE_REG;
478 break;
479 case VDIR:
480 xa->xa_type = NNPFS_FILE_DIR;
481 break;
482 case VBLK:
483 xa->xa_type = NNPFS_FILE_BLK;
484 break;
485 case VCHR:
486 xa->xa_type = NNPFS_FILE_CHR;
487 break;
488 case VLNK:
489 xa->xa_type = NNPFS_FILE_LNK;
490 break;
491 case VSOCK:
492 xa->xa_type = NNPFS_FILE_SOCK;
493 break;
494 case VFIFO:
495 xa->xa_type = NNPFS_FILE_FIFO;
496 break;
497 case VBAD:
498 xa->xa_type = NNPFS_FILE_BAD;
499 break;
500 default:
501 panic("vattr2nnpfs_attr: bad value");
504 #endif
507 * Take care of updating the node's size
510 void
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);
518 void
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 */
524 if (clear_node) {
525 #ifdef __APPLE__
526 VATTR_INIT(va);
527 #else
528 VATTR_NULL(va);
529 #endif
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) {
558 case NNPFS_FILE_NON:
559 nnpfs_vattr_set(va, va_type, VNON);
560 break;
561 case NNPFS_FILE_REG:
562 nnpfs_vattr_set(va, va_type, VREG);
563 break;
564 case NNPFS_FILE_DIR:
565 nnpfs_vattr_set(va, va_type, VDIR);
566 break;
567 case NNPFS_FILE_BLK:
568 nnpfs_vattr_set(va, va_type, VBLK);
569 break;
570 case NNPFS_FILE_CHR:
571 nnpfs_vattr_set(va, va_type, VCHR);
572 break;
573 case NNPFS_FILE_LNK:
574 nnpfs_vattr_set(va, va_type, VLNK);
575 break;
576 case NNPFS_FILE_SOCK:
577 nnpfs_vattr_set(va, va_type, VSOCK);
578 break;
579 case NNPFS_FILE_FIFO:
580 nnpfs_vattr_set(va, va_type, VFIFO);
581 break;
582 case NNPFS_FILE_BAD:
583 nnpfs_vattr_set(va, va_type, VBAD);
584 break;
585 default:
586 panic("nnpfs_attr2vattr: bad value");
589 nnpfs_vattr_set(va, va_flags, 0);
591 #ifdef __APPLE__
592 VATTR_RETURN(va, va_iosize, 8192);
593 va->va_active = va->va_supported;
594 #else
595 nnpfs_vattr_set(va, va_blocksize, 8192);
596 #endif
600 * A single entry DNLC for systems for handling long names that don't
601 * get put into the system DNLC.
604 struct long_entry {
605 struct vnode *dvp, *vp;
606 char name[MAXNAMLEN + 1];
607 size_t len;
608 #ifdef HAVE_STRUCT_VNODE_V_ID
609 u_long dvpid, vpid;
610 #endif
613 static struct long_entry tbl;
616 * Nuke the `tbl'
619 static void
620 tbl_clear (void)
622 tbl.dvp = tbl.vp = NULL;
623 tbl.name[0] = '\0';
624 tbl.len = 0;
625 #ifdef HAVE_STRUCT_VNODE_V_ID
626 tbl.dvpid = tbl.vpid = 0;
627 #endif
631 * Set the entry in the `tbl'
634 static void
635 tbl_enter (size_t len, const char *name, struct vnode *dvp, struct vnode *vp)
637 tbl.len = len;
638 bcopy(name, tbl.name, len);
639 tbl.dvp = dvp;
640 tbl.vp = vp;
641 #ifdef HAVE_STRUCT_VNODE_V_ID
642 tbl.dvpid = dvp->v_id;
643 tbl.vpid = vp->v_id;
644 #endif
648 * Lookup in tbl (`dvp', `name', `len') and return result in `res'.
649 * Return -1 if succesful, otherwise 0.
652 static int
653 tbl_lookup (struct componentname *cnp,
654 struct vnode *dvp,
655 struct vnode **res)
657 if (tbl.dvp == dvp
658 #ifdef HAVE_STRUCT_VNODE_V_ID
659 && tbl.dvpid == tbl.dvp->v_id
660 && tbl.vpid == tbl.vp->v_id
661 #endif
662 && tbl.len == cnp->cn_namelen
663 && strncmp(tbl.name, cnp->cn_nameptr, tbl.len) == 0) {
665 *res = tbl.vp;
667 #ifdef __APPLE__
668 /* darwin's cache_lookup gives us ref:ed nodes, imitate */
669 nnpfs_do_vget(*res, 0, NULL);
670 #endif
672 return -1;
673 } else
674 return 0;
678 * Store a componentname in the DNLC
682 nnpfs_dnlc_enter(struct vnode *dvp,
683 nnpfs_componentname *cnp,
684 struct vnode *vp)
686 NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_enter_cnp(%lx, %lx, %lx)\n",
687 (unsigned long)dvp,
688 (unsigned long)cnp,
689 (unsigned long)vp));
690 #ifdef HAVE_STRUCT_VNODE_V_ID
691 NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_enter: v_id = %lu\n", (u_long)dvp->v_id));
692 #endif
694 NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_enter: calling cache_enter:"
695 "dvp = %lx, vp = %lx, cnp = (%s, %ld), "
696 "nameiop = %lu, flags = %lx\n",
697 (unsigned long)dvp,
698 (unsigned long)vp,
699 cnp->cn_nameptr, cnp->cn_namelen,
700 cnp->cn_nameiop, cnp->cn_flags));
702 #ifdef NCHNAMLEN
703 if (cnp->cn_namelen <= NCHNAMLEN)
704 #endif
707 * This is to make sure there's no negative entry already in the dnlc
709 u_long save_nameiop;
710 u_long save_flags;
711 struct vnode *dummy;
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",
727 cnp->cn_nameptr);
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",
732 cnp->cn_nameptr);
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",
737 cnp->cn_nameptr);
739 #endif
742 cnp->cn_nameiop = save_nameiop;
743 cnp->cn_flags = save_flags;
744 #ifdef __DragonFly__
745 cache_enter(dvp, NCPNULL, vp, cnp);
746 #else
747 cache_enter(dvp, vp, cnp);
748 #endif
751 if (vp != NULL)
752 tbl_enter (cnp->cn_namelen, cnp->cn_nameptr, dvp, vp);
754 return 0;
758 static void
759 nnpfs_cnp_init (struct componentname *cn,
760 char *name,
761 d_thread_t *proc, nnpfs_kernel_cred cred,
762 int nameiop)
764 bzero(cn, sizeof(*cn));
765 cn->cn_nameptr = (char *)name;
766 cn->cn_namelen = strlen(name);
767 cn->cn_flags = 0;
768 #if __APPLE__
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;
779 cn->cn_hash = 0;
780 for (p = cn->cn_nameptr; *p; ++p)
781 cn->cn_hash += *p;
783 #endif
784 cn->cn_nameiop = nameiop;
785 #if defined(__APPLE__)
786 /* apple have not proc */
787 #elif defined(__DragonFly__)
788 cn->cn_td = proc;
789 #elif defined(HAVE_FREEBSD_THREAD)
790 cn->cn_thread = proc;
791 #else
792 #if defined(__NetBSD__) && __NetBSD_Version__ >= 399001400 /* 3.99.14 */
793 cn->cn_lwp = proc;
794 #else
795 cn->cn_proc = proc;
796 #endif
797 #endif
799 #if !defined(__APPLE__)
800 cn->cn_cred = cred;
801 #endif
806 * Store (dvp, name, vp) in the DNLC
810 nnpfs_dnlc_enter_name(struct vnode *dvp,
811 char *name,
812 struct vnode *vp)
814 struct componentname cn;
816 NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_enter_name(%lx, \"%s\", %lx)\n",
817 (unsigned long)dvp,
818 name,
819 (unsigned long)vp));
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.
830 static int
831 nnpfs_dnlc_lookup_int(struct vnode *dvp,
832 nnpfs_componentname *cnp,
833 struct vnode **res)
835 int error;
836 u_long saved_flags;
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));
843 #endif
845 NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_lookup: calling cache_lookup:"
846 "dvp = %lx, cnp = (%s, %ld), flags = %lx\n",
847 (unsigned long)dvp,
848 cnp->cn_nameptr, cnp->cn_namelen,
849 cnp->cn_flags));
851 saved_flags = cnp->cn_flags;
852 cnp->cn_flags |= MAKEENTRY | LOCKPARENT | ISLASTCN;
854 #ifdef __DragonFly__
855 error = cache_lookup(dvp, NCPNULL, res, NCPPNULL, cnp);
856 #else
857 error = cache_lookup(dvp, res, cnp);
858 #endif
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));
865 return error;
869 * do the last (and locking protocol) portion of xnlc_lookup
871 * return:
872 * -1 for succesful
873 * 0 for failed
876 static int
877 nnpfs_dnlc_lock(struct vnode *dvp,
878 nnpfs_componentname *cnp,
879 struct vnode **res)
881 int error = 0;
884 * Try to handle the (complex) BSD locking protocol.
887 if (*res == dvp) { /* "." */
888 nnpfs_vref(dvp);
889 } else if (cnp->cn_flags & ISDOTDOT) { /* ".." */
890 #ifdef HAVE_STRUCT_VNODE_V_ID
891 u_long vpid = dvp->v_id;
892 #endif
894 nnpfs_vfs_unlock(dvp, nnpfs_cnp_to_proc(cnp));
895 #ifndef __APPLE__
896 error = nnpfs_do_vget(*res, LK_EXCLUSIVE, nnpfs_cnp_to_proc(cnp));
897 nnpfs_vfs_writelock(dvp, nnpfs_cnp_to_proc(cnp));
898 #endif
900 #ifdef HAVE_STRUCT_VNODE_V_ID
901 if (error == 0 && dvp->v_id != vpid) {
902 vput(*res);
903 return 0;
905 #endif
906 } else {
907 #ifndef __APPLE__
908 error = nnpfs_do_vget(*res, LK_EXCLUSIVE, nnpfs_cnp_to_proc(cnp));
909 #endif
912 if (error == 0)
913 return -1;
914 else
915 return 0;
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
922 * not to exist.
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,
934 struct vnode **res)
936 int error = nnpfs_dnlc_lookup_int (dvp, cnp, res);
938 if (error == 0)
939 return -1;
940 else if (error == ENOENT)
941 return error;
943 error = tbl_lookup (cnp, dvp, res);
945 if (error != -1)
946 return error;
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,
956 struct vnode **res)
958 int error = nnpfs_dnlc_lookup_int (dvp, cnp, res);
960 if (error == 0)
961 error = tbl_lookup (cnp, dvp, res);
963 if (error != -1)
964 return error;
966 return nnpfs_dnlc_lock (dvp, cnp, res);
969 #endif /* __NetBSD_Version__ >= 104120000 || OpenBSD > 200211 */
972 * Remove one entry from the DNLC
975 void
976 nnpfs_dnlc_purge (struct vnode *vp)
978 NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_purge\n"));
980 if (tbl.dvp == vp || tbl.vp == vp)
981 tbl_clear ();
983 cache_purge(vp);
987 * Remove all entries belong to `mp' from the DNLC
990 void
991 nnpfs_dnlc_purge_mp(struct mount *mp)
993 NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_purge_mp()\n"));
995 tbl_clear ();
996 #ifndef __APPLE__
997 cache_purgevfs(mp);
998 #endif
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)
1008 int i;
1010 for (i = 0; i < NNPFS_MAXRIGHTS; i++)
1011 if (xn->id[i] == pag)
1012 return 1;
1014 return 0;
1017 void
1018 nnpfs_setcred(nnpfs_cred *ncred, nnpfs_kernel_cred cred)
1020 if (cred == NOCRED) {
1021 ncred->uid = 0;
1022 ncred->pag = NNPFS_ANONYMOUSID;
1023 } else {
1024 ncred->uid = nnpfs_cred_get_uid(cred);
1025 ncred->pag = nnpfs_get_pag(cred);