version 1.80.2.1, 2007/02/16 20:05:36 |
version 1.80.2.2, 2007/02/17 23:27:53 |
Line 131 ufs_lookup(void *v) |
|
Line 131 ufs_lookup(void *v) |
|
struct vnode *tdp; /* returned by VFS_VGET */ |
struct vnode *tdp; /* returned by VFS_VGET */ |
doff_t enduseful; /* pointer past last used dir slot */ |
doff_t enduseful; /* pointer past last used dir slot */ |
u_long bmask; /* block offset mask */ |
u_long bmask; /* block offset mask */ |
int lockparent; /* 1 => lockparent flag is set */ |
|
int wantparent; /* 1 => wantparent or lockparent flag */ |
|
int namlen, error; |
int namlen, error; |
struct vnode **vpp = ap->a_vpp; |
struct vnode **vpp = ap->a_vpp; |
struct componentname *cnp = ap->a_cnp; |
struct componentname *cnp = ap->a_cnp; |
Line 144 ufs_lookup(void *v) |
|
Line 142 ufs_lookup(void *v) |
|
int dirblksiz = ump->um_dirblksiz; |
int dirblksiz = ump->um_dirblksiz; |
ino_t foundino; |
ino_t foundino; |
|
|
cnp->cn_flags &= ~PDIRUNLOCK; |
|
flags = cnp->cn_flags; |
flags = cnp->cn_flags; |
|
|
bp = NULL; |
bp = NULL; |
slotoffset = -1; |
slotoffset = -1; |
*vpp = NULL; |
*vpp = NULL; |
lockparent = flags & LOCKPARENT; |
|
wantparent = flags & (LOCKPARENT|WANTPARENT); |
|
endsearch = 0; /* silence compiler warning */ |
endsearch = 0; /* silence compiler warning */ |
/* |
/* |
* Check accessiblity of directory. |
* Check accessiblity of directory. |
Line 170 ufs_lookup(void *v) |
|
Line 165 ufs_lookup(void *v) |
|
* check the name cache to see if the directory/name pair |
* check the name cache to see if the directory/name pair |
* we are looking for is known already. |
* we are looking for is known already. |
*/ |
*/ |
if ((error = cache_lookup(vdp, vpp, cnp)) >= 0) |
if ((error = cache_lookup(vdp, vpp, cnp)) >= 0) { |
return (error); |
return (error); |
|
} |
|
|
/* |
/* |
* Suppress search for slots unless creating |
* Suppress search for slots unless creating |
|
|
* information cannot be used. |
* information cannot be used. |
*/ |
*/ |
cnp->cn_flags |= SAVENAME; |
cnp->cn_flags |= SAVENAME; |
if (!lockparent) { |
|
VOP_UNLOCK(vdp, 0); |
|
cnp->cn_flags |= PDIRUNLOCK; |
|
} |
|
return (EJUSTRETURN); |
return (EJUSTRETURN); |
} |
} |
/* |
/* |
|
|
/* |
/* |
* If deleting, and at end of pathname, return |
* If deleting, and at end of pathname, return |
* parameters which can be used to remove file. |
* parameters which can be used to remove file. |
* If the wantparent flag isn't set, we return only |
* Lock the inode, being careful with ".". |
* the directory (in ndp->ni_dvp), otherwise we go |
|
* on and lock the inode, being careful with ".". |
|
*/ |
*/ |
if (nameiop == DELETE && (flags & ISLASTCN)) { |
if (nameiop == DELETE && (flags & ISLASTCN)) { |
/* |
/* |
|
|
return (EPERM); |
return (EPERM); |
} |
} |
*vpp = tdp; |
*vpp = tdp; |
if (!lockparent) { |
|
VOP_UNLOCK(vdp, 0); |
|
cnp->cn_flags |= PDIRUNLOCK; |
|
} |
|
return (0); |
return (0); |
} |
} |
|
|
|
|
* Must get inode of directory entry to verify it's a |
* Must get inode of directory entry to verify it's a |
* regular file, or empty directory. |
* regular file, or empty directory. |
*/ |
*/ |
if (nameiop == RENAME && wantparent && (flags & ISLASTCN)) { |
if (nameiop == RENAME && (flags & ISLASTCN)) { |
error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_lwp); |
error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_lwp); |
if (error) |
if (error) |
return (error); |
return (error); |
|
|
return (error); |
return (error); |
*vpp = tdp; |
*vpp = tdp; |
cnp->cn_flags |= SAVENAME; |
cnp->cn_flags |= SAVENAME; |
if (!lockparent) { |
|
VOP_UNLOCK(vdp, 0); |
|
cnp->cn_flags |= PDIRUNLOCK; |
|
} |
|
return (0); |
return (0); |
} |
} |
|
|
|
|
pdp = vdp; |
pdp = vdp; |
if (flags & ISDOTDOT) { |
if (flags & ISDOTDOT) { |
VOP_UNLOCK(pdp, 0); /* race to get the inode */ |
VOP_UNLOCK(pdp, 0); /* race to get the inode */ |
cnp->cn_flags |= PDIRUNLOCK; |
|
error = VFS_VGET(vdp->v_mount, foundino, &tdp); |
error = VFS_VGET(vdp->v_mount, foundino, &tdp); |
|
vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY); |
if (error) { |
if (error) { |
if (vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY) == 0) |
return error; |
cnp->cn_flags &= ~PDIRUNLOCK; |
|
return (error); |
|
} |
|
if (lockparent && (flags & ISLASTCN)) { |
|
if ((error = vn_lock(pdp, LK_EXCLUSIVE))) { |
|
vput(tdp); |
|
return (error); |
|
} |
|
cnp->cn_flags &= ~PDIRUNLOCK; |
|
} |
} |
*vpp = tdp; |
*vpp = tdp; |
} else if (dp->i_number == foundino) { |
} else if (dp->i_number == foundino) { |
|
|
error = VFS_VGET(vdp->v_mount, foundino, &tdp); |
error = VFS_VGET(vdp->v_mount, foundino, &tdp); |
if (error) |
if (error) |
return (error); |
return (error); |
if (!lockparent || !(flags & ISLASTCN)) { |
|
VOP_UNLOCK(pdp, 0); |
|
cnp->cn_flags |= PDIRUNLOCK; |
|
} |
|
*vpp = tdp; |
*vpp = tdp; |
} |
} |
|
|