Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164819580
D26726.id78200.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
D26726.id78200.diff
View Options
Index: share/man/man9/VOP_UBOP.9
===================================================================
--- /dev/null
+++ share/man/man9/VOP_UBOP.9
@@ -0,0 +1,71 @@
+.\" -*- nroff -*-
+.\"
+.\" Copyright (c) 2020 Matthew Macy
+.\"
+.\" All rights reserved.
+.\"
+.\" This program is free software.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 13, 2020
+.Dt VOP_UBOP 9
+.Os
+.Sh NAME
+.Nm VOP_UBOP
+.Nd read or write a file system buffer
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/vnode.h
+.In sys/uio.h
+.Ft int
+.Fn VOP_UBOP "struct vnode *vp" "struct uio_bio *uio" "int io_flags"
+.Sh DESCRIPTION
+The arguments are:
+.Bl -tag -width 2n
+.It Fa vp
+The vnode that the operation is for.
+.It Fa uio
+The context for the operation.
+.It Fa flags
+The flags for the operation:
+.Bl -tag -width ".Dv FOF_OFFSET"
+.It Dv FOF_OFFSET
+uio_offset is valid.
+.It Dv FAPPEND
+Write to the end of the file.
+.El
+.El
+.Pp
+This call either reads from, writes to, or syncs a file, depending on the value of
+.Fa uio->uio_cmd .
+.Sh RETURN VALUES
+Zero if completed immediately, EINPROGRESS otherwise.
+Errors should be signalled by setting UIO_BIO_ERROR on uio_flags field in struct uio_bio,
+and setting uio_error to the appropriate errno value.
+.Sh SEE ALSO
+.Xr uio_bio 9 ,
+.Xr vnode 9
+.Sh AUTHORS
+This manual page was written by
+.An Matthew Macy .
Index: share/man/man9/uio_bio.9
===================================================================
--- /dev/null
+++ share/man/man9/uio_bio.9
@@ -0,0 +1,230 @@
+.\"
+.\" Copyright (c) 2020 Matthew Macy
+.\"
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 11, 2020
+.Dt UIO 9
+.Os
+.Sh NAME
+.Nm uio_bio ,
+.Nm uiobiomove ,
+.Nd asynchronous file system I/O routines
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/uio.h
+.Bd -literal
+struct uio_bio {
+ uint8_t uio_cmd; /* operation */
+ uint8_t uio_error; /* Errno for UIO_ERROR. */
+ uint16_t uio_ma_cnt; /* length in pages of scatter/gather list */
+ uint16_t uio_flags; /* General flags */
+ off_t uio_ma_offset; /* offset in to page list */
+ off_t uio_offset; /* offset in target object */
+ uint32_t uio_resid; /* remaining bytes to process */
+ struct thread *uio_td; /* owner */
+ void (*uio_bio_done)(struct uio_bio *); /* I/O completion routine */
+ void *uio_arg; /* argument to completion routine */
+ struct vm_page **uio_ma; /* user buffer's pages */
+};
+.Ed
+.Ft int
+.Fn uiomove "void *buf" "int howmuch" "struct uio_bio *uiop"
+.Sh DESCRIPTION
+The function
+.Fn uiobiomove ,
+is used to transfer data between buffers and pages that might
+possibly cross the user/kernel space boundary.
+.Pp
+As a result of any
+.Xr aio_read 2 ,
+.Xr aio_write 2 ,
+or
+.Xr lio_listio 2
+system call that is being passed to a supporting file system,
+.Va VOP_UBOP
+will be called with a pointer to a
+.Vt "struct uio_bio"
+being passed.
+The transfer request is encoded in this structure.
+The driver itself should use
+.Fn uiobiomove
+to get at the data in this structure.
+.Pp
+The fields in the
+.Vt uio
+structure are:
+.Bl -tag -width ".Va uio_ma_offset"
+.It Va uio_cmd
+The operation to be performed:
+.Bl -tag -width ".Dv UIO_BIO_WRITE"
+.It Dv UIO_BIO_READ
+Read from a file.
+.It Dv UIO_BIO_WRITE
+Write to a file.
+.It Dv UIO_BIO_SYNC
+Sync a file to backing storage.
+.El
+.It Va uio_error
+The error code if the operation was not successful.
+.It Va uio_ma_cnt
+The number of entries in the passed page array.
+.It Va uio_flags
+.Bl -tag -width ".Dv UIO_BIO_SPARSE"
+.It Dv UIO_BIO_ERROR
+The uio_error field is valid.
+.It Dv UIO_BIO_SPARSE
+The page array is not completely populated.
+.El
+.It Va uio_ma_offset
+The starting byte offset in to the page list.
+.It Va uio_offset
+The offset into the file.
+.It Va uio_resid
+The remaining number of bytes to process,
+updated after transfer.
+.It Va uio_td
+The pointer to a
+.Vt "struct thread"
+for the associated thread.
+.It Va uio_bio_done
+The I/O completion routine.
+.It Va uio_arg
+The argument to pass to the I/O completion routine.
+.It Va uio_ma
+A pointer to the caller's pages.
+.El
+.Pp
+.Sh RETURN VALUES
+On success
+.Fn uiobiomove ,
+will return 0; on error it will return an appropriate error code.
+.Sh EXAMPLES
+The idea is that the file system maintains private buffers for its data,
+and processes the request in chunks of maximal the size of these
+buffers.
+.Bd -literal
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/dmu.h>
+#include <sys/dbuf.h>
+
+static uint64_t
+dmu_physmove(dmu_buf_set_t *dbs, dmu_buf_t *db, uint64_t off, uint64_t sz)
+{
+ struct uio_bio *uio = (struct uio_bio *)dbs->dbs_dc->dc_data_buf;
+ uint64_t adv = uio->uio_resid;
+ int err;
+
+ err = uiobiomove((char *)db->db_data + off, sz, uio);
+ if (err)
+ dbs->dbs_err = err;
+ adv -= uio->uio_resid;
+
+ return (adv);
+}
+
+static int
+aio_queue_vfs(struct kaiocb *job)
+{
+ struct aiocb *cb;
+ struct file *fp;
+ struct vnode *vp;
+ struct uio_bio *ubio, ubio_local;
+ vm_prot_t prot;
+ uint32_t io_size, bio_size;
+ int error, cmd;
+ vm_offset_t page_offset;
+
+ cb = &job->uaiocb;
+ fp = job->fd_file;
+ ...
+ vp = fp->f_vnode;
+
+ /*
+ * Zero length read should always succeed
+ * if supported.
+ */
+ bzero(&ubio_local, sizeof(ubio_local));
+ ubio_local.uio_cmd = UIO_BIO_READ;
+ if (VOP_UBOP(vp, &ubio_local, FOF_OFFSET, curthread->td_ucred) == EOPNOTSUPP)
+ return (-1);
+ ...
+ page_offset = ((vm_offset_t)cb->aio_buf) & PAGE_MASK;
+ cmd = cb->aio_lio_opcode == LIO_WRITE ? UIO_BIO_WRITE : UIO_BIO_READ;
+ io_size = cb->aio_nbytes + page_offset + PAGE_MASK;
+ io_size &= ~PAGE_MASK;
+ bio_size = sizeof(*ubio);
+ if (io_size <= MAXPHYS) {
+ ubio = malloc(bio_size, M_AIOS, M_WAITOK);
+ ubio->uio_ma = job->pages;
+ } else {
+ bio_size += sizeof(vm_page_t )*btoc(io_size);
+ ubio = malloc(bio_size, M_AIOS, M_WAITOK);
+ ubio->uio_ma = (vm_page_t*)(ubio + 1);
+ }
+ ubio->uio_cmd = cmd;
+ ubio->uio_error = 0;
+ ubio->uio_flags = 0;
+ ubio->uio_ma_offset = page_offset;
+ ubio->uio_offset = cb->aio_offset;
+ ubio->uio_resid = cb->aio_nbytes;
+ ubio->uio_td = curthread;
+ ubio->uio_bio_done = aio_ubiowakeup;
+ ubio->uio_arg = job;
+
+ prot = VM_PROT_READ;
+ if (cb->aio_lio_opcode == LIO_READ)
+ prot |= VM_PROT_WRITE; /* Less backwards than it looks */
+ ubio->uio_ma_cnt = vm_fault_quick_hold_pages(&curproc->p_vmspace->vm_map,
+ (vm_offset_t)cb->aio_buf, cb->aio_nbytes, prot, ubio->uio_ma,
+ btoc(MAX(io_size, MAXPHYS)));
+ if (ubio->uio_ma_cnt < 0) {
+ error = EFAULT;
+ goto err;
+ }
+
+ error = VOP_UBOP(vp, ubio, FOF_OFFSET, curthread->td_ucred);
+ if (error == EINPROGRESS || error == 0)
+ return (0);
+err:
+ free(ubio, M_AIOS);
+ return (error);
+}
+
+.Ed
+.El
+.Sh SEE ALSO
+.Xr aio_read 2 ,
+.Xr aio_write 2 ,
+.Xr lio_listio 2 ,
+.Xr VOP_UBOP 9 ,
+.Sh HISTORY
+The
+.Nm
+mechanism was introduced to support asynchronous file system requests in OpenZFS.
+.Sh AUTHORS
+This manual page was written by
+.An Matthew Macy .
Index: sys/kern/subr_uio.c
===================================================================
--- sys/kern/subr_uio.c
+++ sys/kern/subr_uio.c
@@ -279,6 +279,132 @@
return (error);
}
+static int
+uiomove_fromphys_sparse(struct vm_page *ma[], int n, struct uio *uio)
+{
+ int rc, pageidx, bytes_avail, sparse_bytes, total_pages;
+ caddr_t baseptr;
+
+ pageidx = 0;
+ total_pages = n >> PAGE_SHIFT;
+ while (n > 0) {
+
+ /*
+ * Consume any populated pages up front.
+ */
+ bytes_avail = 0;
+ for (int i = pageidx; i < total_pages; i++) {
+ if (ma[i] == NULL)
+ break;
+ bytes_avail += PAGE_SIZE;
+ }
+ if (bytes_avail) {
+ rc = uiomove_fromphys(ma + pageidx, 0, bytes_avail, uio);
+ if (rc)
+ return (rc);
+
+ }
+ pageidx += (bytes_avail >> PAGE_SHIFT);
+ n -= bytes_avail;
+ sparse_bytes = 0;
+
+ /*
+ * Consume any subsequent sparse pages.
+ */
+ for (int i = pageidx; i < total_pages; i++) {
+ if (ma[i] != NULL)
+ break;
+
+ sparse_bytes += PAGE_SIZE;
+ }
+ pageidx += (sparse_bytes >> PAGE_SHIFT);
+ n -= sparse_bytes;
+
+ /*
+ * Move cursor forward.
+ */
+ bytes_avail += sparse_bytes;
+ baseptr = uio->uio_iov[0].iov_base;
+ uio->uio_iov[0].iov_base = baseptr + bytes_avail;
+ uio->uio_iov[0].iov_len -= bytes_avail;
+ uio->uio_resid -= bytes_avail;
+ uio->uio_offset += bytes_avail;
+ }
+ return (0);
+}
+
+int
+uiobiomove(void *cp, int n, struct uio_bio *uio)
+{
+ vm_paddr_t paddr;
+ int rc;
+ struct iovec iov[1];
+ struct uio auio;
+ ssize_t resid, size;
+ int pageoff, pageidx;
+
+
+ KASSERT(uio->uio_ma_offset + n <= (uio->uio_ma_cnt << PAGE_SHIFT),
+ ("byte count too large offset: %ju count: %d size: %d",
+ uio->uio_ma_offset, n, uio->uio_ma_cnt << PAGE_SHIFT));
+
+ pageoff = uio->uio_ma_offset & PAGE_MASK;
+ pageidx = uio->uio_ma_offset >> PAGE_SHIFT;
+ if (pageoff) {
+ size = min(PAGE_SIZE - pageoff, n);
+ if ((uio->uio_flags & UIO_BIO_SPARSE) == 0 ||
+ uio->uio_ma[pageidx] != NULL) {
+ paddr = VM_PAGE_TO_PHYS(uio->uio_ma[pageidx]) + pageoff;
+ /*
+ * This is confusing because the user addresses are physical
+ * and the kernel addresses are virtual, so the naming is
+ * reversed.
+ */
+ if (uio->uio_cmd == UIO_BIO_READ)
+ rc = physcopyin(cp, paddr, size);
+ else if (uio->uio_cmd == UIO_BIO_WRITE)
+ rc = physcopyout(paddr, cp, size);
+ else
+ panic("invalid command to uiobiomove: %d", uio->uio_cmd);
+ if (rc != 0)
+ return (rc);
+ }
+ n -= size;
+ pageidx++;
+ uio->uio_ma_offset += size;
+ uio->uio_offset += size;
+ uio->uio_resid -= size;
+ cp = ((char *)cp) + size;
+ }
+ iov[0].iov_base = cp;
+ iov[0].iov_len = n;
+ auio.uio_iov = iov;
+ auio.uio_iovcnt = 1;
+ auio.uio_offset = 0;
+ resid = auio.uio_resid = uio->uio_resid;
+ auio.uio_segflg = UIO_SYSSPACE;
+ /*
+ * Again reversed because user is physical
+ */
+ if (uio->uio_cmd == UIO_BIO_READ)
+ auio.uio_rw = UIO_WRITE;
+ else if (uio->uio_cmd == UIO_BIO_WRITE)
+ auio.uio_rw = UIO_READ;
+ else
+ panic("invalid command to uiobiomove: %d", uio->uio_cmd);
+ if (uio->uio_flags & UIO_BIO_SPARSE)
+ rc = uiomove_fromphys_sparse(uio->uio_ma + pageidx, n, &auio);
+ else
+ rc = uiomove_fromphys(uio->uio_ma + pageidx, 0, n, &auio);
+ if (rc == 0) {
+ size = (resid - auio.uio_resid);
+ uio->uio_resid -= size;
+ uio->uio_offset += size;
+ uio->uio_ma_offset += size;
+ }
+ return (rc);
+}
+
/*
* Wrapper for uiomove() that validates the arguments against a known-good
* kernel buffer. Currently, uiomove accepts a signed (n) argument, which
Index: sys/kern/vfs_aio.c
===================================================================
--- sys/kern/vfs_aio.c
+++ sys/kern/vfs_aio.c
@@ -101,6 +101,10 @@
#define MAX_BUF_AIO 16
#endif
+#ifndef MAX_VFS_XFER
+#define MAX_VFS_XFER (32 * 1024 * 1024) /* 32MB - DMU_MAX_ACCESS/2 */
+#endif
+
FEATURE(aio, "Asynchronous I/O");
SYSCTL_DECL(_p1003_1b);
@@ -319,9 +323,11 @@
struct aioliojob *lio, int type, struct aiocb_ops *ops);
static int aio_queue_file(struct file *fp, struct kaiocb *job);
static void aio_biowakeup(struct bio *bp);
+static void aio_ubiowakeup(struct uio_bio *ubio);
static void aio_proc_rundown(void *arg, struct proc *p);
static void aio_proc_rundown_exec(void *arg, struct proc *p,
struct image_params *imgp);
+static int aio_queue_vfs(struct kaiocb *job);
static int aio_qbio(struct proc *p, struct kaiocb *job);
static void aio_daemon(void *param);
static void aio_bio_done_notify(struct proc *userp, struct kaiocb *job);
@@ -1284,8 +1290,9 @@
bp->bio_caller1 = (void *)job;
prot = VM_PROT_READ;
+ /* Reading from disk means writing to memory */
if (cb->aio_lio_opcode == LIO_READ)
- prot |= VM_PROT_WRITE; /* Less backwards than it looks */
+ prot |= VM_PROT_WRITE;
job->npages = vm_fault_quick_hold_pages(&curproc->p_vmspace->vm_map,
(vm_offset_t)cb->aio_buf, bp->bio_length, prot, job->pages,
nitems(job->pages));
@@ -1327,6 +1334,95 @@
return (error);
}
+/*
+ * aio_queue_vfs works similarly to aio_qbio. It checks
+ * that it supports the aio operation in question and
+ * then if the vnode's file system support asynchronous
+ * requests. It then sets up the request by holding the
+ * user's pages with the appropriate permissions. If that
+ * succeeds it call VOP_UBOP. The uio_bio callback
+ * aio_ubiowakeup will be called when the operation completes.
+ */
+static int
+aio_queue_vfs(struct kaiocb *job)
+{
+ struct aiocb *cb;
+ struct file *fp;
+ struct vnode *vp;
+ struct uio_bio *ubio, ubio_local;
+ vm_prot_t prot;
+ uint32_t io_size, bio_size;
+ int error, cmd;
+ vm_offset_t page_offset;
+
+ cb = &job->uaiocb;
+ fp = job->fd_file;
+
+ if (!(cb->aio_lio_opcode == LIO_WRITE ||
+ cb->aio_lio_opcode == LIO_READ))
+ return (-1);
+ if (fp == NULL || fp->f_type != DTYPE_VNODE)
+ return (-1);
+
+ vp = fp->f_vnode;
+
+ /*
+ * Zero length read should always succeed
+ * if supported.
+ */
+ bzero(&ubio_local, sizeof(ubio_local));
+ ubio_local.uio_cmd = UIO_BIO_READ;
+ if (VOP_UBOP(vp, &ubio_local, FOF_OFFSET) == EOPNOTSUPP)
+ return (-1);
+ /*
+ * Don't punt here - XXX
+ */
+ if (cb->aio_nbytes > MAX_VFS_XFER)
+ return (-1);
+
+ page_offset = ((vm_offset_t)cb->aio_buf) & PAGE_MASK;
+ cmd = cb->aio_lio_opcode == LIO_WRITE ? UIO_BIO_WRITE : UIO_BIO_READ;
+ io_size = cb->aio_nbytes + page_offset + PAGE_MASK;
+ io_size &= ~PAGE_MASK;
+ bio_size = sizeof(*ubio);
+ if (io_size <= MAXPHYS) {
+ ubio = malloc(bio_size, M_AIOS, M_WAITOK);
+ ubio->uio_ma = job->pages;
+ } else {
+ bio_size += sizeof(vm_page_t )*btoc(io_size);
+ ubio = malloc(bio_size, M_AIOS, M_WAITOK);
+ ubio->uio_ma = (vm_page_t*)(ubio + 1);
+ }
+ ubio->uio_cmd = cmd;
+ ubio->uio_error = 0;
+ ubio->uio_flags = 0;
+ ubio->uio_ma_offset = page_offset;
+ ubio->uio_offset = cb->aio_offset;
+ ubio->uio_resid = cb->aio_nbytes;
+ ubio->uio_td = curthread;
+ ubio->uio_bio_done = aio_ubiowakeup;
+ ubio->uio_arg = job;
+
+ prot = VM_PROT_READ;
+ /* Reading from disk means writing to memory */
+ if (cb->aio_lio_opcode == LIO_READ)
+ prot |= VM_PROT_WRITE;
+ ubio->uio_ma_cnt = vm_fault_quick_hold_pages(&curproc->p_vmspace->vm_map,
+ (vm_offset_t)cb->aio_buf, cb->aio_nbytes, prot, ubio->uio_ma,
+ btoc(MAX(io_size, MAXPHYS)));
+ if (ubio->uio_ma_cnt < 0) {
+ error = EFAULT;
+ goto err;
+ }
+
+ error = VOP_UBOP(vp, ubio, FOF_OFFSET);
+ if (error == EINPROGRESS || error == 0)
+ return (0);
+err:
+ free(ubio, M_AIOS);
+ return (error);
+}
+
#ifdef COMPAT_FREEBSD6
static int
convert_old_sigevent(struct osigevent *osig, struct sigevent *nsig)
@@ -1695,6 +1791,9 @@
int error;
bool safe;
+ error = aio_queue_vfs(job);
+ if (error >= 0)
+ return (error);
ki = job->userproc->p_aioinfo;
error = aio_qbio(job->userproc, job);
if (error >= 0)
@@ -2329,6 +2428,33 @@
return (error);
}
+/*
+ * aio_ubiowakeup is the uio_bio completion callback for
+ * aio_queue_vfs. It just drops the hold on the pages
+ * from aio_queue_vfs and marks the aio as completed.
+ */
+static void
+aio_ubiowakeup(struct uio_bio *ubio)
+{
+ struct kaiocb *job = (struct kaiocb *)ubio->uio_arg;
+ size_t nbytes;
+ int error;
+
+ vm_page_unhold_pages(ubio->uio_ma, ubio->uio_ma_cnt);
+
+ nbytes = job->uaiocb.aio_nbytes - ubio->uio_resid;
+ error = 0;
+ if (ubio->uio_flags & UIO_BIO_ERROR)
+ error = ubio->uio_error;
+
+ if (error)
+ aio_complete(job, -1, error);
+ else
+ aio_complete(job, nbytes, 0);
+
+ free(ubio, M_AIOS);
+}
+
static void
aio_biowakeup(struct bio *bp)
{
Index: sys/kern/vnode_if.src
===================================================================
--- sys/kern/vnode_if.src
+++ sys/kern/vnode_if.src
@@ -783,6 +783,14 @@
};
+%% ubop vp U U U
+
+vop_ubop {
+ IN struct vnode *vp;
+ INOUT struct uio_bio *uio;
+ IN int ioflag;
+};
+
# The VOPs below are spares at the end of the table to allow new VOPs to be
# added in stable branches without breaking the KBI. New VOPs in HEAD should
# be added above these spares. When merging a new VOP to a stable branch,
Index: sys/sys/_uio.h
===================================================================
--- sys/sys/_uio.h
+++ sys/sys/_uio.h
@@ -41,6 +41,12 @@
UIO_WRITE
};
+enum uio_bio_cmd {
+ UIO_BIO_READ,
+ UIO_BIO_WRITE,
+ UIO_BIO_SYNC
+};
+
/* Segment flag values. */
enum uio_seg {
UIO_USERSPACE, /* from user data space */
Index: sys/sys/uio.h
===================================================================
--- sys/sys/uio.h
+++ sys/sys/uio.h
@@ -62,6 +62,26 @@
struct thread *uio_td; /* owner */
};
+#define HAVE_UBOP
+enum uio_bio_flags {
+ UIO_BIO_ERROR = 1 << 0,
+ UIO_BIO_SPARSE = 2 << 0,
+};
+
+struct uio_bio {
+ uint8_t uio_cmd; /* operation */
+ uint8_t uio_error; /* Errno for UIO_ERROR. */
+ uint16_t uio_ma_cnt; /* length of scatter/gather list */
+ uint16_t uio_flags; /* General flags */
+ off_t uio_ma_offset; /* offset in to page list */
+ off_t uio_offset; /* offset in target object */
+ uint32_t uio_resid; /* remaining bytes to process */
+ struct thread *uio_td; /* owner */
+ void (*uio_bio_done)(struct uio_bio *);
+ void *uio_arg;
+ struct vm_page **uio_ma; /* user buffer's pages */
+};
+
/*
* Limits
*
@@ -92,6 +112,7 @@
int physcopyout_vlist(vm_paddr_t src, struct bus_dma_segment *dst,
off_t offset, size_t len);
int uiomove(void *cp, int n, struct uio *uio);
+int uiobiomove(void *cp, int n, struct uio_bio *uio);
int uiomove_frombuf(void *buf, int buflen, struct uio *uio);
int uiomove_fromphys(struct vm_page *ma[], vm_offset_t offset, int n,
struct uio *uio);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Aug 5, 5:04 AM (19 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35997321
Default Alt Text
D26726.id78200.diff (19 KB)
Attached To
Mode
D26726: Add support for asynchrous file system operations to aio
Attached
Detach File
Event Timeline
Log In to Comment