Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_default.c
Show First 20 Lines • Show All 947 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
struct iovec aiov; | struct iovec aiov; | ||||
struct vattr vattr, *vap; | struct vattr vattr, *vap; | ||||
struct uio auio; | struct uio auio; | ||||
off_t fsize, len, cur, offset; | off_t fsize, len, cur, offset; | ||||
uint8_t *buf; | uint8_t *buf; | ||||
struct thread *td; | struct thread *td; | ||||
struct vnode *vp; | struct vnode *vp; | ||||
struct ucred *cred; | |||||
size_t iosize; | size_t iosize; | ||||
int error; | int error; | ||||
buf = NULL; | buf = NULL; | ||||
error = 0; | error = 0; | ||||
td = curthread; | td = curthread; | ||||
vap = &vattr; | vap = &vattr; | ||||
vp = ap->a_vp; | vp = ap->a_vp; | ||||
len = *ap->a_len; | len = *ap->a_len; | ||||
offset = *ap->a_offset; | offset = *ap->a_offset; | ||||
cred = ap->a_cred; | |||||
error = VOP_GETATTR(vp, vap, td->td_ucred); | error = VOP_GETATTR(vp, vap, cred); | ||||
if (error != 0) | if (error != 0) | ||||
goto out; | goto out; | ||||
fsize = vap->va_size; | fsize = vap->va_size; | ||||
iosize = vap->va_blocksize; | iosize = vap->va_blocksize; | ||||
if (iosize == 0) | if (iosize == 0) | ||||
iosize = BLKDEV_IOSIZE; | iosize = BLKDEV_IOSIZE; | ||||
if (iosize > maxphys) | if (iosize > maxphys) | ||||
iosize = maxphys; | iosize = maxphys; | ||||
buf = malloc(iosize, M_TEMP, M_WAITOK); | buf = malloc(iosize, M_TEMP, M_WAITOK); | ||||
#ifdef __notyet__ | #ifdef __notyet__ | ||||
/* | /* | ||||
* Check if the filesystem sets f_maxfilesize; if not use | * Check if the filesystem sets f_maxfilesize; if not use | ||||
* VOP_SETATTR to perform the check. | * VOP_SETATTR to perform the check. | ||||
*/ | */ | ||||
sfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); | sfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); | ||||
error = VFS_STATFS(vp->v_mount, sfs, td); | error = VFS_STATFS(vp->v_mount, sfs, td); | ||||
if (error == 0) | if (error == 0) | ||||
maxfilesize = sfs->f_maxfilesize; | maxfilesize = sfs->f_maxfilesize; | ||||
free(sfs, M_STATFS); | free(sfs, M_STATFS); | ||||
if (error != 0) | if (error != 0) | ||||
goto out; | goto out; | ||||
if (maxfilesize) { | if (maxfilesize) { | ||||
if (offset > maxfilesize || len > maxfilesize || | if ((offset > maxfilesize || len > maxfilesize || | ||||
offset + len > maxfilesize) { | offset + len > maxfilesize) && | ||||
(ap->a_flags & SPACECTL_F_CANEXTEND) == 0) { | |||||
error = EFBIG; | error = EFBIG; | ||||
goto out; | goto out; | ||||
} | } | ||||
} else | } else | ||||
#endif | #endif | ||||
if (offset + len > vap->va_size) { | if ((u_quad_t)offset + len > vap->va_size && | ||||
ap->a_flags & SPACECTL_F_CANEXTEND) { | |||||
/* | /* | ||||
* Test offset + len against the filesystem's maxfilesize. | * Test offset + len against the filesystem's maxfilesize. | ||||
*/ | */ | ||||
VATTR_NULL(vap); | VATTR_NULL(vap); | ||||
vap->va_size = offset + len; | vap->va_size = offset + len; | ||||
error = VOP_SETATTR(vp, vap, td->td_ucred); | error = VOP_SETATTR(vp, vap, cred); | ||||
if (error != 0) | if (error != 0) | ||||
goto out; | goto out; | ||||
VATTR_NULL(vap); | VATTR_NULL(vap); | ||||
vap->va_size = fsize; | vap->va_size = fsize; | ||||
error = VOP_SETATTR(vp, vap, td->td_ucred); | error = VOP_SETATTR(vp, vap, cred); | ||||
if (error != 0) | if (error != 0) | ||||
goto out; | goto out; | ||||
} | } | ||||
if ((ap->a_flags & SPACECTL_F_CANEXTEND) == 0) | |||||
len = omin(len, vap->va_size - offset); | |||||
if (len == 0) | |||||
goto out; | |||||
for (;;) { | for (;;) { | ||||
/* | /* | ||||
* Read and write back anything below the nominal file | * Read and write back anything below the nominal file | ||||
* size. There's currently no way outside the filesystem | * size. There's currently no way outside the filesystem | ||||
* to know whether this area is sparse or not. | * to know whether this area is sparse or not. | ||||
*/ | */ | ||||
cur = iosize; | cur = iosize; | ||||
if ((offset % iosize) != 0) | if ((offset % iosize) != 0) | ||||
cur -= (offset % iosize); | cur -= (offset % iosize); | ||||
if (cur > len) | if (cur > len) | ||||
cur = len; | cur = len; | ||||
if (offset < fsize) { | if (offset < fsize) { | ||||
aiov.iov_base = buf; | aiov.iov_base = buf; | ||||
aiov.iov_len = cur; | aiov.iov_len = cur; | ||||
auio.uio_iov = &aiov; | auio.uio_iov = &aiov; | ||||
auio.uio_iovcnt = 1; | auio.uio_iovcnt = 1; | ||||
auio.uio_offset = offset; | auio.uio_offset = offset; | ||||
auio.uio_resid = cur; | auio.uio_resid = cur; | ||||
auio.uio_segflg = UIO_SYSSPACE; | auio.uio_segflg = UIO_SYSSPACE; | ||||
auio.uio_rw = UIO_READ; | auio.uio_rw = UIO_READ; | ||||
auio.uio_td = td; | auio.uio_td = td; | ||||
error = VOP_READ(vp, &auio, 0, td->td_ucred); | error = VOP_READ(vp, &auio, 0, cred); | ||||
if (error != 0) | if (error != 0) | ||||
break; | break; | ||||
if (auio.uio_resid > 0) { | if (auio.uio_resid > 0) { | ||||
bzero(buf + cur - auio.uio_resid, | bzero(buf + cur - auio.uio_resid, | ||||
auio.uio_resid); | auio.uio_resid); | ||||
} | } | ||||
} else { | } else { | ||||
bzero(buf, cur); | bzero(buf, cur); | ||||
} | } | ||||
aiov.iov_base = buf; | aiov.iov_base = buf; | ||||
aiov.iov_len = cur; | aiov.iov_len = cur; | ||||
auio.uio_iov = &aiov; | auio.uio_iov = &aiov; | ||||
auio.uio_iovcnt = 1; | auio.uio_iovcnt = 1; | ||||
auio.uio_offset = offset; | auio.uio_offset = offset; | ||||
auio.uio_resid = cur; | auio.uio_resid = cur; | ||||
auio.uio_segflg = UIO_SYSSPACE; | auio.uio_segflg = UIO_SYSSPACE; | ||||
auio.uio_rw = UIO_WRITE; | auio.uio_rw = UIO_WRITE; | ||||
auio.uio_td = td; | auio.uio_td = td; | ||||
error = VOP_WRITE(vp, &auio, 0, td->td_ucred); | error = VOP_WRITE(vp, &auio, 0, cred); | ||||
if (error != 0) | if (error != 0) | ||||
break; | break; | ||||
len -= cur; | len -= cur; | ||||
offset += cur; | offset += cur; | ||||
if (len == 0) | if (len == 0) | ||||
break; | break; | ||||
if (should_yield()) | if (should_yield()) | ||||
▲ Show 20 Lines • Show All 661 Lines • Show Last 20 Lines |