vfs: Introduce vn_bmap_seekhole_locked()
vn_bmap_seekhole_locked() is factored out version of vn_bmap_seekhole(). This variant requires shared vnode lock being held around the call. Sponsored by: The FreeBSD Foundation Reviewed by: kib, markj Differential Revision: https://reviews.freebsd.org/D31404
This commit is contained in:
parent
de2e152959
commit
abbb57d5a6
@ -2425,7 +2425,8 @@ vn_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end)
|
||||
}
|
||||
|
||||
int
|
||||
vn_bmap_seekhole(struct vnode *vp, u_long cmd, off_t *off, struct ucred *cred)
|
||||
vn_bmap_seekhole_locked(struct vnode *vp, u_long cmd, off_t *off,
|
||||
struct ucred *cred)
|
||||
{
|
||||
struct vattr va;
|
||||
daddr_t bn, bnp;
|
||||
@ -2434,21 +2435,20 @@ vn_bmap_seekhole(struct vnode *vp, u_long cmd, off_t *off, struct ucred *cred)
|
||||
int error;
|
||||
|
||||
KASSERT(cmd == FIOSEEKHOLE || cmd == FIOSEEKDATA,
|
||||
("Wrong command %lu", cmd));
|
||||
("%s: Wrong command %lu", __func__, cmd));
|
||||
ASSERT_VOP_LOCKED(vp, "vn_bmap_seekhole_locked");
|
||||
|
||||
if (vn_lock(vp, LK_SHARED) != 0)
|
||||
return (EBADF);
|
||||
if (vp->v_type != VREG) {
|
||||
error = ENOTTY;
|
||||
goto unlock;
|
||||
goto out;
|
||||
}
|
||||
error = VOP_GETATTR(vp, &va, cred);
|
||||
if (error != 0)
|
||||
goto unlock;
|
||||
goto out;
|
||||
noff = *off;
|
||||
if (noff >= va.va_size) {
|
||||
error = ENXIO;
|
||||
goto unlock;
|
||||
goto out;
|
||||
}
|
||||
bsize = vp->v_mount->mnt_stat.f_iosize;
|
||||
for (bn = noff / bsize; noff < va.va_size; bn++, noff += bsize -
|
||||
@ -2456,14 +2456,14 @@ vn_bmap_seekhole(struct vnode *vp, u_long cmd, off_t *off, struct ucred *cred)
|
||||
error = VOP_BMAP(vp, bn, NULL, &bnp, NULL, NULL);
|
||||
if (error == EOPNOTSUPP) {
|
||||
error = ENOTTY;
|
||||
goto unlock;
|
||||
goto out;
|
||||
}
|
||||
if ((bnp == -1 && cmd == FIOSEEKHOLE) ||
|
||||
(bnp != -1 && cmd == FIOSEEKDATA)) {
|
||||
noff = bn * bsize;
|
||||
if (noff < *off)
|
||||
noff = *off;
|
||||
goto unlock;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (noff > va.va_size)
|
||||
@ -2471,13 +2471,27 @@ vn_bmap_seekhole(struct vnode *vp, u_long cmd, off_t *off, struct ucred *cred)
|
||||
/* noff == va.va_size. There is an implicit hole at the end of file. */
|
||||
if (cmd == FIOSEEKDATA)
|
||||
error = ENXIO;
|
||||
unlock:
|
||||
VOP_UNLOCK(vp);
|
||||
out:
|
||||
if (error == 0)
|
||||
*off = noff;
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
vn_bmap_seekhole(struct vnode *vp, u_long cmd, off_t *off, struct ucred *cred)
|
||||
{
|
||||
int error;
|
||||
|
||||
KASSERT(cmd == FIOSEEKHOLE || cmd == FIOSEEKDATA,
|
||||
("%s: Wrong command %lu", __func__, cmd));
|
||||
|
||||
if (vn_lock(vp, LK_SHARED) != 0)
|
||||
return (EBADF);
|
||||
error = vn_bmap_seekhole_locked(vp, cmd, off, cred);
|
||||
VOP_UNLOCK(vp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
vn_seek(struct file *fp, off_t offset, int whence, struct thread *td)
|
||||
{
|
||||
|
@ -731,6 +731,8 @@ void vunref(struct vnode *);
|
||||
void vn_printf(struct vnode *vp, const char *fmt, ...) __printflike(2,3);
|
||||
int vrecycle(struct vnode *vp);
|
||||
int vrecyclel(struct vnode *vp);
|
||||
int vn_bmap_seekhole_locked(struct vnode *vp, u_long cmd, off_t *off,
|
||||
struct ucred *cred);
|
||||
int vn_bmap_seekhole(struct vnode *vp, u_long cmd, off_t *off,
|
||||
struct ucred *cred);
|
||||
int vn_close(struct vnode *vp,
|
||||
|
Loading…
Reference in New Issue
Block a user