Index: sys/kern/kern_sendfile.c =================================================================== --- sys/kern/kern_sendfile.c +++ sys/kern/kern_sendfile.c @@ -565,7 +565,6 @@ struct vnode **vp_res, struct shmfd **shmfd_res, off_t *obj_size, int *bsize) { - struct vattr va; vm_object_t obj; struct vnode *vp; struct shmfd *shmfd; @@ -588,28 +587,26 @@ goto out; } *bsize = vp->v_mount->mnt_stat.f_iosize; - error = VOP_GETATTR(vp, &va, td->td_ucred); - if (error != 0) - goto out; - *obj_size = va.va_size; obj = vp->v_object; if (obj == NULL) { error = EINVAL; goto out; } + VM_OBJECT_RLOCK(obj); + *obj_size = obj->un_pager.vnp.vnp_size; } else if (fp->f_type == DTYPE_SHM) { error = 0; shmfd = fp->f_data; obj = shmfd->shm_object; - *obj_size = shmfd->shm_size; + VM_OBJECT_RLOCK(obj); + *obj_size = obj->size; } else { error = EINVAL; goto out; } - VM_OBJECT_WLOCK(obj); if ((obj->flags & OBJ_DEAD) != 0) { - VM_OBJECT_WUNLOCK(obj); + VM_OBJECT_RUNLOCK(obj); error = EBADF; goto out; } @@ -620,7 +617,7 @@ * immediately destroy it. */ vm_object_reference_locked(obj); - VM_OBJECT_WUNLOCK(obj); + VM_OBJECT_RUNLOCK(obj); *obj_res = obj; *vp_res = vp; *shmfd_res = shmfd; @@ -678,8 +675,7 @@ struct sf_buf *sf; struct shmfd *shmfd; struct sendfile_sync *sfs; - struct vattr va; - off_t off, sbytes, rem, obj_size; + off_t off, sbytes, rem, obj_size, nobj_size; int bsize, error, ext_pgs_idx, hdrlen, max_pgs, softerr; #ifdef KERN_TLS int tls_enq_cnt; @@ -852,17 +848,27 @@ error = vn_lock(vp, LK_SHARED); if (error != 0) goto done; - error = VOP_GETATTR(vp, &va, td->td_ucred); - if (error != 0 || off >= va.va_size) { + } + + /* + * Check to see if the file size has changed. + */ + VM_OBJECT_RLOCK(obj); + if (obj->type == OBJT_VNODE) + nobj_size = obj->un_pager.vnp.vnp_size; + else + nobj_size = obj->size; + VM_OBJECT_RUNLOCK(obj); + if (off >= nobj_size) { + if (vp != NULL) VOP_UNLOCK(vp); - goto done; - } - if (va.va_size != obj_size) { - obj_size = va.va_size; - rem = nbytes ? - omin(nbytes + offset, obj_size) : obj_size; - rem -= off; - } + goto done; + } + if (nobj_size != obj_size) { + obj_size = nobj_size; + rem = nbytes ? omin(nbytes + offset, obj_size) : + obj_size; + rem -= off; } if (space > rem)