diff options
| -rw-r--r-- | fs/nilfs2/ioctl.c | 60 |
1 files changed, 43 insertions, 17 deletions
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index d6b2b83de363..8e5cad020c30 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/capability.h> /* capable() */ | 26 | #include <linux/capability.h> /* capable() */ |
| 27 | #include <linux/uaccess.h> /* copy_from_user(), copy_to_user() */ | 27 | #include <linux/uaccess.h> /* copy_from_user(), copy_to_user() */ |
| 28 | #include <linux/vmalloc.h> | 28 | #include <linux/vmalloc.h> |
| 29 | #include <linux/mount.h> /* mnt_want_write(), mnt_drop_write() */ | ||
| 29 | #include <linux/nilfs2_fs.h> | 30 | #include <linux/nilfs2_fs.h> |
| 30 | #include "nilfs.h" | 31 | #include "nilfs.h" |
| 31 | #include "segment.h" | 32 | #include "segment.h" |
| @@ -107,20 +108,28 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, | |||
| 107 | 108 | ||
| 108 | if (!capable(CAP_SYS_ADMIN)) | 109 | if (!capable(CAP_SYS_ADMIN)) |
| 109 | return -EPERM; | 110 | return -EPERM; |
| 111 | |||
| 112 | ret = mnt_want_write(filp->f_path.mnt); | ||
| 113 | if (ret) | ||
| 114 | return ret; | ||
| 115 | |||
| 116 | ret = -EFAULT; | ||
| 110 | if (copy_from_user(&cpmode, argp, sizeof(cpmode))) | 117 | if (copy_from_user(&cpmode, argp, sizeof(cpmode))) |
| 111 | return -EFAULT; | 118 | goto out; |
| 112 | 119 | ||
| 113 | mutex_lock(&nilfs->ns_mount_mutex); | 120 | mutex_lock(&nilfs->ns_mount_mutex); |
| 121 | |||
| 114 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 122 | nilfs_transaction_begin(inode->i_sb, &ti, 0); |
| 115 | ret = nilfs_cpfile_change_cpmode( | 123 | ret = nilfs_cpfile_change_cpmode( |
| 116 | cpfile, cpmode.cm_cno, cpmode.cm_mode); | 124 | cpfile, cpmode.cm_cno, cpmode.cm_mode); |
| 117 | if (unlikely(ret < 0)) { | 125 | if (unlikely(ret < 0)) |
| 118 | nilfs_transaction_abort(inode->i_sb); | 126 | nilfs_transaction_abort(inode->i_sb); |
| 119 | mutex_unlock(&nilfs->ns_mount_mutex); | 127 | else |
| 120 | return ret; | 128 | nilfs_transaction_commit(inode->i_sb); /* never fails */ |
| 121 | } | 129 | |
| 122 | nilfs_transaction_commit(inode->i_sb); /* never fails */ | ||
| 123 | mutex_unlock(&nilfs->ns_mount_mutex); | 130 | mutex_unlock(&nilfs->ns_mount_mutex); |
| 131 | out: | ||
| 132 | mnt_drop_write(filp->f_path.mnt); | ||
| 124 | return ret; | 133 | return ret; |
| 125 | } | 134 | } |
| 126 | 135 | ||
| @@ -135,16 +144,23 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, | |||
| 135 | 144 | ||
| 136 | if (!capable(CAP_SYS_ADMIN)) | 145 | if (!capable(CAP_SYS_ADMIN)) |
| 137 | return -EPERM; | 146 | return -EPERM; |
| 147 | |||
| 148 | ret = mnt_want_write(filp->f_path.mnt); | ||
| 149 | if (ret) | ||
| 150 | return ret; | ||
| 151 | |||
| 152 | ret = -EFAULT; | ||
| 138 | if (copy_from_user(&cno, argp, sizeof(cno))) | 153 | if (copy_from_user(&cno, argp, sizeof(cno))) |
| 139 | return -EFAULT; | 154 | goto out; |
| 140 | 155 | ||
| 141 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 156 | nilfs_transaction_begin(inode->i_sb, &ti, 0); |
| 142 | ret = nilfs_cpfile_delete_checkpoint(cpfile, cno); | 157 | ret = nilfs_cpfile_delete_checkpoint(cpfile, cno); |
| 143 | if (unlikely(ret < 0)) { | 158 | if (unlikely(ret < 0)) |
| 144 | nilfs_transaction_abort(inode->i_sb); | 159 | nilfs_transaction_abort(inode->i_sb); |
| 145 | return ret; | 160 | else |
| 146 | } | 161 | nilfs_transaction_commit(inode->i_sb); /* never fails */ |
| 147 | nilfs_transaction_commit(inode->i_sb); /* never fails */ | 162 | out: |
| 163 | mnt_drop_write(filp->f_path.mnt); | ||
| 148 | return ret; | 164 | return ret; |
| 149 | } | 165 | } |
| 150 | 166 | ||
| @@ -496,12 +512,19 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
| 496 | if (!capable(CAP_SYS_ADMIN)) | 512 | if (!capable(CAP_SYS_ADMIN)) |
| 497 | return -EPERM; | 513 | return -EPERM; |
| 498 | 514 | ||
| 515 | ret = mnt_want_write(filp->f_path.mnt); | ||
| 516 | if (ret) | ||
| 517 | return ret; | ||
| 518 | |||
| 519 | ret = -EFAULT; | ||
| 499 | if (copy_from_user(argv, argp, sizeof(argv))) | 520 | if (copy_from_user(argv, argp, sizeof(argv))) |
| 500 | return -EFAULT; | 521 | goto out; |
| 501 | 522 | ||
| 523 | ret = -EINVAL; | ||
| 502 | nsegs = argv[4].v_nmembs; | 524 | nsegs = argv[4].v_nmembs; |
| 503 | if (argv[4].v_size != argsz[4]) | 525 | if (argv[4].v_size != argsz[4]) |
| 504 | return -EINVAL; | 526 | goto out; |
| 527 | |||
| 505 | /* | 528 | /* |
| 506 | * argv[4] points to segment numbers this ioctl cleans. We | 529 | * argv[4] points to segment numbers this ioctl cleans. We |
| 507 | * use kmalloc() for its buffer because memory used for the | 530 | * use kmalloc() for its buffer because memory used for the |
| @@ -509,9 +532,10 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
| 509 | */ | 532 | */ |
| 510 | kbufs[4] = memdup_user((void __user *)(unsigned long)argv[4].v_base, | 533 | kbufs[4] = memdup_user((void __user *)(unsigned long)argv[4].v_base, |
| 511 | nsegs * sizeof(__u64)); | 534 | nsegs * sizeof(__u64)); |
| 512 | if (IS_ERR(kbufs[4])) | 535 | if (IS_ERR(kbufs[4])) { |
| 513 | return PTR_ERR(kbufs[4]); | 536 | ret = PTR_ERR(kbufs[4]); |
| 514 | 537 | goto out; | |
| 538 | } | ||
| 515 | nilfs = NILFS_SB(inode->i_sb)->s_nilfs; | 539 | nilfs = NILFS_SB(inode->i_sb)->s_nilfs; |
| 516 | 540 | ||
| 517 | for (n = 0; n < 4; n++) { | 541 | for (n = 0; n < 4; n++) { |
| @@ -563,10 +587,12 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
| 563 | nilfs_remove_all_gcinode(nilfs); | 587 | nilfs_remove_all_gcinode(nilfs); |
| 564 | clear_nilfs_gc_running(nilfs); | 588 | clear_nilfs_gc_running(nilfs); |
| 565 | 589 | ||
| 566 | out_free: | 590 | out_free: |
| 567 | while (--n >= 0) | 591 | while (--n >= 0) |
| 568 | vfree(kbufs[n]); | 592 | vfree(kbufs[n]); |
| 569 | kfree(kbufs[4]); | 593 | kfree(kbufs[4]); |
| 594 | out: | ||
| 595 | mnt_drop_write(filp->f_path.mnt); | ||
| 570 | return ret; | 596 | return ret; |
| 571 | } | 597 | } |
| 572 | 598 | ||
