Skip to content

Commit 8e46a2d

Browse files
lxbszidryomov
authored andcommitted
libceph: just wait for more data to be available on the socket
A short read may occur while reading the message footer from the socket. Later, when the socket is ready for another read, the messenger invokes all read_partial_*() handlers, including read_partial_sparse_msg_data(). The expectation is that read_partial_sparse_msg_data() would bail, allowing the messenger to invoke read_partial() for the footer and pick up where it left off. However read_partial_sparse_msg_data() violates that and ends up calling into the state machine in the OSD client. The sparse-read state machine assumes that it's a new op and interprets some piece of the footer as the sparse-read header and returns bogus extents/data length, etc. To determine whether read_partial_sparse_msg_data() should bail, let's reuse cursor->total_resid. Because once it reaches to zero that means all the extents and data have been successfully received in last read, else it could break out when partially reading any of the extents and data. And then osd_sparse_read() could continue where it left off. [ idryomov: changelog ] Link: https://tracker.ceph.com/issues/63586 Fixes: d396f89 ("libceph: add sparse read support to msgr1") Signed-off-by: Xiubo Li <xiubli@redhat.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
1 parent ee97302 commit 8e46a2d

File tree

4 files changed

+19
-21
lines changed

4 files changed

+19
-21
lines changed

include/linux/ceph/messenger.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ struct ceph_msg {
283283
struct kref kref;
284284
bool more_to_follow;
285285
bool needs_out_seq;
286-
bool sparse_read;
286+
u64 sparse_read_total;
287287
int front_alloc_len;
288288

289289
struct ceph_msgpool *pool;

net/ceph/messenger_v1.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,9 @@ static size_t sizeof_footer(struct ceph_connection *con)
160160
static void prepare_message_data(struct ceph_msg *msg, u32 data_len)
161161
{
162162
/* Initialize data cursor if it's not a sparse read */
163-
if (!msg->sparse_read)
164-
ceph_msg_data_cursor_init(&msg->cursor, msg, data_len);
163+
u64 len = msg->sparse_read_total ? : data_len;
164+
165+
ceph_msg_data_cursor_init(&msg->cursor, msg, len);
165166
}
166167

167168
/*
@@ -1036,31 +1037,31 @@ static int read_partial_sparse_msg_data(struct ceph_connection *con)
10361037
if (do_datacrc)
10371038
crc = con->in_data_crc;
10381039

1039-
do {
1040+
while (cursor->total_resid) {
10401041
if (con->v1.in_sr_kvec.iov_base)
10411042
ret = read_partial_message_chunk(con,
10421043
&con->v1.in_sr_kvec,
10431044
con->v1.in_sr_len,
10441045
&crc);
10451046
else if (cursor->sr_resid > 0)
10461047
ret = read_partial_sparse_msg_extent(con, &crc);
1047-
1048-
if (ret <= 0) {
1049-
if (do_datacrc)
1050-
con->in_data_crc = crc;
1051-
return ret;
1052-
}
1048+
if (ret <= 0)
1049+
break;
10531050

10541051
memset(&con->v1.in_sr_kvec, 0, sizeof(con->v1.in_sr_kvec));
10551052
ret = con->ops->sparse_read(con, cursor,
10561053
(char **)&con->v1.in_sr_kvec.iov_base);
1054+
if (ret <= 0) {
1055+
ret = ret ? ret : 1; /* must return > 0 to indicate success */
1056+
break;
1057+
}
10571058
con->v1.in_sr_len = ret;
1058-
} while (ret > 0);
1059+
}
10591060

10601061
if (do_datacrc)
10611062
con->in_data_crc = crc;
10621063

1063-
return ret < 0 ? ret : 1; /* must return > 0 to indicate success */
1064+
return ret;
10641065
}
10651066

10661067
static int read_partial_msg_data(struct ceph_connection *con)
@@ -1253,7 +1254,7 @@ static int read_partial_message(struct ceph_connection *con)
12531254
if (!m->num_data_items)
12541255
return -EIO;
12551256

1256-
if (m->sparse_read)
1257+
if (m->sparse_read_total)
12571258
ret = read_partial_sparse_msg_data(con);
12581259
else if (ceph_test_opt(from_msgr(con->msgr), RXBOUNCE))
12591260
ret = read_partial_msg_data_bounce(con);

net/ceph/messenger_v2.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,7 @@ static int decrypt_tail(struct ceph_connection *con)
11281128
struct sg_table enc_sgt = {};
11291129
struct sg_table sgt = {};
11301130
struct page **pages = NULL;
1131-
bool sparse = con->in_msg->sparse_read;
1131+
bool sparse = !!con->in_msg->sparse_read_total;
11321132
int dpos = 0;
11331133
int tail_len;
11341134
int ret;
@@ -2060,7 +2060,7 @@ static int prepare_read_tail_plain(struct ceph_connection *con)
20602060
}
20612061

20622062
if (data_len(msg)) {
2063-
if (msg->sparse_read)
2063+
if (msg->sparse_read_total)
20642064
con->v2.in_state = IN_S_PREPARE_SPARSE_DATA;
20652065
else
20662066
con->v2.in_state = IN_S_PREPARE_READ_DATA;

net/ceph/osd_client.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5510,7 +5510,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
55105510
}
55115511

55125512
m = ceph_msg_get(req->r_reply);
5513-
m->sparse_read = (bool)srlen;
5513+
m->sparse_read_total = srlen;
55145514

55155515
dout("get_reply tid %lld %p\n", tid, m);
55165516

@@ -5777,11 +5777,8 @@ static int prep_next_sparse_read(struct ceph_connection *con,
57775777
}
57785778

57795779
if (o->o_sparse_op_idx < 0) {
5780-
u64 srlen = sparse_data_requested(req);
5781-
5782-
dout("%s: [%d] starting new sparse read req. srlen=0x%llx\n",
5783-
__func__, o->o_osd, srlen);
5784-
ceph_msg_data_cursor_init(cursor, con->in_msg, srlen);
5780+
dout("%s: [%d] starting new sparse read req\n",
5781+
__func__, o->o_osd);
57855782
} else {
57865783
u64 end;
57875784

0 commit comments

Comments
 (0)