diff options
| author | James Morris <james.l.morris@oracle.com> | 2012-09-28 13:37:32 +1000 | 
|---|---|---|
| committer | James Morris <james.l.morris@oracle.com> | 2012-09-28 13:37:32 +1000 | 
| commit | bf5308344527d015ac9a6d2bda4ad4d40fd7d943 (patch) | |
| tree | 566e61e2cfc648c374d15cfc8c661b73e1a471f8 /ipc/mqueue.c | |
| parent | 3585e96cd1049682b8a19a0b699422156e9d735b (diff) | |
| parent | 979570e02981d4a8fc20b3cc8fd651856c98ee9d (diff) | |
| download | olio-linux-3.10-bf5308344527d015ac9a6d2bda4ad4d40fd7d943.tar.xz olio-linux-3.10-bf5308344527d015ac9a6d2bda4ad4d40fd7d943.zip  | |
Merge tag 'v3.6-rc7' into next
Linux 3.6-rc7
Requested by David Howells so he can merge his key susbsystem work into
my tree with requisite -linus changesets.
Diffstat (limited to 'ipc/mqueue.c')
| -rw-r--r-- | ipc/mqueue.c | 61 | 
1 files changed, 28 insertions, 33 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index f8e54f5b908..9a08acc9e64 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -726,7 +726,6 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir,  			struct mq_attr *attr)  {  	const struct cred *cred = current_cred(); -	struct file *result;  	int ret;  	if (attr) { @@ -748,21 +747,11 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir,  	}  	mode &= ~current_umask(); -	ret = mnt_want_write(path->mnt); -	if (ret) -		return ERR_PTR(ret);  	ret = vfs_create(dir, path->dentry, mode, true);  	path->dentry->d_fsdata = NULL; -	if (!ret) -		result = dentry_open(path, oflag, cred); -	else -		result = ERR_PTR(ret); -	/* -	 * dentry_open() took a persistent mnt_want_write(), -	 * so we can now drop this one. -	 */ -	mnt_drop_write(path->mnt); -	return result; +	if (ret) +		return ERR_PTR(ret); +	return dentry_open(path, oflag, cred);  }  /* Opens existing queue */ @@ -788,7 +777,9 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,  	struct mq_attr attr;  	int fd, error;  	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; -	struct dentry *root = ipc_ns->mq_mnt->mnt_root; +	struct vfsmount *mnt = ipc_ns->mq_mnt; +	struct dentry *root = mnt->mnt_root; +	int ro;  	if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))  		return -EFAULT; @@ -802,6 +793,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,  	if (fd < 0)  		goto out_putname; +	ro = mnt_want_write(mnt);	/* we'll drop it in any case */  	error = 0;  	mutex_lock(&root->d_inode->i_mutex);  	path.dentry = lookup_one_len(name, root, strlen(name)); @@ -809,7 +801,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,  		error = PTR_ERR(path.dentry);  		goto out_putfd;  	} -	path.mnt = mntget(ipc_ns->mq_mnt); +	path.mnt = mntget(mnt);  	if (oflag & O_CREAT) {  		if (path.dentry->d_inode) {	/* entry already exists */ @@ -820,6 +812,10 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,  			}  			filp = do_open(&path, oflag);  		} else { +			if (ro) { +				error = ro; +				goto out; +			}  			filp = do_create(ipc_ns, root->d_inode,  						&path, oflag, mode,  						u_attr ? &attr : NULL); @@ -845,6 +841,7 @@ out_putfd:  		fd = error;  	}  	mutex_unlock(&root->d_inode->i_mutex); +	mnt_drop_write(mnt);  out_putname:  	putname(name);  	return fd; @@ -857,40 +854,38 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)  	struct dentry *dentry;  	struct inode *inode = NULL;  	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; +	struct vfsmount *mnt = ipc_ns->mq_mnt;  	name = getname(u_name);  	if (IS_ERR(name))  		return PTR_ERR(name); -	mutex_lock_nested(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex, -			I_MUTEX_PARENT); -	dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name)); +	err = mnt_want_write(mnt); +	if (err) +		goto out_name; +	mutex_lock_nested(&mnt->mnt_root->d_inode->i_mutex, I_MUTEX_PARENT); +	dentry = lookup_one_len(name, mnt->mnt_root, strlen(name));  	if (IS_ERR(dentry)) {  		err = PTR_ERR(dentry);  		goto out_unlock;  	} -	if (!dentry->d_inode) { -		err = -ENOENT; -		goto out_err; -	} -  	inode = dentry->d_inode; -	if (inode) +	if (!inode) { +		err = -ENOENT; +	} else {  		ihold(inode); -	err = mnt_want_write(ipc_ns->mq_mnt); -	if (err) -		goto out_err; -	err = vfs_unlink(dentry->d_parent->d_inode, dentry); -	mnt_drop_write(ipc_ns->mq_mnt); -out_err: +		err = vfs_unlink(dentry->d_parent->d_inode, dentry); +	}  	dput(dentry);  out_unlock: -	mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); -	putname(name); +	mutex_unlock(&mnt->mnt_root->d_inode->i_mutex);  	if (inode)  		iput(inode); +	mnt_drop_write(mnt); +out_name: +	putname(name);  	return err;  }  |