diff options
Diffstat (limited to 'net/sunrpc/xdr.c')
-rw-r--r-- | net/sunrpc/xdr.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 5a6485946f3c..a0af250ca319 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -1021,3 +1021,71 @@ xdr_encode_array2(struct xdr_buf *buf, unsigned int base, | |||
1021 | 1021 | ||
1022 | return xdr_xcode_array2(buf, base, desc, 1); | 1022 | return xdr_xcode_array2(buf, base, desc, 1); |
1023 | } | 1023 | } |
1024 | |||
1025 | int | ||
1026 | xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, | ||
1027 | int (*actor)(struct scatterlist *, void *), void *data) | ||
1028 | { | ||
1029 | int i, ret = 0; | ||
1030 | unsigned page_len, thislen, page_offset; | ||
1031 | struct scatterlist sg[1]; | ||
1032 | |||
1033 | if (offset >= buf->head[0].iov_len) { | ||
1034 | offset -= buf->head[0].iov_len; | ||
1035 | } else { | ||
1036 | thislen = buf->head[0].iov_len - offset; | ||
1037 | if (thislen > len) | ||
1038 | thislen = len; | ||
1039 | sg_set_buf(sg, buf->head[0].iov_base + offset, thislen); | ||
1040 | ret = actor(sg, data); | ||
1041 | if (ret) | ||
1042 | goto out; | ||
1043 | offset = 0; | ||
1044 | len -= thislen; | ||
1045 | } | ||
1046 | if (len == 0) | ||
1047 | goto out; | ||
1048 | |||
1049 | if (offset >= buf->page_len) { | ||
1050 | offset -= buf->page_len; | ||
1051 | } else { | ||
1052 | page_len = buf->page_len - offset; | ||
1053 | if (page_len > len) | ||
1054 | page_len = len; | ||
1055 | len -= page_len; | ||
1056 | page_offset = (offset + buf->page_base) & (PAGE_CACHE_SIZE - 1); | ||
1057 | i = (offset + buf->page_base) >> PAGE_CACHE_SHIFT; | ||
1058 | thislen = PAGE_CACHE_SIZE - page_offset; | ||
1059 | do { | ||
1060 | if (thislen > page_len) | ||
1061 | thislen = page_len; | ||
1062 | sg->page = buf->pages[i]; | ||
1063 | sg->offset = page_offset; | ||
1064 | sg->length = thislen; | ||
1065 | ret = actor(sg, data); | ||
1066 | if (ret) | ||
1067 | goto out; | ||
1068 | page_len -= thislen; | ||
1069 | i++; | ||
1070 | page_offset = 0; | ||
1071 | thislen = PAGE_CACHE_SIZE; | ||
1072 | } while (page_len != 0); | ||
1073 | offset = 0; | ||
1074 | } | ||
1075 | if (len == 0) | ||
1076 | goto out; | ||
1077 | if (offset < buf->tail[0].iov_len) { | ||
1078 | thislen = buf->tail[0].iov_len - offset; | ||
1079 | if (thislen > len) | ||
1080 | thislen = len; | ||
1081 | sg_set_buf(sg, buf->tail[0].iov_base + offset, thislen); | ||
1082 | ret = actor(sg, data); | ||
1083 | len -= thislen; | ||
1084 | } | ||
1085 | if (len != 0) | ||
1086 | ret = -EINVAL; | ||
1087 | out: | ||
1088 | return ret; | ||
1089 | } | ||
1090 | EXPORT_SYMBOL(xdr_process_buf); | ||
1091 | |||