aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nilfs2/ioctl.c')
-rw-r--r--fs/nilfs2/ioctl.c23
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);
131out: 131out:
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
336static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, 336static 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
590out_free: 595out_free: