diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 19:42:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 19:42:18 -0400 |
commit | 97d2eb13a019ec09cc1a7ea2d3705c0b117b3c0d (patch) | |
tree | 86f6382941f8cfc41647d33d87bec7bc1407c18c /net | |
parent | 68d99b2c8efcb6ed3807a55569300c53b5f88be5 (diff) | |
parent | 339573406737461cfb17bebabf7ba536a302d841 (diff) |
Merge branch 'for-linus' of git://ceph.newdream.net/git/ceph-client
* 'for-linus' of git://ceph.newdream.net/git/ceph-client:
libceph: fix double-free of page vector
ceph: fix 32-bit ino numbers
libceph: force resend of osd requests if we skip an osdmap
ceph: use kernel DNS resolver
ceph: fix ceph_monc_init memory leak
ceph: let the set_layout ioctl set single traits
Revert "ceph: don't truncate dirty pages in invalidate work thread"
ceph: replace leading spaces with tabs
libceph: warn on msg allocation failures
libceph: don't complain on msgpool alloc failures
libceph: always preallocate mon connection
libceph: create messenger with client
ceph: document ioctls
ceph: implement (optional) max read size
ceph: rename rsize -> rasize
ceph: make readpages fully async
Diffstat (limited to 'net')
-rw-r--r-- | net/ceph/Kconfig | 14 | ||||
-rw-r--r-- | net/ceph/ceph_common.c | 47 | ||||
-rw-r--r-- | net/ceph/messenger.c | 130 | ||||
-rw-r--r-- | net/ceph/mon_client.c | 79 | ||||
-rw-r--r-- | net/ceph/msgpool.c | 4 | ||||
-rw-r--r-- | net/ceph/osd_client.c | 34 |
6 files changed, 217 insertions, 91 deletions
diff --git a/net/ceph/Kconfig b/net/ceph/Kconfig index be683f2d401f..cc04dd667a10 100644 --- a/net/ceph/Kconfig +++ b/net/ceph/Kconfig | |||
@@ -27,3 +27,17 @@ config CEPH_LIB_PRETTYDEBUG | |||
27 | 27 | ||
28 | If unsure, say N. | 28 | If unsure, say N. |
29 | 29 | ||
30 | config CEPH_LIB_USE_DNS_RESOLVER | ||
31 | bool "Use in-kernel support for DNS lookup" | ||
32 | depends on CEPH_LIB | ||
33 | select DNS_RESOLVER | ||
34 | default n | ||
35 | help | ||
36 | If you say Y here, hostnames (e.g. monitor addresses) will | ||
37 | be resolved using the CONFIG_DNS_RESOLVER facility. | ||
38 | |||
39 | For information on how to use CONFIG_DNS_RESOLVER consult | ||
40 | Documentation/networking/dns_resolver.txt | ||
41 | |||
42 | If unsure, say N. | ||
43 | |||
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 2883ea01e680..97f70e50ad3b 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
@@ -432,9 +432,12 @@ EXPORT_SYMBOL(ceph_client_id); | |||
432 | /* | 432 | /* |
433 | * create a fresh client instance | 433 | * create a fresh client instance |
434 | */ | 434 | */ |
435 | struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private) | 435 | struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, |
436 | unsigned supported_features, | ||
437 | unsigned required_features) | ||
436 | { | 438 | { |
437 | struct ceph_client *client; | 439 | struct ceph_client *client; |
440 | struct ceph_entity_addr *myaddr = NULL; | ||
438 | int err = -ENOMEM; | 441 | int err = -ENOMEM; |
439 | 442 | ||
440 | client = kzalloc(sizeof(*client), GFP_KERNEL); | 443 | client = kzalloc(sizeof(*client), GFP_KERNEL); |
@@ -449,15 +452,27 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private) | |||
449 | client->auth_err = 0; | 452 | client->auth_err = 0; |
450 | 453 | ||
451 | client->extra_mon_dispatch = NULL; | 454 | client->extra_mon_dispatch = NULL; |
452 | client->supported_features = CEPH_FEATURE_SUPPORTED_DEFAULT; | 455 | client->supported_features = CEPH_FEATURE_SUPPORTED_DEFAULT | |
453 | client->required_features = CEPH_FEATURE_REQUIRED_DEFAULT; | 456 | supported_features; |
454 | 457 | client->required_features = CEPH_FEATURE_REQUIRED_DEFAULT | | |
455 | client->msgr = NULL; | 458 | required_features; |
459 | |||
460 | /* msgr */ | ||
461 | if (ceph_test_opt(client, MYIP)) | ||
462 | myaddr = &client->options->my_addr; | ||
463 | client->msgr = ceph_messenger_create(myaddr, | ||
464 | client->supported_features, | ||
465 | client->required_features); | ||
466 | if (IS_ERR(client->msgr)) { | ||
467 | err = PTR_ERR(client->msgr); | ||
468 | goto fail; | ||
469 | } | ||
470 | client->msgr->nocrc = ceph_test_opt(client, NOCRC); | ||
456 | 471 | ||
457 | /* subsystems */ | 472 | /* subsystems */ |
458 | err = ceph_monc_init(&client->monc, client); | 473 | err = ceph_monc_init(&client->monc, client); |
459 | if (err < 0) | 474 | if (err < 0) |
460 | goto fail; | 475 | goto fail_msgr; |
461 | err = ceph_osdc_init(&client->osdc, client); | 476 | err = ceph_osdc_init(&client->osdc, client); |
462 | if (err < 0) | 477 | if (err < 0) |
463 | goto fail_monc; | 478 | goto fail_monc; |
@@ -466,6 +481,8 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private) | |||
466 | 481 | ||
467 | fail_monc: | 482 | fail_monc: |
468 | ceph_monc_stop(&client->monc); | 483 | ceph_monc_stop(&client->monc); |
484 | fail_msgr: | ||
485 | ceph_messenger_destroy(client->msgr); | ||
469 | fail: | 486 | fail: |
470 | kfree(client); | 487 | kfree(client); |
471 | return ERR_PTR(err); | 488 | return ERR_PTR(err); |
@@ -490,8 +507,7 @@ void ceph_destroy_client(struct ceph_client *client) | |||
490 | 507 | ||
491 | ceph_debugfs_client_cleanup(client); | 508 | ceph_debugfs_client_cleanup(client); |
492 | 509 | ||
493 | if (client->msgr) | 510 | ceph_messenger_destroy(client->msgr); |
494 | ceph_messenger_destroy(client->msgr); | ||
495 | 511 | ||
496 | ceph_destroy_options(client->options); | 512 | ceph_destroy_options(client->options); |
497 | 513 | ||
@@ -514,24 +530,9 @@ static int have_mon_and_osd_map(struct ceph_client *client) | |||
514 | */ | 530 | */ |
515 | int __ceph_open_session(struct ceph_client *client, unsigned long started) | 531 | int __ceph_open_session(struct ceph_client *client, unsigned long started) |
516 | { | 532 | { |
517 | struct ceph_entity_addr *myaddr = NULL; | ||
518 | int err; | 533 | int err; |
519 | unsigned long timeout = client->options->mount_timeout * HZ; | 534 | unsigned long timeout = client->options->mount_timeout * HZ; |
520 | 535 | ||
521 | /* initialize the messenger */ | ||
522 | if (client->msgr == NULL) { | ||
523 | if (ceph_test_opt(client, MYIP)) | ||
524 | myaddr = &client->options->my_addr; | ||
525 | client->msgr = ceph_messenger_create(myaddr, | ||
526 | client->supported_features, | ||
527 | client->required_features); | ||
528 | if (IS_ERR(client->msgr)) { | ||
529 | client->msgr = NULL; | ||
530 | return PTR_ERR(client->msgr); | ||
531 | } | ||
532 | client->msgr->nocrc = ceph_test_opt(client, NOCRC); | ||
533 | } | ||
534 | |||
535 | /* open session, and wait for mon and osd maps */ | 536 | /* open session, and wait for mon and osd maps */ |
536 | err = ceph_monc_open_session(&client->monc); | 537 | err = ceph_monc_open_session(&client->monc); |
537 | if (err < 0) | 538 | if (err < 0) |
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 9918e9eb276e..f466930e26fa 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/string.h> | 11 | #include <linux/string.h> |
12 | #include <linux/bio.h> | 12 | #include <linux/bio.h> |
13 | #include <linux/blkdev.h> | 13 | #include <linux/blkdev.h> |
14 | #include <linux/dns_resolver.h> | ||
14 | #include <net/tcp.h> | 15 | #include <net/tcp.h> |
15 | 16 | ||
16 | #include <linux/ceph/libceph.h> | 17 | #include <linux/ceph/libceph.h> |
@@ -1078,6 +1079,101 @@ static void addr_set_port(struct sockaddr_storage *ss, int p) | |||
1078 | } | 1079 | } |
1079 | 1080 | ||
1080 | /* | 1081 | /* |
1082 | * Unlike other *_pton function semantics, zero indicates success. | ||
1083 | */ | ||
1084 | static int ceph_pton(const char *str, size_t len, struct sockaddr_storage *ss, | ||
1085 | char delim, const char **ipend) | ||
1086 | { | ||
1087 | struct sockaddr_in *in4 = (void *)ss; | ||
1088 | struct sockaddr_in6 *in6 = (void *)ss; | ||
1089 | |||
1090 | memset(ss, 0, sizeof(*ss)); | ||
1091 | |||
1092 | if (in4_pton(str, len, (u8 *)&in4->sin_addr.s_addr, delim, ipend)) { | ||
1093 | ss->ss_family = AF_INET; | ||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | if (in6_pton(str, len, (u8 *)&in6->sin6_addr.s6_addr, delim, ipend)) { | ||
1098 | ss->ss_family = AF_INET6; | ||
1099 | return 0; | ||
1100 | } | ||
1101 | |||
1102 | return -EINVAL; | ||
1103 | } | ||
1104 | |||
1105 | /* | ||
1106 | * Extract hostname string and resolve using kernel DNS facility. | ||
1107 | */ | ||
1108 | #ifdef CONFIG_CEPH_LIB_USE_DNS_RESOLVER | ||
1109 | static int ceph_dns_resolve_name(const char *name, size_t namelen, | ||
1110 | struct sockaddr_storage *ss, char delim, const char **ipend) | ||
1111 | { | ||
1112 | const char *end, *delim_p; | ||
1113 | char *colon_p, *ip_addr = NULL; | ||
1114 | int ip_len, ret; | ||
1115 | |||
1116 | /* | ||
1117 | * The end of the hostname occurs immediately preceding the delimiter or | ||
1118 | * the port marker (':') where the delimiter takes precedence. | ||
1119 | */ | ||
1120 | delim_p = memchr(name, delim, namelen); | ||
1121 | colon_p = memchr(name, ':', namelen); | ||
1122 | |||
1123 | if (delim_p && colon_p) | ||
1124 | end = delim_p < colon_p ? delim_p : colon_p; | ||
1125 | else if (!delim_p && colon_p) | ||
1126 | end = colon_p; | ||
1127 | else { | ||
1128 | end = delim_p; | ||
1129 | if (!end) /* case: hostname:/ */ | ||
1130 | end = name + namelen; | ||
1131 | } | ||
1132 | |||
1133 | if (end <= name) | ||
1134 | return -EINVAL; | ||
1135 | |||
1136 | /* do dns_resolve upcall */ | ||
1137 | ip_len = dns_query(NULL, name, end - name, NULL, &ip_addr, NULL); | ||
1138 | if (ip_len > 0) | ||
1139 | ret = ceph_pton(ip_addr, ip_len, ss, -1, NULL); | ||
1140 | else | ||
1141 | ret = -ESRCH; | ||
1142 | |||
1143 | kfree(ip_addr); | ||
1144 | |||
1145 | *ipend = end; | ||
1146 | |||
1147 | pr_info("resolve '%.*s' (ret=%d): %s\n", (int)(end - name), name, | ||
1148 | ret, ret ? "failed" : ceph_pr_addr(ss)); | ||
1149 | |||
1150 | return ret; | ||
1151 | } | ||
1152 | #else | ||
1153 | static inline int ceph_dns_resolve_name(const char *name, size_t namelen, | ||
1154 | struct sockaddr_storage *ss, char delim, const char **ipend) | ||
1155 | { | ||
1156 | return -EINVAL; | ||
1157 | } | ||
1158 | #endif | ||
1159 | |||
1160 | /* | ||
1161 | * Parse a server name (IP or hostname). If a valid IP address is not found | ||
1162 | * then try to extract a hostname to resolve using userspace DNS upcall. | ||
1163 | */ | ||
1164 | static int ceph_parse_server_name(const char *name, size_t namelen, | ||
1165 | struct sockaddr_storage *ss, char delim, const char **ipend) | ||
1166 | { | ||
1167 | int ret; | ||
1168 | |||
1169 | ret = ceph_pton(name, namelen, ss, delim, ipend); | ||
1170 | if (ret) | ||
1171 | ret = ceph_dns_resolve_name(name, namelen, ss, delim, ipend); | ||
1172 | |||
1173 | return ret; | ||
1174 | } | ||
1175 | |||
1176 | /* | ||
1081 | * Parse an ip[:port] list into an addr array. Use the default | 1177 | * Parse an ip[:port] list into an addr array. Use the default |
1082 | * monitor port if a port isn't specified. | 1178 | * monitor port if a port isn't specified. |
1083 | */ | 1179 | */ |
@@ -1085,15 +1181,13 @@ int ceph_parse_ips(const char *c, const char *end, | |||
1085 | struct ceph_entity_addr *addr, | 1181 | struct ceph_entity_addr *addr, |
1086 | int max_count, int *count) | 1182 | int max_count, int *count) |
1087 | { | 1183 | { |
1088 | int i; | 1184 | int i, ret = -EINVAL; |
1089 | const char *p = c; | 1185 | const char *p = c; |
1090 | 1186 | ||
1091 | dout("parse_ips on '%.*s'\n", (int)(end-c), c); | 1187 | dout("parse_ips on '%.*s'\n", (int)(end-c), c); |
1092 | for (i = 0; i < max_count; i++) { | 1188 | for (i = 0; i < max_count; i++) { |
1093 | const char *ipend; | 1189 | const char *ipend; |
1094 | struct sockaddr_storage *ss = &addr[i].in_addr; | 1190 | struct sockaddr_storage *ss = &addr[i].in_addr; |
1095 | struct sockaddr_in *in4 = (void *)ss; | ||
1096 | struct sockaddr_in6 *in6 = (void *)ss; | ||
1097 | int port; | 1191 | int port; |
1098 | char delim = ','; | 1192 | char delim = ','; |
1099 | 1193 | ||
@@ -1102,15 +1196,11 @@ int ceph_parse_ips(const char *c, const char *end, | |||
1102 | p++; | 1196 | p++; |
1103 | } | 1197 | } |
1104 | 1198 | ||
1105 | memset(ss, 0, sizeof(*ss)); | 1199 | ret = ceph_parse_server_name(p, end - p, ss, delim, &ipend); |
1106 | if (in4_pton(p, end - p, (u8 *)&in4->sin_addr.s_addr, | 1200 | if (ret) |
1107 | delim, &ipend)) | ||
1108 | ss->ss_family = AF_INET; | ||
1109 | else if (in6_pton(p, end - p, (u8 *)&in6->sin6_addr.s6_addr, | ||
1110 | delim, &ipend)) | ||
1111 | ss->ss_family = AF_INET6; | ||
1112 | else | ||
1113 | goto bad; | 1201 | goto bad; |
1202 | ret = -EINVAL; | ||
1203 | |||
1114 | p = ipend; | 1204 | p = ipend; |
1115 | 1205 | ||
1116 | if (delim == ']') { | 1206 | if (delim == ']') { |
@@ -1155,7 +1245,7 @@ int ceph_parse_ips(const char *c, const char *end, | |||
1155 | 1245 | ||
1156 | bad: | 1246 | bad: |
1157 | pr_err("parse_ips bad ip '%.*s'\n", (int)(end - c), c); | 1247 | pr_err("parse_ips bad ip '%.*s'\n", (int)(end - c), c); |
1158 | return -EINVAL; | 1248 | return ret; |
1159 | } | 1249 | } |
1160 | EXPORT_SYMBOL(ceph_parse_ips); | 1250 | EXPORT_SYMBOL(ceph_parse_ips); |
1161 | 1251 | ||
@@ -2281,7 +2371,8 @@ EXPORT_SYMBOL(ceph_con_keepalive); | |||
2281 | * construct a new message with given type, size | 2371 | * construct a new message with given type, size |
2282 | * the new msg has a ref count of 1. | 2372 | * the new msg has a ref count of 1. |
2283 | */ | 2373 | */ |
2284 | struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags) | 2374 | struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags, |
2375 | bool can_fail) | ||
2285 | { | 2376 | { |
2286 | struct ceph_msg *m; | 2377 | struct ceph_msg *m; |
2287 | 2378 | ||
@@ -2333,7 +2424,7 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags) | |||
2333 | m->front.iov_base = kmalloc(front_len, flags); | 2424 | m->front.iov_base = kmalloc(front_len, flags); |
2334 | } | 2425 | } |
2335 | if (m->front.iov_base == NULL) { | 2426 | if (m->front.iov_base == NULL) { |
2336 | pr_err("msg_new can't allocate %d bytes\n", | 2427 | dout("ceph_msg_new can't allocate %d bytes\n", |
2337 | front_len); | 2428 | front_len); |
2338 | goto out2; | 2429 | goto out2; |
2339 | } | 2430 | } |
@@ -2348,7 +2439,14 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags) | |||
2348 | out2: | 2439 | out2: |
2349 | ceph_msg_put(m); | 2440 | ceph_msg_put(m); |
2350 | out: | 2441 | out: |
2351 | pr_err("msg_new can't create type %d front %d\n", type, front_len); | 2442 | if (!can_fail) { |
2443 | pr_err("msg_new can't create type %d front %d\n", type, | ||
2444 | front_len); | ||
2445 | WARN_ON(1); | ||
2446 | } else { | ||
2447 | dout("msg_new can't create type %d front %d\n", type, | ||
2448 | front_len); | ||
2449 | } | ||
2352 | return NULL; | 2450 | return NULL; |
2353 | } | 2451 | } |
2354 | EXPORT_SYMBOL(ceph_msg_new); | 2452 | EXPORT_SYMBOL(ceph_msg_new); |
@@ -2398,7 +2496,7 @@ static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, | |||
2398 | } | 2496 | } |
2399 | if (!msg) { | 2497 | if (!msg) { |
2400 | *skip = 0; | 2498 | *skip = 0; |
2401 | msg = ceph_msg_new(type, front_len, GFP_NOFS); | 2499 | msg = ceph_msg_new(type, front_len, GFP_NOFS, false); |
2402 | if (!msg) { | 2500 | if (!msg) { |
2403 | pr_err("unable to allocate msg type %d len %d\n", | 2501 | pr_err("unable to allocate msg type %d len %d\n", |
2404 | type, front_len); | 2502 | type, front_len); |
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index cbe31fa45508..0b62deae42bd 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c | |||
@@ -116,14 +116,12 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) | |||
116 | */ | 116 | */ |
117 | static void __close_session(struct ceph_mon_client *monc) | 117 | static void __close_session(struct ceph_mon_client *monc) |
118 | { | 118 | { |
119 | if (monc->con) { | 119 | dout("__close_session closing mon%d\n", monc->cur_mon); |
120 | dout("__close_session closing mon%d\n", monc->cur_mon); | 120 | ceph_con_revoke(monc->con, monc->m_auth); |
121 | ceph_con_revoke(monc->con, monc->m_auth); | 121 | ceph_con_close(monc->con); |
122 | ceph_con_close(monc->con); | 122 | monc->cur_mon = -1; |
123 | monc->cur_mon = -1; | 123 | monc->pending_auth = 0; |
124 | monc->pending_auth = 0; | 124 | ceph_auth_reset(monc->auth); |
125 | ceph_auth_reset(monc->auth); | ||
126 | } | ||
127 | } | 125 | } |
128 | 126 | ||
129 | /* | 127 | /* |
@@ -302,15 +300,6 @@ void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc) | |||
302 | */ | 300 | */ |
303 | int ceph_monc_open_session(struct ceph_mon_client *monc) | 301 | int ceph_monc_open_session(struct ceph_mon_client *monc) |
304 | { | 302 | { |
305 | if (!monc->con) { | ||
306 | monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL); | ||
307 | if (!monc->con) | ||
308 | return -ENOMEM; | ||
309 | ceph_con_init(monc->client->msgr, monc->con); | ||
310 | monc->con->private = monc; | ||
311 | monc->con->ops = &mon_con_ops; | ||
312 | } | ||
313 | |||
314 | mutex_lock(&monc->mutex); | 303 | mutex_lock(&monc->mutex); |
315 | __open_session(monc); | 304 | __open_session(monc); |
316 | __schedule_delayed(monc); | 305 | __schedule_delayed(monc); |
@@ -528,10 +517,12 @@ int ceph_monc_do_statfs(struct ceph_mon_client *monc, struct ceph_statfs *buf) | |||
528 | init_completion(&req->completion); | 517 | init_completion(&req->completion); |
529 | 518 | ||
530 | err = -ENOMEM; | 519 | err = -ENOMEM; |
531 | req->request = ceph_msg_new(CEPH_MSG_STATFS, sizeof(*h), GFP_NOFS); | 520 | req->request = ceph_msg_new(CEPH_MSG_STATFS, sizeof(*h), GFP_NOFS, |
521 | true); | ||
532 | if (!req->request) | 522 | if (!req->request) |
533 | goto out; | 523 | goto out; |
534 | req->reply = ceph_msg_new(CEPH_MSG_STATFS_REPLY, 1024, GFP_NOFS); | 524 | req->reply = ceph_msg_new(CEPH_MSG_STATFS_REPLY, 1024, GFP_NOFS, |
525 | true); | ||
535 | if (!req->reply) | 526 | if (!req->reply) |
536 | goto out; | 527 | goto out; |
537 | 528 | ||
@@ -626,10 +617,12 @@ int ceph_monc_do_poolop(struct ceph_mon_client *monc, u32 op, | |||
626 | init_completion(&req->completion); | 617 | init_completion(&req->completion); |
627 | 618 | ||
628 | err = -ENOMEM; | 619 | err = -ENOMEM; |
629 | req->request = ceph_msg_new(CEPH_MSG_POOLOP, sizeof(*h), GFP_NOFS); | 620 | req->request = ceph_msg_new(CEPH_MSG_POOLOP, sizeof(*h), GFP_NOFS, |
621 | true); | ||
630 | if (!req->request) | 622 | if (!req->request) |
631 | goto out; | 623 | goto out; |
632 | req->reply = ceph_msg_new(CEPH_MSG_POOLOP_REPLY, 1024, GFP_NOFS); | 624 | req->reply = ceph_msg_new(CEPH_MSG_POOLOP_REPLY, 1024, GFP_NOFS, |
625 | true); | ||
633 | if (!req->reply) | 626 | if (!req->reply) |
634 | goto out; | 627 | goto out; |
635 | 628 | ||
@@ -755,13 +748,21 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) | |||
755 | if (err) | 748 | if (err) |
756 | goto out; | 749 | goto out; |
757 | 750 | ||
758 | monc->con = NULL; | 751 | /* connection */ |
752 | monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL); | ||
753 | if (!monc->con) | ||
754 | goto out_monmap; | ||
755 | ceph_con_init(monc->client->msgr, monc->con); | ||
756 | monc->con->private = monc; | ||
757 | monc->con->ops = &mon_con_ops; | ||
759 | 758 | ||
760 | /* authentication */ | 759 | /* authentication */ |
761 | monc->auth = ceph_auth_init(cl->options->name, | 760 | monc->auth = ceph_auth_init(cl->options->name, |
762 | cl->options->key); | 761 | cl->options->key); |
763 | if (IS_ERR(monc->auth)) | 762 | if (IS_ERR(monc->auth)) { |
764 | return PTR_ERR(monc->auth); | 763 | err = PTR_ERR(monc->auth); |
764 | goto out_con; | ||
765 | } | ||
765 | monc->auth->want_keys = | 766 | monc->auth->want_keys = |
766 | CEPH_ENTITY_TYPE_AUTH | CEPH_ENTITY_TYPE_MON | | 767 | CEPH_ENTITY_TYPE_AUTH | CEPH_ENTITY_TYPE_MON | |
767 | CEPH_ENTITY_TYPE_OSD | CEPH_ENTITY_TYPE_MDS; | 768 | CEPH_ENTITY_TYPE_OSD | CEPH_ENTITY_TYPE_MDS; |
@@ -770,19 +771,21 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) | |||
770 | err = -ENOMEM; | 771 | err = -ENOMEM; |
771 | monc->m_subscribe_ack = ceph_msg_new(CEPH_MSG_MON_SUBSCRIBE_ACK, | 772 | monc->m_subscribe_ack = ceph_msg_new(CEPH_MSG_MON_SUBSCRIBE_ACK, |
772 | sizeof(struct ceph_mon_subscribe_ack), | 773 | sizeof(struct ceph_mon_subscribe_ack), |
773 | GFP_NOFS); | 774 | GFP_NOFS, true); |
774 | if (!monc->m_subscribe_ack) | 775 | if (!monc->m_subscribe_ack) |
775 | goto out_monmap; | 776 | goto out_auth; |
776 | 777 | ||
777 | monc->m_subscribe = ceph_msg_new(CEPH_MSG_MON_SUBSCRIBE, 96, GFP_NOFS); | 778 | monc->m_subscribe = ceph_msg_new(CEPH_MSG_MON_SUBSCRIBE, 96, GFP_NOFS, |
779 | true); | ||
778 | if (!monc->m_subscribe) | 780 | if (!monc->m_subscribe) |
779 | goto out_subscribe_ack; | 781 | goto out_subscribe_ack; |
780 | 782 | ||
781 | monc->m_auth_reply = ceph_msg_new(CEPH_MSG_AUTH_REPLY, 4096, GFP_NOFS); | 783 | monc->m_auth_reply = ceph_msg_new(CEPH_MSG_AUTH_REPLY, 4096, GFP_NOFS, |
784 | true); | ||
782 | if (!monc->m_auth_reply) | 785 | if (!monc->m_auth_reply) |
783 | goto out_subscribe; | 786 | goto out_subscribe; |
784 | 787 | ||
785 | monc->m_auth = ceph_msg_new(CEPH_MSG_AUTH, 4096, GFP_NOFS); | 788 | monc->m_auth = ceph_msg_new(CEPH_MSG_AUTH, 4096, GFP_NOFS, true); |
786 | monc->pending_auth = 0; | 789 | monc->pending_auth = 0; |
787 | if (!monc->m_auth) | 790 | if (!monc->m_auth) |
788 | goto out_auth_reply; | 791 | goto out_auth_reply; |
@@ -808,6 +811,10 @@ out_subscribe: | |||
808 | ceph_msg_put(monc->m_subscribe); | 811 | ceph_msg_put(monc->m_subscribe); |
809 | out_subscribe_ack: | 812 | out_subscribe_ack: |
810 | ceph_msg_put(monc->m_subscribe_ack); | 813 | ceph_msg_put(monc->m_subscribe_ack); |
814 | out_auth: | ||
815 | ceph_auth_destroy(monc->auth); | ||
816 | out_con: | ||
817 | monc->con->ops->put(monc->con); | ||
811 | out_monmap: | 818 | out_monmap: |
812 | kfree(monc->monmap); | 819 | kfree(monc->monmap); |
813 | out: | 820 | out: |
@@ -822,11 +829,11 @@ void ceph_monc_stop(struct ceph_mon_client *monc) | |||
822 | 829 | ||
823 | mutex_lock(&monc->mutex); | 830 | mutex_lock(&monc->mutex); |
824 | __close_session(monc); | 831 | __close_session(monc); |
825 | if (monc->con) { | 832 | |
826 | monc->con->private = NULL; | 833 | monc->con->private = NULL; |
827 | monc->con->ops->put(monc->con); | 834 | monc->con->ops->put(monc->con); |
828 | monc->con = NULL; | 835 | monc->con = NULL; |
829 | } | 836 | |
830 | mutex_unlock(&monc->mutex); | 837 | mutex_unlock(&monc->mutex); |
831 | 838 | ||
832 | ceph_auth_destroy(monc->auth); | 839 | ceph_auth_destroy(monc->auth); |
@@ -973,7 +980,7 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con, | |||
973 | case CEPH_MSG_MON_MAP: | 980 | case CEPH_MSG_MON_MAP: |
974 | case CEPH_MSG_MDS_MAP: | 981 | case CEPH_MSG_MDS_MAP: |
975 | case CEPH_MSG_OSD_MAP: | 982 | case CEPH_MSG_OSD_MAP: |
976 | m = ceph_msg_new(type, front_len, GFP_NOFS); | 983 | m = ceph_msg_new(type, front_len, GFP_NOFS, false); |
977 | break; | 984 | break; |
978 | } | 985 | } |
979 | 986 | ||
@@ -1000,7 +1007,7 @@ static void mon_fault(struct ceph_connection *con) | |||
1000 | if (!con->private) | 1007 | if (!con->private) |
1001 | goto out; | 1008 | goto out; |
1002 | 1009 | ||
1003 | if (monc->con && !monc->hunting) | 1010 | if (!monc->hunting) |
1004 | pr_info("mon%d %s session lost, " | 1011 | pr_info("mon%d %s session lost, " |
1005 | "hunting for new mon\n", monc->cur_mon, | 1012 | "hunting for new mon\n", monc->cur_mon, |
1006 | ceph_pr_addr(&monc->con->peer_addr.in_addr)); | 1013 | ceph_pr_addr(&monc->con->peer_addr.in_addr)); |
diff --git a/net/ceph/msgpool.c b/net/ceph/msgpool.c index 1f4cb30a42c5..11d5f4196a73 100644 --- a/net/ceph/msgpool.c +++ b/net/ceph/msgpool.c | |||
@@ -12,7 +12,7 @@ static void *msgpool_alloc(gfp_t gfp_mask, void *arg) | |||
12 | struct ceph_msgpool *pool = arg; | 12 | struct ceph_msgpool *pool = arg; |
13 | struct ceph_msg *msg; | 13 | struct ceph_msg *msg; |
14 | 14 | ||
15 | msg = ceph_msg_new(0, pool->front_len, gfp_mask); | 15 | msg = ceph_msg_new(0, pool->front_len, gfp_mask, true); |
16 | if (!msg) { | 16 | if (!msg) { |
17 | dout("msgpool_alloc %s failed\n", pool->name); | 17 | dout("msgpool_alloc %s failed\n", pool->name); |
18 | } else { | 18 | } else { |
@@ -61,7 +61,7 @@ struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool, | |||
61 | WARN_ON(1); | 61 | WARN_ON(1); |
62 | 62 | ||
63 | /* try to alloc a fresh message */ | 63 | /* try to alloc a fresh message */ |
64 | return ceph_msg_new(0, front_len, GFP_NOFS); | 64 | return ceph_msg_new(0, front_len, GFP_NOFS, false); |
65 | } | 65 | } |
66 | 66 | ||
67 | msg = mempool_alloc(pool->pool, GFP_NOFS); | 67 | msg = mempool_alloc(pool->pool, GFP_NOFS); |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 88ad8a2501b5..733e46008b89 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -227,7 +227,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, | |||
227 | msg = ceph_msgpool_get(&osdc->msgpool_op_reply, 0); | 227 | msg = ceph_msgpool_get(&osdc->msgpool_op_reply, 0); |
228 | else | 228 | else |
229 | msg = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, | 229 | msg = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, |
230 | OSD_OPREPLY_FRONT_LEN, gfp_flags); | 230 | OSD_OPREPLY_FRONT_LEN, gfp_flags, true); |
231 | if (!msg) { | 231 | if (!msg) { |
232 | ceph_osdc_put_request(req); | 232 | ceph_osdc_put_request(req); |
233 | return NULL; | 233 | return NULL; |
@@ -250,7 +250,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, | |||
250 | if (use_mempool) | 250 | if (use_mempool) |
251 | msg = ceph_msgpool_get(&osdc->msgpool_op, 0); | 251 | msg = ceph_msgpool_get(&osdc->msgpool_op, 0); |
252 | else | 252 | else |
253 | msg = ceph_msg_new(CEPH_MSG_OSD_OP, msg_size, gfp_flags); | 253 | msg = ceph_msg_new(CEPH_MSG_OSD_OP, msg_size, gfp_flags, true); |
254 | if (!msg) { | 254 | if (!msg) { |
255 | ceph_osdc_put_request(req); | 255 | ceph_osdc_put_request(req); |
256 | return NULL; | 256 | return NULL; |
@@ -943,7 +943,7 @@ EXPORT_SYMBOL(ceph_osdc_set_request_linger); | |||
943 | * Caller should hold map_sem for read and request_mutex. | 943 | * Caller should hold map_sem for read and request_mutex. |
944 | */ | 944 | */ |
945 | static int __map_request(struct ceph_osd_client *osdc, | 945 | static int __map_request(struct ceph_osd_client *osdc, |
946 | struct ceph_osd_request *req) | 946 | struct ceph_osd_request *req, int force_resend) |
947 | { | 947 | { |
948 | struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; | 948 | struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; |
949 | struct ceph_pg pgid; | 949 | struct ceph_pg pgid; |
@@ -967,7 +967,8 @@ static int __map_request(struct ceph_osd_client *osdc, | |||
967 | num = err; | 967 | num = err; |
968 | } | 968 | } |
969 | 969 | ||
970 | if ((req->r_osd && req->r_osd->o_osd == o && | 970 | if ((!force_resend && |
971 | req->r_osd && req->r_osd->o_osd == o && | ||
971 | req->r_sent >= req->r_osd->o_incarnation && | 972 | req->r_sent >= req->r_osd->o_incarnation && |
972 | req->r_num_pg_osds == num && | 973 | req->r_num_pg_osds == num && |
973 | memcmp(req->r_pg_osds, acting, sizeof(acting[0])*num) == 0) || | 974 | memcmp(req->r_pg_osds, acting, sizeof(acting[0])*num) == 0) || |
@@ -1289,18 +1290,18 @@ static void reset_changed_osds(struct ceph_osd_client *osdc) | |||
1289 | * | 1290 | * |
1290 | * Caller should hold map_sem for read and request_mutex. | 1291 | * Caller should hold map_sem for read and request_mutex. |
1291 | */ | 1292 | */ |
1292 | static void kick_requests(struct ceph_osd_client *osdc) | 1293 | static void kick_requests(struct ceph_osd_client *osdc, int force_resend) |
1293 | { | 1294 | { |
1294 | struct ceph_osd_request *req, *nreq; | 1295 | struct ceph_osd_request *req, *nreq; |
1295 | struct rb_node *p; | 1296 | struct rb_node *p; |
1296 | int needmap = 0; | 1297 | int needmap = 0; |
1297 | int err; | 1298 | int err; |
1298 | 1299 | ||
1299 | dout("kick_requests\n"); | 1300 | dout("kick_requests %s\n", force_resend ? " (force resend)" : ""); |
1300 | mutex_lock(&osdc->request_mutex); | 1301 | mutex_lock(&osdc->request_mutex); |
1301 | for (p = rb_first(&osdc->requests); p; p = rb_next(p)) { | 1302 | for (p = rb_first(&osdc->requests); p; p = rb_next(p)) { |
1302 | req = rb_entry(p, struct ceph_osd_request, r_node); | 1303 | req = rb_entry(p, struct ceph_osd_request, r_node); |
1303 | err = __map_request(osdc, req); | 1304 | err = __map_request(osdc, req, force_resend); |
1304 | if (err < 0) | 1305 | if (err < 0) |
1305 | continue; /* error */ | 1306 | continue; /* error */ |
1306 | if (req->r_osd == NULL) { | 1307 | if (req->r_osd == NULL) { |
@@ -1318,7 +1319,7 @@ static void kick_requests(struct ceph_osd_client *osdc) | |||
1318 | r_linger_item) { | 1319 | r_linger_item) { |
1319 | dout("linger req=%p req->r_osd=%p\n", req, req->r_osd); | 1320 | dout("linger req=%p req->r_osd=%p\n", req, req->r_osd); |
1320 | 1321 | ||
1321 | err = __map_request(osdc, req); | 1322 | err = __map_request(osdc, req, force_resend); |
1322 | if (err == 0) | 1323 | if (err == 0) |
1323 | continue; /* no change and no osd was specified */ | 1324 | continue; /* no change and no osd was specified */ |
1324 | if (err < 0) | 1325 | if (err < 0) |
@@ -1395,7 +1396,7 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) | |||
1395 | ceph_osdmap_destroy(osdc->osdmap); | 1396 | ceph_osdmap_destroy(osdc->osdmap); |
1396 | osdc->osdmap = newmap; | 1397 | osdc->osdmap = newmap; |
1397 | } | 1398 | } |
1398 | kick_requests(osdc); | 1399 | kick_requests(osdc, 0); |
1399 | reset_changed_osds(osdc); | 1400 | reset_changed_osds(osdc); |
1400 | } else { | 1401 | } else { |
1401 | dout("ignoring incremental map %u len %d\n", | 1402 | dout("ignoring incremental map %u len %d\n", |
@@ -1423,6 +1424,8 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) | |||
1423 | "older than our %u\n", epoch, maplen, | 1424 | "older than our %u\n", epoch, maplen, |
1424 | osdc->osdmap->epoch); | 1425 | osdc->osdmap->epoch); |
1425 | } else { | 1426 | } else { |
1427 | int skipped_map = 0; | ||
1428 | |||
1426 | dout("taking full map %u len %d\n", epoch, maplen); | 1429 | dout("taking full map %u len %d\n", epoch, maplen); |
1427 | newmap = osdmap_decode(&p, p+maplen); | 1430 | newmap = osdmap_decode(&p, p+maplen); |
1428 | if (IS_ERR(newmap)) { | 1431 | if (IS_ERR(newmap)) { |
@@ -1432,9 +1435,12 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) | |||
1432 | BUG_ON(!newmap); | 1435 | BUG_ON(!newmap); |
1433 | oldmap = osdc->osdmap; | 1436 | oldmap = osdc->osdmap; |
1434 | osdc->osdmap = newmap; | 1437 | osdc->osdmap = newmap; |
1435 | if (oldmap) | 1438 | if (oldmap) { |
1439 | if (oldmap->epoch + 1 < newmap->epoch) | ||
1440 | skipped_map = 1; | ||
1436 | ceph_osdmap_destroy(oldmap); | 1441 | ceph_osdmap_destroy(oldmap); |
1437 | kick_requests(osdc); | 1442 | } |
1443 | kick_requests(osdc, skipped_map); | ||
1438 | } | 1444 | } |
1439 | p += maplen; | 1445 | p += maplen; |
1440 | nr_maps--; | 1446 | nr_maps--; |
@@ -1707,7 +1713,7 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, | |||
1707 | * the request still han't been touched yet. | 1713 | * the request still han't been touched yet. |
1708 | */ | 1714 | */ |
1709 | if (req->r_sent == 0) { | 1715 | if (req->r_sent == 0) { |
1710 | rc = __map_request(osdc, req); | 1716 | rc = __map_request(osdc, req, 0); |
1711 | if (rc < 0) { | 1717 | if (rc < 0) { |
1712 | if (nofail) { | 1718 | if (nofail) { |
1713 | dout("osdc_start_request failed map, " | 1719 | dout("osdc_start_request failed map, " |
@@ -2032,7 +2038,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, | |||
2032 | if (front > req->r_reply->front.iov_len) { | 2038 | if (front > req->r_reply->front.iov_len) { |
2033 | pr_warning("get_reply front %d > preallocated %d\n", | 2039 | pr_warning("get_reply front %d > preallocated %d\n", |
2034 | front, (int)req->r_reply->front.iov_len); | 2040 | front, (int)req->r_reply->front.iov_len); |
2035 | m = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, front, GFP_NOFS); | 2041 | m = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, front, GFP_NOFS, false); |
2036 | if (!m) | 2042 | if (!m) |
2037 | goto out; | 2043 | goto out; |
2038 | ceph_msg_put(req->r_reply); | 2044 | ceph_msg_put(req->r_reply); |
@@ -2080,7 +2086,7 @@ static struct ceph_msg *alloc_msg(struct ceph_connection *con, | |||
2080 | switch (type) { | 2086 | switch (type) { |
2081 | case CEPH_MSG_OSD_MAP: | 2087 | case CEPH_MSG_OSD_MAP: |
2082 | case CEPH_MSG_WATCH_NOTIFY: | 2088 | case CEPH_MSG_WATCH_NOTIFY: |
2083 | return ceph_msg_new(type, front, GFP_NOFS); | 2089 | return ceph_msg_new(type, front, GFP_NOFS, false); |
2084 | case CEPH_MSG_OSD_OPREPLY: | 2090 | case CEPH_MSG_OSD_OPREPLY: |
2085 | return get_reply(con, hdr, skip); | 2091 | return get_reply(con, hdr, skip); |
2086 | default: | 2092 | default: |