diff options
author | jeff <jeff@FreeBSD.org> | 2006-02-01 00:25:26 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2006-02-01 00:25:26 +0000 |
commit | 30a231055bbecc02f17f1f4fe10c32564b6bcb22 (patch) | |
tree | 7bf7224bada967b7ee62d1c1257eab0efb97b47e /sys/kern/vfs_syscalls.c | |
parent | 34e5ca5b0218833663b71e333221ff426ec2e440 (diff) | |
download | FreeBSD-src-30a231055bbecc02f17f1f4fe10c32564b6bcb22.zip FreeBSD-src-30a231055bbecc02f17f1f4fe10c32564b6bcb22.tar.gz |
- Reorder calls to vrele() after calls to vput() when the vrele is a
directory. vrele() may lock the passed vnode, which in these cases would
give an invalid lock order of child -> parent. These situations are
deadlock prone although do not typically deadlock because the vrele
is typically not releasing the last reference to the vnode. Users of
vrele must consider it as a call to vn_lock() and order it appropriately.
MFC After: 1 week
Sponsored by: Isilon Systems, Inc.
Tested by: kkenn
Diffstat (limited to 'sys/kern/vfs_syscalls.c')
-rw-r--r-- | sys/kern/vfs_syscalls.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 2d61977..deff4a73 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1185,11 +1185,11 @@ restart: vp = nd.ni_vp; if (vp != NULL) { NDFREE(&nd, NDF_ONLY_PNBUF); - vrele(vp); if (vp == nd.ni_dvp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); + vrele(vp); VFS_UNLOCK_GIANT(vfslocked); return (EEXIST); } else { @@ -1288,11 +1288,11 @@ restart: vfslocked = NDHASGIANT(&nd); if (nd.ni_vp != NULL) { NDFREE(&nd, NDF_ONLY_PNBUF); - vrele(nd.ni_vp); if (nd.ni_vp == nd.ni_dvp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); + vrele(nd.ni_vp); VFS_UNLOCK_GIANT(vfslocked); return (EEXIST); } @@ -1425,11 +1425,11 @@ kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) if ((error = namei(&nd)) == 0) { lvfslocked = NDHASGIANT(&nd); if (nd.ni_vp != NULL) { - vrele(nd.ni_vp); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); + vrele(nd.ni_vp); error = EEXIST; } else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td)) == 0) { @@ -1502,11 +1502,11 @@ restart: vfslocked = NDHASGIANT(&nd); if (nd.ni_vp) { NDFREE(&nd, NDF_ONLY_PNBUF); - vrele(nd.ni_vp); if (nd.ni_vp == nd.ni_dvp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); + vrele(nd.ni_vp); VFS_UNLOCK_GIANT(vfslocked); error = EEXIST; goto out; @@ -1573,12 +1573,12 @@ restart: if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { NDFREE(&nd, NDF_ONLY_PNBUF); - if (nd.ni_vp) - vrele(nd.ni_vp); if (nd.ni_vp == nd.ni_dvp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); + if (nd.ni_vp) + vrele(nd.ni_vp); VFS_UNLOCK_GIANT(vfslocked); return (EEXIST); } @@ -1650,11 +1650,11 @@ restart: if (error == 0) { if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { NDFREE(&nd, NDF_ONLY_PNBUF); + vput(nd.ni_dvp); if (vp == nd.ni_dvp) vrele(vp); else vput(vp); - vput(nd.ni_dvp); VFS_UNLOCK_GIANT(vfslocked); if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) @@ -1675,11 +1675,11 @@ out: vn_finished_write(mp); } NDFREE(&nd, NDF_ONLY_PNBUF); + vput(nd.ni_dvp); if (vp == nd.ni_dvp) vrele(vp); else vput(vp); - vput(nd.ni_dvp); VFS_UNLOCK_GIANT(vfslocked); return (error); } @@ -3322,7 +3322,6 @@ restart: vp = nd.ni_vp; if (vp != NULL) { NDFREE(&nd, NDF_ONLY_PNBUF); - vrele(vp); /* * XXX namei called with LOCKPARENT but not LOCKLEAF has * the strange behaviour of leaving the vnode unlocked @@ -3332,6 +3331,7 @@ restart: vrele(nd.ni_dvp); else vput(nd.ni_dvp); + vrele(vp); VFS_UNLOCK_GIANT(vfslocked); return (EEXIST); } @@ -3429,11 +3429,11 @@ restart: #endif if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { NDFREE(&nd, NDF_ONLY_PNBUF); + vput(vp); if (nd.ni_dvp == vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); - vput(vp); VFS_UNLOCK_GIANT(vfslocked); if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) return (error); @@ -3445,11 +3445,11 @@ restart: vn_finished_write(mp); out: NDFREE(&nd, NDF_ONLY_PNBUF); + vput(vp); if (nd.ni_dvp == vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); - vput(vp); VFS_UNLOCK_GIANT(vfslocked); return (error); } |