}
EXPORT_SYMBOL_GPL(lookup_create);
+struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path, int is_dir)
+{
+ struct nameidata nd;
+ struct dentry *res;
+ int error = do_path_lookup(dfd, pathname, LOOKUP_PARENT, &nd);
+ if (error)
+ return ERR_PTR(error);
+ res = lookup_create(&nd, is_dir);
+ if (IS_ERR(res)) {
+ mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+ path_put(&nd.path);
+ }
+ *path = nd.path;
+ return res;
+}
+EXPORT_SYMBOL(kern_path_create);
+
+struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir)
+{
+ char *tmp = getname(pathname);
+ struct dentry *res;
+ if (IS_ERR(tmp))
+ return ERR_CAST(tmp);
+ res = kern_path_create(dfd, tmp, path, is_dir);
+ putname(tmp);
+ return res;
+}
+EXPORT_SYMBOL(user_path_create);
+
int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
int error = may_create(dir, dentry);
SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode,
unsigned, dev)
{
- int error;
- char *tmp;
struct dentry *dentry;
- struct nameidata nd;
+ struct path path;
+ int error;
if (S_ISDIR(mode))
return -EPERM;
- error = user_path_parent(dfd, filename, &nd, &tmp);
- if (error)
- return error;
+ dentry = user_path_create(dfd, filename, &path, 0);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
- dentry = lookup_create(&nd, 0);
- if (IS_ERR(dentry)) {
- error = PTR_ERR(dentry);
- goto out_unlock;
- }
- if (!IS_POSIXACL(nd.path.dentry->d_inode))
+ if (!IS_POSIXACL(path.dentry->d_inode))
mode &= ~current_umask();
error = may_mknod(mode);
if (error)
goto out_dput;
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(path.mnt);
if (error)
goto out_dput;
- error = security_path_mknod(&nd.path, dentry, mode, dev);
+ error = security_path_mknod(&path, dentry, mode, dev);
if (error)
goto out_drop_write;
switch (mode & S_IFMT) {
case 0: case S_IFREG:
- error = vfs_create(nd.path.dentry->d_inode,dentry,mode,NULL);
+ error = vfs_create(path.dentry->d_inode,dentry,mode,NULL);
break;
case S_IFCHR: case S_IFBLK:
- error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,
+ error = vfs_mknod(path.dentry->d_inode,dentry,mode,
new_decode_dev(dev));
break;
case S_IFIFO: case S_IFSOCK:
- error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0);
+ error = vfs_mknod(path.dentry->d_inode,dentry,mode,0);
break;
}
out_drop_write:
- mnt_drop_write(nd.path.mnt);
+ mnt_drop_write(path.mnt);
out_dput:
dput(dentry);
-out_unlock:
- mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
- path_put(&nd.path);
- putname(tmp);
+ mutex_unlock(&path.dentry->d_inode->i_mutex);
+ path_put(&path);
return error;
}
SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode)
{
- int error = 0;
- char * tmp;
struct dentry *dentry;
- struct nameidata nd;
-
- error = user_path_parent(dfd, pathname, &nd, &tmp);
- if (error)
- goto out_err;
+ struct path path;
+ int error;
- dentry = lookup_create(&nd, 1);
- error = PTR_ERR(dentry);
+ dentry = user_path_create(dfd, pathname, &path, 1);
if (IS_ERR(dentry))
- goto out_unlock;
+ return PTR_ERR(dentry);
- if (!IS_POSIXACL(nd.path.dentry->d_inode))
+ if (!IS_POSIXACL(path.dentry->d_inode))
mode &= ~current_umask();
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(path.mnt);
if (error)
goto out_dput;
- error = security_path_mkdir(&nd.path, dentry, mode);
+ error = security_path_mkdir(&path, dentry, mode);
if (error)
goto out_drop_write;
- error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
+ error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
out_drop_write:
- mnt_drop_write(nd.path.mnt);
+ mnt_drop_write(path.mnt);
out_dput:
dput(dentry);
-out_unlock:
- mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
- path_put(&nd.path);
- putname(tmp);
-out_err:
+ mutex_unlock(&path.dentry->d_inode->i_mutex);
+ path_put(&path);
return error;
}
{
int error;
char *from;
- char *to;
struct dentry *dentry;
- struct nameidata nd;
+ struct path path;
from = getname(oldname);
if (IS_ERR(from))
return PTR_ERR(from);
- error = user_path_parent(newdfd, newname, &nd, &to);
- if (error)
- goto out_putname;
-
- dentry = lookup_create(&nd, 0);
+ dentry = user_path_create(newdfd, newname, &path, 0);
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
- goto out_unlock;
+ goto out_putname;
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(path.mnt);
if (error)
goto out_dput;
- error = security_path_symlink(&nd.path, dentry, from);
+ error = security_path_symlink(&path, dentry, from);
if (error)
goto out_drop_write;
- error = vfs_symlink(nd.path.dentry->d_inode, dentry, from);
+ error = vfs_symlink(path.dentry->d_inode, dentry, from);
out_drop_write:
- mnt_drop_write(nd.path.mnt);
+ mnt_drop_write(path.mnt);
out_dput:
dput(dentry);
-out_unlock:
- mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
- path_put(&nd.path);
- putname(to);
+ mutex_unlock(&path.dentry->d_inode->i_mutex);
+ path_put(&path);
out_putname:
putname(from);
return error;
int, newdfd, const char __user *, newname, int, flags)
{
struct dentry *new_dentry;
- struct nameidata nd;
- struct path old_path;
+ struct path old_path, new_path;
int how = 0;
int error;
- char *to;
if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
return -EINVAL;
if (error)
return error;
- error = user_path_parent(newdfd, newname, &nd, &to);
- if (error)
- goto out;
- error = -EXDEV;
- if (old_path.mnt != nd.path.mnt)
- goto out_release;
- new_dentry = lookup_create(&nd, 0);
+ new_dentry = user_path_create(newdfd, newname, &new_path, 0);
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
- goto out_unlock;
- error = mnt_want_write(nd.path.mnt);
+ goto out;
+
+ error = -EXDEV;
+ if (old_path.mnt != new_path.mnt)
+ goto out_dput;
+ error = mnt_want_write(new_path.mnt);
if (error)
goto out_dput;
- error = security_path_link(old_path.dentry, &nd.path, new_dentry);
+ error = security_path_link(old_path.dentry, &new_path, new_dentry);
if (error)
goto out_drop_write;
- error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
+ error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry);
out_drop_write:
- mnt_drop_write(nd.path.mnt);
+ mnt_drop_write(new_path.mnt);
out_dput:
dput(new_dentry);
-out_unlock:
- mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-out_release:
- path_put(&nd.path);
- putname(to);
+ mutex_unlock(&new_path.dentry->d_inode->i_mutex);
+ path_put(&new_path);
out:
path_put(&old_path);
return inode_permission(dir, MAY_WRITE | MAY_EXEC);
}
-/* copied from user_path_parent. */
-static int ocfs2_user_path_parent(const char __user *path,
- struct nameidata *nd, char **name)
-{
- char *s = getname(path);
- int error;
-
- if (IS_ERR(s))
- return PTR_ERR(s);
-
- error = kern_path_parent(s, nd);
- if (error)
- putname(s);
- else
- *name = s;
-
- return error;
-}
-
/**
* ocfs2_vfs_reflink - Create a reference-counted link
*
bool preserve)
{
struct dentry *new_dentry;
- struct nameidata nd;
- struct path old_path;
+ struct path old_path, new_path;
int error;
- char *to = NULL;
if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb)))
return -EOPNOTSUPP;
return error;
}
- error = ocfs2_user_path_parent(newname, &nd, &to);
- if (error) {
+ new_dentry = user_path_create(AT_FDCWD, newname, &new_path, 0);
+ error = PTR_ERR(new_dentry);
+ if (IS_ERR(new_dentry)) {
mlog_errno(error);
goto out;
}
error = -EXDEV;
- if (old_path.mnt != nd.path.mnt)
- goto out_release;
- new_dentry = lookup_create(&nd, 0);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry)) {
+ if (old_path.mnt != new_path.mnt) {
mlog_errno(error);
- goto out_unlock;
+ goto out_dput;
}
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(new_path.mnt);
if (error) {
mlog_errno(error);
goto out_dput;
}
error = ocfs2_vfs_reflink(old_path.dentry,
- nd.path.dentry->d_inode,
+ new_path.dentry->d_inode,
new_dentry, preserve);
- mnt_drop_write(nd.path.mnt);
+ mnt_drop_write(new_path.mnt);
out_dput:
dput(new_dentry);
-out_unlock:
- mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-out_release:
- path_put(&nd.path);
- putname(to);
+ mutex_unlock(&new_path.dentry->d_inode->i_mutex);
+ path_put(&new_path);
out:
path_put(&old_path);
struct net *net = sock_net(sk);
struct unix_sock *u = unix_sk(sk);
struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
+ char *sun_path = sunaddr->sun_path;
struct dentry *dentry = NULL;
- struct nameidata nd;
+ struct path path;
int err;
unsigned hash;
struct unix_address *addr;
addr->hash = hash ^ sk->sk_type;
atomic_set(&addr->refcnt, 1);
- if (sunaddr->sun_path[0]) {
+ if (sun_path[0]) {
unsigned int mode;
err = 0;
/*
* Get the parent directory, calculate the hash for last
* component.
*/
- err = kern_path_parent(sunaddr->sun_path, &nd);
- if (err)
- goto out_mknod_parent;
-
- dentry = lookup_create(&nd, 0);
+ dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
err = PTR_ERR(dentry);
if (IS_ERR(dentry))
- goto out_mknod_unlock;
+ goto out_mknod_parent;
/*
* All right, let's create it.
*/
mode = S_IFSOCK |
(SOCK_INODE(sock)->i_mode & ~current_umask());
- err = mnt_want_write(nd.path.mnt);
+ err = mnt_want_write(path.mnt);
if (err)
goto out_mknod_dput;
- err = security_path_mknod(&nd.path, dentry, mode, 0);
+ err = security_path_mknod(&path, dentry, mode, 0);
if (err)
goto out_mknod_drop_write;
- err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
+ err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
out_mknod_drop_write:
- mnt_drop_write(nd.path.mnt);
+ mnt_drop_write(path.mnt);
if (err)
goto out_mknod_dput;
- mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
- dput(nd.path.dentry);
- nd.path.dentry = dentry;
+ mutex_unlock(&path.dentry->d_inode->i_mutex);
+ dput(path.dentry);
+ path.dentry = dentry;
addr->hash = UNIX_HASH_SIZE;
}
spin_lock(&unix_table_lock);
- if (!sunaddr->sun_path[0]) {
+ if (!sun_path[0]) {
err = -EADDRINUSE;
if (__unix_find_socket_byname(net, sunaddr, addr_len,
sk->sk_type, hash)) {
list = &unix_socket_table[addr->hash];
} else {
list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
- u->dentry = nd.path.dentry;
- u->mnt = nd.path.mnt;
+ u->dentry = path.dentry;
+ u->mnt = path.mnt;
}
err = 0;
out_mknod_dput:
dput(dentry);
-out_mknod_unlock:
- mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
- path_put(&nd.path);
+ mutex_unlock(&path.dentry->d_inode->i_mutex);
+ path_put(&path);
out_mknod_parent:
if (err == -EEXIST)
err = -EADDRINUSE;