|
@@ -1533,3 +1533,45 @@ u32 svc_max_payload(const struct svc_rqst *rqstp)
|
|
|
return max;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(svc_max_payload);
|
|
|
+
|
|
|
+/**
|
|
|
+ * svc_fill_write_vector - Construct data argument for VFS write call
|
|
|
+ * @rqstp: svc_rqst to operate on
|
|
|
+ * @first: buffer containing first section of write payload
|
|
|
+ * @total: total number of bytes of write payload
|
|
|
+ *
|
|
|
+ * Returns the number of elements populated in the data argument array.
|
|
|
+ */
|
|
|
+unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct kvec *first,
|
|
|
+ size_t total)
|
|
|
+{
|
|
|
+ struct kvec *vec = rqstp->rq_vec;
|
|
|
+ struct page **pages;
|
|
|
+ unsigned int i;
|
|
|
+
|
|
|
+ /* Some types of transport can present the write payload
|
|
|
+ * entirely in rq_arg.pages. In this case, @first is empty.
|
|
|
+ */
|
|
|
+ i = 0;
|
|
|
+ if (first->iov_len) {
|
|
|
+ vec[i].iov_base = first->iov_base;
|
|
|
+ vec[i].iov_len = min_t(size_t, total, first->iov_len);
|
|
|
+ total -= vec[i].iov_len;
|
|
|
+ ++i;
|
|
|
+ }
|
|
|
+
|
|
|
+ WARN_ON_ONCE(rqstp->rq_arg.page_base != 0);
|
|
|
+ pages = rqstp->rq_arg.pages;
|
|
|
+ while (total) {
|
|
|
+ vec[i].iov_base = page_address(*pages);
|
|
|
+ vec[i].iov_len = min_t(size_t, total, PAGE_SIZE);
|
|
|
+ total -= vec[i].iov_len;
|
|
|
+ ++i;
|
|
|
+
|
|
|
+ ++pages;
|
|
|
+ }
|
|
|
+
|
|
|
+ WARN_ON_ONCE(i > ARRAY_SIZE(rqstp->rq_vec));
|
|
|
+ return i;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(svc_fill_write_vector);
|