diff options
author | Kyle Evans <kevans@FreeBSD.org> | 2020-01-08 19:05:32 +0000 |
---|---|---|
committer | Kyle Evans <kevans@FreeBSD.org> | 2020-01-08 19:05:32 +0000 |
commit | 2856d85ecbe2e402e55913c31d77823f83316a5a (patch) | |
tree | 4fff4fdea8b74e3436b02ce7fbcf31319ed0d65b /sys/kern/vfs_vnops.c | |
parent | f57d4d4641a329fad1d373d2d098560da48d53ee (diff) | |
download | src-2856d85ecbe2e402e55913c31d77823f83316a5a.tar.gz src-2856d85ecbe2e402e55913c31d77823f83316a5a.zip |
posix_fallocate: push vnop implementation into the fileop layer
This opens the door for other descriptor types to implement
posix_fallocate(2) as needed.
Reviewed by: kib, bcr (manpages)
Differential Revision: https://reviews.freebsd.org/D23042
Notes
Notes:
svn path=/head/; revision=356510
Diffstat (limited to 'sys/kern/vfs_vnops.c')
-rw-r--r-- | sys/kern/vfs_vnops.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index f15ea0969b7e..61edb3165e01 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -103,6 +103,7 @@ static fo_kqfilter_t vn_kqfilter; static fo_stat_t vn_statfile; static fo_close_t vn_closefile; static fo_mmap_t vn_mmap; +static fo_fallocate_t vn_fallocate; struct fileops vnops = { .fo_read = vn_io_fault, @@ -119,6 +120,7 @@ struct fileops vnops = { .fo_seek = vn_seek, .fo_fill_kinfo = vn_fill_kinfo, .fo_mmap = vn_mmap, + .fo_fallocate = vn_fallocate, .fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE }; @@ -3150,3 +3152,60 @@ out: free(dat, M_TEMP); return (error); } + +static int +vn_fallocate(struct file *fp, off_t offset, off_t len, struct thread *td) +{ + struct mount *mp; + struct vnode *vp; + off_t olen, ooffset; + int error; +#ifdef AUDIT + int audited_vnode1 = 0; +#endif + + vp = fp->f_vnode; + if (vp->v_type != VREG) + return (ENODEV); + + /* 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(); + } + + return (error); +} |