diff options
-rw-r--r-- | drivers/base/devtmpfs.c | 2 | ||||
-rw-r--r-- | fs/cachefiles/namei.c | 2 | ||||
-rw-r--r-- | fs/ecryptfs/inode.c | 4 | ||||
-rw-r--r-- | fs/namei.c | 42 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 2 | ||||
-rw-r--r-- | include/linux/fs.h | 2 | ||||
-rw-r--r-- | ipc/mqueue.c | 2 |
7 files changed, 46 insertions, 10 deletions
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 7413d065906b..1b8490e2fbde 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c | |||
@@ -324,7 +324,7 @@ static int handle_remove(const char *nodename, struct device *dev) | |||
324 | mutex_lock(&dentry->d_inode->i_mutex); | 324 | mutex_lock(&dentry->d_inode->i_mutex); |
325 | notify_change(dentry, &newattrs); | 325 | notify_change(dentry, &newattrs); |
326 | mutex_unlock(&dentry->d_inode->i_mutex); | 326 | mutex_unlock(&dentry->d_inode->i_mutex); |
327 | err = vfs_unlink(parent.dentry->d_inode, dentry); | 327 | err = vfs_unlink(parent.dentry->d_inode, dentry, NULL); |
328 | if (!err || err == -ENOENT) | 328 | if (!err || err == -ENOENT) |
329 | deleted = 1; | 329 | deleted = 1; |
330 | } | 330 | } |
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index f4a08d7fa2f7..31d480c0e046 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c | |||
@@ -294,7 +294,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, | |||
294 | if (ret < 0) { | 294 | if (ret < 0) { |
295 | cachefiles_io_error(cache, "Unlink security error"); | 295 | cachefiles_io_error(cache, "Unlink security error"); |
296 | } else { | 296 | } else { |
297 | ret = vfs_unlink(dir->d_inode, rep); | 297 | ret = vfs_unlink(dir->d_inode, rep, NULL); |
298 | 298 | ||
299 | if (preemptive) | 299 | if (preemptive) |
300 | cachefiles_mark_object_buried(cache, rep); | 300 | cachefiles_mark_object_buried(cache, rep); |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 0f9b66eaa767..dc60b8bd09ec 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -153,7 +153,7 @@ static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry, | |||
153 | 153 | ||
154 | dget(lower_dentry); | 154 | dget(lower_dentry); |
155 | lower_dir_dentry = lock_parent(lower_dentry); | 155 | lower_dir_dentry = lock_parent(lower_dentry); |
156 | rc = vfs_unlink(lower_dir_inode, lower_dentry); | 156 | rc = vfs_unlink(lower_dir_inode, lower_dentry, NULL); |
157 | if (rc) { | 157 | if (rc) { |
158 | printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); | 158 | printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); |
159 | goto out_unlock; | 159 | goto out_unlock; |
@@ -208,7 +208,7 @@ ecryptfs_do_create(struct inode *directory_inode, | |||
208 | inode = __ecryptfs_get_inode(lower_dentry->d_inode, | 208 | inode = __ecryptfs_get_inode(lower_dentry->d_inode, |
209 | directory_inode->i_sb); | 209 | directory_inode->i_sb); |
210 | if (IS_ERR(inode)) { | 210 | if (IS_ERR(inode)) { |
211 | vfs_unlink(lower_dir_dentry->d_inode, lower_dentry); | 211 | vfs_unlink(lower_dir_dentry->d_inode, lower_dentry, NULL); |
212 | goto out_lock; | 212 | goto out_lock; |
213 | } | 213 | } |
214 | fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); | 214 | fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); |
diff --git a/fs/namei.c b/fs/namei.c index e633a58d4222..67ce331a3ed8 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -3615,7 +3615,25 @@ SYSCALL_DEFINE1(rmdir, const char __user *, pathname) | |||
3615 | return do_rmdir(AT_FDCWD, pathname); | 3615 | return do_rmdir(AT_FDCWD, pathname); |
3616 | } | 3616 | } |
3617 | 3617 | ||
3618 | int vfs_unlink(struct inode *dir, struct dentry *dentry) | 3618 | /** |
3619 | * vfs_unlink - unlink a filesystem object | ||
3620 | * @dir: parent directory | ||
3621 | * @dentry: victim | ||
3622 | * @delegated_inode: returns victim inode, if the inode is delegated. | ||
3623 | * | ||
3624 | * The caller must hold dir->i_mutex. | ||
3625 | * | ||
3626 | * If vfs_unlink discovers a delegation, it will return -EWOULDBLOCK and | ||
3627 | * return a reference to the inode in delegated_inode. The caller | ||
3628 | * should then break the delegation on that inode and retry. Because | ||
3629 | * breaking a delegation may take a long time, the caller should drop | ||
3630 | * dir->i_mutex before doing so. | ||
3631 | * | ||
3632 | * Alternatively, a caller may pass NULL for delegated_inode. This may | ||
3633 | * be appropriate for callers that expect the underlying filesystem not | ||
3634 | * to be NFS exported. | ||
3635 | */ | ||
3636 | int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegated_inode) | ||
3619 | { | 3637 | { |
3620 | struct inode *target = dentry->d_inode; | 3638 | struct inode *target = dentry->d_inode; |
3621 | int error = may_delete(dir, dentry, 0); | 3639 | int error = may_delete(dir, dentry, 0); |
@@ -3632,11 +3650,20 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
3632 | else { | 3650 | else { |
3633 | error = security_inode_unlink(dir, dentry); | 3651 | error = security_inode_unlink(dir, dentry); |
3634 | if (!error) { | 3652 | if (!error) { |
3653 | error = break_deleg(target, O_WRONLY|O_NONBLOCK); | ||
3654 | if (error) { | ||
3655 | if (error == -EWOULDBLOCK && delegated_inode) { | ||
3656 | *delegated_inode = target; | ||
3657 | ihold(target); | ||
3658 | } | ||
3659 | goto out; | ||
3660 | } | ||
3635 | error = dir->i_op->unlink(dir, dentry); | 3661 | error = dir->i_op->unlink(dir, dentry); |
3636 | if (!error) | 3662 | if (!error) |
3637 | dont_mount(dentry); | 3663 | dont_mount(dentry); |
3638 | } | 3664 | } |
3639 | } | 3665 | } |
3666 | out: | ||
3640 | mutex_unlock(&target->i_mutex); | 3667 | mutex_unlock(&target->i_mutex); |
3641 | 3668 | ||
3642 | /* We don't d_delete() NFS sillyrenamed files--they still exist. */ | 3669 | /* We don't d_delete() NFS sillyrenamed files--they still exist. */ |
@@ -3661,6 +3688,7 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
3661 | struct dentry *dentry; | 3688 | struct dentry *dentry; |
3662 | struct nameidata nd; | 3689 | struct nameidata nd; |
3663 | struct inode *inode = NULL; | 3690 | struct inode *inode = NULL; |
3691 | struct inode *delegated_inode = NULL; | ||
3664 | unsigned int lookup_flags = 0; | 3692 | unsigned int lookup_flags = 0; |
3665 | retry: | 3693 | retry: |
3666 | name = user_path_parent(dfd, pathname, &nd, lookup_flags); | 3694 | name = user_path_parent(dfd, pathname, &nd, lookup_flags); |
@@ -3675,7 +3703,7 @@ retry: | |||
3675 | error = mnt_want_write(nd.path.mnt); | 3703 | error = mnt_want_write(nd.path.mnt); |
3676 | if (error) | 3704 | if (error) |
3677 | goto exit1; | 3705 | goto exit1; |
3678 | 3706 | retry_deleg: | |
3679 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 3707 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
3680 | dentry = lookup_hash(&nd); | 3708 | dentry = lookup_hash(&nd); |
3681 | error = PTR_ERR(dentry); | 3709 | error = PTR_ERR(dentry); |
@@ -3690,13 +3718,21 @@ retry: | |||
3690 | error = security_path_unlink(&nd.path, dentry); | 3718 | error = security_path_unlink(&nd.path, dentry); |
3691 | if (error) | 3719 | if (error) |
3692 | goto exit2; | 3720 | goto exit2; |
3693 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); | 3721 | error = vfs_unlink(nd.path.dentry->d_inode, dentry, &delegated_inode); |
3694 | exit2: | 3722 | exit2: |
3695 | dput(dentry); | 3723 | dput(dentry); |
3696 | } | 3724 | } |
3697 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 3725 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
3698 | if (inode) | 3726 | if (inode) |
3699 | iput(inode); /* truncate the inode here */ | 3727 | iput(inode); /* truncate the inode here */ |
3728 | inode = NULL; | ||
3729 | if (delegated_inode) { | ||
3730 | error = break_deleg(delegated_inode, O_WRONLY); | ||
3731 | iput(delegated_inode); | ||
3732 | delegated_inode = NULL; | ||
3733 | if (!error) | ||
3734 | goto retry_deleg; | ||
3735 | } | ||
3700 | mnt_drop_write(nd.path.mnt); | 3736 | mnt_drop_write(nd.path.mnt); |
3701 | exit1: | 3737 | exit1: |
3702 | path_put(&nd.path); | 3738 | path_put(&nd.path); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 13886f7f40d5..7a810235d599 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1910,7 +1910,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1910 | if (host_err) | 1910 | if (host_err) |
1911 | goto out_put; | 1911 | goto out_put; |
1912 | if (type != S_IFDIR) | 1912 | if (type != S_IFDIR) |
1913 | host_err = vfs_unlink(dirp, rdentry); | 1913 | host_err = vfs_unlink(dirp, rdentry, NULL); |
1914 | else | 1914 | else |
1915 | host_err = vfs_rmdir(dirp, rdentry); | 1915 | host_err = vfs_rmdir(dirp, rdentry); |
1916 | if (!host_err) | 1916 | if (!host_err) |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 8e4be1be1a62..a5799233142a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1455,7 +1455,7 @@ extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t); | |||
1455 | extern int vfs_symlink(struct inode *, struct dentry *, const char *); | 1455 | extern int vfs_symlink(struct inode *, struct dentry *, const char *); |
1456 | extern int vfs_link(struct dentry *, struct inode *, struct dentry *); | 1456 | extern int vfs_link(struct dentry *, struct inode *, struct dentry *); |
1457 | extern int vfs_rmdir(struct inode *, struct dentry *); | 1457 | extern int vfs_rmdir(struct inode *, struct dentry *); |
1458 | extern int vfs_unlink(struct inode *, struct dentry *); | 1458 | extern int vfs_unlink(struct inode *, struct dentry *, struct inode **); |
1459 | extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); | 1459 | extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); |
1460 | 1460 | ||
1461 | /* | 1461 | /* |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index ae1996d3c539..95827ce2f3c7 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -886,7 +886,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) | |||
886 | err = -ENOENT; | 886 | err = -ENOENT; |
887 | } else { | 887 | } else { |
888 | ihold(inode); | 888 | ihold(inode); |
889 | err = vfs_unlink(dentry->d_parent->d_inode, dentry); | 889 | err = vfs_unlink(dentry->d_parent->d_inode, dentry, NULL); |
890 | } | 890 | } |
891 | dput(dentry); | 891 | dput(dentry); |
892 | 892 | ||