summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavi Hernandez <xhernandez@redhat.com>2019-05-31 18:40:30 +0200
committerAmar Tumballi <amarts@redhat.com>2019-06-11 13:28:07 +0000
commit952cf7e4f4393fcd9cf8c16b013d8f28915c990e (patch)
treecb1285e9e8fde551d2e01cfb8b8ac3233b65cb19
parentc525fdc6bd79684da196e0fe7ca5630c1bac8f21 (diff)
libglusterfs: cleanup iovec functions
This patch cleans some iovec code and creates two additional helper functions to simplify management of iovec structures. iov_range_copy(struct iovec *dst, uint32_t dst_count, uint32_t dst_offset, struct iovec *src, uint32_t src_count, uint32_t src_offset, uint32_t size); This function copies up to 'size' bytes from 'src' at offset 'src_offset' to 'dst' at 'dst_offset'. It returns the number of bytes copied. iov_skip(struct iovec *iovec, uint32_t count, uint32_t size); This function removes the initial 'size' bytes from 'iovec' and returns the updated number of iovec vectors remaining. The signature of iov_subset() has also been modified to make it safer and easier to use. The new signature is: iov_subset(struct iovec *src, int src_count, uint32_t start, uint32_t size, struct iovec **dst, int32_t dst_count); This function creates a new iovec array containing the subset of the 'src' vector starting at 'start' with size 'size'. The resulting array is allocated if '*dst' is NULL, or copied to '*dst' if it fits (based on 'dst_count'). It returns the number of iovec vectors used. A new set of functions to iterate through an iovec array have been created. They can be used to simplify the implementation of other iovec-based helper functions. Change-Id: Ia5fe57e388e23392a8d6cdab17670e337cadd587 Updates: bz#1193929 Signed-off-by: Xavi Hernandez <xhernandez@redhat.com>
-rw-r--r--libglusterfs/src/glusterfs/common-utils.h228
-rw-r--r--xlators/features/quota/src/quota.c10
-rw-r--r--xlators/features/shard/src/shard.c10
-rw-r--r--xlators/performance/io-cache/src/io-cache.c20
-rw-r--r--xlators/performance/io-cache/src/page.c10
-rw-r--r--xlators/performance/read-ahead/src/page.c10
-rw-r--r--xlators/performance/write-behind/src/write-behind.c3
7 files changed, 177 insertions, 114 deletions
diff --git a/libglusterfs/src/glusterfs/common-utils.h b/libglusterfs/src/glusterfs/common-utils.h
index 56ea83c37d9..49ebdba2fc2 100644
--- a/libglusterfs/src/glusterfs/common-utils.h
+++ b/libglusterfs/src/glusterfs/common-utils.h
@@ -512,65 +512,193 @@ static inline struct iovec *
iov_dup(const struct iovec *vector, int count)
{
int bytecount = 0;
- int i;
struct iovec *newvec = NULL;
bytecount = (count * sizeof(struct iovec));
newvec = GF_MALLOC(bytecount, gf_common_mt_iovec);
- if (!newvec)
- return NULL;
-
- for (i = 0; i < count; i++) {
- newvec[i].iov_len = vector[i].iov_len;
- newvec[i].iov_base = vector[i].iov_base;
+ if (newvec != NULL) {
+ memcpy(newvec, vector, bytecount);
}
return newvec;
}
-static inline int
-iov_subset(struct iovec *orig, int orig_count, off_t src_offset,
- off_t dst_offset, struct iovec *new)
+typedef struct _iov_iter {
+ const struct iovec *iovec;
+ void *ptr;
+ uint32_t len;
+ uint32_t count;
+} iov_iter_t;
+
+static inline bool
+iov_iter_init(iov_iter_t *iter, const struct iovec *iovec, uint32_t count,
+ uint32_t offset)
{
- int new_count = 0;
- int i;
- off_t offset = 0;
- size_t start_offset = 0;
- size_t end_offset = 0, origin_iov_len = 0;
+ uint32_t len;
- for (i = 0; i < orig_count; i++) {
- origin_iov_len = orig[i].iov_len;
+ while (count > 0) {
+ count--;
+ len = iovec->iov_len;
+ if (offset < len) {
+ iter->ptr = iovec->iov_base + offset;
+ iter->len = len - offset;
+ iter->iovec = iovec + 1;
+ iter->count = count;
- if ((offset + orig[i].iov_len < src_offset) || (offset > dst_offset)) {
- goto not_subset;
+ return true;
}
+ offset -= len;
+ }
- if (!new) {
- goto count_only;
- }
+ memset(iter, 0, sizeof(*iter));
+
+ return false;
+}
+
+static inline bool
+iov_iter_end(iov_iter_t *iter)
+{
+ return iter->count == 0;
+}
+
+static inline bool
+iov_iter_next(iov_iter_t *iter, uint32_t size)
+{
+ GF_ASSERT(size <= iter->len);
+
+ if (iter->len > size) {
+ iter->len -= size;
+ iter->ptr += size;
+
+ return true;
+ }
+ if (iter->count > 0) {
+ iter->count--;
+ iter->ptr = iter->iovec->iov_base;
+ iter->len = iter->iovec->iov_len;
+ iter->iovec++;
+
+ return true;
+ }
+
+ memset(iter, 0, sizeof(*iter));
+
+ return false;
+}
+
+static inline uint32_t
+iov_iter_copy(iov_iter_t *dst, iov_iter_t *src, uint32_t size)
+{
+ uint32_t len;
+
+ len = src->len;
+ if (len > dst->len) {
+ len = dst->len;
+ }
+ if (len > size) {
+ len = size;
+ }
+ memcpy(dst->ptr, src->ptr, len);
- start_offset = 0;
- end_offset = orig[i].iov_len;
+ return len;
+}
- if (src_offset >= offset) {
- start_offset = (src_offset - offset);
+static inline uint32_t
+iov_iter_to_iovec(iov_iter_t *iter, struct iovec *iovec, int32_t idx,
+ uint32_t size)
+{
+ uint32_t len;
+
+ len = iter->len;
+ if (len > size) {
+ len = size;
+ }
+ iovec[idx].iov_base = iter->ptr;
+ iovec[idx].iov_len = len;
+
+ return len;
+}
+
+static inline int
+iov_subset(struct iovec *src, int src_count, uint32_t start, uint32_t size,
+ struct iovec **dst, int32_t dst_count)
+{
+ struct iovec iovec[src_count];
+ iov_iter_t iter;
+ uint32_t len;
+ int32_t idx;
+
+ if ((size == 0) || !iov_iter_init(&iter, src, src_count, start)) {
+ return 0;
+ }
+
+ idx = 0;
+ do {
+ len = iov_iter_to_iovec(&iter, iovec, idx, size);
+ idx++;
+ size -= len;
+ } while ((size > 0) && iov_iter_next(&iter, len));
+
+ if (*dst == NULL) {
+ *dst = iov_dup(iovec, idx);
+ if (*dst == NULL) {
+ return -1;
}
+ } else if (idx > dst_count) {
+ return -1;
+ } else {
+ memcpy(*dst, iovec, idx * sizeof(struct iovec));
+ }
- if (dst_offset <= (offset + orig[i].iov_len)) {
- end_offset = (dst_offset - offset);
+ return idx;
+}
+
+static inline int
+iov_skip(struct iovec *iovec, uint32_t count, uint32_t size)
+{
+ uint32_t len, idx;
+
+ idx = 0;
+ while ((size > 0) && (idx < count)) {
+ len = iovec[idx].iov_len;
+ if (len > size) {
+ iovec[idx].iov_len -= size;
+ iovec[idx].iov_base += size;
+ break;
}
+ idx++;
+ size -= len;
+ }
+
+ if (idx > 0) {
+ memmove(iovec, iovec + idx, (count - idx) * sizeof(struct iovec));
+ }
- new[new_count].iov_base = orig[i].iov_base + start_offset;
- new[new_count].iov_len = end_offset - start_offset;
+ return count - idx;
+}
- count_only:
- new_count++;
+static inline size_t
+iov_range_copy(const struct iovec *dst, uint32_t dst_count, uint32_t dst_offset,
+ const struct iovec *src, uint32_t src_count, uint32_t src_offset,
+ uint32_t size)
+{
+ iov_iter_t src_iter, dst_iter;
+ uint32_t len, total;
- not_subset:
- offset += origin_iov_len;
+ if ((size == 0) || !iov_iter_init(&src_iter, src, src_count, src_offset) ||
+ !iov_iter_init(&dst_iter, dst, dst_count, dst_offset)) {
+ return 0;
}
- return new_count;
+ total = 0;
+ do {
+ len = iov_iter_copy(&dst_iter, &src_iter, size);
+ total += len;
+ size -= len;
+ } while ((size > 0) && iov_iter_next(&src_iter, len) &&
+ iov_iter_next(&dst_iter, len));
+
+ return total;
}
static inline void
@@ -609,35 +737,7 @@ iov_load(const struct iovec *vector, int count, char *buf, int size)
static inline size_t
iov_copy(const struct iovec *dst, int dcnt, const struct iovec *src, int scnt)
{
- size_t ret = 0;
- size_t left = 0;
- size_t min_i = 0;
- int s_i = 0, s_ii = 0;
- int d_i = 0, d_ii = 0;
-
- ret = min(iov_length(dst, dcnt), iov_length(src, scnt));
- left = ret;
-
- while (left) {
- min_i = min(dst[d_i].iov_len - d_ii, src[s_i].iov_len - s_ii);
- memcpy(dst[d_i].iov_base + d_ii, src[s_i].iov_base + s_ii, min_i);
-
- d_ii += min_i;
- if (d_ii == dst[d_i].iov_len) {
- d_ii = 0;
- d_i++;
- }
-
- s_ii += min_i;
- if (s_ii == src[s_i].iov_len) {
- s_ii = 0;
- s_i++;
- }
-
- left -= min_i;
- }
-
- return ret;
+ return iov_range_copy(dst, dcnt, 0, src, scnt, 0, UINT32_MAX);
}
/* based on the amusing discussion @ https://rusty.ozlabs.org/?p=560 */
diff --git a/xlators/features/quota/src/quota.c b/xlators/features/quota/src/quota.c
index 1335386a197..c787028e7b3 100644
--- a/xlators/features/quota/src/quota.c
+++ b/xlators/features/quota/src/quota.c
@@ -1769,19 +1769,13 @@ quota_writev_helper(call_frame_t *frame, xlator_t *this, fd_t *fd,
if ((op_errno == EDQUOT) && (local->space_available > 0)) {
new_count = iov_subset(vector, count, 0, local->space_available,
- NULL);
-
- new_vector = GF_CALLOC(new_count, sizeof(struct iovec),
- gf_common_mt_iovec);
- if (new_vector == NULL) {
+ &new_vector, 0);
+ if (new_count < 0) {
local->op_ret = -1;
local->op_errno = ENOMEM;
goto unwind;
}
- new_count = iov_subset(vector, count, 0, local->space_available,
- new_vector);
-
vector = new_vector;
count = new_count;
} else if (op_errno == ENOENT || op_errno == ESTALE) {
diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c
index b6908c39ef5..6e78e967214 100644
--- a/xlators/features/shard/src/shard.c
+++ b/xlators/features/shard/src/shard.c
@@ -5476,21 +5476,17 @@ shard_common_inode_write_do(call_frame_t *frame, xlator_t *this)
remaining_size -= shard_write_size;
if (local->fop == GF_FOP_WRITE) {
+ vec = NULL;
count = iov_subset(local->vector, local->count, vec_offset,
- vec_offset + shard_write_size, NULL);
-
- vec = GF_CALLOC(count, sizeof(struct iovec), gf_shard_mt_iovec);
- if (!vec) {
+ shard_write_size, &vec, 0);
+ if (count < 0) {
local->op_ret = -1;
local->op_errno = ENOMEM;
wind_failed = _gf_true;
- GF_FREE(vec);
shard_common_inode_write_do_cbk(frame, (void *)(long)0, this,
-1, ENOMEM, NULL, NULL, NULL);
goto next;
}
- count = iov_subset(local->vector, local->count, vec_offset,
- vec_offset + shard_write_size, vec);
}
if (cur_block == 0) {
diff --git a/xlators/performance/io-cache/src/io-cache.c b/xlators/performance/io-cache/src/io-cache.c
index 95ba2e19b9e..711afdf700d 100644
--- a/xlators/performance/io-cache/src/io-cache.c
+++ b/xlators/performance/io-cache/src/io-cache.c
@@ -87,14 +87,6 @@ ioc_update_pages(call_frame_t *frame, ioc_inode_t *ioc_inode,
write_offset = 0;
off_t page_offset = 0, page_end = 0;
ioc_page_t *trav = NULL;
- struct iovec pagevector =
- {
- 0,
- },
- writevector = {
- 0,
- };
- int pvcount = 0, wvcount;
size = iov_length(vector, count);
size = min(size, op_ret);
@@ -120,16 +112,8 @@ ioc_update_pages(call_frame_t *frame, ioc_inode_t *ioc_inode,
page_end = trav->size;
}
- wvcount = iov_subset(vector, count, write_offset,
- write_offset + (page_end - page_offset),
- &writevector);
- if (wvcount) {
- pvcount = iov_subset(trav->vector, trav->count, page_offset,
- page_end, &pagevector);
- if (pvcount) {
- iov_copy(&pagevector, pvcount, &writevector, wvcount);
- }
- }
+ iov_range_copy(trav->vector, trav->count, page_offset, vector,
+ count, write_offset, page_end - page_offset);
} else if (trav) {
if (!trav->waitq)
ioc_inode->table->cache_used -= __ioc_page_destroy(trav);
diff --git a/xlators/performance/io-cache/src/page.c b/xlators/performance/io-cache/src/page.c
index 4a9679cf0ce..69b4fc0573f 100644
--- a/xlators/performance/io-cache/src/page.c
+++ b/xlators/performance/io-cache/src/page.c
@@ -727,11 +727,8 @@ __ioc_frame_fill(ioc_page_t *page, call_frame_t *frame, off_t offset,
new->size = copy_size;
new->iobref = iobref_ref(page->iobref);
new->count = iov_subset(page->vector, page->count, src_offset,
- src_offset + copy_size, NULL);
-
- new->vector = GF_CALLOC(new->count, sizeof(struct iovec),
- gf_ioc_mt_iovec);
- if (new->vector == NULL) {
+ copy_size, &new->vector, 0);
+ if (new->count < 0) {
local->op_ret = -1;
local->op_errno = ENOMEM;
@@ -740,9 +737,6 @@ __ioc_frame_fill(ioc_page_t *page, call_frame_t *frame, off_t offset,
goto out;
}
- new->count = iov_subset(page->vector, page->count, src_offset,
- src_offset + copy_size, new->vector);
-
/* add the ioc_fill to fill_list for this frame */
if (list_empty(&local->fill_list)) {
/* if list is empty, then this is the first
diff --git a/xlators/performance/read-ahead/src/page.c b/xlators/performance/read-ahead/src/page.c
index 344026352f9..8a58ad8bb7a 100644
--- a/xlators/performance/read-ahead/src/page.c
+++ b/xlators/performance/read-ahead/src/page.c
@@ -347,19 +347,15 @@ ra_frame_fill(ra_page_t *page, call_frame_t *frame)
new->size = copy_size;
new->iobref = iobref_ref(page->iobref);
new->count = iov_subset(page->vector, page->count, src_offset,
- src_offset + copy_size, NULL);
- new->vector = GF_CALLOC(new->count, sizeof(struct iovec),
- gf_ra_mt_iovec);
- if (new->vector == NULL) {
+ copy_size, &new->vector, 0);
+ if (new->count < 0) {
local->op_ret = -1;
local->op_errno = ENOMEM;
+ iobref_unref(new->iobref);
GF_FREE(new);
goto out;
}
- new->count = iov_subset(page->vector, page->count, src_offset,
- src_offset + copy_size, new->vector);
-
new->next = fill;
new->prev = new->next->prev;
new->next->prev = new;
diff --git a/xlators/performance/write-behind/src/write-behind.c b/xlators/performance/write-behind/src/write-behind.c
index 70e281a3c79..aade1c9c563 100644
--- a/xlators/performance/write-behind/src/write-behind.c
+++ b/xlators/performance/write-behind/src/write-behind.c
@@ -971,8 +971,7 @@ __wb_modify_write_request(wb_request_t *req, int synced_size)
vector = req->stub->args.vector;
count = req->stub->args.count;
- req->stub->args.count = iov_subset(vector, count, synced_size,
- iov_length(vector, count), vector);
+ req->stub->args.count = iov_skip(vector, count, synced_size);
out:
return;