version 1.124.2.1, 2014/05/18 17:46:22 |
version 1.125, 2013/09/15 15:08:09 |
|
|
int |
int |
ufs_lookup(void *v) |
ufs_lookup(void *v) |
{ |
{ |
struct vop_lookup_v2_args /* { |
struct vop_lookup_args /* { |
struct vnode *a_dvp; |
struct vnode *a_dvp; |
struct vnode **a_vpp; |
struct vnode **a_vpp; |
struct componentname *a_cnp; |
struct componentname *a_cnp; |
Line 137 ufs_lookup(void *v) |
|
Line 137 ufs_lookup(void *v) |
|
int numdirpasses; /* strategy for directory search */ |
int numdirpasses; /* strategy for directory search */ |
doff_t endsearch; /* offset to end directory search */ |
doff_t endsearch; /* offset to end directory search */ |
doff_t prevoff; /* previous value of ulr_offset */ |
doff_t prevoff; /* previous value of ulr_offset */ |
struct vnode *tdp; /* returned by vcache_get */ |
struct vnode *pdp; /* saved dp during symlink work */ |
|
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. |
used for directory truncation. */ |
used for directory truncation. */ |
u_long bmask; /* block offset mask */ |
u_long bmask; /* block offset mask */ |
|
|
vref(vdp); |
vref(vdp); |
tdp = vdp; |
tdp = vdp; |
} else { |
} else { |
error = vcache_get(vdp->v_mount, |
if (flags & ISDOTDOT) |
&foundino, sizeof(foundino), &tdp); |
VOP_UNLOCK(vdp); /* race to get the inode */ |
|
error = VFS_VGET(vdp->v_mount, foundino, &tdp); |
|
if (flags & ISDOTDOT) |
|
vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY); |
if (error) |
if (error) |
goto out; |
goto out; |
} |
} |
|
|
*/ |
*/ |
error = VOP_ACCESS(vdp, VWRITE, cred); |
error = VOP_ACCESS(vdp, VWRITE, cred); |
if (error) { |
if (error) { |
vrele(tdp); |
if (dp->i_number == foundino) |
|
vrele(tdp); |
|
else |
|
vput(tdp); |
goto out; |
goto out; |
} |
} |
/* |
/* |
|
|
tdp, vdp, genfs_can_sticky(cred, dp->i_uid, |
tdp, vdp, genfs_can_sticky(cred, dp->i_uid, |
VTOI(tdp)->i_uid)); |
VTOI(tdp)->i_uid)); |
if (error) { |
if (error) { |
vrele(tdp); |
if (dp->i_number == foundino) |
|
vrele(tdp); |
|
else |
|
vput(tdp); |
error = EPERM; |
error = EPERM; |
goto out; |
goto out; |
} |
} |
|
|
error = EISDIR; |
error = EISDIR; |
goto out; |
goto out; |
} |
} |
error = vcache_get(vdp->v_mount, |
if (flags & ISDOTDOT) |
&foundino, sizeof(foundino), &tdp); |
VOP_UNLOCK(vdp); /* race to get the inode */ |
|
error = VFS_VGET(vdp->v_mount, foundino, &tdp); |
|
if (flags & ISDOTDOT) |
|
vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY); |
if (error) |
if (error) |
goto out; |
goto out; |
*vpp = tdp; |
*vpp = tdp; |
|
|
goto out; |
goto out; |
} |
} |
|
|
if (dp->i_number == foundino) { |
/* |
|
* Step through the translation in the name. We do not `vput' the |
|
* directory because we may need it again if a symbolic link |
|
* is relative to the current directory. Instead we save it |
|
* unlocked as "pdp". We must get the target inode before unlocking |
|
* the directory to insure that the inode will not be removed |
|
* before we get it. We prevent deadlock by always fetching |
|
* inodes from the root, moving down the directory tree. Thus |
|
* when following backward pointers ".." we must unlock the |
|
* parent directory before getting the requested directory. |
|
* There is a potential race condition here if both the current |
|
* and parent directories are removed before the VFS_VGET for the |
|
* inode associated with ".." returns. We hope that this occurs |
|
* infrequently since we cannot avoid this race condition without |
|
* implementing a sophisticated deadlock detection algorithm. |
|
* Note also that this simple deadlock detection scheme will not |
|
* work if the file system has any hard links other than ".." |
|
* that point backwards in the directory structure. |
|
*/ |
|
pdp = vdp; |
|
if (flags & ISDOTDOT) { |
|
VOP_UNLOCK(pdp); /* race to get the inode */ |
|
error = VFS_VGET(vdp->v_mount, foundino, &tdp); |
|
vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY); |
|
if (error) { |
|
goto out; |
|
} |
|
*vpp = tdp; |
|
} else if (dp->i_number == foundino) { |
vref(vdp); /* we want ourself, ie "." */ |
vref(vdp); /* we want ourself, ie "." */ |
*vpp = vdp; |
*vpp = vdp; |
} else { |
} else { |
error = vcache_get(vdp->v_mount, |
error = VFS_VGET(vdp->v_mount, foundino, &tdp); |
&foundino, sizeof(foundino), &tdp); |
|
if (error) |
if (error) |
goto out; |
goto out; |
*vpp = tdp; |
*vpp = tdp; |
Line 1028 ufs_dirremove(struct vnode *dvp, const s |
|
Line 1068 ufs_dirremove(struct vnode *dvp, const s |
|
struct direct *ep; |
struct direct *ep; |
struct buf *bp; |
struct buf *bp; |
int error; |
int error; |
|
#ifdef FFS_EI |
const int needswap = UFS_MPNEEDSWAP(dp->i_ump); |
const int needswap = UFS_MPNEEDSWAP(dp->i_ump); |
|
#endif |
|
|
UFS_WAPBL_JLOCK_ASSERT(dvp->v_mount); |
UFS_WAPBL_JLOCK_ASSERT(dvp->v_mount); |
|
|
Line 1363 ufs_parentcheck(struct vnode *upper, str |
|
Line 1405 ufs_parentcheck(struct vnode *upper, str |
|
int *found_ret, struct vnode **upperchild_ret) |
int *found_ret, struct vnode **upperchild_ret) |
{ |
{ |
const int needswap = UFS_MPNEEDSWAP(VTOI(lower)->i_ump); |
const int needswap = UFS_MPNEEDSWAP(VTOI(lower)->i_ump); |
ino_t upper_ino, found_ino = 0; /* XXX: gcc */ |
ino_t upper_ino, found_ino; |
struct vnode *current, *next; |
struct vnode *current, *next; |
int error; |
int error; |
|
|
|
|
ufs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp, |
ufs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp, |
bool modify) |
bool modify) |
{ |
{ |
struct inode *ip __diagused; |
struct inode *ip; |
struct buf *bp; |
struct buf *bp; |
daddr_t lbn; |
daddr_t lbn; |
const int dirrablks = ufs_dirrablks; |
const int dirrablks = ufs_dirrablks; |