aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/devtmpfs.c2
-rw-r--r--fs/cachefiles/namei.c2
-rw-r--r--fs/ecryptfs/inode.c4
-rw-r--r--fs/namei.c42
-rw-r--r--fs/nfsd/vfs.c2
-rw-r--r--include/linux/fs.h2
-rw-r--r--ipc/mqueue.c2
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
3618int 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 */
3636int 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 }
3666out:
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;
3665retry: 3693retry:
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 3706retry_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);
3694exit2: 3722exit2:
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);
3701exit1: 3737exit1:
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);
1455extern int vfs_symlink(struct inode *, struct dentry *, const char *); 1455extern int vfs_symlink(struct inode *, struct dentry *, const char *);
1456extern int vfs_link(struct dentry *, struct inode *, struct dentry *); 1456extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
1457extern int vfs_rmdir(struct inode *, struct dentry *); 1457extern int vfs_rmdir(struct inode *, struct dentry *);
1458extern int vfs_unlink(struct inode *, struct dentry *); 1458extern int vfs_unlink(struct inode *, struct dentry *, struct inode **);
1459extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); 1459extern 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