diff options
Diffstat (limited to 'fs')
-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 |