.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | |
---|
2 | 3 | #include <linux/ceph/ceph_debug.h> |
---|
3 | 4 | #include <linux/backing-dev.h> |
---|
.. | .. |
---|
10 | 11 | #include <linux/module.h> |
---|
11 | 12 | #include <linux/mount.h> |
---|
12 | 13 | #include <linux/nsproxy.h> |
---|
13 | | -#include <linux/parser.h> |
---|
| 14 | +#include <linux/fs_parser.h> |
---|
14 | 15 | #include <linux/sched.h> |
---|
| 16 | +#include <linux/sched/mm.h> |
---|
15 | 17 | #include <linux/seq_file.h> |
---|
16 | 18 | #include <linux/slab.h> |
---|
17 | 19 | #include <linux/statfs.h> |
---|
.. | .. |
---|
174 | 176 | } |
---|
175 | 177 | } |
---|
176 | 178 | |
---|
| 179 | + ret = ceph_compare_crush_locs(&opt1->crush_locs, &opt2->crush_locs); |
---|
| 180 | + if (ret) |
---|
| 181 | + return ret; |
---|
| 182 | + |
---|
177 | 183 | /* any matching mon ip implies a match */ |
---|
178 | 184 | for (i = 0; i < opt1->num_mon; i++) { |
---|
179 | 185 | if (ceph_monmap_contains(client->monc.monmap, |
---|
.. | .. |
---|
184 | 190 | } |
---|
185 | 191 | EXPORT_SYMBOL(ceph_compare_options); |
---|
186 | 192 | |
---|
| 193 | +/* |
---|
| 194 | + * kvmalloc() doesn't fall back to the vmalloc allocator unless flags are |
---|
| 195 | + * compatible with (a superset of) GFP_KERNEL. This is because while the |
---|
| 196 | + * actual pages are allocated with the specified flags, the page table pages |
---|
| 197 | + * are always allocated with GFP_KERNEL. |
---|
| 198 | + * |
---|
| 199 | + * ceph_kvmalloc() may be called with GFP_KERNEL, GFP_NOFS or GFP_NOIO. |
---|
| 200 | + */ |
---|
187 | 201 | void *ceph_kvmalloc(size_t size, gfp_t flags) |
---|
188 | 202 | { |
---|
189 | | - if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { |
---|
190 | | - void *ptr = kmalloc(size, flags | __GFP_NOWARN); |
---|
191 | | - if (ptr) |
---|
192 | | - return ptr; |
---|
| 203 | + void *p; |
---|
| 204 | + |
---|
| 205 | + if ((flags & (__GFP_IO | __GFP_FS)) == (__GFP_IO | __GFP_FS)) { |
---|
| 206 | + p = kvmalloc(size, flags); |
---|
| 207 | + } else if ((flags & (__GFP_IO | __GFP_FS)) == __GFP_IO) { |
---|
| 208 | + unsigned int nofs_flag = memalloc_nofs_save(); |
---|
| 209 | + p = kvmalloc(size, GFP_KERNEL); |
---|
| 210 | + memalloc_nofs_restore(nofs_flag); |
---|
| 211 | + } else { |
---|
| 212 | + unsigned int noio_flag = memalloc_noio_save(); |
---|
| 213 | + p = kvmalloc(size, GFP_KERNEL); |
---|
| 214 | + memalloc_noio_restore(noio_flag); |
---|
193 | 215 | } |
---|
194 | 216 | |
---|
195 | | - return __vmalloc(size, flags, PAGE_KERNEL); |
---|
| 217 | + return p; |
---|
196 | 218 | } |
---|
197 | | - |
---|
198 | 219 | |
---|
199 | 220 | static int parse_fsid(const char *str, struct ceph_fsid *fsid) |
---|
200 | 221 | { |
---|
.. | .. |
---|
236 | 257 | Opt_mount_timeout, |
---|
237 | 258 | Opt_osd_idle_ttl, |
---|
238 | 259 | Opt_osd_request_timeout, |
---|
239 | | - Opt_last_int, |
---|
240 | 260 | /* int args above */ |
---|
241 | 261 | Opt_fsid, |
---|
242 | 262 | Opt_name, |
---|
243 | 263 | Opt_secret, |
---|
244 | 264 | Opt_key, |
---|
245 | 265 | Opt_ip, |
---|
246 | | - Opt_last_string, |
---|
| 266 | + Opt_crush_location, |
---|
| 267 | + Opt_read_from_replica, |
---|
247 | 268 | /* string args above */ |
---|
248 | 269 | Opt_share, |
---|
249 | | - Opt_noshare, |
---|
250 | 270 | Opt_crc, |
---|
251 | | - Opt_nocrc, |
---|
252 | 271 | Opt_cephx_require_signatures, |
---|
253 | | - Opt_nocephx_require_signatures, |
---|
254 | 272 | Opt_cephx_sign_messages, |
---|
255 | | - Opt_nocephx_sign_messages, |
---|
256 | 273 | Opt_tcp_nodelay, |
---|
257 | | - Opt_notcp_nodelay, |
---|
| 274 | + Opt_abort_on_full, |
---|
258 | 275 | }; |
---|
259 | 276 | |
---|
260 | | -static match_table_t opt_tokens = { |
---|
261 | | - {Opt_osdtimeout, "osdtimeout=%d"}, |
---|
262 | | - {Opt_osdkeepalivetimeout, "osdkeepalive=%d"}, |
---|
263 | | - {Opt_mount_timeout, "mount_timeout=%d"}, |
---|
264 | | - {Opt_osd_idle_ttl, "osd_idle_ttl=%d"}, |
---|
265 | | - {Opt_osd_request_timeout, "osd_request_timeout=%d"}, |
---|
266 | | - /* int args above */ |
---|
267 | | - {Opt_fsid, "fsid=%s"}, |
---|
268 | | - {Opt_name, "name=%s"}, |
---|
269 | | - {Opt_secret, "secret=%s"}, |
---|
270 | | - {Opt_key, "key=%s"}, |
---|
271 | | - {Opt_ip, "ip=%s"}, |
---|
272 | | - /* string args above */ |
---|
273 | | - {Opt_share, "share"}, |
---|
274 | | - {Opt_noshare, "noshare"}, |
---|
275 | | - {Opt_crc, "crc"}, |
---|
276 | | - {Opt_nocrc, "nocrc"}, |
---|
277 | | - {Opt_cephx_require_signatures, "cephx_require_signatures"}, |
---|
278 | | - {Opt_nocephx_require_signatures, "nocephx_require_signatures"}, |
---|
279 | | - {Opt_cephx_sign_messages, "cephx_sign_messages"}, |
---|
280 | | - {Opt_nocephx_sign_messages, "nocephx_sign_messages"}, |
---|
281 | | - {Opt_tcp_nodelay, "tcp_nodelay"}, |
---|
282 | | - {Opt_notcp_nodelay, "notcp_nodelay"}, |
---|
283 | | - {-1, NULL} |
---|
| 277 | +enum { |
---|
| 278 | + Opt_read_from_replica_no, |
---|
| 279 | + Opt_read_from_replica_balance, |
---|
| 280 | + Opt_read_from_replica_localize, |
---|
284 | 281 | }; |
---|
| 282 | + |
---|
| 283 | +static const struct constant_table ceph_param_read_from_replica[] = { |
---|
| 284 | + {"no", Opt_read_from_replica_no}, |
---|
| 285 | + {"balance", Opt_read_from_replica_balance}, |
---|
| 286 | + {"localize", Opt_read_from_replica_localize}, |
---|
| 287 | + {} |
---|
| 288 | +}; |
---|
| 289 | + |
---|
| 290 | +static const struct fs_parameter_spec ceph_parameters[] = { |
---|
| 291 | + fsparam_flag ("abort_on_full", Opt_abort_on_full), |
---|
| 292 | + fsparam_flag_no ("cephx_require_signatures", Opt_cephx_require_signatures), |
---|
| 293 | + fsparam_flag_no ("cephx_sign_messages", Opt_cephx_sign_messages), |
---|
| 294 | + fsparam_flag_no ("crc", Opt_crc), |
---|
| 295 | + fsparam_string ("crush_location", Opt_crush_location), |
---|
| 296 | + fsparam_string ("fsid", Opt_fsid), |
---|
| 297 | + fsparam_string ("ip", Opt_ip), |
---|
| 298 | + fsparam_string ("key", Opt_key), |
---|
| 299 | + fsparam_u32 ("mount_timeout", Opt_mount_timeout), |
---|
| 300 | + fsparam_string ("name", Opt_name), |
---|
| 301 | + fsparam_u32 ("osd_idle_ttl", Opt_osd_idle_ttl), |
---|
| 302 | + fsparam_u32 ("osd_request_timeout", Opt_osd_request_timeout), |
---|
| 303 | + fsparam_u32 ("osdkeepalive", Opt_osdkeepalivetimeout), |
---|
| 304 | + __fsparam (fs_param_is_s32, "osdtimeout", Opt_osdtimeout, |
---|
| 305 | + fs_param_deprecated, NULL), |
---|
| 306 | + fsparam_enum ("read_from_replica", Opt_read_from_replica, |
---|
| 307 | + ceph_param_read_from_replica), |
---|
| 308 | + fsparam_string ("secret", Opt_secret), |
---|
| 309 | + fsparam_flag_no ("share", Opt_share), |
---|
| 310 | + fsparam_flag_no ("tcp_nodelay", Opt_tcp_nodelay), |
---|
| 311 | + {} |
---|
| 312 | +}; |
---|
| 313 | + |
---|
| 314 | +struct ceph_options *ceph_alloc_options(void) |
---|
| 315 | +{ |
---|
| 316 | + struct ceph_options *opt; |
---|
| 317 | + |
---|
| 318 | + opt = kzalloc(sizeof(*opt), GFP_KERNEL); |
---|
| 319 | + if (!opt) |
---|
| 320 | + return NULL; |
---|
| 321 | + |
---|
| 322 | + opt->crush_locs = RB_ROOT; |
---|
| 323 | + opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr), |
---|
| 324 | + GFP_KERNEL); |
---|
| 325 | + if (!opt->mon_addr) { |
---|
| 326 | + kfree(opt); |
---|
| 327 | + return NULL; |
---|
| 328 | + } |
---|
| 329 | + |
---|
| 330 | + opt->flags = CEPH_OPT_DEFAULT; |
---|
| 331 | + opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT; |
---|
| 332 | + opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; |
---|
| 333 | + opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT; |
---|
| 334 | + opt->osd_request_timeout = CEPH_OSD_REQUEST_TIMEOUT_DEFAULT; |
---|
| 335 | + opt->read_from_replica = CEPH_READ_FROM_REPLICA_DEFAULT; |
---|
| 336 | + return opt; |
---|
| 337 | +} |
---|
| 338 | +EXPORT_SYMBOL(ceph_alloc_options); |
---|
285 | 339 | |
---|
286 | 340 | void ceph_destroy_options(struct ceph_options *opt) |
---|
287 | 341 | { |
---|
288 | 342 | dout("destroy_options %p\n", opt); |
---|
| 343 | + if (!opt) |
---|
| 344 | + return; |
---|
| 345 | + |
---|
| 346 | + ceph_clear_crush_locs(&opt->crush_locs); |
---|
289 | 347 | kfree(opt->name); |
---|
290 | 348 | if (opt->key) { |
---|
291 | 349 | ceph_crypto_key_destroy(opt->key); |
---|
.. | .. |
---|
297 | 355 | EXPORT_SYMBOL(ceph_destroy_options); |
---|
298 | 356 | |
---|
299 | 357 | /* get secret from key store */ |
---|
300 | | -static int get_secret(struct ceph_crypto_key *dst, const char *name) { |
---|
| 358 | +static int get_secret(struct ceph_crypto_key *dst, const char *name, |
---|
| 359 | + struct p_log *log) |
---|
| 360 | +{ |
---|
301 | 361 | struct key *ukey; |
---|
302 | 362 | int key_err; |
---|
303 | 363 | int err = 0; |
---|
.. | .. |
---|
310 | 370 | key_err = PTR_ERR(ukey); |
---|
311 | 371 | switch (key_err) { |
---|
312 | 372 | case -ENOKEY: |
---|
313 | | - pr_warn("ceph: Mount failed due to key not found: %s\n", |
---|
314 | | - name); |
---|
| 373 | + error_plog(log, "Failed due to key not found: %s", |
---|
| 374 | + name); |
---|
315 | 375 | break; |
---|
316 | 376 | case -EKEYEXPIRED: |
---|
317 | | - pr_warn("ceph: Mount failed due to expired key: %s\n", |
---|
318 | | - name); |
---|
| 377 | + error_plog(log, "Failed due to expired key: %s", |
---|
| 378 | + name); |
---|
319 | 379 | break; |
---|
320 | 380 | case -EKEYREVOKED: |
---|
321 | | - pr_warn("ceph: Mount failed due to revoked key: %s\n", |
---|
322 | | - name); |
---|
| 381 | + error_plog(log, "Failed due to revoked key: %s", |
---|
| 382 | + name); |
---|
323 | 383 | break; |
---|
324 | 384 | default: |
---|
325 | | - pr_warn("ceph: Mount failed due to unknown key error %d: %s\n", |
---|
326 | | - key_err, name); |
---|
| 385 | + error_plog(log, "Failed due to key error %d: %s", |
---|
| 386 | + key_err, name); |
---|
327 | 387 | } |
---|
328 | 388 | err = -EPERM; |
---|
329 | 389 | goto out; |
---|
.. | .. |
---|
341 | 401 | return err; |
---|
342 | 402 | } |
---|
343 | 403 | |
---|
344 | | -struct ceph_options * |
---|
345 | | -ceph_parse_options(char *options, const char *dev_name, |
---|
346 | | - const char *dev_name_end, |
---|
347 | | - int (*parse_extra_token)(char *c, void *private), |
---|
348 | | - void *private) |
---|
| 404 | +int ceph_parse_mon_ips(const char *buf, size_t len, struct ceph_options *opt, |
---|
| 405 | + struct fc_log *l) |
---|
349 | 406 | { |
---|
350 | | - struct ceph_options *opt; |
---|
351 | | - const char *c; |
---|
352 | | - int err = -ENOMEM; |
---|
353 | | - substring_t argstr[MAX_OPT_ARGS]; |
---|
| 407 | + struct p_log log = {.prefix = "libceph", .log = l}; |
---|
| 408 | + int ret; |
---|
354 | 409 | |
---|
355 | | - opt = kzalloc(sizeof(*opt), GFP_KERNEL); |
---|
356 | | - if (!opt) |
---|
357 | | - return ERR_PTR(-ENOMEM); |
---|
358 | | - opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr), |
---|
359 | | - GFP_KERNEL); |
---|
360 | | - if (!opt->mon_addr) |
---|
361 | | - goto out; |
---|
362 | | - |
---|
363 | | - dout("parse_options %p options '%s' dev_name '%s'\n", opt, options, |
---|
364 | | - dev_name); |
---|
365 | | - |
---|
366 | | - /* start with defaults */ |
---|
367 | | - opt->flags = CEPH_OPT_DEFAULT; |
---|
368 | | - opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT; |
---|
369 | | - opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; |
---|
370 | | - opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT; |
---|
371 | | - opt->osd_request_timeout = CEPH_OSD_REQUEST_TIMEOUT_DEFAULT; |
---|
372 | | - |
---|
373 | | - /* get mon ip(s) */ |
---|
374 | 410 | /* ip1[:port1][,ip2[:port2]...] */ |
---|
375 | | - err = ceph_parse_ips(dev_name, dev_name_end, opt->mon_addr, |
---|
376 | | - CEPH_MAX_MON, &opt->num_mon); |
---|
377 | | - if (err < 0) |
---|
378 | | - goto out; |
---|
379 | | - |
---|
380 | | - /* parse mount options */ |
---|
381 | | - while ((c = strsep(&options, ",")) != NULL) { |
---|
382 | | - int token, intval; |
---|
383 | | - if (!*c) |
---|
384 | | - continue; |
---|
385 | | - err = -EINVAL; |
---|
386 | | - token = match_token((char *)c, opt_tokens, argstr); |
---|
387 | | - if (token < 0 && parse_extra_token) { |
---|
388 | | - /* extra? */ |
---|
389 | | - err = parse_extra_token((char *)c, private); |
---|
390 | | - if (err < 0) { |
---|
391 | | - pr_err("bad option at '%s'\n", c); |
---|
392 | | - goto out; |
---|
393 | | - } |
---|
394 | | - continue; |
---|
395 | | - } |
---|
396 | | - if (token < Opt_last_int) { |
---|
397 | | - err = match_int(&argstr[0], &intval); |
---|
398 | | - if (err < 0) { |
---|
399 | | - pr_err("bad option arg (not int) at '%s'\n", c); |
---|
400 | | - goto out; |
---|
401 | | - } |
---|
402 | | - dout("got int token %d val %d\n", token, intval); |
---|
403 | | - } else if (token > Opt_last_int && token < Opt_last_string) { |
---|
404 | | - dout("got string token %d val %s\n", token, |
---|
405 | | - argstr[0].from); |
---|
406 | | - } else { |
---|
407 | | - dout("got token %d\n", token); |
---|
408 | | - } |
---|
409 | | - switch (token) { |
---|
410 | | - case Opt_ip: |
---|
411 | | - err = ceph_parse_ips(argstr[0].from, |
---|
412 | | - argstr[0].to, |
---|
413 | | - &opt->my_addr, |
---|
414 | | - 1, NULL); |
---|
415 | | - if (err < 0) |
---|
416 | | - goto out; |
---|
417 | | - opt->flags |= CEPH_OPT_MYIP; |
---|
418 | | - break; |
---|
419 | | - |
---|
420 | | - case Opt_fsid: |
---|
421 | | - err = parse_fsid(argstr[0].from, &opt->fsid); |
---|
422 | | - if (err == 0) |
---|
423 | | - opt->flags |= CEPH_OPT_FSID; |
---|
424 | | - break; |
---|
425 | | - case Opt_name: |
---|
426 | | - kfree(opt->name); |
---|
427 | | - opt->name = kstrndup(argstr[0].from, |
---|
428 | | - argstr[0].to-argstr[0].from, |
---|
429 | | - GFP_KERNEL); |
---|
430 | | - if (!opt->name) { |
---|
431 | | - err = -ENOMEM; |
---|
432 | | - goto out; |
---|
433 | | - } |
---|
434 | | - break; |
---|
435 | | - case Opt_secret: |
---|
436 | | - ceph_crypto_key_destroy(opt->key); |
---|
437 | | - kfree(opt->key); |
---|
438 | | - |
---|
439 | | - opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); |
---|
440 | | - if (!opt->key) { |
---|
441 | | - err = -ENOMEM; |
---|
442 | | - goto out; |
---|
443 | | - } |
---|
444 | | - err = ceph_crypto_key_unarmor(opt->key, argstr[0].from); |
---|
445 | | - if (err < 0) |
---|
446 | | - goto out; |
---|
447 | | - break; |
---|
448 | | - case Opt_key: |
---|
449 | | - ceph_crypto_key_destroy(opt->key); |
---|
450 | | - kfree(opt->key); |
---|
451 | | - |
---|
452 | | - opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); |
---|
453 | | - if (!opt->key) { |
---|
454 | | - err = -ENOMEM; |
---|
455 | | - goto out; |
---|
456 | | - } |
---|
457 | | - err = get_secret(opt->key, argstr[0].from); |
---|
458 | | - if (err < 0) |
---|
459 | | - goto out; |
---|
460 | | - break; |
---|
461 | | - |
---|
462 | | - /* misc */ |
---|
463 | | - case Opt_osdtimeout: |
---|
464 | | - pr_warn("ignoring deprecated osdtimeout option\n"); |
---|
465 | | - break; |
---|
466 | | - case Opt_osdkeepalivetimeout: |
---|
467 | | - /* 0 isn't well defined right now, reject it */ |
---|
468 | | - if (intval < 1 || intval > INT_MAX / 1000) { |
---|
469 | | - pr_err("osdkeepalive out of range\n"); |
---|
470 | | - err = -EINVAL; |
---|
471 | | - goto out; |
---|
472 | | - } |
---|
473 | | - opt->osd_keepalive_timeout = |
---|
474 | | - msecs_to_jiffies(intval * 1000); |
---|
475 | | - break; |
---|
476 | | - case Opt_osd_idle_ttl: |
---|
477 | | - /* 0 isn't well defined right now, reject it */ |
---|
478 | | - if (intval < 1 || intval > INT_MAX / 1000) { |
---|
479 | | - pr_err("osd_idle_ttl out of range\n"); |
---|
480 | | - err = -EINVAL; |
---|
481 | | - goto out; |
---|
482 | | - } |
---|
483 | | - opt->osd_idle_ttl = msecs_to_jiffies(intval * 1000); |
---|
484 | | - break; |
---|
485 | | - case Opt_mount_timeout: |
---|
486 | | - /* 0 is "wait forever" (i.e. infinite timeout) */ |
---|
487 | | - if (intval < 0 || intval > INT_MAX / 1000) { |
---|
488 | | - pr_err("mount_timeout out of range\n"); |
---|
489 | | - err = -EINVAL; |
---|
490 | | - goto out; |
---|
491 | | - } |
---|
492 | | - opt->mount_timeout = msecs_to_jiffies(intval * 1000); |
---|
493 | | - break; |
---|
494 | | - case Opt_osd_request_timeout: |
---|
495 | | - /* 0 is "wait forever" (i.e. infinite timeout) */ |
---|
496 | | - if (intval < 0 || intval > INT_MAX / 1000) { |
---|
497 | | - pr_err("osd_request_timeout out of range\n"); |
---|
498 | | - err = -EINVAL; |
---|
499 | | - goto out; |
---|
500 | | - } |
---|
501 | | - opt->osd_request_timeout = msecs_to_jiffies(intval * 1000); |
---|
502 | | - break; |
---|
503 | | - |
---|
504 | | - case Opt_share: |
---|
505 | | - opt->flags &= ~CEPH_OPT_NOSHARE; |
---|
506 | | - break; |
---|
507 | | - case Opt_noshare: |
---|
508 | | - opt->flags |= CEPH_OPT_NOSHARE; |
---|
509 | | - break; |
---|
510 | | - |
---|
511 | | - case Opt_crc: |
---|
512 | | - opt->flags &= ~CEPH_OPT_NOCRC; |
---|
513 | | - break; |
---|
514 | | - case Opt_nocrc: |
---|
515 | | - opt->flags |= CEPH_OPT_NOCRC; |
---|
516 | | - break; |
---|
517 | | - |
---|
518 | | - case Opt_cephx_require_signatures: |
---|
519 | | - opt->flags &= ~CEPH_OPT_NOMSGAUTH; |
---|
520 | | - break; |
---|
521 | | - case Opt_nocephx_require_signatures: |
---|
522 | | - opt->flags |= CEPH_OPT_NOMSGAUTH; |
---|
523 | | - break; |
---|
524 | | - case Opt_cephx_sign_messages: |
---|
525 | | - opt->flags &= ~CEPH_OPT_NOMSGSIGN; |
---|
526 | | - break; |
---|
527 | | - case Opt_nocephx_sign_messages: |
---|
528 | | - opt->flags |= CEPH_OPT_NOMSGSIGN; |
---|
529 | | - break; |
---|
530 | | - |
---|
531 | | - case Opt_tcp_nodelay: |
---|
532 | | - opt->flags |= CEPH_OPT_TCP_NODELAY; |
---|
533 | | - break; |
---|
534 | | - case Opt_notcp_nodelay: |
---|
535 | | - opt->flags &= ~CEPH_OPT_TCP_NODELAY; |
---|
536 | | - break; |
---|
537 | | - |
---|
538 | | - default: |
---|
539 | | - BUG_ON(token); |
---|
540 | | - } |
---|
| 411 | + ret = ceph_parse_ips(buf, buf + len, opt->mon_addr, CEPH_MAX_MON, |
---|
| 412 | + &opt->num_mon); |
---|
| 413 | + if (ret) { |
---|
| 414 | + error_plog(&log, "Failed to parse monitor IPs: %d", ret); |
---|
| 415 | + return ret; |
---|
541 | 416 | } |
---|
542 | 417 | |
---|
543 | | - /* success */ |
---|
544 | | - return opt; |
---|
545 | | - |
---|
546 | | -out: |
---|
547 | | - ceph_destroy_options(opt); |
---|
548 | | - return ERR_PTR(err); |
---|
| 418 | + return 0; |
---|
549 | 419 | } |
---|
550 | | -EXPORT_SYMBOL(ceph_parse_options); |
---|
| 420 | +EXPORT_SYMBOL(ceph_parse_mon_ips); |
---|
551 | 421 | |
---|
552 | | -int ceph_print_client_options(struct seq_file *m, struct ceph_client *client) |
---|
| 422 | +int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt, |
---|
| 423 | + struct fc_log *l) |
---|
| 424 | +{ |
---|
| 425 | + struct fs_parse_result result; |
---|
| 426 | + int token, err; |
---|
| 427 | + struct p_log log = {.prefix = "libceph", .log = l}; |
---|
| 428 | + |
---|
| 429 | + token = __fs_parse(&log, ceph_parameters, param, &result); |
---|
| 430 | + dout("%s fs_parse '%s' token %d\n", __func__, param->key, token); |
---|
| 431 | + if (token < 0) |
---|
| 432 | + return token; |
---|
| 433 | + |
---|
| 434 | + switch (token) { |
---|
| 435 | + case Opt_ip: |
---|
| 436 | + err = ceph_parse_ips(param->string, |
---|
| 437 | + param->string + param->size, |
---|
| 438 | + &opt->my_addr, |
---|
| 439 | + 1, NULL); |
---|
| 440 | + if (err) { |
---|
| 441 | + error_plog(&log, "Failed to parse ip: %d", err); |
---|
| 442 | + return err; |
---|
| 443 | + } |
---|
| 444 | + opt->flags |= CEPH_OPT_MYIP; |
---|
| 445 | + break; |
---|
| 446 | + |
---|
| 447 | + case Opt_fsid: |
---|
| 448 | + err = parse_fsid(param->string, &opt->fsid); |
---|
| 449 | + if (err) { |
---|
| 450 | + error_plog(&log, "Failed to parse fsid: %d", err); |
---|
| 451 | + return err; |
---|
| 452 | + } |
---|
| 453 | + opt->flags |= CEPH_OPT_FSID; |
---|
| 454 | + break; |
---|
| 455 | + case Opt_name: |
---|
| 456 | + kfree(opt->name); |
---|
| 457 | + opt->name = param->string; |
---|
| 458 | + param->string = NULL; |
---|
| 459 | + break; |
---|
| 460 | + case Opt_secret: |
---|
| 461 | + ceph_crypto_key_destroy(opt->key); |
---|
| 462 | + kfree(opt->key); |
---|
| 463 | + |
---|
| 464 | + opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); |
---|
| 465 | + if (!opt->key) |
---|
| 466 | + return -ENOMEM; |
---|
| 467 | + err = ceph_crypto_key_unarmor(opt->key, param->string); |
---|
| 468 | + if (err) { |
---|
| 469 | + error_plog(&log, "Failed to parse secret: %d", err); |
---|
| 470 | + return err; |
---|
| 471 | + } |
---|
| 472 | + break; |
---|
| 473 | + case Opt_key: |
---|
| 474 | + ceph_crypto_key_destroy(opt->key); |
---|
| 475 | + kfree(opt->key); |
---|
| 476 | + |
---|
| 477 | + opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); |
---|
| 478 | + if (!opt->key) |
---|
| 479 | + return -ENOMEM; |
---|
| 480 | + return get_secret(opt->key, param->string, &log); |
---|
| 481 | + case Opt_crush_location: |
---|
| 482 | + ceph_clear_crush_locs(&opt->crush_locs); |
---|
| 483 | + err = ceph_parse_crush_location(param->string, |
---|
| 484 | + &opt->crush_locs); |
---|
| 485 | + if (err) { |
---|
| 486 | + error_plog(&log, "Failed to parse CRUSH location: %d", |
---|
| 487 | + err); |
---|
| 488 | + return err; |
---|
| 489 | + } |
---|
| 490 | + break; |
---|
| 491 | + case Opt_read_from_replica: |
---|
| 492 | + switch (result.uint_32) { |
---|
| 493 | + case Opt_read_from_replica_no: |
---|
| 494 | + opt->read_from_replica = 0; |
---|
| 495 | + break; |
---|
| 496 | + case Opt_read_from_replica_balance: |
---|
| 497 | + opt->read_from_replica = CEPH_OSD_FLAG_BALANCE_READS; |
---|
| 498 | + break; |
---|
| 499 | + case Opt_read_from_replica_localize: |
---|
| 500 | + opt->read_from_replica = CEPH_OSD_FLAG_LOCALIZE_READS; |
---|
| 501 | + break; |
---|
| 502 | + default: |
---|
| 503 | + BUG(); |
---|
| 504 | + } |
---|
| 505 | + break; |
---|
| 506 | + |
---|
| 507 | + case Opt_osdtimeout: |
---|
| 508 | + warn_plog(&log, "Ignoring osdtimeout"); |
---|
| 509 | + break; |
---|
| 510 | + case Opt_osdkeepalivetimeout: |
---|
| 511 | + /* 0 isn't well defined right now, reject it */ |
---|
| 512 | + if (result.uint_32 < 1 || result.uint_32 > INT_MAX / 1000) |
---|
| 513 | + goto out_of_range; |
---|
| 514 | + opt->osd_keepalive_timeout = |
---|
| 515 | + msecs_to_jiffies(result.uint_32 * 1000); |
---|
| 516 | + break; |
---|
| 517 | + case Opt_osd_idle_ttl: |
---|
| 518 | + /* 0 isn't well defined right now, reject it */ |
---|
| 519 | + if (result.uint_32 < 1 || result.uint_32 > INT_MAX / 1000) |
---|
| 520 | + goto out_of_range; |
---|
| 521 | + opt->osd_idle_ttl = msecs_to_jiffies(result.uint_32 * 1000); |
---|
| 522 | + break; |
---|
| 523 | + case Opt_mount_timeout: |
---|
| 524 | + /* 0 is "wait forever" (i.e. infinite timeout) */ |
---|
| 525 | + if (result.uint_32 > INT_MAX / 1000) |
---|
| 526 | + goto out_of_range; |
---|
| 527 | + opt->mount_timeout = msecs_to_jiffies(result.uint_32 * 1000); |
---|
| 528 | + break; |
---|
| 529 | + case Opt_osd_request_timeout: |
---|
| 530 | + /* 0 is "wait forever" (i.e. infinite timeout) */ |
---|
| 531 | + if (result.uint_32 > INT_MAX / 1000) |
---|
| 532 | + goto out_of_range; |
---|
| 533 | + opt->osd_request_timeout = |
---|
| 534 | + msecs_to_jiffies(result.uint_32 * 1000); |
---|
| 535 | + break; |
---|
| 536 | + |
---|
| 537 | + case Opt_share: |
---|
| 538 | + if (!result.negated) |
---|
| 539 | + opt->flags &= ~CEPH_OPT_NOSHARE; |
---|
| 540 | + else |
---|
| 541 | + opt->flags |= CEPH_OPT_NOSHARE; |
---|
| 542 | + break; |
---|
| 543 | + case Opt_crc: |
---|
| 544 | + if (!result.negated) |
---|
| 545 | + opt->flags &= ~CEPH_OPT_NOCRC; |
---|
| 546 | + else |
---|
| 547 | + opt->flags |= CEPH_OPT_NOCRC; |
---|
| 548 | + break; |
---|
| 549 | + case Opt_cephx_require_signatures: |
---|
| 550 | + if (!result.negated) |
---|
| 551 | + opt->flags &= ~CEPH_OPT_NOMSGAUTH; |
---|
| 552 | + else |
---|
| 553 | + opt->flags |= CEPH_OPT_NOMSGAUTH; |
---|
| 554 | + break; |
---|
| 555 | + case Opt_cephx_sign_messages: |
---|
| 556 | + if (!result.negated) |
---|
| 557 | + opt->flags &= ~CEPH_OPT_NOMSGSIGN; |
---|
| 558 | + else |
---|
| 559 | + opt->flags |= CEPH_OPT_NOMSGSIGN; |
---|
| 560 | + break; |
---|
| 561 | + case Opt_tcp_nodelay: |
---|
| 562 | + if (!result.negated) |
---|
| 563 | + opt->flags |= CEPH_OPT_TCP_NODELAY; |
---|
| 564 | + else |
---|
| 565 | + opt->flags &= ~CEPH_OPT_TCP_NODELAY; |
---|
| 566 | + break; |
---|
| 567 | + |
---|
| 568 | + case Opt_abort_on_full: |
---|
| 569 | + opt->flags |= CEPH_OPT_ABORT_ON_FULL; |
---|
| 570 | + break; |
---|
| 571 | + |
---|
| 572 | + default: |
---|
| 573 | + BUG(); |
---|
| 574 | + } |
---|
| 575 | + |
---|
| 576 | + return 0; |
---|
| 577 | + |
---|
| 578 | +out_of_range: |
---|
| 579 | + return inval_plog(&log, "%s out of range", param->key); |
---|
| 580 | +} |
---|
| 581 | +EXPORT_SYMBOL(ceph_parse_param); |
---|
| 582 | + |
---|
| 583 | +int ceph_print_client_options(struct seq_file *m, struct ceph_client *client, |
---|
| 584 | + bool show_all) |
---|
553 | 585 | { |
---|
554 | 586 | struct ceph_options *opt = client->options; |
---|
555 | 587 | size_t pos = m->count; |
---|
| 588 | + struct rb_node *n; |
---|
556 | 589 | |
---|
557 | 590 | if (opt->name) { |
---|
558 | 591 | seq_puts(m, "name="); |
---|
.. | .. |
---|
561 | 594 | } |
---|
562 | 595 | if (opt->key) |
---|
563 | 596 | seq_puts(m, "secret=<hidden>,"); |
---|
| 597 | + |
---|
| 598 | + if (!RB_EMPTY_ROOT(&opt->crush_locs)) { |
---|
| 599 | + seq_puts(m, "crush_location="); |
---|
| 600 | + for (n = rb_first(&opt->crush_locs); ; ) { |
---|
| 601 | + struct crush_loc_node *loc = |
---|
| 602 | + rb_entry(n, struct crush_loc_node, cl_node); |
---|
| 603 | + |
---|
| 604 | + seq_printf(m, "%s:%s", loc->cl_loc.cl_type_name, |
---|
| 605 | + loc->cl_loc.cl_name); |
---|
| 606 | + n = rb_next(n); |
---|
| 607 | + if (!n) |
---|
| 608 | + break; |
---|
| 609 | + |
---|
| 610 | + seq_putc(m, '|'); |
---|
| 611 | + } |
---|
| 612 | + seq_putc(m, ','); |
---|
| 613 | + } |
---|
| 614 | + if (opt->read_from_replica == CEPH_OSD_FLAG_BALANCE_READS) { |
---|
| 615 | + seq_puts(m, "read_from_replica=balance,"); |
---|
| 616 | + } else if (opt->read_from_replica == CEPH_OSD_FLAG_LOCALIZE_READS) { |
---|
| 617 | + seq_puts(m, "read_from_replica=localize,"); |
---|
| 618 | + } |
---|
564 | 619 | |
---|
565 | 620 | if (opt->flags & CEPH_OPT_FSID) |
---|
566 | 621 | seq_printf(m, "fsid=%pU,", &opt->fsid); |
---|
.. | .. |
---|
574 | 629 | seq_puts(m, "nocephx_sign_messages,"); |
---|
575 | 630 | if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0) |
---|
576 | 631 | seq_puts(m, "notcp_nodelay,"); |
---|
| 632 | + if (show_all && (opt->flags & CEPH_OPT_ABORT_ON_FULL)) |
---|
| 633 | + seq_puts(m, "abort_on_full,"); |
---|
577 | 634 | |
---|
578 | 635 | if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT) |
---|
579 | 636 | seq_printf(m, "mount_timeout=%d,", |
---|
.. | .. |
---|
684 | 741 | } |
---|
685 | 742 | EXPORT_SYMBOL(ceph_destroy_client); |
---|
686 | 743 | |
---|
| 744 | +void ceph_reset_client_addr(struct ceph_client *client) |
---|
| 745 | +{ |
---|
| 746 | + ceph_messenger_reset_nonce(&client->msgr); |
---|
| 747 | + ceph_monc_reopen_session(&client->monc); |
---|
| 748 | + ceph_osdc_reopen_osds(&client->osdc); |
---|
| 749 | +} |
---|
| 750 | +EXPORT_SYMBOL(ceph_reset_client_addr); |
---|
| 751 | + |
---|
687 | 752 | /* |
---|
688 | 753 | * true if we have the mon map (and have thus joined the cluster) |
---|
689 | 754 | */ |
---|
.. | .. |
---|
766 | 831 | { |
---|
767 | 832 | int ret = 0; |
---|
768 | 833 | |
---|
769 | | - ret = ceph_debugfs_init(); |
---|
770 | | - if (ret < 0) |
---|
771 | | - goto out; |
---|
| 834 | + ceph_debugfs_init(); |
---|
772 | 835 | |
---|
773 | 836 | ret = ceph_crypto_init(); |
---|
774 | 837 | if (ret < 0) |
---|
.. | .. |
---|
793 | 856 | ceph_crypto_shutdown(); |
---|
794 | 857 | out_debugfs: |
---|
795 | 858 | ceph_debugfs_cleanup(); |
---|
796 | | -out: |
---|
797 | 859 | return ret; |
---|
798 | 860 | } |
---|
799 | 861 | |
---|