diff options
Diffstat (limited to 'net/ceph/mon_client.c')
-rw-r--r-- | net/ceph/mon_client.c | 457 |
1 files changed, 252 insertions, 205 deletions
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index de85dddc3dc0..cf638c009cfa 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c | |||
@@ -122,51 +122,91 @@ static void __close_session(struct ceph_mon_client *monc) | |||
122 | ceph_msg_revoke(monc->m_subscribe); | 122 | ceph_msg_revoke(monc->m_subscribe); |
123 | ceph_msg_revoke_incoming(monc->m_subscribe_ack); | 123 | ceph_msg_revoke_incoming(monc->m_subscribe_ack); |
124 | ceph_con_close(&monc->con); | 124 | ceph_con_close(&monc->con); |
125 | monc->cur_mon = -1; | 125 | |
126 | monc->pending_auth = 0; | 126 | monc->pending_auth = 0; |
127 | ceph_auth_reset(monc->auth); | 127 | ceph_auth_reset(monc->auth); |
128 | } | 128 | } |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * Open a session with a (new) monitor. | 131 | * Pick a new monitor at random and set cur_mon. If we are repicking |
132 | * (i.e. cur_mon is already set), be sure to pick a different one. | ||
132 | */ | 133 | */ |
133 | static int __open_session(struct ceph_mon_client *monc) | 134 | static void pick_new_mon(struct ceph_mon_client *monc) |
134 | { | 135 | { |
135 | char r; | 136 | int old_mon = monc->cur_mon; |
136 | int ret; | ||
137 | 137 | ||
138 | if (monc->cur_mon < 0) { | 138 | BUG_ON(monc->monmap->num_mon < 1); |
139 | get_random_bytes(&r, 1); | 139 | |
140 | monc->cur_mon = r % monc->monmap->num_mon; | 140 | if (monc->monmap->num_mon == 1) { |
141 | dout("open_session num=%d r=%d -> mon%d\n", | 141 | monc->cur_mon = 0; |
142 | monc->monmap->num_mon, r, monc->cur_mon); | ||
143 | monc->sub_sent = 0; | ||
144 | monc->sub_renew_after = jiffies; /* i.e., expired */ | ||
145 | monc->want_next_osdmap = !!monc->want_next_osdmap; | ||
146 | |||
147 | dout("open_session mon%d opening\n", monc->cur_mon); | ||
148 | ceph_con_open(&monc->con, | ||
149 | CEPH_ENTITY_TYPE_MON, monc->cur_mon, | ||
150 | &monc->monmap->mon_inst[monc->cur_mon].addr); | ||
151 | |||
152 | /* send an initial keepalive to ensure our timestamp is | ||
153 | * valid by the time we are in an OPENED state */ | ||
154 | ceph_con_keepalive(&monc->con); | ||
155 | |||
156 | /* initiatiate authentication handshake */ | ||
157 | ret = ceph_auth_build_hello(monc->auth, | ||
158 | monc->m_auth->front.iov_base, | ||
159 | monc->m_auth->front_alloc_len); | ||
160 | __send_prepared_auth_request(monc, ret); | ||
161 | } else { | 142 | } else { |
162 | dout("open_session mon%d already open\n", monc->cur_mon); | 143 | int max = monc->monmap->num_mon; |
144 | int o = -1; | ||
145 | int n; | ||
146 | |||
147 | if (monc->cur_mon >= 0) { | ||
148 | if (monc->cur_mon < monc->monmap->num_mon) | ||
149 | o = monc->cur_mon; | ||
150 | if (o >= 0) | ||
151 | max--; | ||
152 | } | ||
153 | |||
154 | n = prandom_u32() % max; | ||
155 | if (o >= 0 && n >= o) | ||
156 | n++; | ||
157 | |||
158 | monc->cur_mon = n; | ||
163 | } | 159 | } |
164 | return 0; | 160 | |
161 | dout("%s mon%d -> mon%d out of %d mons\n", __func__, old_mon, | ||
162 | monc->cur_mon, monc->monmap->num_mon); | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Open a session with a new monitor. | ||
167 | */ | ||
168 | static void __open_session(struct ceph_mon_client *monc) | ||
169 | { | ||
170 | int ret; | ||
171 | |||
172 | pick_new_mon(monc); | ||
173 | |||
174 | monc->hunting = true; | ||
175 | if (monc->had_a_connection) { | ||
176 | monc->hunt_mult *= CEPH_MONC_HUNT_BACKOFF; | ||
177 | if (monc->hunt_mult > CEPH_MONC_HUNT_MAX_MULT) | ||
178 | monc->hunt_mult = CEPH_MONC_HUNT_MAX_MULT; | ||
179 | } | ||
180 | |||
181 | monc->sub_renew_after = jiffies; /* i.e., expired */ | ||
182 | monc->sub_renew_sent = 0; | ||
183 | |||
184 | dout("%s opening mon%d\n", __func__, monc->cur_mon); | ||
185 | ceph_con_open(&monc->con, CEPH_ENTITY_TYPE_MON, monc->cur_mon, | ||
186 | &monc->monmap->mon_inst[monc->cur_mon].addr); | ||
187 | |||
188 | /* | ||
189 | * send an initial keepalive to ensure our timestamp is valid | ||
190 | * by the time we are in an OPENED state | ||
191 | */ | ||
192 | ceph_con_keepalive(&monc->con); | ||
193 | |||
194 | /* initiate authentication handshake */ | ||
195 | ret = ceph_auth_build_hello(monc->auth, | ||
196 | monc->m_auth->front.iov_base, | ||
197 | monc->m_auth->front_alloc_len); | ||
198 | BUG_ON(ret <= 0); | ||
199 | __send_prepared_auth_request(monc, ret); | ||
165 | } | 200 | } |
166 | 201 | ||
167 | static bool __sub_expired(struct ceph_mon_client *monc) | 202 | static void reopen_session(struct ceph_mon_client *monc) |
168 | { | 203 | { |
169 | return time_after_eq(jiffies, monc->sub_renew_after); | 204 | if (!monc->hunting) |
205 | pr_info("mon%d %s session lost, hunting for new mon\n", | ||
206 | monc->cur_mon, ceph_pr_addr(&monc->con.peer_addr.in_addr)); | ||
207 | |||
208 | __close_session(monc); | ||
209 | __open_session(monc); | ||
170 | } | 210 | } |
171 | 211 | ||
172 | /* | 212 | /* |
@@ -174,74 +214,70 @@ static bool __sub_expired(struct ceph_mon_client *monc) | |||
174 | */ | 214 | */ |
175 | static void __schedule_delayed(struct ceph_mon_client *monc) | 215 | static void __schedule_delayed(struct ceph_mon_client *monc) |
176 | { | 216 | { |
177 | struct ceph_options *opt = monc->client->options; | ||
178 | unsigned long delay; | 217 | unsigned long delay; |
179 | 218 | ||
180 | if (monc->cur_mon < 0 || __sub_expired(monc)) { | 219 | if (monc->hunting) |
181 | delay = 10 * HZ; | 220 | delay = CEPH_MONC_HUNT_INTERVAL * monc->hunt_mult; |
182 | } else { | 221 | else |
183 | delay = 20 * HZ; | 222 | delay = CEPH_MONC_PING_INTERVAL; |
184 | if (opt->monc_ping_timeout > 0) | 223 | |
185 | delay = min(delay, opt->monc_ping_timeout / 3); | ||
186 | } | ||
187 | dout("__schedule_delayed after %lu\n", delay); | 224 | dout("__schedule_delayed after %lu\n", delay); |
188 | schedule_delayed_work(&monc->delayed_work, | 225 | mod_delayed_work(system_wq, &monc->delayed_work, |
189 | round_jiffies_relative(delay)); | 226 | round_jiffies_relative(delay)); |
190 | } | 227 | } |
191 | 228 | ||
229 | const char *ceph_sub_str[] = { | ||
230 | [CEPH_SUB_MDSMAP] = "mdsmap", | ||
231 | [CEPH_SUB_MONMAP] = "monmap", | ||
232 | [CEPH_SUB_OSDMAP] = "osdmap", | ||
233 | }; | ||
234 | |||
192 | /* | 235 | /* |
193 | * Send subscribe request for mdsmap and/or osdmap. | 236 | * Send subscribe request for one or more maps, according to |
237 | * monc->subs. | ||
194 | */ | 238 | */ |
195 | static void __send_subscribe(struct ceph_mon_client *monc) | 239 | static void __send_subscribe(struct ceph_mon_client *monc) |
196 | { | 240 | { |
197 | dout("__send_subscribe sub_sent=%u exp=%u want_osd=%d\n", | 241 | struct ceph_msg *msg = monc->m_subscribe; |
198 | (unsigned int)monc->sub_sent, __sub_expired(monc), | 242 | void *p = msg->front.iov_base; |
199 | monc->want_next_osdmap); | 243 | void *const end = p + msg->front_alloc_len; |
200 | if ((__sub_expired(monc) && !monc->sub_sent) || | 244 | int num = 0; |
201 | monc->want_next_osdmap == 1) { | 245 | int i; |
202 | struct ceph_msg *msg = monc->m_subscribe; | 246 | |
203 | struct ceph_mon_subscribe_item *i; | 247 | dout("%s sent %lu\n", __func__, monc->sub_renew_sent); |
204 | void *p, *end; | 248 | |
205 | int num; | 249 | BUG_ON(monc->cur_mon < 0); |
206 | 250 | ||
207 | p = msg->front.iov_base; | 251 | if (!monc->sub_renew_sent) |
208 | end = p + msg->front_alloc_len; | 252 | monc->sub_renew_sent = jiffies | 1; /* never 0 */ |
209 | 253 | ||
210 | num = 1 + !!monc->want_next_osdmap + !!monc->want_mdsmap; | 254 | msg->hdr.version = cpu_to_le16(2); |
211 | ceph_encode_32(&p, num); | 255 | |
212 | 256 | for (i = 0; i < ARRAY_SIZE(monc->subs); i++) { | |
213 | if (monc->want_next_osdmap) { | 257 | if (monc->subs[i].want) |
214 | dout("__send_subscribe to 'osdmap' %u\n", | 258 | num++; |
215 | (unsigned int)monc->have_osdmap); | ||
216 | ceph_encode_string(&p, end, "osdmap", 6); | ||
217 | i = p; | ||
218 | i->have = cpu_to_le64(monc->have_osdmap); | ||
219 | i->onetime = 1; | ||
220 | p += sizeof(*i); | ||
221 | monc->want_next_osdmap = 2; /* requested */ | ||
222 | } | ||
223 | if (monc->want_mdsmap) { | ||
224 | dout("__send_subscribe to 'mdsmap' %u+\n", | ||
225 | (unsigned int)monc->have_mdsmap); | ||
226 | ceph_encode_string(&p, end, "mdsmap", 6); | ||
227 | i = p; | ||
228 | i->have = cpu_to_le64(monc->have_mdsmap); | ||
229 | i->onetime = 0; | ||
230 | p += sizeof(*i); | ||
231 | } | ||
232 | ceph_encode_string(&p, end, "monmap", 6); | ||
233 | i = p; | ||
234 | i->have = 0; | ||
235 | i->onetime = 0; | ||
236 | p += sizeof(*i); | ||
237 | |||
238 | msg->front.iov_len = p - msg->front.iov_base; | ||
239 | msg->hdr.front_len = cpu_to_le32(msg->front.iov_len); | ||
240 | ceph_msg_revoke(msg); | ||
241 | ceph_con_send(&monc->con, ceph_msg_get(msg)); | ||
242 | |||
243 | monc->sub_sent = jiffies | 1; /* never 0 */ | ||
244 | } | 259 | } |
260 | BUG_ON(num < 1); /* monmap sub is always there */ | ||
261 | ceph_encode_32(&p, num); | ||
262 | for (i = 0; i < ARRAY_SIZE(monc->subs); i++) { | ||
263 | const char *s = ceph_sub_str[i]; | ||
264 | |||
265 | if (!monc->subs[i].want) | ||
266 | continue; | ||
267 | |||
268 | dout("%s %s start %llu flags 0x%x\n", __func__, s, | ||
269 | le64_to_cpu(monc->subs[i].item.start), | ||
270 | monc->subs[i].item.flags); | ||
271 | ceph_encode_string(&p, end, s, strlen(s)); | ||
272 | memcpy(p, &monc->subs[i].item, sizeof(monc->subs[i].item)); | ||
273 | p += sizeof(monc->subs[i].item); | ||
274 | } | ||
275 | |||
276 | BUG_ON(p != (end - 35 - (ARRAY_SIZE(monc->subs) - num) * 19)); | ||
277 | msg->front.iov_len = p - msg->front.iov_base; | ||
278 | msg->hdr.front_len = cpu_to_le32(msg->front.iov_len); | ||
279 | ceph_msg_revoke(msg); | ||
280 | ceph_con_send(&monc->con, ceph_msg_get(msg)); | ||
245 | } | 281 | } |
246 | 282 | ||
247 | static void handle_subscribe_ack(struct ceph_mon_client *monc, | 283 | static void handle_subscribe_ack(struct ceph_mon_client *monc, |
@@ -255,15 +291,16 @@ static void handle_subscribe_ack(struct ceph_mon_client *monc, | |||
255 | seconds = le32_to_cpu(h->duration); | 291 | seconds = le32_to_cpu(h->duration); |
256 | 292 | ||
257 | mutex_lock(&monc->mutex); | 293 | mutex_lock(&monc->mutex); |
258 | if (monc->hunting) { | 294 | if (monc->sub_renew_sent) { |
259 | pr_info("mon%d %s session established\n", | 295 | monc->sub_renew_after = monc->sub_renew_sent + |
260 | monc->cur_mon, | 296 | (seconds >> 1) * HZ - 1; |
261 | ceph_pr_addr(&monc->con.peer_addr.in_addr)); | 297 | dout("%s sent %lu duration %d renew after %lu\n", __func__, |
262 | monc->hunting = false; | 298 | monc->sub_renew_sent, seconds, monc->sub_renew_after); |
299 | monc->sub_renew_sent = 0; | ||
300 | } else { | ||
301 | dout("%s sent %lu renew after %lu, ignoring\n", __func__, | ||
302 | monc->sub_renew_sent, monc->sub_renew_after); | ||
263 | } | 303 | } |
264 | dout("handle_subscribe_ack after %d seconds\n", seconds); | ||
265 | monc->sub_renew_after = monc->sub_sent + (seconds >> 1)*HZ - 1; | ||
266 | monc->sub_sent = 0; | ||
267 | mutex_unlock(&monc->mutex); | 304 | mutex_unlock(&monc->mutex); |
268 | return; | 305 | return; |
269 | bad: | 306 | bad: |
@@ -272,36 +309,82 @@ bad: | |||
272 | } | 309 | } |
273 | 310 | ||
274 | /* | 311 | /* |
275 | * Keep track of which maps we have | 312 | * Register interest in a map |
313 | * | ||
314 | * @sub: one of CEPH_SUB_* | ||
315 | * @epoch: X for "every map since X", or 0 for "just the latest" | ||
276 | */ | 316 | */ |
277 | int ceph_monc_got_mdsmap(struct ceph_mon_client *monc, u32 got) | 317 | static bool __ceph_monc_want_map(struct ceph_mon_client *monc, int sub, |
318 | u32 epoch, bool continuous) | ||
319 | { | ||
320 | __le64 start = cpu_to_le64(epoch); | ||
321 | u8 flags = !continuous ? CEPH_SUBSCRIBE_ONETIME : 0; | ||
322 | |||
323 | dout("%s %s epoch %u continuous %d\n", __func__, ceph_sub_str[sub], | ||
324 | epoch, continuous); | ||
325 | |||
326 | if (monc->subs[sub].want && | ||
327 | monc->subs[sub].item.start == start && | ||
328 | monc->subs[sub].item.flags == flags) | ||
329 | return false; | ||
330 | |||
331 | monc->subs[sub].item.start = start; | ||
332 | monc->subs[sub].item.flags = flags; | ||
333 | monc->subs[sub].want = true; | ||
334 | |||
335 | return true; | ||
336 | } | ||
337 | |||
338 | bool ceph_monc_want_map(struct ceph_mon_client *monc, int sub, u32 epoch, | ||
339 | bool continuous) | ||
278 | { | 340 | { |
341 | bool need_request; | ||
342 | |||
279 | mutex_lock(&monc->mutex); | 343 | mutex_lock(&monc->mutex); |
280 | monc->have_mdsmap = got; | 344 | need_request = __ceph_monc_want_map(monc, sub, epoch, continuous); |
281 | mutex_unlock(&monc->mutex); | 345 | mutex_unlock(&monc->mutex); |
282 | return 0; | 346 | |
347 | return need_request; | ||
283 | } | 348 | } |
284 | EXPORT_SYMBOL(ceph_monc_got_mdsmap); | 349 | EXPORT_SYMBOL(ceph_monc_want_map); |
285 | 350 | ||
286 | int ceph_monc_got_osdmap(struct ceph_mon_client *monc, u32 got) | 351 | /* |
352 | * Keep track of which maps we have | ||
353 | * | ||
354 | * @sub: one of CEPH_SUB_* | ||
355 | */ | ||
356 | static void __ceph_monc_got_map(struct ceph_mon_client *monc, int sub, | ||
357 | u32 epoch) | ||
358 | { | ||
359 | dout("%s %s epoch %u\n", __func__, ceph_sub_str[sub], epoch); | ||
360 | |||
361 | if (monc->subs[sub].want) { | ||
362 | if (monc->subs[sub].item.flags & CEPH_SUBSCRIBE_ONETIME) | ||
363 | monc->subs[sub].want = false; | ||
364 | else | ||
365 | monc->subs[sub].item.start = cpu_to_le64(epoch + 1); | ||
366 | } | ||
367 | |||
368 | monc->subs[sub].have = epoch; | ||
369 | } | ||
370 | |||
371 | void ceph_monc_got_map(struct ceph_mon_client *monc, int sub, u32 epoch) | ||
287 | { | 372 | { |
288 | mutex_lock(&monc->mutex); | 373 | mutex_lock(&monc->mutex); |
289 | monc->have_osdmap = got; | 374 | __ceph_monc_got_map(monc, sub, epoch); |
290 | monc->want_next_osdmap = 0; | ||
291 | mutex_unlock(&monc->mutex); | 375 | mutex_unlock(&monc->mutex); |
292 | return 0; | ||
293 | } | 376 | } |
377 | EXPORT_SYMBOL(ceph_monc_got_map); | ||
294 | 378 | ||
295 | /* | 379 | /* |
296 | * Register interest in the next osdmap | 380 | * Register interest in the next osdmap |
297 | */ | 381 | */ |
298 | void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc) | 382 | void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc) |
299 | { | 383 | { |
300 | dout("request_next_osdmap have %u\n", monc->have_osdmap); | 384 | dout("%s have %u\n", __func__, monc->subs[CEPH_SUB_OSDMAP].have); |
301 | mutex_lock(&monc->mutex); | 385 | mutex_lock(&monc->mutex); |
302 | if (!monc->want_next_osdmap) | 386 | if (__ceph_monc_want_map(monc, CEPH_SUB_OSDMAP, |
303 | monc->want_next_osdmap = 1; | 387 | monc->subs[CEPH_SUB_OSDMAP].have + 1, false)) |
304 | if (monc->want_next_osdmap < 2) | ||
305 | __send_subscribe(monc); | 388 | __send_subscribe(monc); |
306 | mutex_unlock(&monc->mutex); | 389 | mutex_unlock(&monc->mutex); |
307 | } | 390 | } |
@@ -320,15 +403,15 @@ int ceph_monc_wait_osdmap(struct ceph_mon_client *monc, u32 epoch, | |||
320 | long ret; | 403 | long ret; |
321 | 404 | ||
322 | mutex_lock(&monc->mutex); | 405 | mutex_lock(&monc->mutex); |
323 | while (monc->have_osdmap < epoch) { | 406 | while (monc->subs[CEPH_SUB_OSDMAP].have < epoch) { |
324 | mutex_unlock(&monc->mutex); | 407 | mutex_unlock(&monc->mutex); |
325 | 408 | ||
326 | if (timeout && time_after_eq(jiffies, started + timeout)) | 409 | if (timeout && time_after_eq(jiffies, started + timeout)) |
327 | return -ETIMEDOUT; | 410 | return -ETIMEDOUT; |
328 | 411 | ||
329 | ret = wait_event_interruptible_timeout(monc->client->auth_wq, | 412 | ret = wait_event_interruptible_timeout(monc->client->auth_wq, |
330 | monc->have_osdmap >= epoch, | 413 | monc->subs[CEPH_SUB_OSDMAP].have >= epoch, |
331 | ceph_timeout_jiffies(timeout)); | 414 | ceph_timeout_jiffies(timeout)); |
332 | if (ret < 0) | 415 | if (ret < 0) |
333 | return ret; | 416 | return ret; |
334 | 417 | ||
@@ -341,11 +424,14 @@ int ceph_monc_wait_osdmap(struct ceph_mon_client *monc, u32 epoch, | |||
341 | EXPORT_SYMBOL(ceph_monc_wait_osdmap); | 424 | EXPORT_SYMBOL(ceph_monc_wait_osdmap); |
342 | 425 | ||
343 | /* | 426 | /* |
344 | * | 427 | * Open a session with a random monitor. Request monmap and osdmap, |
428 | * which are waited upon in __ceph_open_session(). | ||
345 | */ | 429 | */ |
346 | int ceph_monc_open_session(struct ceph_mon_client *monc) | 430 | int ceph_monc_open_session(struct ceph_mon_client *monc) |
347 | { | 431 | { |
348 | mutex_lock(&monc->mutex); | 432 | mutex_lock(&monc->mutex); |
433 | __ceph_monc_want_map(monc, CEPH_SUB_MONMAP, 0, true); | ||
434 | __ceph_monc_want_map(monc, CEPH_SUB_OSDMAP, 0, false); | ||
349 | __open_session(monc); | 435 | __open_session(monc); |
350 | __schedule_delayed(monc); | 436 | __schedule_delayed(monc); |
351 | mutex_unlock(&monc->mutex); | 437 | mutex_unlock(&monc->mutex); |
@@ -353,29 +439,15 @@ int ceph_monc_open_session(struct ceph_mon_client *monc) | |||
353 | } | 439 | } |
354 | EXPORT_SYMBOL(ceph_monc_open_session); | 440 | EXPORT_SYMBOL(ceph_monc_open_session); |
355 | 441 | ||
356 | /* | ||
357 | * We require the fsid and global_id in order to initialize our | ||
358 | * debugfs dir. | ||
359 | */ | ||
360 | static bool have_debugfs_info(struct ceph_mon_client *monc) | ||
361 | { | ||
362 | dout("have_debugfs_info fsid %d globalid %lld\n", | ||
363 | (int)monc->client->have_fsid, monc->auth->global_id); | ||
364 | return monc->client->have_fsid && monc->auth->global_id > 0; | ||
365 | } | ||
366 | |||
367 | static void ceph_monc_handle_map(struct ceph_mon_client *monc, | 442 | static void ceph_monc_handle_map(struct ceph_mon_client *monc, |
368 | struct ceph_msg *msg) | 443 | struct ceph_msg *msg) |
369 | { | 444 | { |
370 | struct ceph_client *client = monc->client; | 445 | struct ceph_client *client = monc->client; |
371 | struct ceph_monmap *monmap = NULL, *old = monc->monmap; | 446 | struct ceph_monmap *monmap = NULL, *old = monc->monmap; |
372 | void *p, *end; | 447 | void *p, *end; |
373 | int had_debugfs_info, init_debugfs = 0; | ||
374 | 448 | ||
375 | mutex_lock(&monc->mutex); | 449 | mutex_lock(&monc->mutex); |
376 | 450 | ||
377 | had_debugfs_info = have_debugfs_info(monc); | ||
378 | |||
379 | dout("handle_monmap\n"); | 451 | dout("handle_monmap\n"); |
380 | p = msg->front.iov_base; | 452 | p = msg->front.iov_base; |
381 | end = p + msg->front.iov_len; | 453 | end = p + msg->front.iov_len; |
@@ -395,29 +467,11 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, | |||
395 | client->monc.monmap = monmap; | 467 | client->monc.monmap = monmap; |
396 | kfree(old); | 468 | kfree(old); |
397 | 469 | ||
398 | if (!client->have_fsid) { | 470 | __ceph_monc_got_map(monc, CEPH_SUB_MONMAP, monc->monmap->epoch); |
399 | client->have_fsid = true; | 471 | client->have_fsid = true; |
400 | if (!had_debugfs_info && have_debugfs_info(monc)) { | ||
401 | pr_info("client%lld fsid %pU\n", | ||
402 | ceph_client_id(monc->client), | ||
403 | &monc->client->fsid); | ||
404 | init_debugfs = 1; | ||
405 | } | ||
406 | mutex_unlock(&monc->mutex); | ||
407 | |||
408 | if (init_debugfs) { | ||
409 | /* | ||
410 | * do debugfs initialization without mutex to avoid | ||
411 | * creating a locking dependency | ||
412 | */ | ||
413 | ceph_debugfs_client_init(monc->client); | ||
414 | } | ||
415 | 472 | ||
416 | goto out_unlocked; | ||
417 | } | ||
418 | out: | 473 | out: |
419 | mutex_unlock(&monc->mutex); | 474 | mutex_unlock(&monc->mutex); |
420 | out_unlocked: | ||
421 | wake_up_all(&client->auth_wq); | 475 | wake_up_all(&client->auth_wq); |
422 | } | 476 | } |
423 | 477 | ||
@@ -745,18 +799,15 @@ static void delayed_work(struct work_struct *work) | |||
745 | dout("monc delayed_work\n"); | 799 | dout("monc delayed_work\n"); |
746 | mutex_lock(&monc->mutex); | 800 | mutex_lock(&monc->mutex); |
747 | if (monc->hunting) { | 801 | if (monc->hunting) { |
748 | __close_session(monc); | 802 | dout("%s continuing hunt\n", __func__); |
749 | __open_session(monc); /* continue hunting */ | 803 | reopen_session(monc); |
750 | } else { | 804 | } else { |
751 | struct ceph_options *opt = monc->client->options; | ||
752 | int is_auth = ceph_auth_is_authenticated(monc->auth); | 805 | int is_auth = ceph_auth_is_authenticated(monc->auth); |
753 | if (ceph_con_keepalive_expired(&monc->con, | 806 | if (ceph_con_keepalive_expired(&monc->con, |
754 | opt->monc_ping_timeout)) { | 807 | CEPH_MONC_PING_TIMEOUT)) { |
755 | dout("monc keepalive timeout\n"); | 808 | dout("monc keepalive timeout\n"); |
756 | is_auth = 0; | 809 | is_auth = 0; |
757 | __close_session(monc); | 810 | reopen_session(monc); |
758 | monc->hunting = true; | ||
759 | __open_session(monc); | ||
760 | } | 811 | } |
761 | 812 | ||
762 | if (!monc->hunting) { | 813 | if (!monc->hunting) { |
@@ -764,8 +815,14 @@ static void delayed_work(struct work_struct *work) | |||
764 | __validate_auth(monc); | 815 | __validate_auth(monc); |
765 | } | 816 | } |
766 | 817 | ||
767 | if (is_auth) | 818 | if (is_auth) { |
768 | __send_subscribe(monc); | 819 | unsigned long now = jiffies; |
820 | |||
821 | dout("%s renew subs? now %lu renew after %lu\n", | ||
822 | __func__, now, monc->sub_renew_after); | ||
823 | if (time_after_eq(now, monc->sub_renew_after)) | ||
824 | __send_subscribe(monc); | ||
825 | } | ||
769 | } | 826 | } |
770 | __schedule_delayed(monc); | 827 | __schedule_delayed(monc); |
771 | mutex_unlock(&monc->mutex); | 828 | mutex_unlock(&monc->mutex); |
@@ -852,18 +909,14 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) | |||
852 | &monc->client->msgr); | 909 | &monc->client->msgr); |
853 | 910 | ||
854 | monc->cur_mon = -1; | 911 | monc->cur_mon = -1; |
855 | monc->hunting = true; | 912 | monc->had_a_connection = false; |
856 | monc->sub_renew_after = jiffies; | 913 | monc->hunt_mult = 1; |
857 | monc->sub_sent = 0; | ||
858 | 914 | ||
859 | INIT_DELAYED_WORK(&monc->delayed_work, delayed_work); | 915 | INIT_DELAYED_WORK(&monc->delayed_work, delayed_work); |
860 | monc->generic_request_tree = RB_ROOT; | 916 | monc->generic_request_tree = RB_ROOT; |
861 | monc->num_generic_requests = 0; | 917 | monc->num_generic_requests = 0; |
862 | monc->last_tid = 0; | 918 | monc->last_tid = 0; |
863 | 919 | ||
864 | monc->have_mdsmap = 0; | ||
865 | monc->have_osdmap = 0; | ||
866 | monc->want_next_osdmap = 1; | ||
867 | return 0; | 920 | return 0; |
868 | 921 | ||
869 | out_auth_reply: | 922 | out_auth_reply: |
@@ -888,7 +941,7 @@ void ceph_monc_stop(struct ceph_mon_client *monc) | |||
888 | 941 | ||
889 | mutex_lock(&monc->mutex); | 942 | mutex_lock(&monc->mutex); |
890 | __close_session(monc); | 943 | __close_session(monc); |
891 | 944 | monc->cur_mon = -1; | |
892 | mutex_unlock(&monc->mutex); | 945 | mutex_unlock(&monc->mutex); |
893 | 946 | ||
894 | /* | 947 | /* |
@@ -910,26 +963,40 @@ void ceph_monc_stop(struct ceph_mon_client *monc) | |||
910 | } | 963 | } |
911 | EXPORT_SYMBOL(ceph_monc_stop); | 964 | EXPORT_SYMBOL(ceph_monc_stop); |
912 | 965 | ||
966 | static void finish_hunting(struct ceph_mon_client *monc) | ||
967 | { | ||
968 | if (monc->hunting) { | ||
969 | dout("%s found mon%d\n", __func__, monc->cur_mon); | ||
970 | monc->hunting = false; | ||
971 | monc->had_a_connection = true; | ||
972 | monc->hunt_mult /= 2; /* reduce by 50% */ | ||
973 | if (monc->hunt_mult < 1) | ||
974 | monc->hunt_mult = 1; | ||
975 | } | ||
976 | } | ||
977 | |||
913 | static void handle_auth_reply(struct ceph_mon_client *monc, | 978 | static void handle_auth_reply(struct ceph_mon_client *monc, |
914 | struct ceph_msg *msg) | 979 | struct ceph_msg *msg) |
915 | { | 980 | { |
916 | int ret; | 981 | int ret; |
917 | int was_auth = 0; | 982 | int was_auth = 0; |
918 | int had_debugfs_info, init_debugfs = 0; | ||
919 | 983 | ||
920 | mutex_lock(&monc->mutex); | 984 | mutex_lock(&monc->mutex); |
921 | had_debugfs_info = have_debugfs_info(monc); | ||
922 | was_auth = ceph_auth_is_authenticated(monc->auth); | 985 | was_auth = ceph_auth_is_authenticated(monc->auth); |
923 | monc->pending_auth = 0; | 986 | monc->pending_auth = 0; |
924 | ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base, | 987 | ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base, |
925 | msg->front.iov_len, | 988 | msg->front.iov_len, |
926 | monc->m_auth->front.iov_base, | 989 | monc->m_auth->front.iov_base, |
927 | monc->m_auth->front_alloc_len); | 990 | monc->m_auth->front_alloc_len); |
991 | if (ret > 0) { | ||
992 | __send_prepared_auth_request(monc, ret); | ||
993 | goto out; | ||
994 | } | ||
995 | |||
996 | finish_hunting(monc); | ||
997 | |||
928 | if (ret < 0) { | 998 | if (ret < 0) { |
929 | monc->client->auth_err = ret; | 999 | monc->client->auth_err = ret; |
930 | wake_up_all(&monc->client->auth_wq); | ||
931 | } else if (ret > 0) { | ||
932 | __send_prepared_auth_request(monc, ret); | ||
933 | } else if (!was_auth && ceph_auth_is_authenticated(monc->auth)) { | 1000 | } else if (!was_auth && ceph_auth_is_authenticated(monc->auth)) { |
934 | dout("authenticated, starting session\n"); | 1001 | dout("authenticated, starting session\n"); |
935 | 1002 | ||
@@ -939,23 +1006,15 @@ static void handle_auth_reply(struct ceph_mon_client *monc, | |||
939 | 1006 | ||
940 | __send_subscribe(monc); | 1007 | __send_subscribe(monc); |
941 | __resend_generic_request(monc); | 1008 | __resend_generic_request(monc); |
942 | } | ||
943 | 1009 | ||
944 | if (!had_debugfs_info && have_debugfs_info(monc)) { | 1010 | pr_info("mon%d %s session established\n", monc->cur_mon, |
945 | pr_info("client%lld fsid %pU\n", | 1011 | ceph_pr_addr(&monc->con.peer_addr.in_addr)); |
946 | ceph_client_id(monc->client), | ||
947 | &monc->client->fsid); | ||
948 | init_debugfs = 1; | ||
949 | } | 1012 | } |
950 | mutex_unlock(&monc->mutex); | ||
951 | 1013 | ||
952 | if (init_debugfs) { | 1014 | out: |
953 | /* | 1015 | mutex_unlock(&monc->mutex); |
954 | * do debugfs initialization without mutex to avoid | 1016 | if (monc->client->auth_err < 0) |
955 | * creating a locking dependency | 1017 | wake_up_all(&monc->client->auth_wq); |
956 | */ | ||
957 | ceph_debugfs_client_init(monc->client); | ||
958 | } | ||
959 | } | 1018 | } |
960 | 1019 | ||
961 | static int __validate_auth(struct ceph_mon_client *monc) | 1020 | static int __validate_auth(struct ceph_mon_client *monc) |
@@ -1096,29 +1155,17 @@ static void mon_fault(struct ceph_connection *con) | |||
1096 | { | 1155 | { |
1097 | struct ceph_mon_client *monc = con->private; | 1156 | struct ceph_mon_client *monc = con->private; |
1098 | 1157 | ||
1099 | if (!monc) | ||
1100 | return; | ||
1101 | |||
1102 | dout("mon_fault\n"); | ||
1103 | mutex_lock(&monc->mutex); | 1158 | mutex_lock(&monc->mutex); |
1104 | if (!con->private) | 1159 | dout("%s mon%d\n", __func__, monc->cur_mon); |
1105 | goto out; | 1160 | if (monc->cur_mon >= 0) { |
1106 | 1161 | if (!monc->hunting) { | |
1107 | if (!monc->hunting) | 1162 | dout("%s hunting for new mon\n", __func__); |
1108 | pr_info("mon%d %s session lost, " | 1163 | reopen_session(monc); |
1109 | "hunting for new mon\n", monc->cur_mon, | 1164 | __schedule_delayed(monc); |
1110 | ceph_pr_addr(&monc->con.peer_addr.in_addr)); | 1165 | } else { |
1111 | 1166 | dout("%s already hunting\n", __func__); | |
1112 | __close_session(monc); | 1167 | } |
1113 | if (!monc->hunting) { | ||
1114 | /* start hunting */ | ||
1115 | monc->hunting = true; | ||
1116 | __open_session(monc); | ||
1117 | } else { | ||
1118 | /* already hunting, let's wait a bit */ | ||
1119 | __schedule_delayed(monc); | ||
1120 | } | 1168 | } |
1121 | out: | ||
1122 | mutex_unlock(&monc->mutex); | 1169 | mutex_unlock(&monc->mutex); |
1123 | } | 1170 | } |
1124 | 1171 | ||