diff options
| -rw-r--r-- | fs/nilfs2/ioctl.c | 26 | ||||
| -rw-r--r-- | fs/nilfs2/the_nilfs.h | 2 |
2 files changed, 21 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) |
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 68e9626e3d44..20abd55881e0 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
| @@ -37,6 +37,7 @@ enum { | |||
| 37 | THE_NILFS_LOADED, /* Roll-back/roll-forward has done and | 37 | THE_NILFS_LOADED, /* Roll-back/roll-forward has done and |
| 38 | the latest checkpoint was loaded */ | 38 | the latest checkpoint was loaded */ |
| 39 | THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */ | 39 | THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */ |
| 40 | THE_NILFS_GC_RUNNING, /* gc process is running */ | ||
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| 42 | /** | 43 | /** |
| @@ -195,6 +196,7 @@ static inline int nilfs_##name(struct the_nilfs *nilfs) \ | |||
| 195 | THE_NILFS_FNS(INIT, init) | 196 | THE_NILFS_FNS(INIT, init) |
| 196 | THE_NILFS_FNS(LOADED, loaded) | 197 | THE_NILFS_FNS(LOADED, loaded) |
| 197 | THE_NILFS_FNS(DISCONTINUED, discontinued) | 198 | THE_NILFS_FNS(DISCONTINUED, discontinued) |
| 199 | THE_NILFS_FNS(GC_RUNNING, gc_running) | ||
| 198 | 200 | ||
| 199 | /* Minimum interval of periodical update of superblocks (in seconds) */ | 201 | /* Minimum interval of periodical update of superblocks (in seconds) */ |
| 200 | #define NILFS_SB_FREQ 10 | 202 | #define NILFS_SB_FREQ 10 |
