This source file includes following definitions.
- xfs_getnewvnode
- new_xfs_node
- free_xfs_node
- xfs_vflush
- free_all_xfs_nodes
- vattr2xfs_attr
- xfs_attr2vattr
- tbl_clear
- tbl_enter
- tbl_lookup
- xfs_dnlc_enter
- xfs_cnp_init
- xfs_dnlc_enter_name
- xfs_dnlc_lookup_int
- xfs_dnlc_lock
- xfs_dnlc_lookup
- xfs_dnlc_lookup
- xfs_dnlc_purge
- xfs_dnlc_purge_mp
- xfs_has_pag
- xfs_update_write_cred
- xfs_update_read_cred
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #include <sys/queue.h>
35 #include <xfs/xfs_locl.h>
36 #include <xfs/xfs_common.h>
37 #include <xfs/xfs_fs.h>
38 #include <xfs/xfs_deb.h>
39 #include <xfs/xfs_vnodeops.h>
40
41 RCSID("$arla: xfs_node-bsd.c,v 1.70 2003/02/28 02:01:06 lha Exp $");
42
43 extern vop_t **xfs_vnodeop_p;
44
45 #ifndef LK_NOPAUSE
46 #define LK_NOPAUSE 0
47 #endif
48
49
50
51
52
53
54 int
55 xfs_getnewvnode(struct xfs *xfsp, struct vnode **vpp,
56 struct xfs_handle *handle)
57 {
58 struct xfs_node *result, *check;
59 int error;
60
61 error = getnewvnode(VT_XFS, NNPFS_TO_VFS(xfsp), xfs_vnodeop_p, vpp);
62 if (error)
63 return error;
64
65 result = xfs_alloc(sizeof(*result), M_NNPFS_NODE);
66 bzero(result, sizeof(*result));
67
68 (*vpp)->v_data = result;
69 result->vn = *vpp;
70
71 result->handle = *handle;
72 result->flags = 0;
73 result->tokens = 0;
74 result->offset = 0;
75 #if defined(HAVE_KERNEL_LOCKMGR) || defined(HAVE_KERNEL_DEBUGLOCKMGR)
76 lockinit (&result->lock, PVFS, "xfs_lock", 0, LK_NOPAUSE);
77 #else
78 result->vnlocks = 0;
79 #endif
80 result->anonrights = 0;
81 result->rd_cred = NULL;
82 result->wr_cred = NULL;
83
84 #if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105280000
85 genfs_node_init(*vpp, &xfs_genfsops);
86 #endif
87
88 check = xfs_node_find(&xfsp->nodehead, handle);
89 if (check) {
90 vput(*vpp);
91 *vpp = result->vn;
92 return 0;
93 }
94
95 xfs_insert(&xfs->nodehead, result);
96
97 return 0;
98 }
99
100
101
102
103
104
105
106
107 int
108 new_xfs_node(struct xfs *xfsp,
109 struct xfs_msg_node *node,
110 struct xfs_node **xpp,
111 d_thread_t *p)
112 {
113 struct xfs_node *result;
114
115 NNPFSDEB(XDEBNODE, ("new_xfs_node (%d,%d,%d,%d)\n",
116 node->handle.a,
117 node->handle.b,
118 node->handle.c,
119 node->handle.d));
120
121 retry:
122
123 result = xfs_node_find(&xfsp->nodehead, &node->handle);
124 if (result == 0) {
125 int error;
126 struct vnode *v;
127
128 error = xfs_getnewvnode(xfsp, &v, &node->handle);
129 if (error)
130 return error;
131
132 result = VNODE_TO_XNODE(v);
133 result->anonrights = node->anonrights;
134
135 xfsp->nnodes++;
136 } else {
137
138 if(xfs_do_vget(XNODE_TO_VNODE(result), 0, p))
139 goto retry;
140 }
141
142
143 xfs_attr2vattr(&node->attr, &result->attr, 1);
144 result->vn->v_type = result->attr.va_type;
145 result->tokens = node->tokens;
146 bcopy(node->id, result->id, sizeof(result->id));
147 bcopy(node->rights, result->rights, sizeof(result->rights));
148
149 #ifdef __APPLE__
150 if (result->vn->v_type == VREG && (!UBCINFOEXISTS(result->vn)))
151 ubc_info_init(result->vn);
152 #endif
153
154 *xpp = result;
155 NNPFSDEB(XDEBNODE, ("return: new_xfs_node\n"));
156 return 0;
157 }
158
159 void
160 free_xfs_node(struct xfs_node *node)
161 {
162 struct xfs *xfsp = NNPFS_FROM_XNODE(node);
163
164 NNPFSDEB(XDEBNODE, ("free_xfs_node(%lx) (%d,%d,%d,%d)\n",
165 (unsigned long)node,
166 node->handle.a,
167 node->handle.b,
168 node->handle.c,
169 node->handle.d));
170
171
172
173 if (DATA_FROM_XNODE(node)) {
174 vrele(DATA_FROM_XNODE(node));
175 DATA_FROM_XNODE(node) = NULL;
176 }
177 xfsp->nnodes--;
178 XNODE_TO_VNODE(node)->v_data = NULL;
179 if (node->rd_cred) {
180 crfree (node->rd_cred);
181 node->rd_cred = NULL;
182 }
183 if (node->wr_cred) {
184 crfree (node->wr_cred);
185 node->wr_cred = NULL;
186 }
187
188 xfs_free(node, sizeof(*node), M_NNPFS_NODE);
189
190 NNPFSDEB(XDEBNODE, ("free_xfs_node done\n"));
191 }
192
193
194
195
196
197 static int
198 xfs_vflush(struct mount *mp, int flags)
199 {
200 #if __FreeBSD__ && __FreeBSD_version > 430000
201 return vflush(mp, 0, flags);
202 #else
203 return vflush(mp, NULL, flags);
204 #endif
205 }
206
207 int
208 free_all_xfs_nodes(struct xfs *xfsp, int flags, int unmountp)
209 {
210 int error = 0;
211 struct mount *mp = NNPFS_TO_VFS(xfsp);
212
213 if (mp == NULL) {
214 NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes already freed\n"));
215 return 0;
216 }
217
218 NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes starting\n"));
219
220 xfs_dnlc_purge_mp(mp);
221
222 if (xfsp->root) {
223 NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes now removing root\n"));
224
225 vgone(XNODE_TO_VNODE(xfsp->root));
226 xfsp->root = NULL;
227 }
228
229 NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes root removed\n"));
230 NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes now killing all remaining nodes\n"));
231
232
233
234
235
236
237 #ifdef HAVE_STRUCT_MOUNT_MNT_SYNCER
238 if (!unmountp) {
239 if (mp->mnt_syncer != NULL) {
240 #ifdef HAVE_KERNEL_VFS_DEALLOCATE_SYNCVNODE
241 vfs_deallocate_syncvnode(mp);
242 #else
243
244
245
246
247 #if defined(__OpenBSD__)
248 vgone(mp->mnt_syncer);
249 #elif defined(__FreeBSD__)
250 vrele(mp->mnt_syncer);
251 #else
252 #error what os do you use ?
253 #endif
254 mp->mnt_syncer = NULL;
255 #endif
256 }
257 }
258 #endif
259 error = xfs_vflush(mp, flags);
260 #ifdef HAVE_STRUCT_MOUNT_MNT_SYNCER
261 if (!unmountp) {
262 NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes not flushing syncer vnode\n"));
263 if (mp->mnt_syncer == NULL)
264 if (vfs_allocate_syncvnode(mp))
265 panic("failed to allocate syncer node when xfs daemon died");
266 }
267 #endif
268
269 if (error) {
270 NNPFSDEB(XDEBNODE, ("xfree_all_xfs_nodes: vflush() error == %d\n",
271 error));
272 return error;
273 }
274
275 NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes done\n"));
276 return error;
277 }
278
279 void
280 vattr2xfs_attr(const struct vattr *va, struct xfs_attr *xa)
281 {
282 bzero(xa, sizeof(*xa));
283 if (va->va_mode != (mode_t)VNOVAL)
284 XA_SET_MODE(xa, va->va_mode);
285 if (va->va_nlink != VNOVAL)
286 XA_SET_NLINK(xa, va->va_nlink);
287 if (va->va_size != VNOVAL)
288 XA_SET_SIZE(xa, va->va_size);
289 if (va->va_uid != VNOVAL)
290 XA_SET_UID(xa, va->va_uid);
291 if (va->va_gid != VNOVAL)
292 XA_SET_GID(xa, va->va_gid);
293 if (va->va_atime.tv_sec != VNOVAL)
294 XA_SET_ATIME(xa, va->va_atime.tv_sec);
295 if (va->va_mtime.tv_sec != VNOVAL)
296 XA_SET_MTIME(xa, va->va_mtime.tv_sec);
297 if (va->va_ctime.tv_sec != VNOVAL)
298 XA_SET_CTIME(xa, va->va_ctime.tv_sec);
299 if (va->va_fileid != VNOVAL)
300 XA_SET_FILEID(xa, va->va_fileid);
301 switch (va->va_type) {
302 case VNON:
303 xa->xa_type = NNPFS_FILE_NON;
304 break;
305 case VREG:
306 xa->xa_type = NNPFS_FILE_REG;
307 break;
308 case VDIR:
309 xa->xa_type = NNPFS_FILE_DIR;
310 break;
311 case VBLK:
312 xa->xa_type = NNPFS_FILE_BLK;
313 break;
314 case VCHR:
315 xa->xa_type = NNPFS_FILE_CHR;
316 break;
317 case VLNK:
318 xa->xa_type = NNPFS_FILE_LNK;
319 break;
320 case VSOCK:
321 xa->xa_type = NNPFS_FILE_SOCK;
322 break;
323 case VFIFO:
324 xa->xa_type = NNPFS_FILE_FIFO;
325 break;
326 case VBAD:
327 xa->xa_type = NNPFS_FILE_BAD;
328 break;
329 default:
330 panic("xfs_attr2attr: bad value");
331 }
332 }
333
334 #define SET_TIMEVAL(X, S, N) do { (X)->tv_sec = (S); (X)->tv_nsec = (N); } while(0)
335
336 void
337 xfs_attr2vattr(const struct xfs_attr *xa, struct vattr *va, int clear_node)
338 {
339 if (clear_node)
340 VATTR_NULL(va);
341 if (XA_VALID_MODE(xa))
342 va->va_mode = xa->xa_mode;
343 if (XA_VALID_NLINK(xa))
344 va->va_nlink = xa->xa_nlink;
345 if (XA_VALID_SIZE(xa)) {
346 va->va_size = xa->xa_size;
347 va->va_bytes = va->va_size;
348 }
349 if (XA_VALID_UID(xa))
350 va->va_uid = xa->xa_uid;
351 if (XA_VALID_GID(xa))
352 va->va_gid = xa->xa_gid;
353 if (XA_VALID_ATIME(xa)) {
354 SET_TIMEVAL(&va->va_atime, xa->xa_atime, 0);
355 }
356 if (XA_VALID_MTIME(xa)) {
357 SET_TIMEVAL(&va->va_mtime, xa->xa_mtime, 0);
358 }
359 if (XA_VALID_CTIME(xa)) {
360 SET_TIMEVAL(&va->va_ctime, xa->xa_ctime, 0);
361 }
362 if (XA_VALID_FILEID(xa)) {
363 va->va_fileid = xa->xa_fileid;
364 }
365 if (XA_VALID_TYPE(xa)) {
366 switch (xa->xa_type) {
367 case NNPFS_FILE_NON:
368 va->va_type = VNON;
369 break;
370 case NNPFS_FILE_REG:
371 va->va_type = VREG;
372 break;
373 case NNPFS_FILE_DIR:
374 va->va_type = VDIR;
375 break;
376 case NNPFS_FILE_BLK:
377 va->va_type = VBLK;
378 break;
379 case NNPFS_FILE_CHR:
380 va->va_type = VCHR;
381 break;
382 case NNPFS_FILE_LNK:
383 va->va_type = VLNK;
384 break;
385 case NNPFS_FILE_SOCK:
386 va->va_type = VSOCK;
387 break;
388 case NNPFS_FILE_FIFO:
389 va->va_type = VFIFO;
390 break;
391 case NNPFS_FILE_BAD:
392 va->va_type = VBAD;
393 break;
394 default:
395 panic("xfs_attr2vattr: bad value");
396 }
397 }
398 va->va_flags = 0;
399 va->va_blocksize = 8192;
400 }
401
402
403
404
405
406
407 struct long_entry {
408 struct vnode *dvp, *vp;
409 char name[MAXNAMLEN + 1];
410 size_t len;
411 u_long dvpid, vpid;
412 };
413
414 static struct long_entry tbl;
415
416
417
418
419
420 static void
421 tbl_clear (void)
422 {
423 tbl.dvp = tbl.vp = NULL;
424 tbl.name[0] = '\0';
425 tbl.len = 0;
426 tbl.dvpid = tbl.vpid = 0;
427 }
428
429
430
431
432
433 static void
434 tbl_enter (size_t len, const char *name, struct vnode *dvp, struct vnode *vp)
435 {
436 tbl.len = len;
437 bcopy(name, tbl.name, len);
438 tbl.dvp = dvp;
439 tbl.vp = vp;
440 tbl.dvpid = dvp->v_id;
441 tbl.vpid = vp->v_id;
442 }
443
444
445
446
447
448
449 static int
450 tbl_lookup (struct componentname *cnp,
451 struct vnode *dvp,
452 struct vnode **res)
453 {
454 if (tbl.dvp == dvp
455 && tbl.len == cnp->cn_namelen
456 && strncmp(tbl.name, cnp->cn_nameptr, tbl.len) == 0
457 && tbl.dvpid == tbl.dvp->v_id
458 && tbl.vpid == tbl.vp->v_id) {
459
460 *res = tbl.vp;
461 return -1;
462 } else
463 return 0;
464 }
465
466
467
468
469
470 int
471 xfs_dnlc_enter(struct vnode *dvp,
472 xfs_componentname *cnp,
473 struct vnode *vp)
474 {
475 NNPFSDEB(XDEBDNLC, ("xfs_dnlc_enter_cnp(%lx, %lx, %lx)\n",
476 (unsigned long)dvp,
477 (unsigned long)cnp,
478 (unsigned long)vp));
479 NNPFSDEB(XDEBDNLC, ("xfs_dnlc_enter: v_id = %lu\n", (u_long)dvp->v_id));
480
481 NNPFSDEB(XDEBDNLC, ("xfs_dnlc_enter: calling cache_enter:"
482 "dvp = %lx, vp = %lx, cnp = (%s, %ld), "
483 "nameiop = %lu, flags = %lx\n",
484 (unsigned long)dvp,
485 (unsigned long)vp,
486 cnp->cn_nameptr, cnp->cn_namelen,
487 cnp->cn_nameiop, cnp->cn_flags));
488
489 #ifdef NCHNAMLEN
490 if (cnp->cn_namelen <= NCHNAMLEN)
491 #endif
492 {
493
494
495
496 u_long save_nameiop;
497 u_long save_flags;
498 struct vnode *dummy;
499
500 save_nameiop = cnp->cn_nameiop;
501 save_flags = cnp->cn_flags;
502 cnp->cn_nameiop = CREATE;
503 cnp->cn_flags &= ~MAKEENTRY;
504
505
506
507
508
509
510 #if __NetBSD_Version__ >= 104120000 || OpenBSD > 200211
511 if (cache_lookup(dvp, &dummy, cnp) != -1) {
512 xfs_vfs_unlock(dummy, xfs_cnp_to_proc(cnp));
513 printf ("NNPFS PANIC WARNING! xfs_dnlc_enter: %s already in cache\n",
514 cnp->cn_nameptr);
515 }
516 #else
517 if (cache_lookup(dvp, &dummy, cnp) != 0) {
518 printf ("NNPFS PANIC WARNING! xfs_dnlc_enter: %s already in cache\n",
519 cnp->cn_nameptr);
520 }
521 #endif
522
523
524 cnp->cn_nameiop = save_nameiop;
525 cnp->cn_flags = save_flags;
526 cache_enter(dvp, vp, cnp);
527 }
528
529 if (vp != NULL)
530 tbl_enter (cnp->cn_namelen, cnp->cn_nameptr, dvp, vp);
531
532 return 0;
533 }
534
535
536 static void
537 xfs_cnp_init (struct componentname *cn,
538 const char *name,
539 d_thread_t *proc, struct ucred *cred,
540 int nameiop)
541 {
542 bzero(cn, sizeof(*cn));
543 cn->cn_nameptr = (char *)name;
544 cn->cn_namelen = strlen(name);
545 cn->cn_flags = 0;
546 #if __APPLE__
547 {
548 const unsigned char *p;
549 int i;
550
551 cn->cn_hash = 0;
552 for (p = cn->cn_nameptr, i = 1; *p; ++p, ++i)
553 cn->cn_hash += *p * i;
554 }
555 #elif defined(HAVE_KERNEL_NAMEI_HASH)
556 {
557 const char *cp = name + cn->cn_namelen;
558 cn->cn_hash = namei_hash(name, &cp);
559 }
560 #elif defined(HAVE_STRUCT_COMPONENTNAME_CN_HASH)
561 {
562 const unsigned char *p;
563
564 cn->cn_hash = 0;
565 for (p = cn->cn_nameptr; *p; ++p)
566 cn->cn_hash += *p;
567 }
568 #endif
569 cn->cn_nameiop = nameiop;
570 #ifdef HAVE_FREEBSD_THREAD
571 cn->cn_thread = proc;
572 #else
573 cn->cn_proc = proc;
574 #endif
575 cn->cn_cred = cred;
576 }
577
578
579
580
581
582
583 int
584 xfs_dnlc_enter_name(struct vnode *dvp,
585 const char *name,
586 struct vnode *vp)
587 {
588 struct componentname cn;
589
590 NNPFSDEB(XDEBDNLC, ("xfs_dnlc_enter_name(%lx, \"%s\", %lx)\n",
591 (unsigned long)dvp,
592 name,
593 (unsigned long)vp));
594
595 xfs_cnp_init (&cn, name, NULL, NULL, LOOKUP);
596 return xfs_dnlc_enter (dvp, &cn, vp);
597 }
598
599
600
601
602
603
604 static int
605 xfs_dnlc_lookup_int(struct vnode *dvp,
606 xfs_componentname *cnp,
607 struct vnode **res)
608 {
609 int error;
610 u_long saved_flags;
611
612 NNPFSDEB(XDEBDNLC, ("xfs_dnlc_lookup(%lx, \"%s\")\n",
613 (unsigned long)dvp, cnp->cn_nameptr));
614
615 NNPFSDEB(XDEBDNLC, ("xfs_dnlc_lookup: v_id = %lu\n", (u_long)dvp->v_id));
616
617 NNPFSDEB(XDEBDNLC, ("xfs_dnlc_lookup: calling cache_lookup:"
618 "dvp = %lx, cnp = (%s, %ld), flags = %lx\n",
619 (unsigned long)dvp,
620 cnp->cn_nameptr, cnp->cn_namelen,
621 cnp->cn_flags));
622
623 saved_flags = cnp->cn_flags;
624 cnp->cn_flags |= MAKEENTRY | LOCKPARENT | ISLASTCN;
625
626 error = cache_lookup(dvp, res, cnp);
627
628 cnp->cn_flags = saved_flags;
629
630 NNPFSDEB(XDEBDNLC, ("xfs_dnlc_lookup: cache_lookup returned. "
631 "error = %d, *res = %lx\n", error,
632 (unsigned long)*res));
633 return error;
634 }
635
636
637
638
639
640
641
642
643
644 static int
645 xfs_dnlc_lock(struct vnode *dvp,
646 xfs_componentname *cnp,
647 struct vnode **res)
648 {
649 int error = 0;
650
651
652
653
654
655 if (*res == dvp) {
656 VREF(dvp);
657 } else if (cnp->cn_flags & ISDOTDOT) {
658 u_long vpid = dvp->v_id;
659
660 #ifdef HAVE_FREEBSD_THREAD
661 xfs_vfs_unlock(dvp, xfs_cnp_to_thread(cnp));
662 error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_thread(cnp));
663 xfs_vfs_writelock(dvp, xfs_cnp_to_thread(cnp));
664 #else
665 xfs_vfs_unlock(dvp, xfs_cnp_to_proc(cnp));
666 error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_proc(cnp));
667 xfs_vfs_writelock(dvp, xfs_cnp_to_proc(cnp));
668 #endif
669
670 if (error == 0 && dvp->v_id != vpid) {
671 vput(*res);
672 return 0;
673 }
674 } else {
675 #ifdef HAVE_FREEBSD_THREAD
676 error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_thread(cnp));
677 #else
678 error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_proc(cnp));
679 #endif
680 }
681
682 if (error == 0)
683 return -1;
684 else
685 return 0;
686 }
687
688
689
690
691
692
693
694
695
696
697
698
699 #if __NetBSD_Version__ >= 104120000 || defined(__OpenBSD__)
700
701 int
702 xfs_dnlc_lookup(struct vnode *dvp,
703 xfs_componentname *cnp,
704 struct vnode **res)
705 {
706 int error = xfs_dnlc_lookup_int (dvp, cnp, res);
707
708 if (error == 0)
709 return -1;
710 else if (error == ENOENT)
711 return error;
712
713 error = tbl_lookup (cnp, dvp, res);
714
715 if (error != -1)
716 return error;
717
718 return xfs_dnlc_lock (dvp, cnp, res);
719 }
720
721 #else
722
723 int
724 xfs_dnlc_lookup(struct vnode *dvp,
725 xfs_componentname *cnp,
726 struct vnode **res)
727 {
728 int error = xfs_dnlc_lookup_int (dvp, cnp, res);
729
730 if (error == 0)
731 error = tbl_lookup (cnp, dvp, res);
732
733 if (error != -1)
734 return error;
735
736 return xfs_dnlc_lock (dvp, cnp, res);
737 }
738
739 #endif
740
741
742
743
744
745 void
746 xfs_dnlc_purge (struct vnode *vp)
747 {
748 NNPFSDEB(XDEBDNLC, ("xfs_dnlc_purge\n"));
749
750 if (tbl.dvp == vp || tbl.vp == vp)
751 tbl_clear ();
752
753 cache_purge(vp);
754 }
755
756
757
758
759
760 void
761 xfs_dnlc_purge_mp(struct mount *mp)
762 {
763 NNPFSDEB(XDEBDNLC, ("xfs_dnlc_purge_mp()\n"));
764
765 tbl_clear ();
766 cache_purgevfs(mp);
767 }
768
769
770
771
772
773 int
774 xfs_has_pag(const struct xfs_node *xn, xfs_pag_t pag)
775 {
776 int i;
777
778 for (i = 0; i < MAXRIGHTS; i++)
779 if (xn->id[i] == pag)
780 return 1;
781
782 return 0;
783 }
784
785 void
786 xfs_update_write_cred(struct xfs_node *xn, struct ucred *cred)
787 {
788 if (xn->wr_cred)
789 crfree (xn->wr_cred);
790 crhold (cred);
791 xn->wr_cred = cred;
792 }
793
794 void
795 xfs_update_read_cred(struct xfs_node *xn, struct ucred *cred)
796 {
797 if (xn->rd_cred)
798 crfree (xn->rd_cred);
799 crhold (cred);
800 xn->rd_cred = cred;
801 }