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:
Ka Ho Ng 2021-08-05 03:20:59 +08:00
parent de2e152959
commit abbb57d5a6
2 changed files with 27 additions and 11 deletions

View File

@ -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)
{

View File

@ -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,