diff options
Diffstat (limited to 'fs/exofs/super.c')
-rw-r--r-- | fs/exofs/super.c | 130 |
1 files changed, 99 insertions, 31 deletions
diff --git a/fs/exofs/super.c b/fs/exofs/super.c index a1d1e77b12eb..03149b9a5178 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/vfs.h> | 37 | #include <linux/vfs.h> |
38 | #include <linux/random.h> | 38 | #include <linux/random.h> |
39 | #include <linux/exportfs.h> | 39 | #include <linux/exportfs.h> |
40 | #include <linux/slab.h> | ||
40 | 41 | ||
41 | #include "exofs.h" | 42 | #include "exofs.h" |
42 | 43 | ||
@@ -210,7 +211,7 @@ int exofs_sync_fs(struct super_block *sb, int wait) | |||
210 | sbi = sb->s_fs_info; | 211 | sbi = sb->s_fs_info; |
211 | fscb = &sbi->s_fscb; | 212 | fscb = &sbi->s_fscb; |
212 | 213 | ||
213 | ret = exofs_get_io_state(sbi, &ios); | 214 | ret = exofs_get_io_state(&sbi->layout, &ios); |
214 | if (ret) | 215 | if (ret) |
215 | goto out; | 216 | goto out; |
216 | 217 | ||
@@ -264,12 +265,12 @@ static void _exofs_print_device(const char *msg, const char *dev_path, | |||
264 | 265 | ||
265 | void exofs_free_sbi(struct exofs_sb_info *sbi) | 266 | void exofs_free_sbi(struct exofs_sb_info *sbi) |
266 | { | 267 | { |
267 | while (sbi->s_numdevs) { | 268 | while (sbi->layout.s_numdevs) { |
268 | int i = --sbi->s_numdevs; | 269 | int i = --sbi->layout.s_numdevs; |
269 | struct osd_dev *od = sbi->s_ods[i]; | 270 | struct osd_dev *od = sbi->layout.s_ods[i]; |
270 | 271 | ||
271 | if (od) { | 272 | if (od) { |
272 | sbi->s_ods[i] = NULL; | 273 | sbi->layout.s_ods[i] = NULL; |
273 | osduld_put_device(od); | 274 | osduld_put_device(od); |
274 | } | 275 | } |
275 | } | 276 | } |
@@ -298,8 +299,10 @@ static void exofs_put_super(struct super_block *sb) | |||
298 | msecs_to_jiffies(100)); | 299 | msecs_to_jiffies(100)); |
299 | } | 300 | } |
300 | 301 | ||
301 | _exofs_print_device("Unmounting", NULL, sbi->s_ods[0], sbi->s_pid); | 302 | _exofs_print_device("Unmounting", NULL, sbi->layout.s_ods[0], |
303 | sbi->layout.s_pid); | ||
302 | 304 | ||
305 | bdi_destroy(&sbi->bdi); | ||
303 | exofs_free_sbi(sbi); | 306 | exofs_free_sbi(sbi); |
304 | sb->s_fs_info = NULL; | 307 | sb->s_fs_info = NULL; |
305 | } | 308 | } |
@@ -307,6 +310,8 @@ static void exofs_put_super(struct super_block *sb) | |||
307 | static int _read_and_match_data_map(struct exofs_sb_info *sbi, unsigned numdevs, | 310 | static int _read_and_match_data_map(struct exofs_sb_info *sbi, unsigned numdevs, |
308 | struct exofs_device_table *dt) | 311 | struct exofs_device_table *dt) |
309 | { | 312 | { |
313 | u64 stripe_length; | ||
314 | |||
310 | sbi->data_map.odm_num_comps = | 315 | sbi->data_map.odm_num_comps = |
311 | le32_to_cpu(dt->dt_data_map.cb_num_comps); | 316 | le32_to_cpu(dt->dt_data_map.cb_num_comps); |
312 | sbi->data_map.odm_stripe_unit = | 317 | sbi->data_map.odm_stripe_unit = |
@@ -320,14 +325,63 @@ static int _read_and_match_data_map(struct exofs_sb_info *sbi, unsigned numdevs, | |||
320 | sbi->data_map.odm_raid_algorithm = | 325 | sbi->data_map.odm_raid_algorithm = |
321 | le32_to_cpu(dt->dt_data_map.cb_raid_algorithm); | 326 | le32_to_cpu(dt->dt_data_map.cb_raid_algorithm); |
322 | 327 | ||
323 | /* FIXME: Hard coded mirror only for now. if not so do not mount */ | 328 | /* FIXME: Only raid0 for now. if not so, do not mount */ |
324 | if ((sbi->data_map.odm_num_comps != numdevs) || | 329 | if (sbi->data_map.odm_num_comps != numdevs) { |
325 | (sbi->data_map.odm_stripe_unit != EXOFS_BLKSIZE) || | 330 | EXOFS_ERR("odm_num_comps(%u) != numdevs(%u)\n", |
326 | (sbi->data_map.odm_raid_algorithm != PNFS_OSD_RAID_0) || | 331 | sbi->data_map.odm_num_comps, numdevs); |
327 | (sbi->data_map.odm_mirror_cnt != (numdevs - 1))) | ||
328 | return -EINVAL; | 332 | return -EINVAL; |
329 | else | 333 | } |
330 | return 0; | 334 | if (sbi->data_map.odm_raid_algorithm != PNFS_OSD_RAID_0) { |
335 | EXOFS_ERR("Only RAID_0 for now\n"); | ||
336 | return -EINVAL; | ||
337 | } | ||
338 | if (0 != (numdevs % (sbi->data_map.odm_mirror_cnt + 1))) { | ||
339 | EXOFS_ERR("Data Map wrong, numdevs=%d mirrors=%d\n", | ||
340 | numdevs, sbi->data_map.odm_mirror_cnt); | ||
341 | return -EINVAL; | ||
342 | } | ||
343 | |||
344 | if (0 != (sbi->data_map.odm_stripe_unit & ~PAGE_MASK)) { | ||
345 | EXOFS_ERR("Stripe Unit(0x%llx)" | ||
346 | " must be Multples of PAGE_SIZE(0x%lx)\n", | ||
347 | _LLU(sbi->data_map.odm_stripe_unit), PAGE_SIZE); | ||
348 | return -EINVAL; | ||
349 | } | ||
350 | |||
351 | sbi->layout.stripe_unit = sbi->data_map.odm_stripe_unit; | ||
352 | sbi->layout.mirrors_p1 = sbi->data_map.odm_mirror_cnt + 1; | ||
353 | |||
354 | if (sbi->data_map.odm_group_width) { | ||
355 | sbi->layout.group_width = sbi->data_map.odm_group_width; | ||
356 | sbi->layout.group_depth = sbi->data_map.odm_group_depth; | ||
357 | if (!sbi->layout.group_depth) { | ||
358 | EXOFS_ERR("group_depth == 0 && group_width != 0\n"); | ||
359 | return -EINVAL; | ||
360 | } | ||
361 | sbi->layout.group_count = sbi->data_map.odm_num_comps / | ||
362 | sbi->layout.mirrors_p1 / | ||
363 | sbi->data_map.odm_group_width; | ||
364 | } else { | ||
365 | if (sbi->data_map.odm_group_depth) { | ||
366 | printk(KERN_NOTICE "Warning: group_depth ignored " | ||
367 | "group_width == 0 && group_depth == %d\n", | ||
368 | sbi->data_map.odm_group_depth); | ||
369 | sbi->data_map.odm_group_depth = 0; | ||
370 | } | ||
371 | sbi->layout.group_width = sbi->data_map.odm_num_comps / | ||
372 | sbi->layout.mirrors_p1; | ||
373 | sbi->layout.group_depth = -1; | ||
374 | sbi->layout.group_count = 1; | ||
375 | } | ||
376 | |||
377 | stripe_length = (u64)sbi->layout.group_width * sbi->layout.stripe_unit; | ||
378 | if (stripe_length >= (1ULL << 32)) { | ||
379 | EXOFS_ERR("Total Stripe length(0x%llx)" | ||
380 | " >= 32bit is not supported\n", _LLU(stripe_length)); | ||
381 | return -EINVAL; | ||
382 | } | ||
383 | |||
384 | return 0; | ||
331 | } | 385 | } |
332 | 386 | ||
333 | /* @odi is valid only as long as @fscb_dev is valid */ | 387 | /* @odi is valid only as long as @fscb_dev is valid */ |
@@ -361,7 +415,7 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi, | |||
361 | { | 415 | { |
362 | struct exofs_sb_info *sbi = *psbi; | 416 | struct exofs_sb_info *sbi = *psbi; |
363 | struct osd_dev *fscb_od; | 417 | struct osd_dev *fscb_od; |
364 | struct osd_obj_id obj = {.partition = sbi->s_pid, | 418 | struct osd_obj_id obj = {.partition = sbi->layout.s_pid, |
365 | .id = EXOFS_DEVTABLE_ID}; | 419 | .id = EXOFS_DEVTABLE_ID}; |
366 | struct exofs_device_table *dt; | 420 | struct exofs_device_table *dt; |
367 | unsigned table_bytes = table_count * sizeof(dt->dt_dev_table[0]) + | 421 | unsigned table_bytes = table_count * sizeof(dt->dt_dev_table[0]) + |
@@ -376,9 +430,9 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi, | |||
376 | return -ENOMEM; | 430 | return -ENOMEM; |
377 | } | 431 | } |
378 | 432 | ||
379 | fscb_od = sbi->s_ods[0]; | 433 | fscb_od = sbi->layout.s_ods[0]; |
380 | sbi->s_ods[0] = NULL; | 434 | sbi->layout.s_ods[0] = NULL; |
381 | sbi->s_numdevs = 0; | 435 | sbi->layout.s_numdevs = 0; |
382 | ret = exofs_read_kern(fscb_od, sbi->s_cred, &obj, 0, dt, table_bytes); | 436 | ret = exofs_read_kern(fscb_od, sbi->s_cred, &obj, 0, dt, table_bytes); |
383 | if (unlikely(ret)) { | 437 | if (unlikely(ret)) { |
384 | EXOFS_ERR("ERROR: reading device table\n"); | 438 | EXOFS_ERR("ERROR: reading device table\n"); |
@@ -397,14 +451,15 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi, | |||
397 | goto out; | 451 | goto out; |
398 | 452 | ||
399 | if (likely(numdevs > 1)) { | 453 | if (likely(numdevs > 1)) { |
400 | unsigned size = numdevs * sizeof(sbi->s_ods[0]); | 454 | unsigned size = numdevs * sizeof(sbi->layout.s_ods[0]); |
401 | 455 | ||
402 | sbi = krealloc(sbi, sizeof(*sbi) + size, GFP_KERNEL); | 456 | sbi = krealloc(sbi, sizeof(*sbi) + size, GFP_KERNEL); |
403 | if (unlikely(!sbi)) { | 457 | if (unlikely(!sbi)) { |
404 | ret = -ENOMEM; | 458 | ret = -ENOMEM; |
405 | goto out; | 459 | goto out; |
406 | } | 460 | } |
407 | memset(&sbi->s_ods[1], 0, size - sizeof(sbi->s_ods[0])); | 461 | memset(&sbi->layout.s_ods[1], 0, |
462 | size - sizeof(sbi->layout.s_ods[0])); | ||
408 | *psbi = sbi; | 463 | *psbi = sbi; |
409 | } | 464 | } |
410 | 465 | ||
@@ -427,8 +482,8 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi, | |||
427 | * line. We always keep them in device-table order. | 482 | * line. We always keep them in device-table order. |
428 | */ | 483 | */ |
429 | if (fscb_od && osduld_device_same(fscb_od, &odi)) { | 484 | if (fscb_od && osduld_device_same(fscb_od, &odi)) { |
430 | sbi->s_ods[i] = fscb_od; | 485 | sbi->layout.s_ods[i] = fscb_od; |
431 | ++sbi->s_numdevs; | 486 | ++sbi->layout.s_numdevs; |
432 | fscb_od = NULL; | 487 | fscb_od = NULL; |
433 | continue; | 488 | continue; |
434 | } | 489 | } |
@@ -441,8 +496,8 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi, | |||
441 | goto out; | 496 | goto out; |
442 | } | 497 | } |
443 | 498 | ||
444 | sbi->s_ods[i] = od; | 499 | sbi->layout.s_ods[i] = od; |
445 | ++sbi->s_numdevs; | 500 | ++sbi->layout.s_numdevs; |
446 | 501 | ||
447 | /* Read the fscb of the other devices to make sure the FS | 502 | /* Read the fscb of the other devices to make sure the FS |
448 | * partition is there. | 503 | * partition is there. |
@@ -492,6 +547,10 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) | |||
492 | if (!sbi) | 547 | if (!sbi) |
493 | return -ENOMEM; | 548 | return -ENOMEM; |
494 | 549 | ||
550 | ret = bdi_setup_and_register(&sbi->bdi, "exofs", BDI_CAP_MAP_COPY); | ||
551 | if (ret) | ||
552 | goto free_bdi; | ||
553 | |||
495 | /* use mount options to fill superblock */ | 554 | /* use mount options to fill superblock */ |
496 | od = osduld_path_lookup(opts->dev_name); | 555 | od = osduld_path_lookup(opts->dev_name); |
497 | if (IS_ERR(od)) { | 556 | if (IS_ERR(od)) { |
@@ -499,9 +558,15 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) | |||
499 | goto free_sbi; | 558 | goto free_sbi; |
500 | } | 559 | } |
501 | 560 | ||
502 | sbi->s_ods[0] = od; | 561 | /* Default layout in case we do not have a device-table */ |
503 | sbi->s_numdevs = 1; | 562 | sbi->layout.stripe_unit = PAGE_SIZE; |
504 | sbi->s_pid = opts->pid; | 563 | sbi->layout.mirrors_p1 = 1; |
564 | sbi->layout.group_width = 1; | ||
565 | sbi->layout.group_depth = -1; | ||
566 | sbi->layout.group_count = 1; | ||
567 | sbi->layout.s_ods[0] = od; | ||
568 | sbi->layout.s_numdevs = 1; | ||
569 | sbi->layout.s_pid = opts->pid; | ||
505 | sbi->s_timeout = opts->timeout; | 570 | sbi->s_timeout = opts->timeout; |
506 | 571 | ||
507 | /* fill in some other data by hand */ | 572 | /* fill in some other data by hand */ |
@@ -514,7 +579,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) | |||
514 | sb->s_bdev = NULL; | 579 | sb->s_bdev = NULL; |
515 | sb->s_dev = 0; | 580 | sb->s_dev = 0; |
516 | 581 | ||
517 | obj.partition = sbi->s_pid; | 582 | obj.partition = sbi->layout.s_pid; |
518 | obj.id = EXOFS_SUPER_ID; | 583 | obj.id = EXOFS_SUPER_ID; |
519 | exofs_make_credential(sbi->s_cred, &obj); | 584 | exofs_make_credential(sbi->s_cred, &obj); |
520 | 585 | ||
@@ -552,6 +617,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) | |||
552 | } | 617 | } |
553 | 618 | ||
554 | /* set up operation vectors */ | 619 | /* set up operation vectors */ |
620 | sb->s_bdi = &sbi->bdi; | ||
555 | sb->s_fs_info = sbi; | 621 | sb->s_fs_info = sbi; |
556 | sb->s_op = &exofs_sops; | 622 | sb->s_op = &exofs_sops; |
557 | sb->s_export_op = &exofs_export_ops; | 623 | sb->s_export_op = &exofs_export_ops; |
@@ -578,13 +644,15 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) | |||
578 | goto free_sbi; | 644 | goto free_sbi; |
579 | } | 645 | } |
580 | 646 | ||
581 | _exofs_print_device("Mounting", opts->dev_name, sbi->s_ods[0], | 647 | _exofs_print_device("Mounting", opts->dev_name, sbi->layout.s_ods[0], |
582 | sbi->s_pid); | 648 | sbi->layout.s_pid); |
583 | return 0; | 649 | return 0; |
584 | 650 | ||
585 | free_sbi: | 651 | free_sbi: |
652 | bdi_destroy(&sbi->bdi); | ||
653 | free_bdi: | ||
586 | EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n", | 654 | EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n", |
587 | opts->dev_name, sbi->s_pid, ret); | 655 | opts->dev_name, sbi->layout.s_pid, ret); |
588 | exofs_free_sbi(sbi); | 656 | exofs_free_sbi(sbi); |
589 | return ret; | 657 | return ret; |
590 | } | 658 | } |
@@ -627,7 +695,7 @@ static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
627 | uint8_t cred_a[OSD_CAP_LEN]; | 695 | uint8_t cred_a[OSD_CAP_LEN]; |
628 | int ret; | 696 | int ret; |
629 | 697 | ||
630 | ret = exofs_get_io_state(sbi, &ios); | 698 | ret = exofs_get_io_state(&sbi->layout, &ios); |
631 | if (ret) { | 699 | if (ret) { |
632 | EXOFS_DBGMSG("exofs_get_io_state failed.\n"); | 700 | EXOFS_DBGMSG("exofs_get_io_state failed.\n"); |
633 | return ret; | 701 | return ret; |