unsigned long exp_op_flags = 0;
unsigned int pflags = current->flags;
bool restore_flags = false;
- unsigned int nvecs;
+ int nvecs;
trace_nfsd_write_opened(rqstp, fhp, offset, *cnt);
}
nvecs = xdr_buf_to_bvec(rqstp->rq_bvec, rqstp->rq_maxpages, payload);
+ if (nvecs < 0) {
+ host_err = nvecs;
+ goto out_nfserr;
+ }
since = READ_ONCE(file->f_wb_err);
if (verf)
size_t xdr_buf_pagecount(const struct xdr_buf *buf);
int xdr_alloc_bvec(struct xdr_buf *buf, gfp_t gfp);
void xdr_free_bvec(struct xdr_buf *buf);
-unsigned int xdr_buf_to_bvec(struct bio_vec *bvec, unsigned int bvec_size,
- const struct xdr_buf *xdr);
+int xdr_buf_to_bvec(struct bio_vec *bvec, unsigned int bvec_size,
+ const struct xdr_buf *xdr);
int xdr_buf_to_sg(const struct xdr_buf *buf, unsigned int offset,
unsigned int len, struct scatterlist *sg, unsigned int nsg);
int xdr_buf_to_sg_alloc(const struct xdr_buf *buf, unsigned int offset,
.msg_flags = MSG_SPLICE_PAGES,
.msg_controllen = sizeof(buffer),
};
- unsigned int count;
+ int count;
int err;
svc_udp_release_ctxt(xprt, rqstp->rq_xprt_ctxt);
goto out_notconn;
count = xdr_buf_to_bvec(svsk->sk_bvec, SUNRPC_MAX_UDP_SENDPAGES, xdr);
+ if (count < 0) {
+ err = count;
+ goto out_trace;
+ }
iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, svsk->sk_bvec,
count, rqstp->rq_res.len);
err = sock_sendmsg(svsk->sk_sock, &msg);
}
+out_trace:
trace_svcsock_udp_send(xprt, err);
mutex_unlock(&xprt->xpt_mutex);
struct msghdr msg = {
.msg_flags = MSG_SPLICE_PAGES,
};
- unsigned int count;
+ int count;
void *buf;
int ret;
count = xdr_buf_to_bvec(svsk->sk_bvec + 1, rqstp->rq_maxpages,
&rqstp->rq_res);
+ if (count < 0) {
+ ret = count;
+ goto out;
+ }
iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, svsk->sk_bvec,
1 + count, sizeof(marker) + rqstp->rq_res.len);
ret = sock_sendmsg(svsk->sk_sock, &msg);
+out:
page_frag_free(buf);
return ret;
}
/**
* xdr_buf_to_bvec - Copy components of an xdr_buf into a bio_vec array
* @bvec: bio_vec array to populate
- * @bvec_size: element count of @bio_vec
+ * @bvec_size: element count of @bvec
* @xdr: xdr_buf to be copied
*
- * Returns the number of entries consumed in @bvec.
+ * Returns the number of entries consumed in @bvec on success, or
+ * -ESERVERFAULT when @xdr does not fit within @bvec_size entries.
*/
-unsigned int xdr_buf_to_bvec(struct bio_vec *bvec, unsigned int bvec_size,
- const struct xdr_buf *xdr)
+int xdr_buf_to_bvec(struct bio_vec *bvec, unsigned int bvec_size,
+ const struct xdr_buf *xdr)
{
const struct kvec *head = xdr->head;
const struct kvec *tail = xdr->tail;
bvec_overflow:
pr_warn_once("%s: bio_vec array overflow\n", __func__);
- return count;
+ return -ESERVERFAULT;
}
EXPORT_SYMBOL_GPL(xdr_buf_to_bvec);