Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_syscalls.c
Show First 20 Lines • Show All 4,563 Lines • ▼ Show 20 Lines | out: | ||||
vfs_unbusy(mp); | vfs_unbusy(mp); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len) | kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len) | ||||
{ | { | ||||
struct file *fp; | struct file *fp; | ||||
struct mount *mp; | |||||
struct vnode *vp; | |||||
off_t olen, ooffset; | |||||
int error; | int error; | ||||
#ifdef AUDIT | |||||
int audited_vnode1 = 0; | |||||
#endif | |||||
AUDIT_ARG_FD(fd); | AUDIT_ARG_FD(fd); | ||||
if (offset < 0 || len <= 0) | if (offset < 0 || len <= 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* Check for wrap. */ | /* Check for wrap. */ | ||||
if (offset > OFF_MAX - len) | if (offset > OFF_MAX - len) | ||||
return (EFBIG); | return (EFBIG); | ||||
AUDIT_ARG_FD(fd); | AUDIT_ARG_FD(fd); | ||||
error = fget(td, fd, &cap_pwrite_rights, &fp); | error = fget(td, fd, &cap_pwrite_rights, &fp); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
AUDIT_ARG_FILE(td->td_proc, fp); | AUDIT_ARG_FILE(td->td_proc, fp); | ||||
if ((fp->f_ops->fo_flags & DFLAG_SEEKABLE) == 0) { | if ((fp->f_ops->fo_flags & DFLAG_SEEKABLE) == 0) { | ||||
error = ESPIPE; | error = ESPIPE; | ||||
goto out; | goto out; | ||||
} | } | ||||
if ((fp->f_flag & FWRITE) == 0) { | if ((fp->f_flag & FWRITE) == 0) { | ||||
error = EBADF; | error = EBADF; | ||||
goto out; | goto out; | ||||
} | } | ||||
if (fp->f_type != DTYPE_VNODE) { | |||||
error = ENODEV; | |||||
goto out; | |||||
} | |||||
vp = fp->f_vnode; | |||||
if (vp->v_type != VREG) { | |||||
error = ENODEV; | |||||
goto out; | |||||
} | |||||
/* Allocating blocks may take a long time, so iterate. */ | error = fo_fallocate(fp, offset, len, td); | ||||
for (;;) { | |||||
olen = len; | |||||
ooffset = offset; | |||||
bwillwrite(); | |||||
mp = NULL; | |||||
error = vn_start_write(vp, &mp, V_WAIT | PCATCH); | |||||
if (error != 0) | |||||
break; | |||||
error = vn_lock(vp, LK_EXCLUSIVE); | |||||
if (error != 0) { | |||||
vn_finished_write(mp); | |||||
break; | |||||
} | |||||
#ifdef AUDIT | |||||
if (!audited_vnode1) { | |||||
AUDIT_ARG_VNODE1(vp); | |||||
audited_vnode1 = 1; | |||||
} | |||||
#endif | |||||
#ifdef MAC | |||||
error = mac_vnode_check_write(td->td_ucred, fp->f_cred, vp); | |||||
if (error == 0) | |||||
#endif | |||||
error = VOP_ALLOCATE(vp, &offset, &len); | |||||
VOP_UNLOCK(vp); | |||||
vn_finished_write(mp); | |||||
if (olen + ooffset != offset + len) { | |||||
panic("offset + len changed from %jx/%jx to %jx/%jx", | |||||
ooffset, olen, offset, len); | |||||
} | |||||
if (error != 0 || len == 0) | |||||
break; | |||||
KASSERT(olen > len, ("Iteration did not make progress?")); | |||||
maybe_yield(); | |||||
} | |||||
out: | out: | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
sys_posix_fallocate(struct thread *td, struct posix_fallocate_args *uap) | sys_posix_fallocate(struct thread *td, struct posix_fallocate_args *uap) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 273 Lines • Show Last 20 Lines |