summaryrefslogtreecommitdiff
path: root/net/ceph/messenger.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ceph/messenger.c')
-rw-r--r--net/ceph/messenger.c86
1 files changed, 60 insertions, 26 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index 6e0bd36d676a..3120a6c81a76 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -471,6 +471,22 @@ static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len)
return r;
}
+static int ceph_tcp_recvpage(struct socket *sock, struct page *page,
+ int page_offset, size_t length)
+{
+ void *kaddr;
+ int ret;
+
+ BUG_ON(page_offset + length > PAGE_SIZE);
+
+ kaddr = kmap(page);
+ BUG_ON(!kaddr);
+ ret = ceph_tcp_recvmsg(sock, kaddr + page_offset, length);
+ kunmap(page);
+
+ return ret;
+}
+
/*
* write something. @more is true if caller will be sending more data
* shortly.
@@ -1809,26 +1825,36 @@ static int read_partial_message_pages(struct ceph_connection *con,
{
struct ceph_msg_pos *msg_pos = &con->in_msg_pos;
struct page *page;
- void *p;
+ size_t page_offset;
+ size_t length;
+ unsigned int left;
int ret;
- int left;
- left = min((int)(data_len - msg_pos->data_pos),
- (int)(PAGE_SIZE - msg_pos->page_pos));
/* (page) data */
BUG_ON(pages == NULL);
page = pages[msg_pos->page];
- p = kmap(page);
- ret = ceph_tcp_recvmsg(con->sock, p + msg_pos->page_pos, left);
- if (ret > 0 && do_datacrc)
- con->in_data_crc =
- crc32c(con->in_data_crc,
- p + msg_pos->page_pos, ret);
- kunmap(page);
+ page_offset = msg_pos->page_pos;
+ BUG_ON(msg_pos->data_pos >= data_len);
+ left = data_len - msg_pos->data_pos;
+ BUG_ON(page_offset >= PAGE_SIZE);
+ length = min_t(unsigned int, PAGE_SIZE - page_offset, left);
+
+ ret = ceph_tcp_recvpage(con->sock, page, page_offset, length);
if (ret <= 0)
return ret;
- in_msg_pos_next(con, left, ret);
+ if (do_datacrc) {
+ void *kaddr;
+ void *base;
+
+ kaddr = kmap(page);
+ BUG_ON(!kaddr);
+ base = kaddr + page_offset;
+ con->in_data_crc = crc32c(con->in_data_crc, base, ret);
+ kunmap(page);
+ }
+
+ in_msg_pos_next(con, length, ret);
return ret;
}
@@ -1841,29 +1867,37 @@ static int read_partial_message_bio(struct ceph_connection *con,
struct ceph_msg_pos *msg_pos = &con->in_msg_pos;
struct bio_vec *bv;
struct page *page;
- void *p;
- int ret, left;
+ size_t page_offset;
+ size_t length;
+ unsigned int left;
+ int ret;
BUG_ON(!msg);
BUG_ON(!msg->bio_iter);
bv = bio_iovec_idx(msg->bio_iter, msg->bio_seg);
-
- left = min((int)(data_len - msg_pos->data_pos),
- (int)(bv->bv_len - msg_pos->page_pos));
-
page = bv->bv_page;
- p = kmap(page) + bv->bv_offset;
+ page_offset = bv->bv_offset + msg_pos->page_pos;
+ BUG_ON(msg_pos->data_pos >= data_len);
+ left = data_len - msg_pos->data_pos;
+ BUG_ON(msg_pos->page_pos >= bv->bv_len);
+ length = min_t(unsigned int, bv->bv_len - msg_pos->page_pos, left);
- ret = ceph_tcp_recvmsg(con->sock, p + msg_pos->page_pos, left);
- if (ret > 0 && do_datacrc)
- con->in_data_crc =
- crc32c(con->in_data_crc,
- p + msg_pos->page_pos, ret);
- kunmap(page);
+ ret = ceph_tcp_recvpage(con->sock, page, page_offset, length);
if (ret <= 0)
return ret;
- in_msg_pos_next(con, left, ret);
+ if (do_datacrc) {
+ void *kaddr;
+ void *base;
+
+ kaddr = kmap(page);
+ BUG_ON(!kaddr);
+ base = kaddr + page_offset;
+ con->in_data_crc = crc32c(con->in_data_crc, base, ret);
+ kunmap(page);
+ }
+
+ in_msg_pos_next(con, length, ret);
return ret;
}