diff options
Diffstat (limited to 'fs/nilfs2/ioctl.c')
-rw-r--r-- | fs/nilfs2/ioctl.c | 63 |
1 files changed, 42 insertions, 21 deletions
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index cfb27892ffe8..108d281ebca5 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
@@ -489,14 +489,14 @@ nilfs_ioctl_do_mark_blocks_dirty(struct the_nilfs *nilfs, __u64 *posp, | |||
489 | ret = nilfs_mdt_mark_block_dirty(dat, | 489 | ret = nilfs_mdt_mark_block_dirty(dat, |
490 | bdescs[i].bd_offset); | 490 | bdescs[i].bd_offset); |
491 | if (ret < 0) { | 491 | if (ret < 0) { |
492 | BUG_ON(ret == -ENOENT); | 492 | WARN_ON(ret == -ENOENT); |
493 | return ret; | 493 | return ret; |
494 | } | 494 | } |
495 | } else { | 495 | } else { |
496 | ret = nilfs_bmap_mark(bmap, bdescs[i].bd_offset, | 496 | ret = nilfs_bmap_mark(bmap, bdescs[i].bd_offset, |
497 | bdescs[i].bd_level); | 497 | bdescs[i].bd_level); |
498 | if (ret < 0) { | 498 | if (ret < 0) { |
499 | BUG_ON(ret == -ENOENT); | 499 | WARN_ON(ret == -ENOENT); |
500 | return ret; | 500 | return ret; |
501 | } | 501 | } |
502 | } | 502 | } |
@@ -519,7 +519,8 @@ nilfs_ioctl_do_free_segments(struct the_nilfs *nilfs, __u64 *posp, int flags, | |||
519 | struct nilfs_sb_info *sbi = nilfs_get_writer(nilfs); | 519 | struct nilfs_sb_info *sbi = nilfs_get_writer(nilfs); |
520 | int ret; | 520 | int ret; |
521 | 521 | ||
522 | BUG_ON(!sbi); | 522 | if (unlikely(!sbi)) |
523 | return -EROFS; | ||
523 | ret = nilfs_segctor_add_segments_to_be_freed( | 524 | ret = nilfs_segctor_add_segments_to_be_freed( |
524 | NILFS_SC(sbi), buf, nmembs); | 525 | NILFS_SC(sbi), buf, nmembs); |
525 | nilfs_put_writer(nilfs); | 526 | nilfs_put_writer(nilfs); |
@@ -539,6 +540,7 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, | |||
539 | void __user *argp) | 540 | void __user *argp) |
540 | { | 541 | { |
541 | struct nilfs_argv argv[5]; | 542 | struct nilfs_argv argv[5]; |
543 | const char *msg; | ||
542 | int dir, ret; | 544 | int dir, ret; |
543 | 545 | ||
544 | if (copy_from_user(argv, argp, sizeof(argv))) | 546 | if (copy_from_user(argv, argp, sizeof(argv))) |
@@ -546,31 +548,50 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, | |||
546 | 548 | ||
547 | dir = _IOC_WRITE; | 549 | dir = _IOC_WRITE; |
548 | ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], dir); | 550 | ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], dir); |
549 | if (ret < 0) | 551 | if (ret < 0) { |
550 | goto out_move_blks; | 552 | msg = "cannot read source blocks"; |
553 | goto failed; | ||
554 | } | ||
551 | ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], dir); | 555 | ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], dir); |
552 | if (ret < 0) | 556 | if (ret < 0) { |
553 | goto out_del_cps; | 557 | /* |
558 | * can safely abort because checkpoints can be removed | ||
559 | * independently. | ||
560 | */ | ||
561 | msg = "cannot delete checkpoints"; | ||
562 | goto failed; | ||
563 | } | ||
554 | ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], dir); | 564 | ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], dir); |
555 | if (ret < 0) | 565 | if (ret < 0) { |
556 | goto out_free_vbns; | 566 | /* |
567 | * can safely abort because DAT file is updated atomically | ||
568 | * using a copy-on-write technique. | ||
569 | */ | ||
570 | msg = "cannot delete virtual blocks from DAT file"; | ||
571 | goto failed; | ||
572 | } | ||
557 | ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], dir); | 573 | ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], dir); |
558 | if (ret < 0) | 574 | if (ret < 0) { |
559 | goto out_free_vbns; | 575 | /* |
576 | * can safely abort because the operation is nondestructive. | ||
577 | */ | ||
578 | msg = "cannot mark copying blocks dirty"; | ||
579 | goto failed; | ||
580 | } | ||
560 | ret = nilfs_ioctl_free_segments(nilfs, &argv[4], dir); | 581 | ret = nilfs_ioctl_free_segments(nilfs, &argv[4], dir); |
561 | if (ret < 0) | 582 | if (ret < 0) { |
562 | goto out_free_segs; | 583 | /* |
563 | 584 | * can safely abort because this operation is atomic. | |
585 | */ | ||
586 | msg = "cannot set segments to be freed"; | ||
587 | goto failed; | ||
588 | } | ||
564 | return 0; | 589 | return 0; |
565 | 590 | ||
566 | out_free_segs: | 591 | failed: |
567 | BUG(); /* XXX: not implemented yet */ | ||
568 | out_free_vbns: | ||
569 | BUG();/* XXX: not implemented yet */ | ||
570 | out_del_cps: | ||
571 | BUG();/* XXX: not implemented yet */ | ||
572 | out_move_blks: | ||
573 | nilfs_remove_all_gcinode(nilfs); | 592 | nilfs_remove_all_gcinode(nilfs); |
593 | printk(KERN_ERR "NILFS: GC failed during preparation: %s: err=%d\n", | ||
594 | msg, ret); | ||
574 | return ret; | 595 | return ret; |
575 | } | 596 | } |
576 | 597 | ||