diff options
Diffstat (limited to 'fs/ocfs2/refcounttree.c')
-rw-r--r-- | fs/ocfs2/refcounttree.c | 49 |
1 files changed, 11 insertions, 38 deletions
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index ebfd3825f12a..cf7823382664 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
@@ -4368,25 +4368,6 @@ static inline int ocfs2_may_create(struct inode *dir, struct dentry *child) | |||
4368 | return inode_permission(dir, MAY_WRITE | MAY_EXEC); | 4368 | return inode_permission(dir, MAY_WRITE | MAY_EXEC); |
4369 | } | 4369 | } |
4370 | 4370 | ||
4371 | /* copied from user_path_parent. */ | ||
4372 | static int ocfs2_user_path_parent(const char __user *path, | ||
4373 | struct nameidata *nd, char **name) | ||
4374 | { | ||
4375 | char *s = getname(path); | ||
4376 | int error; | ||
4377 | |||
4378 | if (IS_ERR(s)) | ||
4379 | return PTR_ERR(s); | ||
4380 | |||
4381 | error = kern_path_parent(s, nd); | ||
4382 | if (error) | ||
4383 | putname(s); | ||
4384 | else | ||
4385 | *name = s; | ||
4386 | |||
4387 | return error; | ||
4388 | } | ||
4389 | |||
4390 | /** | 4371 | /** |
4391 | * ocfs2_vfs_reflink - Create a reference-counted link | 4372 | * ocfs2_vfs_reflink - Create a reference-counted link |
4392 | * | 4373 | * |
@@ -4460,10 +4441,8 @@ int ocfs2_reflink_ioctl(struct inode *inode, | |||
4460 | bool preserve) | 4441 | bool preserve) |
4461 | { | 4442 | { |
4462 | struct dentry *new_dentry; | 4443 | struct dentry *new_dentry; |
4463 | struct nameidata nd; | 4444 | struct path old_path, new_path; |
4464 | struct path old_path; | ||
4465 | int error; | 4445 | int error; |
4466 | char *to = NULL; | ||
4467 | 4446 | ||
4468 | if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) | 4447 | if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) |
4469 | return -EOPNOTSUPP; | 4448 | return -EOPNOTSUPP; |
@@ -4474,39 +4453,33 @@ int ocfs2_reflink_ioctl(struct inode *inode, | |||
4474 | return error; | 4453 | return error; |
4475 | } | 4454 | } |
4476 | 4455 | ||
4477 | error = ocfs2_user_path_parent(newname, &nd, &to); | 4456 | new_dentry = user_path_create(AT_FDCWD, newname, &new_path, 0); |
4478 | if (error) { | 4457 | error = PTR_ERR(new_dentry); |
4458 | if (IS_ERR(new_dentry)) { | ||
4479 | mlog_errno(error); | 4459 | mlog_errno(error); |
4480 | goto out; | 4460 | goto out; |
4481 | } | 4461 | } |
4482 | 4462 | ||
4483 | error = -EXDEV; | 4463 | error = -EXDEV; |
4484 | if (old_path.mnt != nd.path.mnt) | 4464 | if (old_path.mnt != new_path.mnt) { |
4485 | goto out_release; | ||
4486 | new_dentry = lookup_create(&nd, 0); | ||
4487 | error = PTR_ERR(new_dentry); | ||
4488 | if (IS_ERR(new_dentry)) { | ||
4489 | mlog_errno(error); | 4465 | mlog_errno(error); |
4490 | goto out_unlock; | 4466 | goto out_dput; |
4491 | } | 4467 | } |
4492 | 4468 | ||
4493 | error = mnt_want_write(nd.path.mnt); | 4469 | error = mnt_want_write(new_path.mnt); |
4494 | if (error) { | 4470 | if (error) { |
4495 | mlog_errno(error); | 4471 | mlog_errno(error); |
4496 | goto out_dput; | 4472 | goto out_dput; |
4497 | } | 4473 | } |
4498 | 4474 | ||
4499 | error = ocfs2_vfs_reflink(old_path.dentry, | 4475 | error = ocfs2_vfs_reflink(old_path.dentry, |
4500 | nd.path.dentry->d_inode, | 4476 | new_path.dentry->d_inode, |
4501 | new_dentry, preserve); | 4477 | new_dentry, preserve); |
4502 | mnt_drop_write(nd.path.mnt); | 4478 | mnt_drop_write(new_path.mnt); |
4503 | out_dput: | 4479 | out_dput: |
4504 | dput(new_dentry); | 4480 | dput(new_dentry); |
4505 | out_unlock: | 4481 | mutex_unlock(&new_path.dentry->d_inode->i_mutex); |
4506 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 4482 | path_put(&new_path); |
4507 | out_release: | ||
4508 | path_put(&nd.path); | ||
4509 | putname(to); | ||
4510 | out: | 4483 | out: |
4511 | path_put(&old_path); | 4484 | path_put(&old_path); |
4512 | 4485 | ||