svn commit: r356510 - in head: lib/libc/sys sys/kern sys/sys

Kyle Evans kevans at FreeBSD.org
Wed Jan 8 19:05:34 UTC 2020


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 */


More information about the svn-src-head mailing list