Lines Matching +full:layer +full:- +full:base +full:- +full:offset

1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1994 Jan-Simon Pendry
11 * Jan-Simon Pendry.
66 #define UNIONFSHASHMASK (NUNIONFSNODECACHE - 1)
122 MPASS(unp->un_dvp != NULL); in unionfs_deferred_rele()
123 vrele(unp->un_dvp); in unionfs_deferred_rele()
127 /* We expect this function to be single-threaded, thus no atomic */ in unionfs_deferred_rele()
138 return (&(unp->un_hashtbl[vfs_hash_index(lookup) & UNIONFSHASHMASK])); in unionfs_get_hashhead()
155 if (unp->un_uppervp == lookup || in unionfs_get_cached_vnode_locked()
156 unp->un_lowervp == lookup) { in unionfs_get_cached_vnode_locked()
159 vp->v_iflag &= ~VI_OWEINACT; in unionfs_get_cached_vnode_locked()
161 ((vp->v_iflag & VI_DOINGINACT) != 0)) { in unionfs_get_cached_vnode_locked()
208 if (uncp->un_uppervp != NULLVP) { in unionfs_ins_cached_vnode()
209 ASSERT_VOP_ELOCKED(uncp->un_uppervp, __func__); in unionfs_ins_cached_vnode()
210 KASSERT(uncp->un_uppervp->v_type == VDIR, in unionfs_ins_cached_vnode()
212 vp = unionfs_get_cached_vnode_locked(uncp->un_uppervp, dvp); in unionfs_ins_cached_vnode()
213 } else if (uncp->un_lowervp != NULLVP) { in unionfs_ins_cached_vnode()
214 ASSERT_VOP_ELOCKED(uncp->un_lowervp, __func__); in unionfs_ins_cached_vnode()
215 KASSERT(uncp->un_lowervp->v_type == VDIR, in unionfs_ins_cached_vnode()
217 vp = unionfs_get_cached_vnode_locked(uncp->un_lowervp, dvp); in unionfs_ins_cached_vnode()
220 hd = unionfs_get_hashhead(dvp, (uncp->un_uppervp != NULLVP ? in unionfs_ins_cached_vnode()
221 uncp->un_uppervp : uncp->un_lowervp)); in unionfs_ins_cached_vnode()
240 if (unp->un_hash.le_prev != NULL) { in unionfs_rem_cached_vnode()
242 unp->un_hash.le_next = NULL; in unionfs_rem_cached_vnode()
243 unp->un_hash.le_prev = NULL; in unionfs_rem_cached_vnode()
251 * the caller. Upper and lower vnodes, if non-NULL, are also expected to be
263 lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL); in unionfs_nodeget_cleanup()
270 vp->v_data = NULL; in unionfs_nodeget_cleanup()
271 vp->v_vnlock = &vp->v_lock; in unionfs_nodeget_cleanup()
272 vp->v_op = &dead_vnodeops; in unionfs_nodeget_cleanup()
277 if (unp->un_dvp != NULLVP) in unionfs_nodeget_cleanup()
278 vrele(unp->un_dvp); in unionfs_nodeget_cleanup()
279 if (unp->un_uppervp != NULLVP) { in unionfs_nodeget_cleanup()
280 vput(unp->un_uppervp); in unionfs_nodeget_cleanup()
281 if (unp->un_lowervp != NULLVP) in unionfs_nodeget_cleanup()
282 vrele(unp->un_lowervp); in unionfs_nodeget_cleanup()
283 } else if (unp->un_lowervp != NULLVP) in unionfs_nodeget_cleanup()
284 vput(unp->un_lowervp); in unionfs_nodeget_cleanup()
285 if (unp->un_hashtbl != NULL) in unionfs_nodeget_cleanup()
286 hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, UNIONFSHASHMASK); in unionfs_nodeget_cleanup()
287 free(unp->un_path, M_UNIONFSPATH); in unionfs_nodeget_cleanup()
314 lkflags = (cnp ? cnp->cn_lkflags : 0); in unionfs_nodeget()
315 path = (cnp ? cnp->cn_nameptr : NULL); in unionfs_nodeget()
321 vt = (uppervp != NULLVP ? uppervp->v_type : lowervp->v_type); in unionfs_nodeget()
324 if (cnp && !(cnp->cn_flags & ISLASTCN)) in unionfs_nodeget()
354 unp->un_hashtbl = hashinit(NUNIONFSNODECACHE, M_UNIONFSHASH, in unionfs_nodeget()
360 unp->un_vnode = vp; in unionfs_nodeget()
361 unp->un_uppervp = uppervp; in unionfs_nodeget()
362 unp->un_lowervp = lowervp; in unionfs_nodeget()
363 unp->un_dvp = dvp; in unionfs_nodeget()
365 vp->v_vnlock = uppervp->v_vnlock; in unionfs_nodeget()
367 vp->v_vnlock = lowervp->v_vnlock; in unionfs_nodeget()
370 unp->un_path = malloc(cnp->cn_namelen + 1, in unionfs_nodeget()
372 bcopy(cnp->cn_nameptr, unp->un_path, cnp->cn_namelen); in unionfs_nodeget()
373 unp->un_path[cnp->cn_namelen] = '\0'; in unionfs_nodeget()
374 unp->un_pathlen = cnp->cn_namelen; in unionfs_nodeget()
376 vp->v_type = vt; in unionfs_nodeget()
377 vp->v_data = unp; in unionfs_nodeget()
387 if (ump->um_uppervp == uppervp || ump->um_lowervp == lowervp) in unionfs_nodeget()
388 vp->v_vflag |= VV_ROOT; in unionfs_nodeget()
389 KASSERT(dvp != NULL || (vp->v_vflag & VV_ROOT) != 0, in unionfs_nodeget()
390 ("%s: NULL dvp for non-root vp %p", __func__, vp)); in unionfs_nodeget()
394 * NOTE: There is still a possibility for cross-filesystem locking here. in unionfs_nodeget()
396 * created here only has a lower-layer FS component, then we will end in unionfs_nodeget()
397 * up taking a lower-FS lock while holding an upper-FS lock. in unionfs_nodeget()
402 * a few places within unionfs (which could lead to the same cross-FS in unionfs_nodeget()
479 KASSERT(vp->v_vnlock->lk_recurse == 0 || (vp->v_vflag & VV_ROOT) != 0, in unionfs_noderem()
484 lvp = unp->un_lowervp; in unionfs_noderem()
485 uvp = unp->un_uppervp; in unionfs_noderem()
486 dvp = unp->un_dvp; in unionfs_noderem()
494 * base vnodes for its entire lifecycled, so unionfs_lock() should in unionfs_noderem()
496 * Moreover, during unmount of a non-"below" unionfs mount, the lower in unionfs_noderem()
499 if (uvp != NULLVP && lvp != NULLVP && (vp->v_vflag & VV_ROOT) == 0) { in unionfs_noderem()
504 if (lockmgr(&vp->v_lock, LK_EXCLUSIVE | LK_NOWAIT, NULL) != 0) in unionfs_noderem()
511 unp->un_lowervp = unp->un_uppervp = NULLVP; in unionfs_noderem()
512 vp->v_vnlock = &(vp->v_lock); in unionfs_noderem()
513 vp->v_data = NULL; in unionfs_noderem()
514 vp->v_object = NULL; in unionfs_noderem()
515 if (unp->un_hashtbl != NULL) { in unionfs_noderem()
519 * be reclaimed with a non-zero use count. Otherwise the in unionfs_noderem()
523 hd = unp->un_hashtbl + count; in unionfs_noderem()
526 unp_t1->un_hash.le_next = NULL; in unionfs_noderem()
527 unp_t1->un_hash.le_prev = NULL; in unionfs_noderem()
533 writerefs = atomic_load_int(&vp->v_writecount); in unionfs_noderem()
544 VOP_ADD_WRITECOUNT(uvp, -writerefs); in unionfs_noderem()
556 if (unp->un_path != NULL) { in unionfs_noderem()
557 free(unp->un_path, M_UNIONFSPATH); in unionfs_noderem()
558 unp->un_path = NULL; in unionfs_noderem()
559 unp->un_pathlen = 0; in unionfs_noderem()
562 if (unp->un_hashtbl != NULL) { in unionfs_noderem()
563 hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, UNIONFSHASHMASK); in unionfs_noderem()
566 LIST_FOREACH_SAFE(unsp, &(unp->un_unshead), uns_list, unsp_tmp) { in unionfs_noderem()
590 pid = td->td_proc->p_pid; in unionfs_find_node_status()
594 LIST_FOREACH(unsp, &(unp->un_unshead), uns_list) { in unionfs_find_node_status()
595 if (unsp->uns_pid == pid) { in unionfs_find_node_status()
615 pid = td->td_proc->p_pid; in unionfs_get_node_status()
624 unsp->uns_pid = pid; in unionfs_get_node_status()
625 LIST_INSERT_HEAD(&(unp->un_unshead), unsp, uns_list); in unionfs_get_node_status()
642 if (0 < unsp->uns_lower_opencnt || 0 < unsp->uns_upper_opencnt) in unionfs_tryrem_node_status()
657 uva->va_type = lva->va_type; in unionfs_create_uppervattr_core()
658 uva->va_atime = lva->va_atime; in unionfs_create_uppervattr_core()
659 uva->va_mtime = lva->va_mtime; in unionfs_create_uppervattr_core()
660 uva->va_ctime = lva->va_ctime; in unionfs_create_uppervattr_core()
662 switch (ump->um_copymode) { in unionfs_create_uppervattr_core()
664 uva->va_mode = lva->va_mode; in unionfs_create_uppervattr_core()
665 uva->va_uid = lva->va_uid; in unionfs_create_uppervattr_core()
666 uva->va_gid = lva->va_gid; in unionfs_create_uppervattr_core()
669 if (ump->um_uid == lva->va_uid) { in unionfs_create_uppervattr_core()
670 uva->va_mode = lva->va_mode & 077077; in unionfs_create_uppervattr_core()
671 uva->va_mode |= (lva->va_type == VDIR ? in unionfs_create_uppervattr_core()
672 ump->um_udir : ump->um_ufile) & 0700; in unionfs_create_uppervattr_core()
673 uva->va_uid = lva->va_uid; in unionfs_create_uppervattr_core()
674 uva->va_gid = lva->va_gid; in unionfs_create_uppervattr_core()
676 uva->va_mode = (lva->va_type == VDIR ? in unionfs_create_uppervattr_core()
677 ump->um_udir : ump->um_ufile); in unionfs_create_uppervattr_core()
678 uva->va_uid = ump->um_uid; in unionfs_create_uppervattr_core()
679 uva->va_gid = ump->um_gid; in unionfs_create_uppervattr_core()
683 uva->va_mode = 0777 & ~td->td_proc->p_pd->pd_cmask; in unionfs_create_uppervattr_core()
684 uva->va_uid = ump->um_uid; in unionfs_create_uppervattr_core()
685 uva->va_gid = ump->um_gid; in unionfs_create_uppervattr_core()
725 cn->cn_namelen = pathlen; in unionfs_relookup()
726 cn->cn_pnbuf = path; in unionfs_relookup()
727 cn->cn_nameiop = nameiop; in unionfs_relookup()
728 cn->cn_flags = (LOCKPARENT | LOCKLEAF | ISLASTCN); in unionfs_relookup()
729 cn->cn_lkflags = LK_EXCLUSIVE; in unionfs_relookup()
730 cn->cn_cred = cnp->cn_cred; in unionfs_relookup()
731 cn->cn_nameptr = cn->cn_pnbuf; in unionfs_relookup()
735 cn->cn_flags |= (cnp->cn_flags & DOWHITEOUT); in unionfs_relookup()
739 cn->cn_flags |= NOCACHE; in unionfs_relookup()
750 KASSERT(cn->cn_pnbuf == path, ("%s: cn_pnbuf changed", __func__)); in unionfs_relookup()
772 lvp = unp->un_lowervp; in unionfs_node_update()
775 dvp = unp->un_dvp; in unionfs_node_update()
777 VNASSERT(vp->v_writecount == 0, vp, in unionfs_node_update()
778 ("%s: non-zero writecount", __func__)); in unionfs_node_update()
783 lockrec = lvp->v_vnlock->lk_recurse; in unionfs_node_update()
787 unp->un_uppervp = uvp; in unionfs_node_update()
788 vp->v_vnlock = uvp->v_vnlock; in unionfs_node_update()
794 * Re-cache the unionfs vnode against the upper vnode in unionfs_node_update()
796 if (dvp != NULLVP && vp->v_type == VDIR) { in unionfs_node_update()
798 if (unp->un_hash.le_prev != NULL) { in unionfs_node_update()
803 VI_UNLOCK(unp->un_dvp); in unionfs_node_update()
810 * This is useful, for example, during copy-up operations in which
812 * possibility of a concurrent copy-up on the same vnode triggering
825 while (error == 0 && (unp->un_flag & flag) != 0) { in unionfs_set_in_progress_flag()
832 * If we waited on a concurrent copy-up and that in unionfs_set_in_progress_flag()
833 * copy-up was successful, return a non-fatal in unionfs_set_in_progress_flag()
837 * be re-queried to avoid creating a duplicate unionfs in unionfs_set_in_progress_flag()
844 unp->un_uppervp != NULLVP) in unionfs_set_in_progress_flag()
851 unp->un_flag |= flag; in unionfs_set_in_progress_flag()
866 VNASSERT((unp->un_flag & flag) != 0, vp, in unionfs_clear_in_progress_flag()
868 unp->un_flag &= ~flag; in unionfs_clear_in_progress_flag()
903 ump = MOUNTTOUNIONFSMOUNT(vp->v_mount); in unionfs_mkshadowdir()
905 if (unp->un_uppervp != NULLVP) in unionfs_mkshadowdir()
908 udvp = dunp->un_uppervp; in unionfs_mkshadowdir()
916 lvp = unp->un_lowervp; in unionfs_mkshadowdir()
918 credbk = cnp->cn_cred; in unionfs_mkshadowdir()
922 cred = crdup(cnp->cn_cred); in unionfs_mkshadowdir()
927 cnp->cn_cred = cred; in unionfs_mkshadowdir()
932 if ((error = VOP_GETATTR(lvp, &lva, cnp->cn_cred))) in unionfs_mkshadowdir()
938 cnp->cn_nameptr, cnp->cn_namelen, CREATE))) { in unionfs_mkshadowdir()
974 * Temporarily NUL-terminate the current pathname component. in unionfs_mkshadowdir()
984 * NUL-termination will not have an effect on other threads. in unionfs_mkshadowdir()
1043 cnp->cn_cred = credbk; in unionfs_mkshadowdir()
1061 * The unionfs vnode shares its lock with the base-layer vnode(s); if the
1062 * base FS must transiently drop its vnode lock, the unionfs vnode may
1068 * it stops sharing its lock with the base vnode, so even if the
1069 * forwarded VOP reacquires the base vnode lock the unionfs vnode
1073 * 2) Loss of reference on the base vnode. The caller is expected to
1075 * unionfs vnode holds a reference on the base-layer vnode(s). But
1077 * doomed, violating the base layer's expectation that its caller
1080 * basevp1 and basevp2 represent two base-layer vnodes which are
1095 * Take an additional reference on the base-layer vnodes to in unionfs_forward_vop_start_pair()
1135 * used to re-lock unionvp1 and unionvp2, respectively, if either
1150 * a flag indicating that it needs to be re-locked. in unionfs_forward_vop_finish_pair()
1151 * Otherwise, simply drop the base-vnode reference that in unionfs_forward_vop_finish_pair()
1162 * If any of the unionfs vnodes need to be re-locked, that in unionfs_forward_vop_finish_pair()
1163 * means the unionfs vnode's lock is now de-coupled from the in unionfs_forward_vop_finish_pair()
1164 * corresponding base vnode. We therefore need to drop the in unionfs_forward_vop_finish_pair()
1165 * base vnode lock (since nothing else will after this point), in unionfs_forward_vop_finish_pair()
1182 * scenario would require at least re-locking the unionfs in unionfs_forward_vop_finish_pair()
1220 udvp = VTOUNIONFS(dvp)->un_uppervp; in unionfs_mkwhiteout()
1283 ump = MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp)->v_mount); in unionfs_vn_create_on_upper()
1285 lvp = unp->un_lowervp; in unionfs_vn_create_on_upper()
1286 cred = td->td_ucred; in unionfs_vn_create_on_upper()
1294 if (unp->un_path == NULL) in unionfs_vn_create_on_upper()
1297 nd.ni_cnd.cn_namelen = unp->un_pathlen; in unionfs_vn_create_on_upper()
1298 nd.ni_cnd.cn_pnbuf = unp->un_path; in unionfs_vn_create_on_upper()
1331 __func__, uvp, uvp->v_writecount); in unionfs_vn_create_on_upper()
1356 off_t offset; in unionfs_copyfile_core() local
1371 offset = uio.uio_offset; in unionfs_copyfile_core()
1382 if ((count = MAXBSIZE - uio.uio_resid) == 0) in unionfs_copyfile_core()
1390 iov.iov_len = count - bufoffset; in unionfs_copyfile_core()
1391 uio.uio_offset = offset + bufoffset; in unionfs_copyfile_core()
1398 bufoffset += (count - bufoffset) - uio.uio_resid; in unionfs_copyfile_core()
1401 uio.uio_offset = offset + bufoffset; in unionfs_copyfile_core()
1435 lvp = unp->un_lowervp; in unionfs_copyfile()
1438 if ((UNIONFSTOV(unp)->v_mount->mnt_flag & MNT_RDONLY)) in unionfs_copyfile()
1440 if (unp->un_dvp == NULLVP) in unionfs_copyfile()
1442 if (unp->un_uppervp != NULLVP) in unionfs_copyfile()
1446 VI_LOCK(unp->un_dvp); in unionfs_copyfile()
1447 dunp = VTOUNIONFS(unp->un_dvp); in unionfs_copyfile()
1449 udvp = dunp->un_uppervp; in unionfs_copyfile()
1450 VI_UNLOCK(unp->un_dvp); in unionfs_copyfile()
1454 if ((udvp->v_mount->mnt_flag & MNT_RDONLY)) in unionfs_copyfile()
1499 VOP_ADD_WRITECOUNT_CHECKED(uvp, -1); in unionfs_copyfile()
1501 __func__, uvp, uvp->v_writecount); in unionfs_copyfile()
1521 * We assume the VOP_RMDIR() against the upper layer vnode will take
1525 * then cross-check any files we find against the upper FS to see if
1527 * non-present).
1555 * to hold both the upper and lower layer locks as well as the upper in unionfs_check_rmdir()
1557 * deadlock. However, if the cross-check logic below needs to call in unionfs_check_rmdir()
1561 * below, such as VOP_OPEN() and VOP_READDIR(), may also re-lock the in unionfs_check_rmdir()
1568 * read-only) may change while the relevant lock is dropped. But in unionfs_check_rmdir()
1569 * since re-locking may happen here and open up such a window anyway, in unionfs_check_rmdir()
1573 * of out-of-band state changes) that we can avoid these costly checks in unionfs_check_rmdir()
1616 if (dp->d_type == DT_WHT) in unionfs_check_rmdir()
1623 switch (dp->d_namlen) { in unionfs_check_rmdir()
1625 if (dp->d_name[1] != '.') { in unionfs_check_rmdir()
1631 if (dp->d_name[0] != '.') { in unionfs_check_rmdir()
1640 cn.cn_namelen = dp->d_namlen; in unionfs_check_rmdir()
1642 cn.cn_nameptr = dp->d_name; in unionfs_check_rmdir()