diff options
Diffstat (limited to 'fs/nilfs2/ioctl.c')
-rw-r--r-- | fs/nilfs2/ioctl.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 0442ee3b394f..3e90f86d5bfe 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
@@ -117,7 +117,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, | |||
117 | if (copy_from_user(&cpmode, argp, sizeof(cpmode))) | 117 | if (copy_from_user(&cpmode, argp, sizeof(cpmode))) |
118 | goto out; | 118 | goto out; |
119 | 119 | ||
120 | mutex_lock(&nilfs->ns_mount_mutex); | 120 | down_read(&inode->i_sb->s_umount); |
121 | 121 | ||
122 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 122 | nilfs_transaction_begin(inode->i_sb, &ti, 0); |
123 | ret = nilfs_cpfile_change_cpmode( | 123 | ret = nilfs_cpfile_change_cpmode( |
@@ -127,7 +127,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, | |||
127 | else | 127 | else |
128 | nilfs_transaction_commit(inode->i_sb); /* never fails */ | 128 | nilfs_transaction_commit(inode->i_sb); /* never fails */ |
129 | 129 | ||
130 | mutex_unlock(&nilfs->ns_mount_mutex); | 130 | up_read(&inode->i_sb->s_umount); |
131 | out: | 131 | out: |
132 | mnt_drop_write(filp->f_path.mnt); | 132 | mnt_drop_write(filp->f_path.mnt); |
133 | return ret; | 133 | return ret; |
@@ -333,7 +333,7 @@ static int nilfs_ioctl_move_inode_block(struct inode *inode, | |||
333 | return 0; | 333 | return 0; |
334 | } | 334 | } |
335 | 335 | ||
336 | static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, | 336 | static int nilfs_ioctl_move_blocks(struct super_block *sb, |
337 | struct nilfs_argv *argv, void *buf) | 337 | struct nilfs_argv *argv, void *buf) |
338 | { | 338 | { |
339 | size_t nmembs = argv->v_nmembs; | 339 | size_t nmembs = argv->v_nmembs; |
@@ -348,7 +348,7 @@ static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, | |||
348 | for (i = 0, vdesc = buf; i < nmembs; ) { | 348 | for (i = 0, vdesc = buf; i < nmembs; ) { |
349 | ino = vdesc->vd_ino; | 349 | ino = vdesc->vd_ino; |
350 | cno = vdesc->vd_cno; | 350 | cno = vdesc->vd_cno; |
351 | inode = nilfs_gc_iget(nilfs, ino, cno); | 351 | inode = nilfs_iget_for_gc(sb, ino, cno); |
352 | if (unlikely(inode == NULL)) { | 352 | if (unlikely(inode == NULL)) { |
353 | ret = -ENOMEM; | 353 | ret = -ENOMEM; |
354 | goto failed; | 354 | goto failed; |
@@ -356,11 +356,15 @@ static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, | |||
356 | do { | 356 | do { |
357 | ret = nilfs_ioctl_move_inode_block(inode, vdesc, | 357 | ret = nilfs_ioctl_move_inode_block(inode, vdesc, |
358 | &buffers); | 358 | &buffers); |
359 | if (unlikely(ret < 0)) | 359 | if (unlikely(ret < 0)) { |
360 | iput(inode); | ||
360 | goto failed; | 361 | goto failed; |
362 | } | ||
361 | vdesc++; | 363 | vdesc++; |
362 | } while (++i < nmembs && | 364 | } while (++i < nmembs && |
363 | vdesc->vd_ino == ino && vdesc->vd_cno == cno); | 365 | vdesc->vd_ino == ino && vdesc->vd_cno == cno); |
366 | |||
367 | iput(inode); /* The inode still remains in GC inode list */ | ||
364 | } | 368 | } |
365 | 369 | ||
366 | list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { | 370 | list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { |
@@ -566,7 +570,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
566 | } | 570 | } |
567 | 571 | ||
568 | /* | 572 | /* |
569 | * nilfs_ioctl_move_blocks() will call nilfs_gc_iget(), | 573 | * nilfs_ioctl_move_blocks() will call nilfs_iget_for_gc(), |
570 | * which will operates an inode list without blocking. | 574 | * which will operates an inode list without blocking. |
571 | * To protect the list from concurrent operations, | 575 | * To protect the list from concurrent operations, |
572 | * nilfs_ioctl_move_blocks should be atomic operation. | 576 | * nilfs_ioctl_move_blocks should be atomic operation. |
@@ -576,15 +580,16 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
576 | goto out_free; | 580 | goto out_free; |
577 | } | 581 | } |
578 | 582 | ||
579 | ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]); | 583 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); |
584 | |||
585 | ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]); | ||
580 | if (ret < 0) | 586 | if (ret < 0) |
581 | printk(KERN_ERR "NILFS: GC failed during preparation: " | 587 | printk(KERN_ERR "NILFS: GC failed during preparation: " |
582 | "cannot read source blocks: err=%d\n", ret); | 588 | "cannot read source blocks: err=%d\n", ret); |
583 | else | 589 | else |
584 | ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); | 590 | ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); |
585 | 591 | ||
586 | if (ret < 0) | 592 | nilfs_remove_all_gcinodes(nilfs); |
587 | nilfs_remove_all_gcinode(nilfs); | ||
588 | clear_nilfs_gc_running(nilfs); | 593 | clear_nilfs_gc_running(nilfs); |
589 | 594 | ||
590 | out_free: | 595 | out_free: |