diff options
Diffstat (limited to 'fs/nilfs2/ioctl.c')
-rw-r--r-- | fs/nilfs2/ioctl.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 6ea5f872e2de..6572ea4bc4df 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
@@ -442,12 +442,6 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, | |||
442 | const char *msg; | 442 | const char *msg; |
443 | int ret; | 443 | int ret; |
444 | 444 | ||
445 | ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]); | ||
446 | if (ret < 0) { | ||
447 | msg = "cannot read source blocks"; | ||
448 | goto failed; | ||
449 | } | ||
450 | |||
451 | ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]); | 445 | ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]); |
452 | if (ret < 0) { | 446 | if (ret < 0) { |
453 | /* | 447 | /* |
@@ -548,7 +542,25 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
548 | } | 542 | } |
549 | } | 543 | } |
550 | 544 | ||
551 | ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); | 545 | /* |
546 | * nilfs_ioctl_move_blocks() will call nilfs_gc_iget(), | ||
547 | * which will operates an inode list without blocking. | ||
548 | * To protect the list from concurrent operations, | ||
549 | * nilfs_ioctl_move_blocks should be atomic operation. | ||
550 | */ | ||
551 | if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags)) { | ||
552 | ret = -EBUSY; | ||
553 | goto out_free; | ||
554 | } | ||
555 | |||
556 | ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]); | ||
557 | if (ret < 0) | ||
558 | printk(KERN_ERR "NILFS: GC failed during preparation: " | ||
559 | "cannot read source blocks: err=%d\n", ret); | ||
560 | else | ||
561 | ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); | ||
562 | |||
563 | clear_nilfs_gc_running(nilfs); | ||
552 | 564 | ||
553 | out_free: | 565 | out_free: |
554 | while (--n >= 0) | 566 | while (--n >= 0) |