diff options
author | Yehuda Sadeh <yehuda@hq.newdream.net> | 2010-01-08 16:58:34 -0500 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2010-01-25 15:57:37 -0500 |
commit | 2450418c47b7998ad55a73f23707b1e21c371eef (patch) | |
tree | 1e17dd88f86c5daa1bfbca1aeea0c909391b5829 /fs/ceph/messenger.c | |
parent | 5b1daecd59f95eb24dc629407ed80369c9929520 (diff) |
ceph: allocate middle of message before stating to read
Both front and middle parts of the message are now being
allocated at the ceph_alloc_msg().
Signed-off-by: Yehuda Sadeh <yehuda@hq.newdream.net>
Diffstat (limited to 'fs/ceph/messenger.c')
-rw-r--r-- | fs/ceph/messenger.c | 142 |
1 files changed, 82 insertions, 60 deletions
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c index 1360708d7505..25de15c006b1 100644 --- a/fs/ceph/messenger.c +++ b/fs/ceph/messenger.c | |||
@@ -1279,8 +1279,34 @@ static void process_ack(struct ceph_connection *con) | |||
1279 | 1279 | ||
1280 | 1280 | ||
1281 | 1281 | ||
1282 | static int read_partial_message_section(struct ceph_connection *con, | ||
1283 | struct kvec *section, unsigned int sec_len, | ||
1284 | u32 *crc) | ||
1285 | { | ||
1286 | int left; | ||
1287 | int ret; | ||
1288 | |||
1289 | BUG_ON(!section); | ||
1290 | |||
1291 | while (section->iov_len < sec_len) { | ||
1292 | BUG_ON(section->iov_base == NULL); | ||
1293 | left = sec_len - section->iov_len; | ||
1294 | ret = ceph_tcp_recvmsg(con->sock, (char *)section->iov_base + | ||
1295 | section->iov_len, left); | ||
1296 | if (ret <= 0) | ||
1297 | return ret; | ||
1298 | section->iov_len += ret; | ||
1299 | if (section->iov_len == sec_len) | ||
1300 | *crc = crc32c(0, section->iov_base, | ||
1301 | section->iov_len); | ||
1302 | } | ||
1282 | 1303 | ||
1304 | return 1; | ||
1305 | } | ||
1283 | 1306 | ||
1307 | static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, | ||
1308 | struct ceph_msg_header *hdr, | ||
1309 | int *skip); | ||
1284 | /* | 1310 | /* |
1285 | * read (part of) a message. | 1311 | * read (part of) a message. |
1286 | */ | 1312 | */ |
@@ -1292,6 +1318,7 @@ static int read_partial_message(struct ceph_connection *con) | |||
1292 | int to, want, left; | 1318 | int to, want, left; |
1293 | unsigned front_len, middle_len, data_len, data_off; | 1319 | unsigned front_len, middle_len, data_len, data_off; |
1294 | int datacrc = con->msgr->nocrc; | 1320 | int datacrc = con->msgr->nocrc; |
1321 | int skip; | ||
1295 | 1322 | ||
1296 | dout("read_partial_message con %p msg %p\n", con, m); | 1323 | dout("read_partial_message con %p msg %p\n", con, m); |
1297 | 1324 | ||
@@ -1315,7 +1342,6 @@ static int read_partial_message(struct ceph_connection *con) | |||
1315 | } | 1342 | } |
1316 | } | 1343 | } |
1317 | } | 1344 | } |
1318 | |||
1319 | front_len = le32_to_cpu(con->in_hdr.front_len); | 1345 | front_len = le32_to_cpu(con->in_hdr.front_len); |
1320 | if (front_len > CEPH_MSG_MAX_FRONT_LEN) | 1346 | if (front_len > CEPH_MSG_MAX_FRONT_LEN) |
1321 | return -EIO; | 1347 | return -EIO; |
@@ -1330,8 +1356,8 @@ static int read_partial_message(struct ceph_connection *con) | |||
1330 | if (!con->in_msg) { | 1356 | if (!con->in_msg) { |
1331 | dout("got hdr type %d front %d data %d\n", con->in_hdr.type, | 1357 | dout("got hdr type %d front %d data %d\n", con->in_hdr.type, |
1332 | con->in_hdr.front_len, con->in_hdr.data_len); | 1358 | con->in_hdr.front_len, con->in_hdr.data_len); |
1333 | con->in_msg = con->ops->alloc_msg(con, &con->in_hdr); | 1359 | con->in_msg = ceph_alloc_msg(con, &con->in_hdr, &skip); |
1334 | if (!con->in_msg) { | 1360 | if (skip) { |
1335 | /* skip this message */ | 1361 | /* skip this message */ |
1336 | pr_err("alloc_msg returned NULL, skipping message\n"); | 1362 | pr_err("alloc_msg returned NULL, skipping message\n"); |
1337 | con->in_base_pos = -front_len - middle_len - data_len - | 1363 | con->in_base_pos = -front_len - middle_len - data_len - |
@@ -1342,56 +1368,28 @@ static int read_partial_message(struct ceph_connection *con) | |||
1342 | if (IS_ERR(con->in_msg)) { | 1368 | if (IS_ERR(con->in_msg)) { |
1343 | ret = PTR_ERR(con->in_msg); | 1369 | ret = PTR_ERR(con->in_msg); |
1344 | con->in_msg = NULL; | 1370 | con->in_msg = NULL; |
1345 | con->error_msg = "out of memory for incoming message"; | 1371 | con->error_msg = "error allocating memory for incoming message"; |
1346 | return ret; | 1372 | return ret; |
1347 | } | 1373 | } |
1348 | m = con->in_msg; | 1374 | m = con->in_msg; |
1349 | m->front.iov_len = 0; /* haven't read it yet */ | 1375 | m->front.iov_len = 0; /* haven't read it yet */ |
1376 | if (m->middle) | ||
1377 | m->middle->vec.iov_len = 0; | ||
1350 | memcpy(&m->hdr, &con->in_hdr, sizeof(con->in_hdr)); | 1378 | memcpy(&m->hdr, &con->in_hdr, sizeof(con->in_hdr)); |
1351 | } | 1379 | } |
1352 | 1380 | ||
1353 | /* front */ | 1381 | /* front */ |
1354 | while (m->front.iov_len < front_len) { | 1382 | ret = read_partial_message_section(con, &m->front, front_len, |
1355 | BUG_ON(m->front.iov_base == NULL); | 1383 | &con->in_front_crc); |
1356 | left = front_len - m->front.iov_len; | 1384 | if (ret <= 0) |
1357 | ret = ceph_tcp_recvmsg(con->sock, (char *)m->front.iov_base + | 1385 | return ret; |
1358 | m->front.iov_len, left); | ||
1359 | if (ret <= 0) | ||
1360 | return ret; | ||
1361 | m->front.iov_len += ret; | ||
1362 | if (m->front.iov_len == front_len) | ||
1363 | con->in_front_crc = crc32c(0, m->front.iov_base, | ||
1364 | m->front.iov_len); | ||
1365 | } | ||
1366 | 1386 | ||
1367 | /* middle */ | 1387 | /* middle */ |
1368 | while (middle_len > 0 && (!m->middle || | 1388 | if (m->middle) { |
1369 | m->middle->vec.iov_len < middle_len)) { | 1389 | ret = read_partial_message_section(con, &m->middle->vec, middle_len, |
1370 | if (m->middle == NULL) { | 1390 | &con->in_middle_crc); |
1371 | ret = -EOPNOTSUPP; | ||
1372 | if (con->ops->alloc_middle) | ||
1373 | ret = con->ops->alloc_middle(con, m); | ||
1374 | if (ret < 0) { | ||
1375 | pr_err("alloc_middle fail skipping payload\n"); | ||
1376 | con->in_base_pos = -middle_len - data_len | ||
1377 | - sizeof(m->footer); | ||
1378 | ceph_msg_put(con->in_msg); | ||
1379 | con->in_msg = NULL; | ||
1380 | con->in_tag = CEPH_MSGR_TAG_READY; | ||
1381 | return 0; | ||
1382 | } | ||
1383 | m->middle->vec.iov_len = 0; | ||
1384 | } | ||
1385 | left = middle_len - m->middle->vec.iov_len; | ||
1386 | ret = ceph_tcp_recvmsg(con->sock, | ||
1387 | (char *)m->middle->vec.iov_base + | ||
1388 | m->middle->vec.iov_len, left); | ||
1389 | if (ret <= 0) | 1391 | if (ret <= 0) |
1390 | return ret; | 1392 | return ret; |
1391 | m->middle->vec.iov_len += ret; | ||
1392 | if (m->middle->vec.iov_len == middle_len) | ||
1393 | con->in_middle_crc = crc32c(0, m->middle->vec.iov_base, | ||
1394 | m->middle->vec.iov_len); | ||
1395 | } | 1393 | } |
1396 | 1394 | ||
1397 | /* (page) data */ | 1395 | /* (page) data */ |
@@ -2116,31 +2114,13 @@ out: | |||
2116 | } | 2114 | } |
2117 | 2115 | ||
2118 | /* | 2116 | /* |
2119 | * Generic message allocator, for incoming messages. | ||
2120 | */ | ||
2121 | struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, | ||
2122 | struct ceph_msg_header *hdr) | ||
2123 | { | ||
2124 | int type = le16_to_cpu(hdr->type); | ||
2125 | int front_len = le32_to_cpu(hdr->front_len); | ||
2126 | struct ceph_msg *msg = ceph_msg_new(type, front_len, 0, 0, NULL); | ||
2127 | |||
2128 | if (!msg) { | ||
2129 | pr_err("unable to allocate msg type %d len %d\n", | ||
2130 | type, front_len); | ||
2131 | return ERR_PTR(-ENOMEM); | ||
2132 | } | ||
2133 | return msg; | ||
2134 | } | ||
2135 | |||
2136 | /* | ||
2137 | * Allocate "middle" portion of a message, if it is needed and wasn't | 2117 | * Allocate "middle" portion of a message, if it is needed and wasn't |
2138 | * allocated by alloc_msg. This allows us to read a small fixed-size | 2118 | * allocated by alloc_msg. This allows us to read a small fixed-size |
2139 | * per-type header in the front and then gracefully fail (i.e., | 2119 | * per-type header in the front and then gracefully fail (i.e., |
2140 | * propagate the error to the caller based on info in the front) when | 2120 | * propagate the error to the caller based on info in the front) when |
2141 | * the middle is too large. | 2121 | * the middle is too large. |
2142 | */ | 2122 | */ |
2143 | int ceph_alloc_middle(struct ceph_connection *con, struct ceph_msg *msg) | 2123 | static int ceph_alloc_middle(struct ceph_connection *con, struct ceph_msg *msg) |
2144 | { | 2124 | { |
2145 | int type = le16_to_cpu(msg->hdr.type); | 2125 | int type = le16_to_cpu(msg->hdr.type); |
2146 | int middle_len = le32_to_cpu(msg->hdr.middle_len); | 2126 | int middle_len = le32_to_cpu(msg->hdr.middle_len); |
@@ -2156,6 +2136,48 @@ int ceph_alloc_middle(struct ceph_connection *con, struct ceph_msg *msg) | |||
2156 | return 0; | 2136 | return 0; |
2157 | } | 2137 | } |
2158 | 2138 | ||
2139 | /* | ||
2140 | * Generic message allocator, for incoming messages. | ||
2141 | */ | ||
2142 | static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, | ||
2143 | struct ceph_msg_header *hdr, | ||
2144 | int *skip) | ||
2145 | { | ||
2146 | int type = le16_to_cpu(hdr->type); | ||
2147 | int front_len = le32_to_cpu(hdr->front_len); | ||
2148 | int middle_len = le32_to_cpu(hdr->middle_len); | ||
2149 | struct ceph_msg *msg = NULL; | ||
2150 | int ret; | ||
2151 | |||
2152 | if (con->ops->alloc_msg) { | ||
2153 | msg = con->ops->alloc_msg(con, hdr, skip); | ||
2154 | if (IS_ERR(msg)) | ||
2155 | return msg; | ||
2156 | |||
2157 | if (*skip) | ||
2158 | return NULL; | ||
2159 | } | ||
2160 | if (!msg) { | ||
2161 | *skip = 0; | ||
2162 | msg = ceph_msg_new(type, front_len, 0, 0, NULL); | ||
2163 | if (!msg) { | ||
2164 | pr_err("unable to allocate msg type %d len %d\n", | ||
2165 | type, front_len); | ||
2166 | return ERR_PTR(-ENOMEM); | ||
2167 | } | ||
2168 | } | ||
2169 | |||
2170 | if (middle_len) { | ||
2171 | ret = ceph_alloc_middle(con, msg); | ||
2172 | |||
2173 | if (ret < 0) { | ||
2174 | ceph_msg_put(msg); | ||
2175 | return msg; | ||
2176 | } | ||
2177 | } | ||
2178 | return msg; | ||
2179 | } | ||
2180 | |||
2159 | 2181 | ||
2160 | /* | 2182 | /* |
2161 | * Free a generically kmalloc'd message. | 2183 | * Free a generically kmalloc'd message. |