| .. | .. |
|---|
| 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 | |
|---|