summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbryanv <bryanv@FreeBSD.org>2014-01-18 18:36:41 +0000
committerbryanv <bryanv@FreeBSD.org>2014-01-18 18:36:41 +0000
commitef8dde25f6ddbaeffa47fc0925b18eddfff83bfc (patch)
tree694907fe149beec229ad06fbcf9c99d355251870
parent84f240d84540546ebb7cad7ad3b71ad86b149250 (diff)
downloadFreeBSD-src-ef8dde25f6ddbaeffa47fc0925b18eddfff83bfc.zip
FreeBSD-src-ef8dde25f6ddbaeffa47fc0925b18eddfff83bfc.tar.gz
MFC r260581: Add sglist_append_bio(9) to append a struct bio's data to
a sglist
-rw-r--r--share/man/man9/Makefile1
-rw-r--r--share/man/man9/sglist.913
-rw-r--r--sys/kern/subr_sglist.c40
-rw-r--r--sys/sys/sglist.h2
4 files changed, 55 insertions, 1 deletions
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index 026ffea..2d5817c 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -1172,6 +1172,7 @@ MLINKS+=sf_buf.9 sf_buf_alloc.9 \
sf_buf.9 sf_buf_page.9
MLINKS+=sglist.9 sglist_alloc.9 \
sglist.9 sglist_append.9 \
+ sglist.9 sglist_append_bio.9 \
sglist.9 sglist_append_mbuf.9 \
sglist.9 sglist_append_phys.9 \
sglist.9 sglist_append_uio.9 \
diff --git a/share/man/man9/sglist.9 b/share/man/man9/sglist.9
index 64f8935..280a993 100644
--- a/share/man/man9/sglist.9
+++ b/share/man/man9/sglist.9
@@ -26,13 +26,14 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 15, 2009
+.Dd January 12, 2014
.Dt SGLIST 9
.Os
.Sh NAME
.Nm sglist ,
.Nm sglist_alloc ,
.Nm sglist_append ,
+.Nm sglist_append_bio ,
.Nm sglist_append_mbuf ,
.Nm sglist_append_phys ,
.Nm sglist_append_uio ,
@@ -58,6 +59,8 @@
.Ft int
.Fn sglist_append "struct sglist *sg" "void *buf" "size_t len"
.Ft int
+.Fn sglist_append_bio "struct sglist *sg" "struct bio *bp"
+.Ft int
.Fn sglist_append_mbuf "struct sglist *sg" "struct mbuf *m"
.Ft int
.Fn sglist_append_phys "struct sglist *sg" "vm_paddr_t paddr" "size_t len"
@@ -206,6 +209,13 @@ and is
bytes long.
.Pp
The
+.Nm sglist_append_bio
+function appends the physical address ranges described by a single bio
+.Fa bp
+to the scatter/gather list
+.Fa sg .
+.Pp
+The
.Nm sglist_append_mbuf
function appends the physical address ranges described by an entire mbuf
chain
@@ -499,6 +509,7 @@ list in
to describe the requested physical address ranges.
.El
.Sh SEE ALSO
+.Xr g_bio 9 ,
.Xr malloc 9 ,
.Xr mbuf 9 ,
.Xr uio 9
diff --git a/sys/kern/subr_sglist.c b/sys/kern/subr_sglist.c
index ea77161..c66973a 100644
--- a/sys/kern/subr_sglist.c
+++ b/sys/kern/subr_sglist.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/bio.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/proc.h>
@@ -40,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/uio.h>
#include <vm/vm.h>
+#include <vm/vm_page.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
@@ -239,6 +241,44 @@ sglist_append(struct sglist *sg, void *buf, size_t len)
}
/*
+ * Append the segments to describe a bio's data to a scatter/gather list.
+ * If there are insufficient segments, then this fails with EFBIG.
+ *
+ * NOTE: This function expects bio_bcount to be initialized.
+ */
+int
+sglist_append_bio(struct sglist *sg, struct bio *bp)
+{
+ struct sgsave save;
+ vm_paddr_t paddr;
+ size_t len, tlen;
+ int error, i, ma_offs;
+
+ if ((bp->bio_flags & BIO_UNMAPPED) == 0) {
+ error = sglist_append(sg, bp->bio_data, bp->bio_bcount);
+ return (error);
+ }
+
+ if (sg->sg_maxseg == 0)
+ return (EINVAL);
+
+ SGLIST_SAVE(sg, save);
+ tlen = bp->bio_bcount;
+ ma_offs = bp->bio_ma_offset;
+ for (i = 0; tlen > 0; i++, tlen -= len) {
+ len = min(PAGE_SIZE - ma_offs, tlen);
+ paddr = VM_PAGE_TO_PHYS(bp->bio_ma[i]) + ma_offs;
+ error = sglist_append_phys(sg, paddr, len);
+ if (error) {
+ SGLIST_RESTORE(sg, save);
+ return (error);
+ }
+ ma_offs = 0;
+ }
+ return (0);
+}
+
+/*
* Append a single physical address range to a scatter/gather list.
* If there are insufficient segments, then this fails with EFBIG.
*/
diff --git a/sys/sys/sglist.h b/sys/sys/sglist.h
index 7c17baa..c712f63 100644
--- a/sys/sys/sglist.h
+++ b/sys/sys/sglist.h
@@ -53,6 +53,7 @@ struct sglist {
u_short sg_maxseg;
};
+struct bio;
struct mbuf;
struct uio;
@@ -83,6 +84,7 @@ sglist_hold(struct sglist *sg)
struct sglist *sglist_alloc(int nsegs, int mflags);
int sglist_append(struct sglist *sg, void *buf, size_t len);
+int sglist_append_bio(struct sglist *sg, struct bio *bp);
int sglist_append_mbuf(struct sglist *sg, struct mbuf *m0);
int sglist_append_phys(struct sglist *sg, vm_paddr_t paddr,
size_t len);
OpenPOWER on IntegriCloud