xref: /spdk/lib/util/iov.c (revision 588dfe314bb83d86effdf67ec42837b11c2620bf)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2019 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/util.h"
7 
8 size_t
9 spdk_ioviter_first(struct spdk_ioviter *iter,
10 		   struct iovec *siov, size_t siovcnt,
11 		   struct iovec *diov, size_t diovcnt,
12 		   void **src, void **dst)
13 {
14 	iter->siov = siov;
15 	iter->siovcnt = siovcnt;
16 
17 	iter->diov = diov;
18 	iter->diovcnt = diovcnt;
19 
20 	iter->sidx = 0;
21 	iter->didx = 0;
22 	iter->siov_len = siov[0].iov_len;
23 	iter->siov_base = siov[0].iov_base;
24 	iter->diov_len = diov[0].iov_len;
25 	iter->diov_base = diov[0].iov_base;
26 
27 	return spdk_ioviter_next(iter, src, dst);
28 }
29 
30 size_t
31 spdk_ioviter_next(struct spdk_ioviter *iter, void **src, void **dst)
32 {
33 	size_t len = 0;
34 
35 	if (iter->sidx == iter->siovcnt ||
36 	    iter->didx == iter->diovcnt ||
37 	    iter->siov_len == 0 ||
38 	    iter->diov_len == 0) {
39 		return 0;
40 	}
41 
42 	*src = iter->siov_base;
43 	*dst = iter->diov_base;
44 	len = spdk_min(iter->siov_len, iter->diov_len);
45 
46 	if (iter->siov_len == iter->diov_len) {
47 		/* Advance both iovs to the next element */
48 		iter->sidx++;
49 		if (iter->sidx == iter->siovcnt) {
50 			return len;
51 		}
52 
53 		iter->didx++;
54 		if (iter->didx == iter->diovcnt) {
55 			return len;
56 		}
57 
58 		iter->siov_len = iter->siov[iter->sidx].iov_len;
59 		iter->siov_base = iter->siov[iter->sidx].iov_base;
60 		iter->diov_len = iter->diov[iter->didx].iov_len;
61 		iter->diov_base = iter->diov[iter->didx].iov_base;
62 	} else if (iter->siov_len < iter->diov_len) {
63 		/* Advance only the source to the next element */
64 		iter->sidx++;
65 		if (iter->sidx == iter->siovcnt) {
66 			return len;
67 		}
68 
69 		iter->diov_base += iter->siov_len;
70 		iter->diov_len -= iter->siov_len;
71 		iter->siov_len = iter->siov[iter->sidx].iov_len;
72 		iter->siov_base = iter->siov[iter->sidx].iov_base;
73 	} else {
74 		/* Advance only the destination to the next element */
75 		iter->didx++;
76 		if (iter->didx == iter->diovcnt) {
77 			return len;
78 		}
79 
80 		iter->siov_base += iter->diov_len;
81 		iter->siov_len -= iter->diov_len;
82 		iter->diov_len = iter->diov[iter->didx].iov_len;
83 		iter->diov_base = iter->diov[iter->didx].iov_base;
84 	}
85 
86 	return len;
87 }
88 
89 size_t
90 spdk_iovcpy(struct iovec *siov, size_t siovcnt, struct iovec *diov, size_t diovcnt)
91 {
92 	struct spdk_ioviter iter;
93 	size_t len, total_sz;
94 	void *src, *dst;
95 
96 	total_sz = 0;
97 	for (len = spdk_ioviter_first(&iter, siov, siovcnt, diov, diovcnt, &src, &dst);
98 	     len != 0;
99 	     len = spdk_ioviter_next(&iter, &src, &dst)) {
100 		memcpy(dst, src, len);
101 		total_sz += len;
102 	}
103 
104 	return total_sz;
105 }
106 
107 void
108 spdk_copy_iovs_to_buf(void *buf, size_t buf_len, struct iovec *iovs, int iovcnt)
109 {
110 	int i;
111 	size_t len;
112 
113 	for (i = 0; i < iovcnt; i++) {
114 		len = spdk_min(iovs[i].iov_len, buf_len);
115 		memcpy(buf, iovs[i].iov_base, len);
116 		buf += len;
117 		assert(buf_len >= len);
118 		buf_len -= len;
119 	}
120 }
121 
122 void
123 spdk_copy_buf_to_iovs(struct iovec *iovs, int iovcnt, void *buf, size_t buf_len)
124 {
125 	int i;
126 	size_t len;
127 
128 	for (i = 0; i < iovcnt; i++) {
129 		len = spdk_min(iovs[i].iov_len, buf_len);
130 		memcpy(iovs[i].iov_base, buf, len);
131 		buf += len;
132 		assert(buf_len >= len);
133 		buf_len -= len;
134 	}
135 }
136