Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109461535
D26726.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.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,255 @@
+.\"
+.\" 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 bio_vec {
+ vm_page_t bv_page;
+ uint32_t bv_len;
+ uint32_t bv_offset;
+};
+
+struct uio_bio {
+ uint8_t uio_cmd; /* operation */
+ uint8_t uio_error; /* Errno for UIO_ERROR. */
+ uint16_t uio_flags; /* General flags */
+ uint16_t uio_bv_cnt; /* length of scatter/gather list */
+ uint32_t uio_bv_offset; /* offset in to page list */
+ off_t uio_offset; /* offset in target object */
+ ssize_t uio_resid; /* remaining bytes to process */
+ struct ucred *uio_cred; /* owner credentials */
+ struct bio_vec *uio_bvec; /* caller buffer's pages */
+ void (*uio_bio_done)(struct uio_bio *);
+ void *uio_arg;
+};
+.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_bv_cnt
+The number of entries in the passed bio_vec 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_bv_offset
+The starting byte offset in to the bio_vec array.
+.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_cred
+The pointer to a
+.Vt "struct ucred"
+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_bvec
+A pointer to the caller's bio_vec array.
+.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;
+ map_bytes = btoc(cb->aio_nbytes + page_offset)*PAGE_SIZE;
+ io_pages = btoc(map_bytes);
+ if (io_pages <= (MAXPHYS >> PAGE_SHIFT))
+ ma = job->pages;
+ else
+ ma = malloc(sizeof(vm_page_t )*io_pages, M_AIOS, M_WAITOK);
+
+ bio_size = sizeof(*ubio) + sizeof(*bv)*io_pages;
+ ubio = malloc(bio_size, M_AIOS, M_WAITOK);
+ bv = ubio->uio_bvec = (struct bio_vec*)(ubio + 1);
+ ubio->uio_cmd = cmd;
+ ubio->uio_error = 0;
+ ubio->uio_flags = 0;
+ ubio->uio_bv_offset = 0;
+ ubio->uio_offset = cb->aio_offset;
+ ubio->uio_resid = cb->aio_nbytes;
+ ubio->uio_cred = crhold(curthread->td_ucred);
+ 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_bv_cnt = vm_fault_quick_hold_pages(&curproc->p_vmspace->vm_map,
+ (vm_offset_t)cb->aio_buf, cb->aio_nbytes, prot, ma, io_pages);
+
+ if (ubio->uio_bv_cnt != io_pages) {
+ vm_page_unhold_pages(ma, ubio->uio_bv_cnt);
+ /*
+ * Punt to synchronous path
+ */
+ error = -1;
+ goto err;
+ }
+ if (ubio->uio_bv_cnt < 0) {
+ error = EFAULT;
+ goto err;
+ }
+ for (int i = 0; i < ubio->uio_bv_cnt; i++, bv++) {
+ bv->bv_offset = page_offset;
+ bv->bv_len = PAGE_SIZE - page_offset;
+ bv->bv_page = ma[i];
+ page_offset = 0;
+ }
+ if (ma != job->pages) {
+ free(ma, M_AIOS);
+ ma = NULL;
+ }
+ error = VOP_UBOP(vp, ubio, FOF_OFFSET);
+ if (error == EINPROGRESS || error == 0)
+ return (0);
+err:
+ if (ma != job->pages)
+ free(ma, M_AIOS);
+ 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
@@ -54,6 +54,7 @@
#include <sys/resourcevar.h>
#include <sys/rwlock.h>
#include <sys/sched.h>
+#include <sys/sf_buf.h>
#include <sys/sysctl.h>
#include <sys/vnode.h>
@@ -63,6 +64,7 @@
#include <vm/vm_page.h>
#include <vm/vm_pageout.h>
#include <vm/vm_map.h>
+#include <vm/vm_object.h>
#include <machine/bus.h>
@@ -279,6 +281,73 @@
return (error);
}
+int
+uiobiomove(void *cp, int n, struct uio_bio *uio)
+{
+ int bv_idx, bv_idx_start __unused;
+ off_t boff, off, off_start __unused, bv_start __unused;
+ struct bio_vec *bv;
+ struct sf_buf *sf;
+ caddr_t va;
+
+ off = uio->uio_bv_offset;
+ bv = uio->uio_bvec;
+ boff = off & PAGE_MASK;
+ bv_idx = OFF_TO_IDX(off);
+ bv += bv_idx;
+ MPASS(boff < bv->bv_len);
+#ifdef INVARIANTS
+ off_start = uio->uio_offset;
+ bv_start = off;
+ bv_idx_start = bv_idx;
+#endif
+ while (n > 0 && uio->uio_resid > 0) {
+ int bytes = imin(bv->bv_len - boff, n);
+
+ MPASS(boff + bytes <= bv->bv_len);
+ MPASS(bytes <= PAGE_SIZE - bv->bv_offset);
+ MPASS(bytes > 0);
+
+ if ((uio->uio_flags & UIO_BIO_SPARSE) == 0 ||
+ bv->bv_page != NULL) {
+ sf = sf_buf_alloc(bv->bv_page, 0);
+ va = ((caddr_t)sf_buf_kva(sf)) + boff + bv->bv_offset;
+
+ switch(uio->uio_cmd) {
+ case UIO_BIO_READ:
+ memcpy(va, cp, bytes);
+ break;
+ case UIO_BIO_WRITE:
+ memcpy(cp, va, bytes);
+ break;
+ default:
+ panic("invalid command to uiobiomove: %d", uio->uio_cmd);
+ }
+ sf_buf_free(sf);
+ }
+ boff += bytes;
+ uio->uio_bv_offset += bytes;
+ if (boff == bv->bv_len) {
+ uio->uio_bv_offset += (PAGE_SIZE - bv->bv_len);
+ MPASS((uio->uio_bv_offset & PAGE_MASK) == 0);
+ boff = 0;
+ bv++;
+ bv_idx++;
+ }
+ uio->uio_resid -= bytes;
+ uio->uio_offset += bytes;
+ cp = (caddr_t)cp + bytes;
+ n -= bytes;
+ }
+#ifdef INVARIANTS
+ MPASS(uio->uio_offset - off_start ==
+ uio->uio_bv_offset - bv_start - uio->uio_bvec[bv_idx_start].bv_offset);
+ MPASS(OFF_TO_IDX(uio->uio_bv_offset) == bv_idx);
+ MPASS((uio->uio_bv_offset & PAGE_MASK) == boff);
+#endif
+ return (0);
+}
+
/*
* 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);
@@ -1285,8 +1291,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));
@@ -1328,6 +1335,115 @@
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_pages, bio_size, map_bytes;
+ int error, cmd;
+ vm_offset_t page_offset;
+ vm_page_t *ma;
+ struct bio_vec *bv;
+
+ 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;
+ map_bytes = btoc(cb->aio_nbytes + page_offset)*PAGE_SIZE;
+ io_pages = btoc(map_bytes);
+ if (io_pages <= (MAXPHYS >> PAGE_SHIFT))
+ ma = job->pages;
+ else
+ ma = malloc(sizeof(vm_page_t )*io_pages, M_AIOS, M_WAITOK);
+
+ bio_size = sizeof(*ubio) + sizeof(*bv)*io_pages;
+ ubio = malloc(bio_size, M_AIOS, M_WAITOK);
+ bv = ubio->uio_bvec = (struct bio_vec*)(ubio + 1);
+ ubio->uio_cmd = cmd;
+ ubio->uio_error = 0;
+ ubio->uio_flags = 0;
+ ubio->uio_bv_offset = 0;
+ ubio->uio_offset = cb->aio_offset;
+ ubio->uio_resid = cb->aio_nbytes;
+ ubio->uio_cred = crhold(curthread->td_ucred);
+ 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_bv_cnt = vm_fault_quick_hold_pages(&curproc->p_vmspace->vm_map,
+ (vm_offset_t)cb->aio_buf, cb->aio_nbytes, prot, ma, io_pages);
+
+ if (ubio->uio_bv_cnt != io_pages) {
+ vm_page_unhold_pages(ma, ubio->uio_bv_cnt);
+ /*
+ * Punt to synchronous path
+ */
+ error = -1;
+ goto err;
+ }
+ if (ubio->uio_bv_cnt < 0) {
+ error = EFAULT;
+ goto err;
+ }
+ for (int i = 0; i < ubio->uio_bv_cnt; i++, bv++) {
+ bv->bv_offset = page_offset;
+ bv->bv_len = PAGE_SIZE - page_offset;
+ bv->bv_page = ma[i];
+ page_offset = 0;
+ }
+ if (ma != job->pages) {
+ free(ma, M_AIOS);
+ ma = NULL;
+ }
+ error = VOP_UBOP(vp, ubio, FOF_OFFSET);
+ if (error == EINPROGRESS || error == 0)
+ return (0);
+err:
+ if (ma != job->pages)
+ free(ma, M_AIOS);
+ free(ubio, M_AIOS);
+ return (error);
+}
+
#ifdef COMPAT_FREEBSD6
static int
convert_old_sigevent(struct osigevent *osig, struct sigevent *nsig)
@@ -1696,6 +1812,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)
@@ -2330,6 +2449,37 @@
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;
+ struct bio_vec *bv;
+ size_t nbytes;
+ int error, cnt;
+
+ bv = ubio->uio_bvec;
+ cnt = ubio->uio_bv_cnt;
+ for (; cnt != 0; cnt--, bv++)
+ vm_page_unwire(bv->bv_page, PQ_ACTIVE);
+
+ 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);
+ crfree(ubio->uio_cred);
+ 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
@@ -782,6 +782,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,35 @@
struct thread *uio_td; /* owner */
};
+#define HAVE_UBOP
+enum uio_bio_flags {
+ UIO_BIO_ERROR = 1 << 0,
+ UIO_BIO_SPARSE = 1 << 1,
+ UIO_BIO_USER = 1 << 2,
+ UIO_BIO_PREEMPTED = 1 << 3,
+ UIO_BIO_SG = 1 << 4,
+};
+
+struct bio_vec {
+ vm_page_t bv_page;
+ uint32_t bv_len;
+ uint32_t bv_offset;
+};
+
+struct uio_bio {
+ uint8_t uio_cmd; /* operation */
+ uint8_t uio_error; /* Errno for UIO_ERROR. */
+ uint16_t uio_flags; /* General flags */
+ uint16_t uio_bv_cnt; /* length of scatter/gather list */
+ uint32_t uio_bv_offset; /* offset in to page list */
+ off_t uio_offset; /* offset in target object */
+ ssize_t uio_resid; /* remaining bytes to process */
+ struct ucred *uio_cred; /* owner credentials */
+ struct bio_vec *uio_bvec; /* caller buffer's pages */
+ void (*uio_bio_done)(struct uio_bio *);
+ void *uio_arg;
+};
+
/*
* Limits
*
@@ -92,6 +121,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
Thu, Feb 6, 9:26 AM (21 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16490790
Default Alt Text
D26726.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