Hi,

A slightly updated patch.  Removed some checks that were
redundant.

Index: kern/init_sysent.c
===================================================================
RCS file: /cvs/src/sys/kern/init_sysent.c,v
retrieving revision 1.171
diff -u -p -r1.171 init_sysent.c
--- kern/init_sysent.c  9 Sep 2015 17:57:57 -0000       1.171
+++ kern/init_sysent.c  13 Sep 2015 15:47:11 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: init_sysent.c,v 1.171 2015/09/09 17:57:57 deraadt Exp $       
*/
+/*     $OpenBSD$       */
 
 /*
  * System call switch table.
@@ -751,5 +751,7 @@ struct sysent sysent[] = {
            sys___set_tcb },                    /* 329 = __set_tcb */
        { 0, 0, SY_NOLOCK | 0,
            sys___get_tcb },                    /* 330 = __get_tcb */
+       { 3, s(struct sys_posix_fallocate_args), 0,
+           sys_posix_fallocate },              /* 331 = posix_fallocate */
 };
 
Index: kern/syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.c,v
retrieving revision 1.170
diff -u -p -r1.170 syscalls.c
--- kern/syscalls.c     9 Sep 2015 17:57:57 -0000       1.170
+++ kern/syscalls.c     13 Sep 2015 15:47:11 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscalls.c,v 1.170 2015/09/09 17:57:57 deraadt Exp $  */
+/*     $OpenBSD$       */
 
 /*
  * System call names.
@@ -393,4 +393,5 @@ char *syscallnames[] = {
        "#328 (obsolete __tfork51)",            /* 328 = obsolete __tfork51 */
        "__set_tcb",                    /* 329 = __set_tcb */
        "__get_tcb",                    /* 330 = __get_tcb */
+       "posix_fallocate",                      /* 331 = posix_fallocate */
 };
Index: kern/syscalls.master
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.158
diff -u -p -r1.158 syscalls.master
--- kern/syscalls.master        9 Sep 2015 17:56:59 -0000       1.158
+++ kern/syscalls.master        13 Sep 2015 15:47:12 -0000
@@ -561,3 +561,4 @@
 328    OBSOL           __tfork51
 329    STD NOLOCK      { void sys___set_tcb(void *tcb); }
 330    STD NOLOCK      { void *sys___get_tcb(void); }
+331    STD             { int sys_posix_fallocate(int fd, off_t offset, off_t 
len); }
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.227
diff -u -p -r1.227 vfs_syscalls.c
--- kern/vfs_syscalls.c 31 Aug 2015 16:13:11 -0000      1.227
+++ kern/vfs_syscalls.c 13 Sep 2015 15:47:12 -0000
@@ -3023,3 +3023,40 @@ sys_pwritev(struct proc *p, void *v, reg
            1, &offset, retval));
 }
 
+int
+sys_posix_fallocate(struct proc *p, void *v, register_t *retval)
+{
+       struct sys_posix_fallocate_args /* {
+               syscallarg(int) fd;
+               syscallarg(off_t) offset;
+               syscallarg(off_t) len;
+       } */ *uap = v;
+       struct vnode *vp;
+       struct file *fp;
+       int error;
+
+       if (SCARG(uap, offset) < 0 || SCARG(uap, len) < 0)
+               return (EINVAL);
+       if (SCARG(uap, offset) > LLONG_MAX - SCARG(uap, len))
+               return (EFBIG);
+
+       if ((error = getvnode(p, SCARG(uap, fd), &fp)) != 0)
+               return (error);
+       if ((fp->f_flag & FWRITE) == 0) {
+               error = EBADF;
+               goto bad;
+       }
+       vp = fp->f_data;
+       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+       if (vp->v_type == VFIFO)
+               error = ESPIPE;
+       else if (vp->v_type != VREG)
+               error = ENODEV;
+       else if ((error = vn_writechk(vp)) == 0)
+               error = vn_fallocate(vp, SCARG(uap, offset),
+                                    SCARG(uap, len), p);
+       VOP_UNLOCK(vp, 0, p);
+bad:
+       FRELE(fp, p);
+       return (error);
+}
Index: kern/vfs_vnops.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_vnops.c,v
retrieving revision 1.82
diff -u -p -r1.82 vfs_vnops.c
--- kern/vfs_vnops.c    1 May 2015 01:30:58 -0000       1.82
+++ kern/vfs_vnops.c    13 Sep 2015 15:47:12 -0000
@@ -573,3 +573,70 @@ vn_isunder(struct vnode *lvp, struct vno
 
        return (0);
 }
