Lines Matching +full:parent +full:- +full:locked
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 != NULL) { 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 != NULL) { 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 != NULL ? in unionfs_ins_cached_vnode()
221 uncp->un_uppervp : uncp->un_lowervp)); in unionfs_ins_cached_vnode()
237 ("%s: null parent vnode", __func__)); in unionfs_rem_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()
250 * Upper, lower, and parent directory vnodes are expected to be referenced by
251 * the caller. Upper and lower vnodes, if non-NULL, are also expected to be
252 * exclusively locked by the caller.
260 * Lock and reset the default vnode lock; vgone() expects a locked in unionfs_nodeget_cleanup()
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 != NULL) in unionfs_nodeget_cleanup()
278 vrele(unp->un_dvp); in unionfs_nodeget_cleanup()
279 if (unp->un_uppervp != NULL) { in unionfs_nodeget_cleanup()
280 vput(unp->un_uppervp); in unionfs_nodeget_cleanup()
281 if (unp->un_lowervp != NULL) in unionfs_nodeget_cleanup()
282 vrele(unp->un_lowervp); in unionfs_nodeget_cleanup()
283 } else if (unp->un_lowervp != NULL) 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()
295 * locked, uppervp or lowervp is locked too. In order to prevent dead lock,
314 lkflags = (cnp ? cnp->cn_lkflags : 0); in unionfs_nodeget()
315 path = (cnp ? cnp->cn_nameptr : NULL); in unionfs_nodeget()
321 vt = (uppervp != NULL ? 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()
395 * If dvp has an upper FS component and is locked, while the new vnode 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()
400 * a child vnode lock is taken while holding a lock on its parent in unionfs_nodeget()
402 * a few places within unionfs (which could lead to the same cross-FS in unionfs_nodeget()
473 * which is locked across VFS_UNMOUNT(). This lock will then be in unionfs_noderem()
479 KASSERT(vp->v_vnlock->lk_recurse == 0 || (vp->v_vflag & VV_ROOT) != 0, in unionfs_noderem()
480 ("%s: vnode %p locked recursively", __func__, vp)); 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()
496 * Moreover, during unmount of a non-"below" unionfs mount, the lower in unionfs_noderem()
497 * root vnode will already be locked as it is the covered vnode. in unionfs_noderem()
499 if (uvp != NULL && lvp != NULL && (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 = NULL; 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()
591 pid = td->td_proc->p_pid; in unionfs_find_node_status()
595 LIST_FOREACH(unsp, &(unp->un_unshead), uns_list) { in unionfs_find_node_status()
596 if (unsp->uns_pid == pid) { in unionfs_find_node_status()
617 pid = td->td_proc->p_pid; in unionfs_get_node_status()
626 unsp->uns_pid = pid; in unionfs_get_node_status()
627 LIST_INSERT_HEAD(&(unp->un_unshead), unsp, uns_list); in unionfs_get_node_status()
644 if (0 < unsp->uns_lower_opencnt || 0 < unsp->uns_upper_opencnt) in unionfs_tryrem_node_status()
659 uva->va_type = lva->va_type; in unionfs_create_uppervattr_core()
660 uva->va_atime = lva->va_atime; in unionfs_create_uppervattr_core()
661 uva->va_mtime = lva->va_mtime; in unionfs_create_uppervattr_core()
662 uva->va_ctime = lva->va_ctime; in unionfs_create_uppervattr_core()
664 switch (ump->um_copymode) { in unionfs_create_uppervattr_core()
666 uva->va_mode = lva->va_mode; in unionfs_create_uppervattr_core()
667 uva->va_uid = lva->va_uid; in unionfs_create_uppervattr_core()
668 uva->va_gid = lva->va_gid; in unionfs_create_uppervattr_core()
671 if (ump->um_uid == lva->va_uid) { in unionfs_create_uppervattr_core()
672 uva->va_mode = lva->va_mode & 077077; in unionfs_create_uppervattr_core()
673 uva->va_mode |= (lva->va_type == VDIR ? in unionfs_create_uppervattr_core()
674 ump->um_udir : ump->um_ufile) & 0700; in unionfs_create_uppervattr_core()
675 uva->va_uid = lva->va_uid; in unionfs_create_uppervattr_core()
676 uva->va_gid = lva->va_gid; in unionfs_create_uppervattr_core()
678 uva->va_mode = (lva->va_type == VDIR ? in unionfs_create_uppervattr_core()
679 ump->um_udir : ump->um_ufile); in unionfs_create_uppervattr_core()
680 uva->va_uid = ump->um_uid; in unionfs_create_uppervattr_core()
681 uva->va_gid = ump->um_gid; in unionfs_create_uppervattr_core()
685 uva->va_mode = 0777 & ~td->td_proc->p_pd->pd_cmask; in unionfs_create_uppervattr_core()
686 uva->va_uid = ump->um_uid; in unionfs_create_uppervattr_core()
687 uva->va_gid = ump->um_gid; in unionfs_create_uppervattr_core()
713 * dvp should be locked on entry and will be locked on return.
716 * locked, referenced vnode. If *vpp == dvp then remember that only one
727 cn->cn_namelen = pathlen; in unionfs_relookup()
728 cn->cn_pnbuf = path; in unionfs_relookup()
729 cn->cn_nameiop = nameiop; in unionfs_relookup()
730 cn->cn_flags = (LOCKPARENT | LOCKLEAF | ISLASTCN); in unionfs_relookup()
731 cn->cn_lkflags = LK_EXCLUSIVE; in unionfs_relookup()
732 cn->cn_cred = cnp->cn_cred; in unionfs_relookup()
733 cn->cn_nameptr = cn->cn_pnbuf; in unionfs_relookup()
737 cn->cn_flags |= (cnp->cn_flags & DOWHITEOUT); in unionfs_relookup()
741 cn->cn_flags |= NOCACHE; in unionfs_relookup()
752 KASSERT(cn->cn_pnbuf == path, ("%s: cn_pnbuf changed", __func__)); in unionfs_relookup()
760 * uvp is new locked upper vnode. unionfs vnode's lock will be exchanged to the
774 lvp = unp->un_lowervp; in unionfs_node_update()
777 dvp = unp->un_dvp; in unionfs_node_update()
779 VNASSERT(vp->v_writecount == 0, vp, in unionfs_node_update()
780 ("%s: non-zero writecount", __func__)); in unionfs_node_update()
785 lockrec = lvp->v_vnlock->lk_recurse; in unionfs_node_update()
789 unp->un_uppervp = uvp; in unionfs_node_update()
790 vp->v_vnlock = uvp->v_vnlock; in unionfs_node_update()
796 * Re-cache the unionfs vnode against the upper vnode in unionfs_node_update()
798 if (dvp != NULL && vp->v_type == VDIR) { in unionfs_node_update()
800 if (unp->un_hash.le_prev != NULL) { in unionfs_node_update()
805 VI_UNLOCK(unp->un_dvp); in unionfs_node_update()
812 * This is useful, for example, during copy-up operations in which
814 * possibility of a concurrent copy-up on the same vnode triggering
827 while (error == 0 && (unp->un_flag & flag) != 0) { in unionfs_set_in_progress_flag()
834 * If we waited on a concurrent copy-up and that in unionfs_set_in_progress_flag()
835 * copy-up was successful, return a non-fatal in unionfs_set_in_progress_flag()
839 * be re-queried to avoid creating a duplicate unionfs in unionfs_set_in_progress_flag()
846 unp->un_uppervp != NULL) in unionfs_set_in_progress_flag()
853 unp->un_flag |= flag; in unionfs_set_in_progress_flag()
868 VNASSERT((unp->un_flag & flag) != 0, vp, in unionfs_clear_in_progress_flag()
870 unp->un_flag &= ~flag; in unionfs_clear_in_progress_flag()
879 * dvp and vp are unionfs vnodes representing a parent directory and
880 * child file, should be locked on entry, and will be locked on return.
905 ump = MOUNTTOUNIONFSMOUNT(vp->v_mount); in unionfs_mkshadowdir()
907 if (unp->un_uppervp != NULL) in unionfs_mkshadowdir()
910 udvp = dunp->un_uppervp; in unionfs_mkshadowdir()
918 lvp = unp->un_lowervp; in unionfs_mkshadowdir()
920 credbk = cnp->cn_cred; in unionfs_mkshadowdir()
924 cred = crdup(cnp->cn_cred); in unionfs_mkshadowdir()
929 cnp->cn_cred = cred; in unionfs_mkshadowdir()
934 if ((error = VOP_GETATTR(lvp, &lva, cnp->cn_cred))) in unionfs_mkshadowdir()
940 cnp->cn_nameptr, cnp->cn_namelen, CREATE))) { in unionfs_mkshadowdir()
976 * Temporarily NUL-terminate the current pathname component. in unionfs_mkshadowdir()
986 * NUL-termination will not have an effect on other threads. in unionfs_mkshadowdir()
1045 cnp->cn_cred = credbk; in unionfs_mkshadowdir()
1063 * The unionfs vnode shares its lock with the base-layer vnode(s); if the
1077 * unionfs vnode holds a reference on the base-layer vnode(s). But
1082 * basevp1 and basevp2 represent two base-layer vnodes which are
1083 * expected to be locked when this function is called. basevp2
1085 * a parent directory and a filed linked to it, respectively.
1097 * Take an additional reference on the base-layer vnodes to in unionfs_forward_vop_start_pair()
1133 * basevp1 and basevp2 (if not NULL) must be locked when this function
1137 * used to re-lock unionvp1 and unionvp2, respectively, if either
1152 * a flag indicating that it needs to be re-locked. in unionfs_forward_vop_finish_pair()
1153 * Otherwise, simply drop the base-vnode reference that in unionfs_forward_vop_finish_pair()
1164 * If any of the unionfs vnodes need to be re-locked, that in unionfs_forward_vop_finish_pair()
1165 * means the unionfs vnode's lock is now de-coupled from the in unionfs_forward_vop_finish_pair()
1176 * be able to safely unlock it with basevp2 still locked, in unionfs_forward_vop_finish_pair()
1184 * scenario would require at least re-locking the unionfs in unionfs_forward_vop_finish_pair()
1205 * dvp and vp are unionfs vnodes representing a parent directory and
1206 * child file, should be locked on entry, and will be locked on return.
1222 udvp = VTOUNIONFS(dvp)->un_uppervp; in unionfs_mkwhiteout()
1265 * locked, referenced and opened vnode.
1285 ump = MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp)->v_mount); in unionfs_vn_create_on_upper()
1287 lvp = unp->un_lowervp; in unionfs_vn_create_on_upper()
1288 cred = td->td_ucred; in unionfs_vn_create_on_upper()
1296 if (unp->un_path == NULL) in unionfs_vn_create_on_upper()
1299 nd.ni_cnd.cn_namelen = unp->un_pathlen; in unionfs_vn_create_on_upper()
1300 nd.ni_cnd.cn_pnbuf = unp->un_path; in unionfs_vn_create_on_upper()
1333 __func__, uvp, uvp->v_writecount); in unionfs_vn_create_on_upper()
1348 * lvp and uvp should be locked and opened on entry and will be locked and
1384 if ((count = MAXBSIZE - uio.uio_resid) == 0) in unionfs_copyfile_core()
1392 iov.iov_len = count - bufoffset; in unionfs_copyfile_core()
1400 bufoffset += (count - bufoffset) - uio.uio_resid; in unionfs_copyfile_core()
1417 * vp is a unionfs vnode that should be locked on entry and will be
1418 * locked on return.
1437 lvp = unp->un_lowervp; in unionfs_copyfile()
1440 if ((UNIONFSTOV(unp)->v_mount->mnt_flag & MNT_RDONLY)) in unionfs_copyfile()
1442 if (unp->un_dvp == NULL) in unionfs_copyfile()
1444 if (unp->un_uppervp != NULL) in unionfs_copyfile()
1448 VI_LOCK(unp->un_dvp); in unionfs_copyfile()
1449 dunp = VTOUNIONFS(unp->un_dvp); in unionfs_copyfile()
1451 udvp = dunp->un_uppervp; in unionfs_copyfile()
1452 VI_UNLOCK(unp->un_dvp); in unionfs_copyfile()
1456 if ((udvp->v_mount->mnt_flag & MNT_RDONLY)) in unionfs_copyfile()
1481 * uvp below while holding vp[=lvp] locked. Replacing in unionfs_copyfile()
1501 VOP_ADD_WRITECOUNT_CHECKED(uvp, -1); in unionfs_copyfile()
1503 __func__, uvp, uvp->v_writecount); in unionfs_copyfile()
1527 * then cross-check any files we find against the upper FS to see if
1529 * non-present).
1533 * vp should be a locked unionfs node, and vp's lowervp should also be
1534 * locked.
1558 * parent directory lock, which it can do in a manner that avoids in unionfs_check_rmdir()
1559 * deadlock. However, if the cross-check logic below needs to call in unionfs_check_rmdir()
1563 * below, such as VOP_OPEN() and VOP_READDIR(), may also re-lock the in unionfs_check_rmdir()
1566 * (and its parent directory lock) and the lower vnode lock as needed, in unionfs_check_rmdir()
1570 * read-only) may change while the relevant lock is dropped. But in unionfs_check_rmdir()
1571 * since re-locking may happen here and open up such a window anyway, in unionfs_check_rmdir()
1575 * of out-of-band state changes) that we can avoid these costly checks in unionfs_check_rmdir()
1618 if (dp->d_type == DT_WHT) in unionfs_check_rmdir()
1625 switch (dp->d_namlen) { in unionfs_check_rmdir()
1627 if (dp->d_name[1] != '.') { in unionfs_check_rmdir()
1633 if (dp->d_name[0] != '.') { in unionfs_check_rmdir()
1642 cn.cn_namelen = dp->d_namlen; in unionfs_check_rmdir()
1644 cn.cn_nameptr = dp->d_name; in unionfs_check_rmdir()