Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_syscalls.c
Show First 20 Lines • Show All 4,559 Lines • ▼ Show 20 Lines | if (error != 0) | ||||
goto out; | goto out; | ||||
#endif | #endif | ||||
error = VFS_STATFS(mp, buf); | error = VFS_STATFS(mp, buf); | ||||
out: | out: | ||||
vfs_unbusy(mp); | vfs_unbusy(mp); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | |||||
kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len) | |||||
{ | |||||
struct file *fp; | |||||
struct mount *mp; | |||||
struct vnode *vp; | |||||
off_t olen, ooffset; | |||||
int error; | |||||
#ifdef AUDIT | |||||
int audited_vnode1 = 0; | |||||
#endif | |||||
AUDIT_ARG_FD(fd); | |||||
if (offset < 0 || len <= 0) | |||||
return (EINVAL); | |||||
/* Check for wrap. */ | |||||
if (offset > OFF_MAX - len) | |||||
return (EFBIG); | |||||
AUDIT_ARG_FD(fd); | |||||
error = fget(td, fd, &cap_pwrite_rights, &fp); | |||||
if (error != 0) | |||||
return (error); | |||||
AUDIT_ARG_FILE(td->td_proc, fp); | |||||
if ((fp->f_ops->fo_flags & DFLAG_SEEKABLE) == 0) { | |||||
error = ESPIPE; | |||||
goto out; | |||||
} | |||||
if ((fp->f_flag & FWRITE) == 0) { | |||||
error = EBADF; | |||||
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. */ | |||||
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: | |||||
fdrop(fp, td); | |||||
return (error); | |||||
} | |||||
int | |||||
sys_posix_fallocate(struct thread *td, struct posix_fallocate_args *uap) | |||||
{ | |||||
int error; | |||||
error = kern_posix_fallocate(td, uap->fd, uap->offset, uap->len); | |||||
return (kern_posix_error(td, error)); | |||||
} | |||||
/* | /* | ||||
* Unlike madvise(2), we do not make a best effort to remember every | * Unlike madvise(2), we do not make a best effort to remember every | ||||
* possible caching hint. Instead, we remember the last setting with | * possible caching hint. Instead, we remember the last setting with | ||||
* the exception that we will allow POSIX_FADV_NORMAL to adjust the | * the exception that we will allow POSIX_FADV_NORMAL to adjust the | ||||
* region of any current setting. | * region of any current setting. | ||||
*/ | */ | ||||
int | int | ||||
kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len, | kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len, | ||||
▲ Show 20 Lines • Show All 259 Lines • Show Last 20 Lines |