+
+int
+vn_fallocate(struct vnode *vp, off_t offset, off_t len, struct proc *p)
+{
+       struct vattr va;
+       uint8_t *buf;
+       off_t cur, fsize;
+       long blksize;
+       size_t resid;
+       int error;
+
+       if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0)
+               return (error);
+       fsize = va.va_size;
+       blksize = va.va_blocksize;
+
+       if (offset + len > fsize) {
+               /*
+                * Check if the filesystem supports the resulting
+                * filesystem size.
+                */
+               VATTR_NULL(&va);
+               va.va_size = offset + len;
+               if ((error = VOP_SETATTR(vp, &va, p->p_ucred, p)) != 0)
+                       return (error);
+
+               /* All good, restore original file size. */
+               VATTR_NULL(&va);
+               va.va_size = fsize;
+               if ((error = VOP_SETATTR(vp, &va, p->p_ucred, p)) != 0)
+                       return (error);
+       }
+
+       buf = malloc(blksize, M_TEMP, M_WAITOK);
+       /*
+        * We have to go through the entire region
+        * because there is no way to know at this level if
+        * the region has holes or not.
+        */
+       while (len != 0) {
+               cur = blksize;
+               if ((offset % blksize) != 0)
+                       cur -= (offset % blksize);
+               if (cur > len)
+                       cur = len;
+               if (offset < fsize) {
+                       error = vn_rdwr(UIO_READ, vp, buf, cur, offset,
+                                       UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
+                                       &resid, p);
+                       if (error != 0)
+                               break;
+                       if (resid > 0)
+                               memset(buf + cur - resid, 0, resid);
+               } else {
+                       memset(buf, 0, cur);
+               }
+               error = vn_rdwr(UIO_WRITE, vp, buf, cur, offset,
+                               UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
+                               NULL, p);
+               if (error != 0)
+                       break;
+               len -= cur;
+               offset += cur;
+       }
+       free(buf, M_TEMP, blksize);
+       return (error);
+}
Index: sys/fcntl.h
===================================================================
RCS file: /cvs/src/sys/sys/fcntl.h,v
retrieving revision 1.21
diff -u -p -r1.21 fcntl.h
--- sys/fcntl.h 17 May 2015 01:22:01 -0000      1.21
+++ sys/fcntl.h 13 Sep 2015 15:47:12 -0000
@@ -207,6 +207,7 @@ __BEGIN_DECLS
 int    open(const char *, int, ...);
 int    creat(const char *, mode_t);
 int    fcntl(int, int, ...);
+int    posix_fallocate(int, off_t, off_t);
 #if __BSD_VISIBLE
 int    flock(int, int);
 #endif
Index: sys/syscall.h
===================================================================
RCS file: /cvs/src/sys/sys/syscall.h,v
retrieving revision 1.169
diff -u -p -r1.169 syscall.h
--- sys/syscall.h       9 Sep 2015 17:57:57 -0000       1.169
+++ sys/syscall.h       13 Sep 2015 15:47:12 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscall.h,v 1.169 2015/09/09 17:57:57 deraadt Exp $   */
+/*     $OpenBSD$       */
 
 /*
  * System call numbers.
@@ -696,4 +696,7 @@
 /* syscall: "__get_tcb" ret: "void *" args: */
 #define        SYS___get_tcb   330
 
-#define        SYS_MAXSYSCALL  331
+/* syscall: "posix_fallocate" ret: "int" args: "int" "off_t" "off_t" */
+#define        SYS_posix_fallocate     331
+
+#define        SYS_MAXSYSCALL  332
Index: sys/syscallargs.h
===================================================================
RCS file: /cvs/src/sys/sys/syscallargs.h,v
retrieving revision 1.172
diff -u -p -r1.172 syscallargs.h
--- sys/syscallargs.h   9 Sep 2015 17:57:57 -0000       1.172
+++ sys/syscallargs.h   13 Sep 2015 15:47:12 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscallargs.h,v 1.172 2015/09/09 17:57:57 deraadt Exp $       
*/
+/*     $OpenBSD$       */
 
 /*
  * System call argument lists.
@@ -1081,6 +1081,12 @@ struct sys___set_tcb_args {
        syscallarg(void *) tcb;
 };
 
+struct sys_posix_fallocate_args {
+       syscallarg(int) fd;
+       syscallarg(off_t) offset;
+       syscallarg(off_t) len;
+};
+
 /*
  * System call prototypes.
  */
@@ -1327,3 +1333,4 @@ int       sys_symlinkat(struct proc *, void *,
 int    sys_unlinkat(struct proc *, void *, register_t *);
 int    sys___set_tcb(struct proc *, void *, register_t *);
 int    sys___get_tcb(struct proc *, void *, register_t *);
+int    sys_posix_fallocate(struct proc *, void *, register_t *);
Index: sys/vnode.h
===================================================================
RCS file: /cvs/src/sys/sys/vnode.h,v
retrieving revision 1.132
diff -u -p -r1.132 vnode.h
--- sys/vnode.h 7 May 2015 08:53:33 -0000       1.132
+++ sys/vnode.h 13 Sep 2015 15:47:12 -0000
@@ -633,6 +633,7 @@ int vop_generic_kqfilter(void *);
 int    vop_generic_lookup(void *);
 
 /* vfs_vnops.c */
+int    vn_fallocate(struct vnode *, off_t, off_t, struct proc *);
 int    vn_isunder(struct vnode *, struct vnode *, struct proc *);
 int    vn_close(struct vnode *, int, struct ucred *, struct proc *);
 int    vn_open(struct nameidata *, int, int);

Reply via email to