diff options
Diffstat (limited to 'fs/nilfs2/ioctl.c')
| -rw-r--r-- | fs/nilfs2/ioctl.c | 39 |
1 files changed, 20 insertions, 19 deletions
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 6572ea4bc4d..f6af76042d8 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
| @@ -99,7 +99,8 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, | |||
| 99 | static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, | 99 | static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, |
| 100 | unsigned int cmd, void __user *argp) | 100 | unsigned int cmd, void __user *argp) |
| 101 | { | 101 | { |
| 102 | struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile; | 102 | struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; |
| 103 | struct inode *cpfile = nilfs->ns_cpfile; | ||
| 103 | struct nilfs_transaction_info ti; | 104 | struct nilfs_transaction_info ti; |
| 104 | struct nilfs_cpmode cpmode; | 105 | struct nilfs_cpmode cpmode; |
| 105 | int ret; | 106 | int ret; |
| @@ -109,14 +110,17 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, | |||
| 109 | if (copy_from_user(&cpmode, argp, sizeof(cpmode))) | 110 | if (copy_from_user(&cpmode, argp, sizeof(cpmode))) |
| 110 | return -EFAULT; | 111 | return -EFAULT; |
| 111 | 112 | ||
| 113 | mutex_lock(&nilfs->ns_mount_mutex); | ||
| 112 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 114 | nilfs_transaction_begin(inode->i_sb, &ti, 0); |
| 113 | ret = nilfs_cpfile_change_cpmode( | 115 | ret = nilfs_cpfile_change_cpmode( |
| 114 | cpfile, cpmode.cm_cno, cpmode.cm_mode); | 116 | cpfile, cpmode.cm_cno, cpmode.cm_mode); |
| 115 | if (unlikely(ret < 0)) { | 117 | if (unlikely(ret < 0)) { |
| 116 | nilfs_transaction_abort(inode->i_sb); | 118 | nilfs_transaction_abort(inode->i_sb); |
| 119 | mutex_unlock(&nilfs->ns_mount_mutex); | ||
| 117 | return ret; | 120 | return ret; |
| 118 | } | 121 | } |
| 119 | nilfs_transaction_commit(inode->i_sb); /* never fails */ | 122 | nilfs_transaction_commit(inode->i_sb); /* never fails */ |
| 123 | mutex_unlock(&nilfs->ns_mount_mutex); | ||
| 120 | return ret; | 124 | return ret; |
| 121 | } | 125 | } |
| 122 | 126 | ||
| @@ -297,7 +301,18 @@ static int nilfs_ioctl_move_inode_block(struct inode *inode, | |||
| 297 | (unsigned long long)vdesc->vd_vblocknr); | 301 | (unsigned long long)vdesc->vd_vblocknr); |
| 298 | return ret; | 302 | return ret; |
| 299 | } | 303 | } |
| 300 | bh->b_private = vdesc; | 304 | if (unlikely(!list_empty(&bh->b_assoc_buffers))) { |
| 305 | printk(KERN_CRIT "%s: conflicting %s buffer: ino=%llu, " | ||
| 306 | "cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu\n", | ||
| 307 | __func__, vdesc->vd_flags ? "node" : "data", | ||
| 308 | (unsigned long long)vdesc->vd_ino, | ||
| 309 | (unsigned long long)vdesc->vd_cno, | ||
| 310 | (unsigned long long)vdesc->vd_offset, | ||
| 311 | (unsigned long long)vdesc->vd_blocknr, | ||
| 312 | (unsigned long long)vdesc->vd_vblocknr); | ||
| 313 | brelse(bh); | ||
| 314 | return -EEXIST; | ||
| 315 | } | ||
| 301 | list_add_tail(&bh->b_assoc_buffers, buffers); | 316 | list_add_tail(&bh->b_assoc_buffers, buffers); |
| 302 | return 0; | 317 | return 0; |
| 303 | } | 318 | } |
| @@ -335,24 +350,10 @@ static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, | |||
| 335 | list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { | 350 | list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { |
| 336 | ret = nilfs_gccache_wait_and_mark_dirty(bh); | 351 | ret = nilfs_gccache_wait_and_mark_dirty(bh); |
| 337 | if (unlikely(ret < 0)) { | 352 | if (unlikely(ret < 0)) { |
| 338 | if (ret == -EEXIST) { | 353 | WARN_ON(ret == -EEXIST); |
| 339 | vdesc = bh->b_private; | ||
| 340 | printk(KERN_CRIT | ||
| 341 | "%s: conflicting %s buffer: " | ||
| 342 | "ino=%llu, cno=%llu, offset=%llu, " | ||
| 343 | "blocknr=%llu, vblocknr=%llu\n", | ||
| 344 | __func__, | ||
| 345 | vdesc->vd_flags ? "node" : "data", | ||
| 346 | (unsigned long long)vdesc->vd_ino, | ||
| 347 | (unsigned long long)vdesc->vd_cno, | ||
| 348 | (unsigned long long)vdesc->vd_offset, | ||
| 349 | (unsigned long long)vdesc->vd_blocknr, | ||
| 350 | (unsigned long long)vdesc->vd_vblocknr); | ||
| 351 | } | ||
| 352 | goto failed; | 354 | goto failed; |
| 353 | } | 355 | } |
| 354 | list_del_init(&bh->b_assoc_buffers); | 356 | list_del_init(&bh->b_assoc_buffers); |
| 355 | bh->b_private = NULL; | ||
| 356 | brelse(bh); | 357 | brelse(bh); |
| 357 | } | 358 | } |
| 358 | return nmembs; | 359 | return nmembs; |
| @@ -360,7 +361,6 @@ static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, | |||
| 360 | failed: | 361 | failed: |
| 361 | list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { | 362 | list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { |
| 362 | list_del_init(&bh->b_assoc_buffers); | 363 | list_del_init(&bh->b_assoc_buffers); |
| 363 | bh->b_private = NULL; | ||
| 364 | brelse(bh); | 364 | brelse(bh); |
| 365 | } | 365 | } |
| 366 | return ret; | 366 | return ret; |
| @@ -471,7 +471,6 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, | |||
| 471 | return 0; | 471 | return 0; |
| 472 | 472 | ||
| 473 | failed: | 473 | failed: |
| 474 | nilfs_remove_all_gcinode(nilfs); | ||
| 475 | printk(KERN_ERR "NILFS: GC failed during preparation: %s: err=%d\n", | 474 | printk(KERN_ERR "NILFS: GC failed during preparation: %s: err=%d\n", |
| 476 | msg, ret); | 475 | msg, ret); |
| 477 | return ret; | 476 | return ret; |
| @@ -560,6 +559,8 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
| 560 | else | 559 | else |
| 561 | ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); | 560 | ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); |
| 562 | 561 | ||
| 562 | if (ret < 0) | ||
| 563 | nilfs_remove_all_gcinode(nilfs); | ||
| 563 | clear_nilfs_gc_running(nilfs); | 564 | clear_nilfs_gc_running(nilfs); |
| 564 | 565 | ||
| 565 | out_free: | 566 | out_free: |
