From: Jeff Layton Date: Thu, 19 May 2022 20:42:56 +0000 (-0400) Subject: libceph: X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=812c93951d3539aef6025ec93b966c86e6fee46a;p=ceph-client.git libceph: Signed-off-by: Jeff Layton --- diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index edd27e12e1d91..175f795bcf469 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -228,6 +228,7 @@ struct ceph_msg_data_cursor { struct page *page; /* page from list */ size_t offset; /* bytes from list */ }; + struct iov_iter iov_iter; }; }; diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 9caa6eaee7371..90ceaac9c70e7 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -990,6 +990,47 @@ static bool ceph_msg_data_pagelist_advance(struct ceph_msg_data_cursor *cursor, return true; } +static void ceph_msg_data_iter_cursor_init(struct ceph_msg_data_cursor *cursor, + size_t length) +{ + struct ceph_msg_data *data = cursor->data; + size_t count = iov_iter_count(&data->iter); + + cursor->resid = min_t(size_t, length, count); + cursor->iov_iter = data->iter; + cursor->last_piece = cursor->resid == count; +} + +static struct page *ceph_msg_data_iter_next(struct ceph_msg_data_cursor *cursor, + size_t *page_offset, + size_t *length) +{ + struct page *page; + ssize_t len = iov_iter_get_pages(&cursor->iov_iter, &page, PAGE_SIZE, + 1, page_offset); + + BUG_ON(len < 0); + *length = len; + return page; +} + +static bool ceph_msg_data_iter_advance(struct ceph_msg_data_cursor *cursor, + size_t bytes) +{ + BUG_ON(bytes > cursor->resid); + cursor->resid -= bytes; + iov_iter_advance(&cursor->iov_iter, bytes); + + if (!cursor->resid) { + BUG_ON(!cursor->last_piece); + return false; /* no more data */ + } + + BUG_ON(cursor->last_piece); + cursor->last_piece = cursor->resid == iov_iter_count(&cursor->iov_iter); + return true; +} + /* * Message data is handled (sent or received) in pieces, where each * piece resides on a single page. The network layer might not @@ -1023,7 +1064,7 @@ static void __ceph_msg_data_cursor_init(struct ceph_msg_data_cursor *cursor) ceph_msg_data_bvecs_cursor_init(cursor, length); break; case CEPH_MSG_DATA_ITER: - cursor->last_piece = true; + ceph_msg_data_iter_cursor_init(cursor, length); break; case CEPH_MSG_DATA_NONE: default: @@ -1073,7 +1114,8 @@ struct page *ceph_msg_data_next(struct ceph_msg_data_cursor *cursor, page = ceph_msg_data_bvecs_next(cursor, page_offset, length); break; case CEPH_MSG_DATA_ITER: - BUG(); /* Shouldn't get here */ + page = ceph_msg_data_iter_next(cursor, page_offset, length); + break; case CEPH_MSG_DATA_NONE: default: page = NULL; @@ -1115,7 +1157,8 @@ void ceph_msg_data_advance(struct ceph_msg_data_cursor *cursor, size_t bytes) new_piece = ceph_msg_data_bvecs_advance(cursor, bytes); break; case CEPH_MSG_DATA_ITER: - BUG(); /* Shouldn't get here */ + new_piece = ceph_msg_data_iter_advance(cursor, bytes); + break; case CEPH_MSG_DATA_NONE: default: BUG(); diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c index c6e5bfc717d54..7fab0e170c592 100644 --- a/net/ceph/messenger_v2.c +++ b/net/ceph/messenger_v2.c @@ -1059,6 +1059,16 @@ static int decrypt_tail(struct ceph_connection *con) if (ret) goto out; + if (con->v2.in_cursor.data->type == CEPH_MSG_DATA_ITER) { + int i; + struct scatterlist *sg; +#if 0 + for_each_sg_table_sg(&sgt, sg, i) { + put_page(sg_page(sg)); + } +#endif + } + WARN_ON(!con->v2.in_enc_page_cnt); ceph_release_page_vector(con->v2.in_enc_pages, con->v2.in_enc_page_cnt); @@ -1792,6 +1802,7 @@ static void prepare_read_data_cont(struct ceph_connection *con) memcpy_to_page(bv.bv_page, bv.bv_offset, page_address(con->bounce_page), con->v2.in_bvec.bv_len); + } else { con->in_data_crc = ceph_crc32c_page(con->in_data_crc, con->v2.in_bvec.bv_page, @@ -1799,6 +1810,9 @@ static void prepare_read_data_cont(struct ceph_connection *con) con->v2.in_bvec.bv_len); } + if (con->v2.in_cursor.data->type == CEPH_MSG_DATA_ITER) + put_page(bv.bv_page); + ceph_msg_data_advance(&con->v2.in_cursor, con->v2.in_bvec.bv_len); if (con->v2.in_cursor.total_resid) { get_bvec_at(&con->v2.in_cursor, &bv);