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