Deleted Added
full compact
null_vnops.c (140165) null_vnops.c (140728)
1/*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * John Heidemann of the UCLA Ficus project.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 22 unchanged lines hidden (view full) ---

31 *
32 * @(#)null_vnops.c 8.6 (Berkeley) 5/27/95
33 *
34 * Ancestors:
35 * @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
36 * ...and...
37 * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
38 *
1/*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * John Heidemann of the UCLA Ficus project.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 22 unchanged lines hidden (view full) ---

31 *
32 * @(#)null_vnops.c 8.6 (Berkeley) 5/27/95
33 *
34 * Ancestors:
35 * @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
36 * ...and...
37 * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
38 *
39 * $FreeBSD: head/sys/fs/nullfs/null_vnops.c 140165 2005-01-13 07:53:01Z phk $
39 * $FreeBSD: head/sys/fs/nullfs/null_vnops.c 140728 2005-01-24 11:49:41Z phk $
40 */
41
42/*
43 * Null Layer
44 *
45 * (See mount_nullfs(8) for more information.)
46 *
47 * The null layer duplicates a portion of the filesystem

--- 139 unchanged lines hidden (view full) ---

187#include <vm/vm_extern.h>
188#include <vm/vm_object.h>
189#include <vm/vnode_pager.h>
190
191static int null_bug_bypass = 0; /* for debugging: enables bypass printf'ing */
192SYSCTL_INT(_debug, OID_AUTO, nullfs_bug_bypass, CTLFLAG_RW,
193 &null_bug_bypass, 0, "");
194
40 */
41
42/*
43 * Null Layer
44 *
45 * (See mount_nullfs(8) for more information.)
46 *
47 * The null layer duplicates a portion of the filesystem

--- 139 unchanged lines hidden (view full) ---

187#include <vm/vm_extern.h>
188#include <vm/vm_object.h>
189#include <vm/vnode_pager.h>
190
191static int null_bug_bypass = 0; /* for debugging: enables bypass printf'ing */
192SYSCTL_INT(_debug, OID_AUTO, nullfs_bug_bypass, CTLFLAG_RW,
193 &null_bug_bypass, 0, "");
194
195static vop_access_t null_access;
196static vop_createvobject_t null_createvobject;
197static vop_destroyvobject_t null_destroyvobject;
198static vop_getattr_t null_getattr;
199static vop_getvobject_t null_getvobject;
200static vop_inactive_t null_inactive;
201static vop_islocked_t null_islocked;
202static vop_lock_t null_lock;
203static vop_lookup_t null_lookup;
204static vop_print_t null_print;
205static vop_reclaim_t null_reclaim;
206static vop_rename_t null_rename;
207static vop_setattr_t null_setattr;
208static vop_unlock_t null_unlock;
209
210/*
211 * This is the 10-Apr-92 bypass routine.
212 * This version has been optimized for speed, throwing away some
213 * safety checks. It should still always work, but it's not as
214 * robust to programmer errors.
215 *
216 * In general, we map all vnodes going down and unmap them on the way back.
217 * As an exception to this, vnodes can be marked "unmapped" by setting

--- 9 unchanged lines hidden (view full) ---

227 * - only one returned vpp
228 * - no INOUT vpp's (Sun's vop_open has one of these)
229 * - the vnode operation vector of the first vnode should be used
230 * to determine what implementation of the op should be invoked
231 * - all mapped vnodes are of our vnode-type (NEEDSWORK:
232 * problems on rmdir'ing mount points and renaming?)
233 */
234int
195/*
196 * This is the 10-Apr-92 bypass routine.
197 * This version has been optimized for speed, throwing away some
198 * safety checks. It should still always work, but it's not as
199 * robust to programmer errors.
200 *
201 * In general, we map all vnodes going down and unmap them on the way back.
202 * As an exception to this, vnodes can be marked "unmapped" by setting

--- 9 unchanged lines hidden (view full) ---

212 * - only one returned vpp
213 * - no INOUT vpp's (Sun's vop_open has one of these)
214 * - the vnode operation vector of the first vnode should be used
215 * to determine what implementation of the op should be invoked
216 * - all mapped vnodes are of our vnode-type (NEEDSWORK:
217 * problems on rmdir'ing mount points and renaming?)
218 */
219int
235null_bypass(ap)
236 struct vop_generic_args /* {
237 struct vnodeop_desc *a_desc;
238 <other random data follows, presumably>
239 } */ *ap;
220null_bypass(struct vop_generic_args *ap)
240{
241 register struct vnode **this_vp_p;
242 int error;
243 struct vnode *old_vps[VDESC_MAX_VPS];
244 struct vnode **vps_p[VDESC_MAX_VPS];
245 struct vnode ***vppp;
246 struct vnodeop_desc *descp = ap->a_desc;
247 int reles, i;

--- 101 unchanged lines hidden (view full) ---

349}
350
351/*
352 * We have to carry on the locking protocol on the null layer vnodes
353 * as we progress through the tree. We also have to enforce read-only
354 * if this layer is mounted read-only.
355 */
356static int
221{
222 register struct vnode **this_vp_p;
223 int error;
224 struct vnode *old_vps[VDESC_MAX_VPS];
225 struct vnode **vps_p[VDESC_MAX_VPS];
226 struct vnode ***vppp;
227 struct vnodeop_desc *descp = ap->a_desc;
228 int reles, i;

--- 101 unchanged lines hidden (view full) ---

330}
331
332/*
333 * We have to carry on the locking protocol on the null layer vnodes
334 * as we progress through the tree. We also have to enforce read-only
335 * if this layer is mounted read-only.
336 */
337static int
357null_lookup(ap)
358 struct vop_lookup_args /* {
359 struct vnode * a_dvp;
360 struct vnode ** a_vpp;
361 struct componentname * a_cnp;
362 } */ *ap;
338null_lookup(struct vop_lookup_args *ap)
363{
364 struct componentname *cnp = ap->a_cnp;
365 struct vnode *dvp = ap->a_dvp;
366 struct thread *td = cnp->cn_thread;
367 int flags = cnp->cn_flags;
368 struct vnode *vp, *ldvp, *lvp;
369 int error;
370

--- 34 unchanged lines hidden (view full) ---

405 }
406 return (error);
407}
408
409/*
410 * Setattr call. Disallow write attempts if the layer is mounted read-only.
411 */
412static int
339{
340 struct componentname *cnp = ap->a_cnp;
341 struct vnode *dvp = ap->a_dvp;
342 struct thread *td = cnp->cn_thread;
343 int flags = cnp->cn_flags;
344 struct vnode *vp, *ldvp, *lvp;
345 int error;
346

--- 34 unchanged lines hidden (view full) ---

381 }
382 return (error);
383}
384
385/*
386 * Setattr call. Disallow write attempts if the layer is mounted read-only.
387 */
388static int
413null_setattr(ap)
414 struct vop_setattr_args /* {
415 struct vnodeop_desc *a_desc;
416 struct vnode *a_vp;
417 struct vattr *a_vap;
418 struct ucred *a_cred;
419 struct thread *a_td;
420 } */ *ap;
389null_setattr(struct vop_setattr_args *ap)
421{
422 struct vnode *vp = ap->a_vp;
423 struct vattr *vap = ap->a_vap;
424
425 if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
426 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
427 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
428 (vp->v_mount->mnt_flag & MNT_RDONLY))

--- 23 unchanged lines hidden (view full) ---

452
453 return (null_bypass((struct vop_generic_args *)ap));
454}
455
456/*
457 * We handle getattr only to change the fsid.
458 */
459static int
390{
391 struct vnode *vp = ap->a_vp;
392 struct vattr *vap = ap->a_vap;
393
394 if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
395 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
396 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
397 (vp->v_mount->mnt_flag & MNT_RDONLY))

--- 23 unchanged lines hidden (view full) ---

421
422 return (null_bypass((struct vop_generic_args *)ap));
423}
424
425/*
426 * We handle getattr only to change the fsid.
427 */
428static int
460null_getattr(ap)
461 struct vop_getattr_args /* {
462 struct vnode *a_vp;
463 struct vattr *a_vap;
464 struct ucred *a_cred;
465 struct thread *a_td;
466 } */ *ap;
429null_getattr(struct vop_getattr_args *ap)
467{
468 int error;
469
470 if ((error = null_bypass((struct vop_generic_args *)ap)) != 0)
471 return (error);
472
473 ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
474 return (0);
475}
476
477/*
478 * Handle to disallow write access if mounted read-only.
479 */
480static int
430{
431 int error;
432
433 if ((error = null_bypass((struct vop_generic_args *)ap)) != 0)
434 return (error);
435
436 ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
437 return (0);
438}
439
440/*
441 * Handle to disallow write access if mounted read-only.
442 */
443static int
481null_access(ap)
482 struct vop_access_args /* {
483 struct vnode *a_vp;
484 int a_mode;
485 struct ucred *a_cred;
486 struct thread *a_td;
487 } */ *ap;
444null_access(struct vop_access_args *ap)
488{
489 struct vnode *vp = ap->a_vp;
490 mode_t mode = ap->a_mode;
491
492 /*
493 * Disallow write attempts on read-only layers;
494 * unless the file is a socket, fifo, or a block or
495 * character device resident on the filesystem.

--- 14 unchanged lines hidden (view full) ---

510}
511
512/*
513 * We handle this to eliminate null FS to lower FS
514 * file moving. Don't know why we don't allow this,
515 * possibly we should.
516 */
517static int
445{
446 struct vnode *vp = ap->a_vp;
447 mode_t mode = ap->a_mode;
448
449 /*
450 * Disallow write attempts on read-only layers;
451 * unless the file is a socket, fifo, or a block or
452 * character device resident on the filesystem.

--- 14 unchanged lines hidden (view full) ---

467}
468
469/*
470 * We handle this to eliminate null FS to lower FS
471 * file moving. Don't know why we don't allow this,
472 * possibly we should.
473 */
474static int
518null_rename(ap)
519 struct vop_rename_args /* {
520 struct vnode *a_fdvp;
521 struct vnode *a_fvp;
522 struct componentname *a_fcnp;
523 struct vnode *a_tdvp;
524 struct vnode *a_tvp;
525 struct componentname *a_tcnp;
526 } */ *ap;
475null_rename(struct vop_rename_args *ap)
527{
528 struct vnode *tdvp = ap->a_tdvp;
529 struct vnode *fvp = ap->a_fvp;
530 struct vnode *fdvp = ap->a_fdvp;
531 struct vnode *tvp = ap->a_tvp;
532
533 /* Check for cross-device rename. */
534 if ((fvp->v_mount != tdvp->v_mount) ||

--- 13 unchanged lines hidden (view full) ---

548}
549
550/*
551 * We need to process our own vnode lock and then clear the
552 * interlock flag as it applies only to our vnode, not the
553 * vnodes below us on the stack.
554 */
555static int
476{
477 struct vnode *tdvp = ap->a_tdvp;
478 struct vnode *fvp = ap->a_fvp;
479 struct vnode *fdvp = ap->a_fdvp;
480 struct vnode *tvp = ap->a_tvp;
481
482 /* Check for cross-device rename. */
483 if ((fvp->v_mount != tdvp->v_mount) ||

--- 13 unchanged lines hidden (view full) ---

497}
498
499/*
500 * We need to process our own vnode lock and then clear the
501 * interlock flag as it applies only to our vnode, not the
502 * vnodes below us on the stack.
503 */
504static int
556null_lock(ap)
557 struct vop_lock_args /* {
558 struct vnode *a_vp;
559 int a_flags;
560 struct thread *a_td;
561 } */ *ap;
505null_lock(struct vop_lock_args *ap)
562{
563 struct vnode *vp = ap->a_vp;
564 int flags = ap->a_flags;
565 struct thread *td = ap->a_td;
566 struct vnode *lvp;
567 int error;
568 struct null_node *nn;
569

--- 108 unchanged lines hidden (view full) ---

678}
679
680/*
681 * We need to process our own vnode unlock and then clear the
682 * interlock flag as it applies only to our vnode, not the
683 * vnodes below us on the stack.
684 */
685static int
506{
507 struct vnode *vp = ap->a_vp;
508 int flags = ap->a_flags;
509 struct thread *td = ap->a_td;
510 struct vnode *lvp;
511 int error;
512 struct null_node *nn;
513

--- 108 unchanged lines hidden (view full) ---

622}
623
624/*
625 * We need to process our own vnode unlock and then clear the
626 * interlock flag as it applies only to our vnode, not the
627 * vnodes below us on the stack.
628 */
629static int
686null_unlock(ap)
687 struct vop_unlock_args /* {
688 struct vnode *a_vp;
689 int a_flags;
690 struct thread *a_td;
691 } */ *ap;
630null_unlock(struct vop_unlock_args *ap)
692{
693 struct vnode *vp = ap->a_vp;
694 int flags = ap->a_flags;
695 struct thread *td = ap->a_td;
696 struct vnode *lvp;
697
698 if (vp->v_vnlock != NULL) {
699 if (flags & LK_THISLAYER)

--- 12 unchanged lines hidden (view full) ---

712 }
713 VOP_UNLOCK(lvp, flags & ~LK_INTERLOCK, td);
714 } else
715 flags &= ~LK_THISLAYER;
716 return (lockmgr(&vp->v_lock, flags | LK_RELEASE, &vp->v_interlock, td));
717}
718
719static int
631{
632 struct vnode *vp = ap->a_vp;
633 int flags = ap->a_flags;
634 struct thread *td = ap->a_td;
635 struct vnode *lvp;
636
637 if (vp->v_vnlock != NULL) {
638 if (flags & LK_THISLAYER)

--- 12 unchanged lines hidden (view full) ---

651 }
652 VOP_UNLOCK(lvp, flags & ~LK_INTERLOCK, td);
653 } else
654 flags &= ~LK_THISLAYER;
655 return (lockmgr(&vp->v_lock, flags | LK_RELEASE, &vp->v_interlock, td));
656}
657
658static int
720null_islocked(ap)
721 struct vop_islocked_args /* {
722 struct vnode *a_vp;
723 struct thread *a_td;
724 } */ *ap;
659null_islocked(struct vop_islocked_args *ap)
725{
726 struct vnode *vp = ap->a_vp;
727 struct thread *td = ap->a_td;
728
729 if (vp->v_vnlock != NULL)
730 return (lockstatus(vp->v_vnlock, td));
731 return (lockstatus(&vp->v_lock, td));
732}

--- 4 unchanged lines hidden (view full) ---

737 * as soon as possible.
738 *
739 * Note, we can't release any resources nor remove vnode from hash before
740 * appropriate VXLOCK stuff is is done because other process can find this
741 * vnode in hash during inactivation and may be sitting in vget() and waiting
742 * for null_inactive to unlock vnode. Thus we will do all those in VOP_RECLAIM.
743 */
744static int
660{
661 struct vnode *vp = ap->a_vp;
662 struct thread *td = ap->a_td;
663
664 if (vp->v_vnlock != NULL)
665 return (lockstatus(vp->v_vnlock, td));
666 return (lockstatus(&vp->v_lock, td));
667}

--- 4 unchanged lines hidden (view full) ---

672 * as soon as possible.
673 *
674 * Note, we can't release any resources nor remove vnode from hash before
675 * appropriate VXLOCK stuff is is done because other process can find this
676 * vnode in hash during inactivation and may be sitting in vget() and waiting
677 * for null_inactive to unlock vnode. Thus we will do all those in VOP_RECLAIM.
678 */
679static int
745null_inactive(ap)
746 struct vop_inactive_args /* {
747 struct vnode *a_vp;
748 struct thread *a_td;
749 } */ *ap;
680null_inactive(struct vop_inactive_args *ap)
750{
751 struct vnode *vp = ap->a_vp;
752 struct thread *td = ap->a_td;
753
754 VOP_UNLOCK(vp, 0, td);
755
756 /*
757 * If this is the last reference, then free up the vnode
758 * so as not to tie up the lower vnodes.
759 */
760 vrecycle(vp, NULL, td);
761
762 return (0);
763}
764
765/*
766 * Now, the VXLOCK is in force and we're free to destroy the null vnode.
767 */
768static int
681{
682 struct vnode *vp = ap->a_vp;
683 struct thread *td = ap->a_td;
684
685 VOP_UNLOCK(vp, 0, td);
686
687 /*
688 * If this is the last reference, then free up the vnode
689 * so as not to tie up the lower vnodes.
690 */
691 vrecycle(vp, NULL, td);
692
693 return (0);
694}
695
696/*
697 * Now, the VXLOCK is in force and we're free to destroy the null vnode.
698 */
699static int
769null_reclaim(ap)
770 struct vop_reclaim_args /* {
771 struct vnode *a_vp;
772 struct thread *a_td;
773 } */ *ap;
700null_reclaim(struct vop_reclaim_args *ap)
774{
775 struct vnode *vp = ap->a_vp;
776 struct null_node *xp = VTONULL(vp);
777 struct vnode *lowervp = xp->null_lowervp;
778
779 if (lowervp) {
780 null_hashrem(xp);
781

--- 4 unchanged lines hidden (view full) ---

786 vp->v_data = NULL;
787 vp->v_vnlock = &vp->v_lock;
788 FREE(xp, M_NULLFSNODE);
789
790 return (0);
791}
792
793static int
701{
702 struct vnode *vp = ap->a_vp;
703 struct null_node *xp = VTONULL(vp);
704 struct vnode *lowervp = xp->null_lowervp;
705
706 if (lowervp) {
707 null_hashrem(xp);
708

--- 4 unchanged lines hidden (view full) ---

713 vp->v_data = NULL;
714 vp->v_vnlock = &vp->v_lock;
715 FREE(xp, M_NULLFSNODE);
716
717 return (0);
718}
719
720static int
794null_print(ap)
795 struct vop_print_args /* {
796 struct vnode *a_vp;
797 } */ *ap;
721null_print(struct vop_print_args *ap)
798{
799 register struct vnode *vp = ap->a_vp;
800 printf("\tvp=%p, lowervp=%p\n", vp, NULLVPTOLOWERVP(vp));
801 return (0);
802}
803
804/*
805 * Let an underlying filesystem do the work
806 */
807static int
722{
723 register struct vnode *vp = ap->a_vp;
724 printf("\tvp=%p, lowervp=%p\n", vp, NULLVPTOLOWERVP(vp));
725 return (0);
726}
727
728/*
729 * Let an underlying filesystem do the work
730 */
731static int
808null_createvobject(ap)
809 struct vop_createvobject_args /* {
810 struct vnode *vp;
811 struct ucred *cred;
812 struct thread *td;
813 } */ *ap;
732null_createvobject(struct vop_createvobject_args *ap)
814{
815 struct vnode *vp = ap->a_vp;
816 struct vnode *lowervp = VTONULL(vp) ? NULLVPTOLOWERVP(vp) : NULL;
817 int error;
818
819 if (vp->v_type == VNON || lowervp == NULL)
820 return 0;
821 error = VOP_CREATEVOBJECT(lowervp, ap->a_cred, ap->a_td);
822 if (error)
823 return (error);
824 vp->v_vflag |= VV_OBJBUF;
825 return (0);
826}
827
828/*
829 * We have nothing to destroy and this operation shouldn't be bypassed.
830 */
831static int
733{
734 struct vnode *vp = ap->a_vp;
735 struct vnode *lowervp = VTONULL(vp) ? NULLVPTOLOWERVP(vp) : NULL;
736 int error;
737
738 if (vp->v_type == VNON || lowervp == NULL)
739 return 0;
740 error = VOP_CREATEVOBJECT(lowervp, ap->a_cred, ap->a_td);
741 if (error)
742 return (error);
743 vp->v_vflag |= VV_OBJBUF;
744 return (0);
745}
746
747/*
748 * We have nothing to destroy and this operation shouldn't be bypassed.
749 */
750static int
832null_destroyvobject(ap)
833 struct vop_destroyvobject_args /* {
834 struct vnode *vp;
835 } */ *ap;
751null_destroyvobject(struct vop_destroyvobject_args *ap)
836{
837 struct vnode *vp = ap->a_vp;
838
839 vp->v_vflag &= ~VV_OBJBUF;
840 return (0);
841}
842
843static int
752{
753 struct vnode *vp = ap->a_vp;
754
755 vp->v_vflag &= ~VV_OBJBUF;
756 return (0);
757}
758
759static int
844null_getvobject(ap)
845 struct vop_getvobject_args /* {
846 struct vnode *vp;
847 struct vm_object **objpp;
848 } */ *ap;
760null_getvobject(struct vop_getvobject_args *ap)
849{
850 struct vnode *lvp = NULLVPTOLOWERVP(ap->a_vp);
851
852 if (lvp == NULL)
853 return EINVAL;
854 return (VOP_GETVOBJECT(lvp, ap->a_objpp));
855}
856

--- 24 unchanged lines hidden ---
761{
762 struct vnode *lvp = NULLVPTOLOWERVP(ap->a_vp);
763
764 if (lvp == NULL)
765 return EINVAL;
766 return (VOP_GETVOBJECT(lvp, ap->a_objpp));
767}
768

--- 24 unchanged lines hidden ---