Author: kevans
Date: Wed Jan  8 19:05:32 2020
New Revision: 356510
URL: https://svnweb.freebsd.org/changeset/base/356510

Log:
  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

Modified:
  head/lib/libc/sys/posix_fallocate.2
  head/sys/kern/sys_generic.c
  head/sys/kern/vfs_syscalls.c
  head/sys/kern/vfs_vnops.c
  head/sys/sys/file.h

Modified: head/lib/libc/sys/posix_fallocate.2
==============================================================================
--- head/lib/libc/sys/posix_fallocate.2 Wed Jan  8 19:05:23 2020        
(r356509)
+++ head/lib/libc/sys/posix_fallocate.2 Wed Jan  8 19:05:32 2020        
(r356510)
@@ -28,7 +28,7 @@
 .\"     @(#)open.2     8.2 (Berkeley) 11/16/93
 .\" $FreeBSD$
 .\"
-.Dd November 4, 2017
+.Dd January 5, 2020
 .Dt POSIX_FALLOCATE 2
 .Os
 .Sh NAME
@@ -115,7 +115,8 @@ An I/O error occurred while reading from or writing to
 .It Bq Er ENODEV
 The
 .Fa fd
-argument does not refer to a regular file.
+argument does not refer to a file that supports
+.Nm .
 .It Bq Er ENOSPC
 There is insufficient free space remaining on the file system storage
 media.

Modified: head/sys/kern/sys_generic.c
==============================================================================
--- head/sys/kern/sys_generic.c Wed Jan  8 19:05:23 2020        (r356509)
+++ head/sys/kern/sys_generic.c Wed Jan  8 19:05:32 2020        (r356510)
@@ -819,6 +819,47 @@ out:
 }
 
 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));
+}
+
+int
+kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len)
+{
+       struct file *fp;
+       int error;
+
+       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;
+       }
+
+       error = fo_fallocate(fp, offset, len, td);
+ out:
+       fdrop(fp, td);
+       return (error);
+}
+
+int
 poll_no_poll(int events)
 {
        /*

Modified: head/sys/kern/vfs_syscalls.c
==============================================================================
--- head/sys/kern/vfs_syscalls.c        Wed Jan  8 19:05:23 2020        
(r356509)
+++ head/sys/kern/vfs_syscalls.c        Wed Jan  8 19:05:32 2020        
(r356510)
@@ -4565,99 +4565,6 @@ out:
        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
  * possible caching hint.  Instead, we remember the last setting with

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c   Wed Jan  8 19:05:23 2020        (r356509)
+++ head/sys/kern/vfs_vnops.c   Wed Jan  8 19:05:32 2020        (r356510)
@@ -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
 };
 
@@ -3148,5 +3150,62 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *
 out:
        *lenp = savlen - len;
        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);
 }

Modified: head/sys/sys/file.h
==============================================================================
--- head/sys/sys/file.h Wed Jan  8 19:05:23 2020        (r356509)
+++ head/sys/sys/file.h Wed Jan  8 19:05:32 2020        (r356510)
@@ -125,6 +125,8 @@ typedef int fo_mmap_t(struct file *fp, vm_map_t map, v
 typedef int fo_aio_queue_t(struct file *fp, struct kaiocb *job);
 typedef int fo_add_seals_t(struct file *fp, int flags);
 typedef int fo_get_seals_t(struct file *fp, int *flags);
+typedef int fo_fallocate_t(struct file *fp, off_t offset, off_t len,
+                   struct thread *td);
 typedef        int fo_flags_t;
 
 struct fileops {
@@ -145,6 +147,7 @@ struct fileops {
        fo_aio_queue_t  *fo_aio_queue;
        fo_add_seals_t  *fo_add_seals;
        fo_get_seals_t  *fo_get_seals;
+       fo_fallocate_t  *fo_fallocate;
        fo_flags_t      fo_flags;       /* DFLAG_* below */
 };
 
@@ -444,6 +447,15 @@ fo_get_seals(struct file *fp, int *seals)
        if (fp->f_ops->fo_get_seals == NULL)
                return (EINVAL);
        return ((*fp->f_ops->fo_get_seals)(fp, seals));
+}
+
+static __inline int
+fo_fallocate(struct file *fp, off_t offset, off_t len, struct thread *td)
+{
+
+       if (fp->f_ops->fo_fallocate == NULL)
+               return (ENODEV);
+       return ((*fp->f_ops->fo_fallocate)(fp, offset, len, td));
 }
 
 #endif /* _KERNEL */
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to