mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-16 10:20:30 +00:00
Use NET_LOCK_GIANT() and VFS_LOCK_GIANT() instead of unconditionally
acquiring Giant in kern_sendfile(). Guard against the forced reclamation of a vnode in kern_sendfile(). Discussed with: jeff Reviewed by: tegge MFC after: 3 weeks
This commit is contained in:
parent
1322b45c3d
commit
7c8dcf2def
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=157171
@ -1799,15 +1799,16 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap,
|
||||
struct uio *hdr_uio, struct uio *trl_uio, int compat)
|
||||
{
|
||||
struct vnode *vp;
|
||||
struct vm_object *obj;
|
||||
struct vm_object *obj = NULL;
|
||||
struct socket *so = NULL;
|
||||
struct mbuf *m, *m_header = NULL;
|
||||
struct sf_buf *sf;
|
||||
struct vm_page *pg;
|
||||
off_t off, xfsize, hdtr_size, sbytes = 0;
|
||||
int error, headersize = 0, headersent = 0;
|
||||
int vfslocked;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
NET_LOCK_GIANT();
|
||||
|
||||
hdtr_size = 0;
|
||||
|
||||
@ -1816,9 +1817,26 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap,
|
||||
*/
|
||||
if ((error = fgetvp_read(td, uap->fd, &vp)) != 0)
|
||||
goto done;
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
|
||||
obj = vp->v_object;
|
||||
if (obj != NULL) {
|
||||
/*
|
||||
* Temporarily increase the backing VM object's reference
|
||||
* count so that a forced reclamation of its vnode does not
|
||||
* immediately destroy it.
|
||||
*/
|
||||
VM_OBJECT_LOCK(obj);
|
||||
if ((obj->flags & OBJ_DEAD) == 0) {
|
||||
vm_object_reference_locked(obj);
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
} else {
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
obj = NULL;
|
||||
}
|
||||
}
|
||||
VOP_UNLOCK(vp, 0, td);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
if (obj == NULL) {
|
||||
error = EINVAL;
|
||||
goto done;
|
||||
@ -1974,6 +1992,7 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap,
|
||||
* Get the page from backing store.
|
||||
*/
|
||||
bsize = vp->v_mount->mnt_stat.f_iosize;
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
vn_lock(vp, LK_SHARED | LK_RETRY, td);
|
||||
/*
|
||||
* XXXMAC: Because we don't have fp->f_cred here,
|
||||
@ -1985,6 +2004,7 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap,
|
||||
IO_VMIO | ((MAXBSIZE / bsize) << IO_SEQSHIFT),
|
||||
td->td_ucred, NOCRED, &resid, td);
|
||||
VOP_UNLOCK(vp, 0, td);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
VM_OBJECT_LOCK(obj);
|
||||
vm_page_lock_queues();
|
||||
vm_page_io_finish(pg);
|
||||
@ -2164,14 +2184,19 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap,
|
||||
sbytes += hdtr_size;
|
||||
copyout(&sbytes, uap->sbytes, sizeof(off_t));
|
||||
}
|
||||
if (vp)
|
||||
if (obj != NULL)
|
||||
vm_object_deallocate(obj);
|
||||
if (vp != NULL) {
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
vrele(vp);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
}
|
||||
if (so)
|
||||
fputsock(so);
|
||||
if (m_header)
|
||||
m_freem(m_header);
|
||||
|
||||
mtx_unlock(&Giant);
|
||||
NET_UNLOCK_GIANT();
|
||||
|
||||
if (error == ERESTART)
|
||||
error = EINTR;
|
||||
|
Loading…
Reference in New Issue
Block a user