mirror of
https://github.com/torvalds/linux.git
synced 2025-12-01 07:26:02 +07:00
Merge tag 'vfs-6.18-rc1.async' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs async directory updates from Christian Brauner:
"This contains further preparatory changes for the asynchronous directory
locking scheme:
- Add lookup_one_positive_killable() which allows overlayfs to
perform lookup that won't block on a fatal signal
- Unify the mount idmap handling in struct renamedata as a rename can
only happen within a single mount
- Introduce kern_path_parent() for audit which sets the path to the
parent and returns a dentry for the target without holding any
locks on return
- Rename kern_path_locked() as it is only used to prepare for the
removal of an object from the filesystem:
kern_path_locked() => start_removing_path()
kern_path_create() => start_creating_path()
user_path_create() => start_creating_user_path()
user_path_locked_at() => start_removing_user_path_at()
done_path_create() => end_creating_path()
NA => end_removing_path()"
* tag 'vfs-6.18-rc1.async' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
debugfs: rename start_creating() to debugfs_start_creating()
VFS: rename kern_path_locked() and related functions.
VFS/audit: introduce kern_path_parent() for audit
VFS: unify old_mnt_idmap and new_mnt_idmap in renamedata
VFS: discard err2 in filename_create()
VFS/ovl: add lookup_one_positive_killable()
This commit is contained in:
@@ -1285,3 +1285,15 @@ rather than a VMA, as the VMA at this stage is not yet valid.
|
|||||||
The vm_area_desc provides the minimum required information for a filesystem
|
The vm_area_desc provides the minimum required information for a filesystem
|
||||||
to initialise state upon memory mapping of a file-backed region, and output
|
to initialise state upon memory mapping of a file-backed region, and output
|
||||||
parameters for the file system to set this state.
|
parameters for the file system to set this state.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**mandatory**
|
||||||
|
|
||||||
|
Several functions are renamed:
|
||||||
|
|
||||||
|
- kern_path_locked -> start_removing_path
|
||||||
|
- kern_path_create -> start_creating_path
|
||||||
|
- user_path_create -> start_creating_user_path
|
||||||
|
- user_path_locked_at -> start_removing_user_path_at
|
||||||
|
- done_path_create -> end_creating_path
|
||||||
|
|||||||
@@ -67,11 +67,11 @@ static long do_spu_create(const char __user *pathname, unsigned int flags,
|
|||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dentry = user_path_create(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY);
|
dentry = start_creating_user_path(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY);
|
||||||
ret = PTR_ERR(dentry);
|
ret = PTR_ERR(dentry);
|
||||||
if (!IS_ERR(dentry)) {
|
if (!IS_ERR(dentry)) {
|
||||||
ret = spufs_create(&path, dentry, flags, mode, neighbor);
|
ret = spufs_create(&path, dentry, flags, mode, neighbor);
|
||||||
done_path_create(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ static int dev_mkdir(const char *name, umode_t mode)
|
|||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
struct path path;
|
struct path path;
|
||||||
|
|
||||||
dentry = kern_path_create(AT_FDCWD, name, &path, LOOKUP_DIRECTORY);
|
dentry = start_creating_path(AT_FDCWD, name, &path, LOOKUP_DIRECTORY);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ static int dev_mkdir(const char *name, umode_t mode)
|
|||||||
if (!IS_ERR(dentry))
|
if (!IS_ERR(dentry))
|
||||||
/* mark as kernel-created inode */
|
/* mark as kernel-created inode */
|
||||||
d_inode(dentry)->i_private = &thread;
|
d_inode(dentry)->i_private = &thread;
|
||||||
done_path_create(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
return PTR_ERR_OR_ZERO(dentry);
|
return PTR_ERR_OR_ZERO(dentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,10 +222,10 @@ static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
|
|||||||
struct path path;
|
struct path path;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
|
dentry = start_creating_path(AT_FDCWD, nodename, &path, 0);
|
||||||
if (dentry == ERR_PTR(-ENOENT)) {
|
if (dentry == ERR_PTR(-ENOENT)) {
|
||||||
create_path(nodename);
|
create_path(nodename);
|
||||||
dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
|
dentry = start_creating_path(AT_FDCWD, nodename, &path, 0);
|
||||||
}
|
}
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
@@ -246,7 +246,7 @@ static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
|
|||||||
/* mark as kernel-created inode */
|
/* mark as kernel-created inode */
|
||||||
d_inode(dentry)->i_private = &thread;
|
d_inode(dentry)->i_private = &thread;
|
||||||
}
|
}
|
||||||
done_path_create(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +256,7 @@ static int dev_rmdir(const char *name)
|
|||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
dentry = kern_path_locked(name, &parent);
|
dentry = start_removing_path(name, &parent);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
if (d_inode(dentry)->i_private == &thread)
|
if (d_inode(dentry)->i_private == &thread)
|
||||||
@@ -265,9 +265,7 @@ static int dev_rmdir(const char *name)
|
|||||||
else
|
else
|
||||||
err = -EPERM;
|
err = -EPERM;
|
||||||
|
|
||||||
dput(dentry);
|
end_removing_path(&parent, dentry);
|
||||||
inode_unlock(d_inode(parent.dentry));
|
|
||||||
path_put(&parent);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,7 +323,7 @@ static int handle_remove(const char *nodename, struct device *dev)
|
|||||||
int deleted = 0;
|
int deleted = 0;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
dentry = kern_path_locked(nodename, &parent);
|
dentry = start_removing_path(nodename, &parent);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
|
|
||||||
@@ -349,10 +347,8 @@ static int handle_remove(const char *nodename, struct device *dev)
|
|||||||
if (!err || err == -ENOENT)
|
if (!err || err == -ENOENT)
|
||||||
deleted = 1;
|
deleted = 1;
|
||||||
}
|
}
|
||||||
dput(dentry);
|
end_removing_path(&parent, dentry);
|
||||||
inode_unlock(d_inode(parent.dentry));
|
|
||||||
|
|
||||||
path_put(&parent);
|
|
||||||
if (deleted && strchr(nodename, '/'))
|
if (deleted && strchr(nodename, '/'))
|
||||||
delete_path(nodename);
|
delete_path(nodename);
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp,
|
|||||||
snapshot_src = inode_inum(to_bch_ei(src_path.dentry->d_inode));
|
snapshot_src = inode_inum(to_bch_ei(src_path.dentry->d_inode));
|
||||||
}
|
}
|
||||||
|
|
||||||
dst_dentry = user_path_create(arg.dirfd,
|
dst_dentry = start_creating_user_path(arg.dirfd,
|
||||||
(const char __user *)(unsigned long)arg.dst_ptr,
|
(const char __user *)(unsigned long)arg.dst_ptr,
|
||||||
&dst_path, lookup_flags);
|
&dst_path, lookup_flags);
|
||||||
error = PTR_ERR_OR_ZERO(dst_dentry);
|
error = PTR_ERR_OR_ZERO(dst_dentry);
|
||||||
@@ -314,7 +314,7 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp,
|
|||||||
d_instantiate(dst_dentry, &inode->v);
|
d_instantiate(dst_dentry, &inode->v);
|
||||||
fsnotify_mkdir(dir, dst_dentry);
|
fsnotify_mkdir(dir, dst_dentry);
|
||||||
err3:
|
err3:
|
||||||
done_path_create(&dst_path, dst_dentry);
|
end_creating_path(&dst_path, dst_dentry);
|
||||||
err2:
|
err2:
|
||||||
if (arg.src_ptr)
|
if (arg.src_ptr)
|
||||||
path_put(&src_path);
|
path_put(&src_path);
|
||||||
@@ -334,7 +334,7 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
|
|||||||
if (arg.flags)
|
if (arg.flags)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
victim = user_path_locked_at(arg.dirfd, name, &path);
|
victim = start_removing_user_path_at(arg.dirfd, name, &path);
|
||||||
if (IS_ERR(victim))
|
if (IS_ERR(victim))
|
||||||
return PTR_ERR(victim);
|
return PTR_ERR(victim);
|
||||||
|
|
||||||
@@ -351,9 +351,7 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
|
|||||||
d_invalidate(victim);
|
d_invalidate(victim);
|
||||||
}
|
}
|
||||||
err:
|
err:
|
||||||
inode_unlock(dir);
|
end_removing_path(&path, victim);
|
||||||
dput(victim);
|
|
||||||
path_put(&path);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -387,10 +387,9 @@ try_again:
|
|||||||
cachefiles_io_error(cache, "Rename security error %d", ret);
|
cachefiles_io_error(cache, "Rename security error %d", ret);
|
||||||
} else {
|
} else {
|
||||||
struct renamedata rd = {
|
struct renamedata rd = {
|
||||||
.old_mnt_idmap = &nop_mnt_idmap,
|
.mnt_idmap = &nop_mnt_idmap,
|
||||||
.old_parent = dir,
|
.old_parent = dir,
|
||||||
.old_dentry = rep,
|
.old_dentry = rep,
|
||||||
.new_mnt_idmap = &nop_mnt_idmap,
|
|
||||||
.new_parent = cache->graveyard,
|
.new_parent = cache->graveyard,
|
||||||
.new_dentry = grave,
|
.new_dentry = grave,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -362,7 +362,8 @@ struct dentry *debugfs_lookup(const char *name, struct dentry *parent)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(debugfs_lookup);
|
EXPORT_SYMBOL_GPL(debugfs_lookup);
|
||||||
|
|
||||||
static struct dentry *start_creating(const char *name, struct dentry *parent)
|
static struct dentry *debugfs_start_creating(const char *name,
|
||||||
|
struct dentry *parent)
|
||||||
{
|
{
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
int error;
|
int error;
|
||||||
@@ -428,7 +429,7 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
|
|||||||
if (!(mode & S_IFMT))
|
if (!(mode & S_IFMT))
|
||||||
mode |= S_IFREG;
|
mode |= S_IFREG;
|
||||||
BUG_ON(!S_ISREG(mode));
|
BUG_ON(!S_ISREG(mode));
|
||||||
dentry = start_creating(name, parent);
|
dentry = debugfs_start_creating(name, parent);
|
||||||
|
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return dentry;
|
return dentry;
|
||||||
@@ -577,7 +578,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file_size);
|
|||||||
*/
|
*/
|
||||||
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
|
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
|
||||||
{
|
{
|
||||||
struct dentry *dentry = start_creating(name, parent);
|
struct dentry *dentry = debugfs_start_creating(name, parent);
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
|
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
@@ -624,7 +625,7 @@ struct dentry *debugfs_create_automount(const char *name,
|
|||||||
debugfs_automount_t f,
|
debugfs_automount_t f,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct dentry *dentry = start_creating(name, parent);
|
struct dentry *dentry = debugfs_start_creating(name, parent);
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
|
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
@@ -687,7 +688,7 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
|
|||||||
if (!link)
|
if (!link)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
dentry = start_creating(name, parent);
|
dentry = debugfs_start_creating(name, parent);
|
||||||
if (IS_ERR(dentry)) {
|
if (IS_ERR(dentry)) {
|
||||||
kfree(link);
|
kfree(link);
|
||||||
return dentry;
|
return dentry;
|
||||||
|
|||||||
@@ -634,10 +634,9 @@ ecryptfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
|
|||||||
goto out_lock;
|
goto out_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
rd.old_mnt_idmap = &nop_mnt_idmap;
|
rd.mnt_idmap = &nop_mnt_idmap;
|
||||||
rd.old_parent = lower_old_dir_dentry;
|
rd.old_parent = lower_old_dir_dentry;
|
||||||
rd.old_dentry = lower_old_dentry;
|
rd.old_dentry = lower_old_dentry;
|
||||||
rd.new_mnt_idmap = &nop_mnt_idmap;
|
|
||||||
rd.new_parent = lower_new_dir_dentry;
|
rd.new_parent = lower_new_dir_dentry;
|
||||||
rd.new_dentry = lower_new_dentry;
|
rd.new_dentry = lower_new_dentry;
|
||||||
rc = vfs_rename(&rd);
|
rc = vfs_rename(&rd);
|
||||||
|
|||||||
17
fs/init.c
17
fs/init.c
@@ -149,7 +149,7 @@ int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
|
|||||||
else if (!(S_ISBLK(mode) || S_ISCHR(mode)))
|
else if (!(S_ISBLK(mode) || S_ISCHR(mode)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
dentry = kern_path_create(AT_FDCWD, filename, &path, 0);
|
dentry = start_creating_path(AT_FDCWD, filename, &path, 0);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
|
|||||||
if (!error)
|
if (!error)
|
||||||
error = vfs_mknod(mnt_idmap(path.mnt), path.dentry->d_inode,
|
error = vfs_mknod(mnt_idmap(path.mnt), path.dentry->d_inode,
|
||||||
dentry, mode, new_decode_dev(dev));
|
dentry, mode, new_decode_dev(dev));
|
||||||
done_path_create(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ int __init init_link(const char *oldname, const char *newname)
|
|||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
new_dentry = kern_path_create(AT_FDCWD, newname, &new_path, 0);
|
new_dentry = start_creating_path(AT_FDCWD, newname, &new_path, 0);
|
||||||
error = PTR_ERR(new_dentry);
|
error = PTR_ERR(new_dentry);
|
||||||
if (IS_ERR(new_dentry))
|
if (IS_ERR(new_dentry))
|
||||||
goto out;
|
goto out;
|
||||||
@@ -191,7 +191,7 @@ int __init init_link(const char *oldname, const char *newname)
|
|||||||
error = vfs_link(old_path.dentry, idmap, new_path.dentry->d_inode,
|
error = vfs_link(old_path.dentry, idmap, new_path.dentry->d_inode,
|
||||||
new_dentry, NULL);
|
new_dentry, NULL);
|
||||||
out_dput:
|
out_dput:
|
||||||
done_path_create(&new_path, new_dentry);
|
end_creating_path(&new_path, new_dentry);
|
||||||
out:
|
out:
|
||||||
path_put(&old_path);
|
path_put(&old_path);
|
||||||
return error;
|
return error;
|
||||||
@@ -203,14 +203,14 @@ int __init init_symlink(const char *oldname, const char *newname)
|
|||||||
struct path path;
|
struct path path;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
dentry = kern_path_create(AT_FDCWD, newname, &path, 0);
|
dentry = start_creating_path(AT_FDCWD, newname, &path, 0);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
error = security_path_symlink(&path, dentry, oldname);
|
error = security_path_symlink(&path, dentry, oldname);
|
||||||
if (!error)
|
if (!error)
|
||||||
error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode,
|
error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode,
|
||||||
dentry, oldname);
|
dentry, oldname);
|
||||||
done_path_create(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +225,8 @@ int __init init_mkdir(const char *pathname, umode_t mode)
|
|||||||
struct path path;
|
struct path path;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
dentry = kern_path_create(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY);
|
dentry = start_creating_path(AT_FDCWD, pathname, &path,
|
||||||
|
LOOKUP_DIRECTORY);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
mode = mode_strip_umask(d_inode(path.dentry), mode);
|
mode = mode_strip_umask(d_inode(path.dentry), mode);
|
||||||
@@ -236,7 +237,7 @@ int __init init_mkdir(const char *pathname, umode_t mode)
|
|||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
error = PTR_ERR(dentry);
|
error = PTR_ERR(dentry);
|
||||||
}
|
}
|
||||||
done_path_create(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
160
fs/namei.c
160
fs/namei.c
@@ -1835,6 +1835,20 @@ static struct dentry *lookup_slow(const struct qstr *name,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct dentry *lookup_slow_killable(const struct qstr *name,
|
||||||
|
struct dentry *dir,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
struct inode *inode = dir->d_inode;
|
||||||
|
struct dentry *res;
|
||||||
|
|
||||||
|
if (inode_lock_shared_killable(inode))
|
||||||
|
return ERR_PTR(-EINTR);
|
||||||
|
res = __lookup_slow(name, dir, flags);
|
||||||
|
inode_unlock_shared(inode);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int may_lookup(struct mnt_idmap *idmap,
|
static inline int may_lookup(struct mnt_idmap *idmap,
|
||||||
struct nameidata *restrict nd)
|
struct nameidata *restrict nd)
|
||||||
{
|
{
|
||||||
@@ -2752,7 +2766,8 @@ static int filename_parentat(int dfd, struct filename *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* does lookup, returns the object with parent locked */
|
/* does lookup, returns the object with parent locked */
|
||||||
static struct dentry *__kern_path_locked(int dfd, struct filename *name, struct path *path)
|
static struct dentry *__start_removing_path(int dfd, struct filename *name,
|
||||||
|
struct path *path)
|
||||||
{
|
{
|
||||||
struct path parent_path __free(path_put) = {};
|
struct path parent_path __free(path_put) = {};
|
||||||
struct dentry *d;
|
struct dentry *d;
|
||||||
@@ -2764,18 +2779,42 @@ static struct dentry *__kern_path_locked(int dfd, struct filename *name, struct
|
|||||||
return ERR_PTR(error);
|
return ERR_PTR(error);
|
||||||
if (unlikely(type != LAST_NORM))
|
if (unlikely(type != LAST_NORM))
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
/* don't fail immediately if it's r/o, at least try to report other errors */
|
||||||
|
error = mnt_want_write(parent_path.mnt);
|
||||||
inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
|
inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
|
||||||
d = lookup_one_qstr_excl(&last, parent_path.dentry, 0);
|
d = lookup_one_qstr_excl(&last, parent_path.dentry, 0);
|
||||||
if (IS_ERR(d)) {
|
if (IS_ERR(d))
|
||||||
inode_unlock(parent_path.dentry->d_inode);
|
goto unlock;
|
||||||
return d;
|
if (error)
|
||||||
}
|
goto fail;
|
||||||
path->dentry = no_free_ptr(parent_path.dentry);
|
path->dentry = no_free_ptr(parent_path.dentry);
|
||||||
path->mnt = no_free_ptr(parent_path.mnt);
|
path->mnt = no_free_ptr(parent_path.mnt);
|
||||||
return d;
|
return d;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
dput(d);
|
||||||
|
d = ERR_PTR(error);
|
||||||
|
unlock:
|
||||||
|
inode_unlock(parent_path.dentry->d_inode);
|
||||||
|
if (!error)
|
||||||
|
mnt_drop_write(parent_path.mnt);
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dentry *kern_path_locked_negative(const char *name, struct path *path)
|
/**
|
||||||
|
* kern_path_parent: lookup path returning parent and target
|
||||||
|
* @name: path name
|
||||||
|
* @path: path to store parent in
|
||||||
|
*
|
||||||
|
* The path @name should end with a normal component, not "." or ".." or "/".
|
||||||
|
* A lookup is performed and if successful the parent information
|
||||||
|
* is store in @parent and the dentry is returned.
|
||||||
|
*
|
||||||
|
* The dentry maybe negative, the parent will be positive.
|
||||||
|
*
|
||||||
|
* Returns: dentry or error.
|
||||||
|
*/
|
||||||
|
struct dentry *kern_path_parent(const char *name, struct path *path)
|
||||||
{
|
{
|
||||||
struct path parent_path __free(path_put) = {};
|
struct path parent_path __free(path_put) = {};
|
||||||
struct filename *filename __free(putname) = getname_kernel(name);
|
struct filename *filename __free(putname) = getname_kernel(name);
|
||||||
@@ -2788,35 +2827,35 @@ struct dentry *kern_path_locked_negative(const char *name, struct path *path)
|
|||||||
return ERR_PTR(error);
|
return ERR_PTR(error);
|
||||||
if (unlikely(type != LAST_NORM))
|
if (unlikely(type != LAST_NORM))
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
|
|
||||||
d = lookup_one_qstr_excl(&last, parent_path.dentry, LOOKUP_CREATE);
|
d = lookup_noperm_unlocked(&last, parent_path.dentry);
|
||||||
if (IS_ERR(d)) {
|
if (IS_ERR(d))
|
||||||
inode_unlock(parent_path.dentry->d_inode);
|
|
||||||
return d;
|
return d;
|
||||||
}
|
|
||||||
path->dentry = no_free_ptr(parent_path.dentry);
|
path->dentry = no_free_ptr(parent_path.dentry);
|
||||||
path->mnt = no_free_ptr(parent_path.mnt);
|
path->mnt = no_free_ptr(parent_path.mnt);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dentry *kern_path_locked(const char *name, struct path *path)
|
struct dentry *start_removing_path(const char *name, struct path *path)
|
||||||
{
|
{
|
||||||
struct filename *filename = getname_kernel(name);
|
struct filename *filename = getname_kernel(name);
|
||||||
struct dentry *res = __kern_path_locked(AT_FDCWD, filename, path);
|
struct dentry *res = __start_removing_path(AT_FDCWD, filename, path);
|
||||||
|
|
||||||
putname(filename);
|
putname(filename);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dentry *user_path_locked_at(int dfd, const char __user *name, struct path *path)
|
struct dentry *start_removing_user_path_at(int dfd,
|
||||||
|
const char __user *name,
|
||||||
|
struct path *path)
|
||||||
{
|
{
|
||||||
struct filename *filename = getname(name);
|
struct filename *filename = getname(name);
|
||||||
struct dentry *res = __kern_path_locked(dfd, filename, path);
|
struct dentry *res = __start_removing_path(dfd, filename, path);
|
||||||
|
|
||||||
putname(filename);
|
putname(filename);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(user_path_locked_at);
|
EXPORT_SYMBOL(start_removing_user_path_at);
|
||||||
|
|
||||||
int kern_path(const char *name, unsigned int flags, struct path *path)
|
int kern_path(const char *name, unsigned int flags, struct path *path)
|
||||||
{
|
{
|
||||||
@@ -3018,6 +3057,47 @@ struct dentry *lookup_one_unlocked(struct mnt_idmap *idmap, struct qstr *name,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(lookup_one_unlocked);
|
EXPORT_SYMBOL(lookup_one_unlocked);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lookup_one_positive_killable - lookup single pathname component
|
||||||
|
* @idmap: idmap of the mount the lookup is performed from
|
||||||
|
* @name: qstr olding pathname component to lookup
|
||||||
|
* @base: base directory to lookup from
|
||||||
|
*
|
||||||
|
* This helper will yield ERR_PTR(-ENOENT) on negatives. The helper returns
|
||||||
|
* known positive or ERR_PTR(). This is what most of the users want.
|
||||||
|
*
|
||||||
|
* Note that pinned negative with unlocked parent _can_ become positive at any
|
||||||
|
* time, so callers of lookup_one_unlocked() need to be very careful; pinned
|
||||||
|
* positives have >d_inode stable, so this one avoids such problems.
|
||||||
|
*
|
||||||
|
* This can be used for in-kernel filesystem clients such as file servers.
|
||||||
|
*
|
||||||
|
* It should be called without the parent i_rwsem held, and will take
|
||||||
|
* the i_rwsem itself if necessary. If a fatal signal is pending or
|
||||||
|
* delivered, it will return %-EINTR if the lock is needed.
|
||||||
|
*/
|
||||||
|
struct dentry *lookup_one_positive_killable(struct mnt_idmap *idmap,
|
||||||
|
struct qstr *name,
|
||||||
|
struct dentry *base)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct dentry *ret;
|
||||||
|
|
||||||
|
err = lookup_one_common(idmap, name, base);
|
||||||
|
if (err)
|
||||||
|
return ERR_PTR(err);
|
||||||
|
|
||||||
|
ret = lookup_dcache(name, base, 0);
|
||||||
|
if (!ret)
|
||||||
|
ret = lookup_slow_killable(name, base, 0);
|
||||||
|
if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) {
|
||||||
|
dput(ret);
|
||||||
|
ret = ERR_PTR(-ENOENT);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(lookup_one_positive_killable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lookup_one_positive_unlocked - lookup single pathname component
|
* lookup_one_positive_unlocked - lookup single pathname component
|
||||||
* @idmap: idmap of the mount the lookup is performed from
|
* @idmap: idmap of the mount the lookup is performed from
|
||||||
@@ -4122,7 +4202,6 @@ static struct dentry *filename_create(int dfd, struct filename *name,
|
|||||||
unsigned int reval_flag = lookup_flags & LOOKUP_REVAL;
|
unsigned int reval_flag = lookup_flags & LOOKUP_REVAL;
|
||||||
unsigned int create_flags = LOOKUP_CREATE | LOOKUP_EXCL;
|
unsigned int create_flags = LOOKUP_CREATE | LOOKUP_EXCL;
|
||||||
int type;
|
int type;
|
||||||
int err2;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = filename_parentat(dfd, name, reval_flag, path, &last, &type);
|
error = filename_parentat(dfd, name, reval_flag, path, &last, &type);
|
||||||
@@ -4137,7 +4216,7 @@ static struct dentry *filename_create(int dfd, struct filename *name,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* don't fail immediately if it's r/o, at least try to report other errors */
|
/* don't fail immediately if it's r/o, at least try to report other errors */
|
||||||
err2 = mnt_want_write(path->mnt);
|
error = mnt_want_write(path->mnt);
|
||||||
/*
|
/*
|
||||||
* Do the final lookup. Suppress 'create' if there is a trailing
|
* Do the final lookup. Suppress 'create' if there is a trailing
|
||||||
* '/', and a directory wasn't requested.
|
* '/', and a directory wasn't requested.
|
||||||
@@ -4150,24 +4229,23 @@ static struct dentry *filename_create(int dfd, struct filename *name,
|
|||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
if (unlikely(err2)) {
|
if (unlikely(error))
|
||||||
error = err2;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
|
||||||
return dentry;
|
return dentry;
|
||||||
fail:
|
fail:
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
dentry = ERR_PTR(error);
|
dentry = ERR_PTR(error);
|
||||||
unlock:
|
unlock:
|
||||||
inode_unlock(path->dentry->d_inode);
|
inode_unlock(path->dentry->d_inode);
|
||||||
if (!err2)
|
if (!error)
|
||||||
mnt_drop_write(path->mnt);
|
mnt_drop_write(path->mnt);
|
||||||
out:
|
out:
|
||||||
path_put(path);
|
path_put(path);
|
||||||
return dentry;
|
return dentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dentry *kern_path_create(int dfd, const char *pathname,
|
struct dentry *start_creating_path(int dfd, const char *pathname,
|
||||||
struct path *path, unsigned int lookup_flags)
|
struct path *path, unsigned int lookup_flags)
|
||||||
{
|
{
|
||||||
struct filename *filename = getname_kernel(pathname);
|
struct filename *filename = getname_kernel(pathname);
|
||||||
@@ -4176,9 +4254,9 @@ struct dentry *kern_path_create(int dfd, const char *pathname,
|
|||||||
putname(filename);
|
putname(filename);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kern_path_create);
|
EXPORT_SYMBOL(start_creating_path);
|
||||||
|
|
||||||
void done_path_create(struct path *path, struct dentry *dentry)
|
void end_creating_path(struct path *path, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
if (!IS_ERR(dentry))
|
if (!IS_ERR(dentry))
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
@@ -4186,9 +4264,10 @@ void done_path_create(struct path *path, struct dentry *dentry)
|
|||||||
mnt_drop_write(path->mnt);
|
mnt_drop_write(path->mnt);
|
||||||
path_put(path);
|
path_put(path);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(done_path_create);
|
EXPORT_SYMBOL(end_creating_path);
|
||||||
|
|
||||||
inline struct dentry *user_path_create(int dfd, const char __user *pathname,
|
inline struct dentry *start_creating_user_path(
|
||||||
|
int dfd, const char __user *pathname,
|
||||||
struct path *path, unsigned int lookup_flags)
|
struct path *path, unsigned int lookup_flags)
|
||||||
{
|
{
|
||||||
struct filename *filename = getname(pathname);
|
struct filename *filename = getname(pathname);
|
||||||
@@ -4197,7 +4276,7 @@ inline struct dentry *user_path_create(int dfd, const char __user *pathname,
|
|||||||
putname(filename);
|
putname(filename);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(user_path_create);
|
EXPORT_SYMBOL(start_creating_user_path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vfs_mknod - create device node or file
|
* vfs_mknod - create device node or file
|
||||||
@@ -4305,7 +4384,7 @@ retry:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
out2:
|
out2:
|
||||||
done_path_create(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
if (retry_estale(error, lookup_flags)) {
|
if (retry_estale(error, lookup_flags)) {
|
||||||
lookup_flags |= LOOKUP_REVAL;
|
lookup_flags |= LOOKUP_REVAL;
|
||||||
goto retry;
|
goto retry;
|
||||||
@@ -4409,7 +4488,7 @@ retry:
|
|||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
error = PTR_ERR(dentry);
|
error = PTR_ERR(dentry);
|
||||||
}
|
}
|
||||||
done_path_create(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
if (retry_estale(error, lookup_flags)) {
|
if (retry_estale(error, lookup_flags)) {
|
||||||
lookup_flags |= LOOKUP_REVAL;
|
lookup_flags |= LOOKUP_REVAL;
|
||||||
goto retry;
|
goto retry;
|
||||||
@@ -4763,7 +4842,7 @@ retry:
|
|||||||
if (!error)
|
if (!error)
|
||||||
error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode,
|
error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode,
|
||||||
dentry, from->name);
|
dentry, from->name);
|
||||||
done_path_create(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
if (retry_estale(error, lookup_flags)) {
|
if (retry_estale(error, lookup_flags)) {
|
||||||
lookup_flags |= LOOKUP_REVAL;
|
lookup_flags |= LOOKUP_REVAL;
|
||||||
goto retry;
|
goto retry;
|
||||||
@@ -4932,7 +5011,7 @@ retry:
|
|||||||
error = vfs_link(old_path.dentry, idmap, new_path.dentry->d_inode,
|
error = vfs_link(old_path.dentry, idmap, new_path.dentry->d_inode,
|
||||||
new_dentry, &delegated_inode);
|
new_dentry, &delegated_inode);
|
||||||
out_dput:
|
out_dput:
|
||||||
done_path_create(&new_path, new_dentry);
|
end_creating_path(&new_path, new_dentry);
|
||||||
if (delegated_inode) {
|
if (delegated_inode) {
|
||||||
error = break_deleg_wait(&delegated_inode);
|
error = break_deleg_wait(&delegated_inode);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
@@ -5032,20 +5111,20 @@ int vfs_rename(struct renamedata *rd)
|
|||||||
if (source == target)
|
if (source == target)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error = may_delete(rd->old_mnt_idmap, old_dir, old_dentry, is_dir);
|
error = may_delete(rd->mnt_idmap, old_dir, old_dentry, is_dir);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (!target) {
|
if (!target) {
|
||||||
error = may_create(rd->new_mnt_idmap, new_dir, new_dentry);
|
error = may_create(rd->mnt_idmap, new_dir, new_dentry);
|
||||||
} else {
|
} else {
|
||||||
new_is_dir = d_is_dir(new_dentry);
|
new_is_dir = d_is_dir(new_dentry);
|
||||||
|
|
||||||
if (!(flags & RENAME_EXCHANGE))
|
if (!(flags & RENAME_EXCHANGE))
|
||||||
error = may_delete(rd->new_mnt_idmap, new_dir,
|
error = may_delete(rd->mnt_idmap, new_dir,
|
||||||
new_dentry, is_dir);
|
new_dentry, is_dir);
|
||||||
else
|
else
|
||||||
error = may_delete(rd->new_mnt_idmap, new_dir,
|
error = may_delete(rd->mnt_idmap, new_dir,
|
||||||
new_dentry, new_is_dir);
|
new_dentry, new_is_dir);
|
||||||
}
|
}
|
||||||
if (error)
|
if (error)
|
||||||
@@ -5060,13 +5139,13 @@ int vfs_rename(struct renamedata *rd)
|
|||||||
*/
|
*/
|
||||||
if (new_dir != old_dir) {
|
if (new_dir != old_dir) {
|
||||||
if (is_dir) {
|
if (is_dir) {
|
||||||
error = inode_permission(rd->old_mnt_idmap, source,
|
error = inode_permission(rd->mnt_idmap, source,
|
||||||
MAY_WRITE);
|
MAY_WRITE);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
if ((flags & RENAME_EXCHANGE) && new_is_dir) {
|
if ((flags & RENAME_EXCHANGE) && new_is_dir) {
|
||||||
error = inode_permission(rd->new_mnt_idmap, target,
|
error = inode_permission(rd->mnt_idmap, target,
|
||||||
MAY_WRITE);
|
MAY_WRITE);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
@@ -5134,7 +5213,7 @@ int vfs_rename(struct renamedata *rd)
|
|||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
error = old_dir->i_op->rename(rd->new_mnt_idmap, old_dir, old_dentry,
|
error = old_dir->i_op->rename(rd->mnt_idmap, old_dir, old_dentry,
|
||||||
new_dir, new_dentry, flags);
|
new_dir, new_dentry, flags);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -5277,10 +5356,9 @@ retry_deleg:
|
|||||||
|
|
||||||
rd.old_parent = old_path.dentry;
|
rd.old_parent = old_path.dentry;
|
||||||
rd.old_dentry = old_dentry;
|
rd.old_dentry = old_dentry;
|
||||||
rd.old_mnt_idmap = mnt_idmap(old_path.mnt);
|
rd.mnt_idmap = mnt_idmap(old_path.mnt);
|
||||||
rd.new_parent = new_path.dentry;
|
rd.new_parent = new_path.dentry;
|
||||||
rd.new_dentry = new_dentry;
|
rd.new_dentry = new_dentry;
|
||||||
rd.new_mnt_idmap = mnt_idmap(new_path.mnt);
|
|
||||||
rd.delegated_inode = &delegated_inode;
|
rd.delegated_inode = &delegated_inode;
|
||||||
rd.flags = flags;
|
rd.flags = flags;
|
||||||
error = vfs_rename(&rd);
|
error = vfs_rename(&rd);
|
||||||
|
|||||||
@@ -1951,10 +1951,9 @@ retry:
|
|||||||
goto out_dput_old;
|
goto out_dput_old;
|
||||||
} else {
|
} else {
|
||||||
struct renamedata rd = {
|
struct renamedata rd = {
|
||||||
.old_mnt_idmap = &nop_mnt_idmap,
|
.mnt_idmap = &nop_mnt_idmap,
|
||||||
.old_parent = fdentry,
|
.old_parent = fdentry,
|
||||||
.old_dentry = odentry,
|
.old_dentry = odentry,
|
||||||
.new_mnt_idmap = &nop_mnt_idmap,
|
|
||||||
.new_parent = tdentry,
|
.new_parent = tdentry,
|
||||||
.new_dentry = ndentry,
|
.new_dentry = ndentry,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4418,7 +4418,7 @@ int ocfs2_reflink_ioctl(struct inode *inode,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_dentry = user_path_create(AT_FDCWD, newname, &new_path, 0);
|
new_dentry = start_creating_user_path(AT_FDCWD, newname, &new_path, 0);
|
||||||
error = PTR_ERR(new_dentry);
|
error = PTR_ERR(new_dentry);
|
||||||
if (IS_ERR(new_dentry)) {
|
if (IS_ERR(new_dentry)) {
|
||||||
mlog_errno(error);
|
mlog_errno(error);
|
||||||
@@ -4435,7 +4435,7 @@ int ocfs2_reflink_ioctl(struct inode *inode,
|
|||||||
d_inode(new_path.dentry),
|
d_inode(new_path.dentry),
|
||||||
new_dentry, preserve);
|
new_dentry, preserve);
|
||||||
out_dput:
|
out_dput:
|
||||||
done_path_create(&new_path, new_dentry);
|
end_creating_path(&new_path, new_dentry);
|
||||||
out:
|
out:
|
||||||
path_put(&old_path);
|
path_put(&old_path);
|
||||||
|
|
||||||
|
|||||||
@@ -361,10 +361,9 @@ static inline int ovl_do_rename(struct ovl_fs *ofs, struct dentry *olddir,
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
struct renamedata rd = {
|
struct renamedata rd = {
|
||||||
.old_mnt_idmap = ovl_upper_mnt_idmap(ofs),
|
.mnt_idmap = ovl_upper_mnt_idmap(ofs),
|
||||||
.old_parent = olddir,
|
.old_parent = olddir,
|
||||||
.old_dentry = olddentry,
|
.old_dentry = olddentry,
|
||||||
.new_mnt_idmap = ovl_upper_mnt_idmap(ofs),
|
|
||||||
.new_parent = newdir,
|
.new_parent = newdir,
|
||||||
.new_dentry = newdentry,
|
.new_dentry = newdentry,
|
||||||
.flags = flags,
|
.flags = flags,
|
||||||
|
|||||||
@@ -270,27 +270,27 @@ static bool ovl_fill_merge(struct dir_context *ctx, const char *name,
|
|||||||
|
|
||||||
static int ovl_check_whiteouts(const struct path *path, struct ovl_readdir_data *rdd)
|
static int ovl_check_whiteouts(const struct path *path, struct ovl_readdir_data *rdd)
|
||||||
{
|
{
|
||||||
int err;
|
int err = 0;
|
||||||
struct dentry *dentry, *dir = path->dentry;
|
struct dentry *dentry, *dir = path->dentry;
|
||||||
const struct cred *old_cred;
|
const struct cred *old_cred;
|
||||||
|
|
||||||
old_cred = ovl_override_creds(rdd->dentry->d_sb);
|
old_cred = ovl_override_creds(rdd->dentry->d_sb);
|
||||||
|
|
||||||
err = down_write_killable(&dir->d_inode->i_rwsem);
|
|
||||||
if (!err) {
|
|
||||||
while (rdd->first_maybe_whiteout) {
|
while (rdd->first_maybe_whiteout) {
|
||||||
struct ovl_cache_entry *p =
|
struct ovl_cache_entry *p =
|
||||||
rdd->first_maybe_whiteout;
|
rdd->first_maybe_whiteout;
|
||||||
rdd->first_maybe_whiteout = p->next_maybe_whiteout;
|
rdd->first_maybe_whiteout = p->next_maybe_whiteout;
|
||||||
dentry = lookup_one(mnt_idmap(path->mnt),
|
dentry = lookup_one_positive_killable(mnt_idmap(path->mnt),
|
||||||
&QSTR_LEN(p->name, p->len), dir);
|
&QSTR_LEN(p->name, p->len),
|
||||||
|
dir);
|
||||||
if (!IS_ERR(dentry)) {
|
if (!IS_ERR(dentry)) {
|
||||||
p->is_whiteout = ovl_is_whiteout(dentry);
|
p->is_whiteout = ovl_is_whiteout(dentry);
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
|
} else if (PTR_ERR(dentry) == -EINTR) {
|
||||||
|
err = -EINTR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inode_unlock(dir->d_inode);
|
|
||||||
}
|
|
||||||
ovl_revert_creds(old_cred);
|
ovl_revert_creds(old_cred);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
|
|||||||
pr_err("File(%s): creation failed (err:%d)\n", name, err);
|
pr_err("File(%s): creation failed (err:%d)\n", name, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
done_path_create(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +237,7 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
|
|||||||
if (!err && dentry != d)
|
if (!err && dentry != d)
|
||||||
ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(dentry));
|
ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(dentry));
|
||||||
|
|
||||||
done_path_create(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
if (err)
|
if (err)
|
||||||
pr_err("mkdir(%s): creation failed (err:%d)\n", name, err);
|
pr_err("mkdir(%s): creation failed (err:%d)\n", name, err);
|
||||||
return err;
|
return err;
|
||||||
@@ -669,7 +669,7 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
|
|||||||
ksmbd_debug(VFS, "vfs_link failed err %d\n", err);
|
ksmbd_debug(VFS, "vfs_link failed err %d\n", err);
|
||||||
|
|
||||||
out3:
|
out3:
|
||||||
done_path_create(&newpath, dentry);
|
end_creating_path(&newpath, dentry);
|
||||||
out2:
|
out2:
|
||||||
path_put(&oldpath);
|
path_put(&oldpath);
|
||||||
out1:
|
out1:
|
||||||
@@ -770,10 +770,9 @@ retry:
|
|||||||
goto out4;
|
goto out4;
|
||||||
}
|
}
|
||||||
|
|
||||||
rd.old_mnt_idmap = mnt_idmap(old_path->mnt),
|
rd.mnt_idmap = mnt_idmap(old_path->mnt),
|
||||||
rd.old_parent = old_parent,
|
rd.old_parent = old_parent,
|
||||||
rd.old_dentry = old_child,
|
rd.old_dentry = old_child,
|
||||||
rd.new_mnt_idmap = mnt_idmap(new_path.mnt),
|
|
||||||
rd.new_parent = new_path.dentry,
|
rd.new_parent = new_path.dentry,
|
||||||
rd.new_dentry = new_dentry,
|
rd.new_dentry = new_dentry,
|
||||||
rd.flags = flags,
|
rd.flags = flags,
|
||||||
@@ -1326,7 +1325,7 @@ struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
|
|||||||
if (!abs_name)
|
if (!abs_name)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
dent = kern_path_create(AT_FDCWD, abs_name, path, flags);
|
dent = start_creating_path(AT_FDCWD, abs_name, path, flags);
|
||||||
kfree(abs_name);
|
kfree(abs_name);
|
||||||
return dent;
|
return dent;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2118,20 +2118,18 @@ int vfs_unlink(struct mnt_idmap *, struct inode *, struct dentry *,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* struct renamedata - contains all information required for renaming
|
* struct renamedata - contains all information required for renaming
|
||||||
* @old_mnt_idmap: idmap of the old mount the inode was found from
|
* @mnt_idmap: idmap of the mount in which the rename is happening.
|
||||||
* @old_parent: parent of source
|
* @old_parent: parent of source
|
||||||
* @old_dentry: source
|
* @old_dentry: source
|
||||||
* @new_mnt_idmap: idmap of the new mount the inode was found from
|
|
||||||
* @new_parent: parent of destination
|
* @new_parent: parent of destination
|
||||||
* @new_dentry: destination
|
* @new_dentry: destination
|
||||||
* @delegated_inode: returns an inode needing a delegation break
|
* @delegated_inode: returns an inode needing a delegation break
|
||||||
* @flags: rename flags
|
* @flags: rename flags
|
||||||
*/
|
*/
|
||||||
struct renamedata {
|
struct renamedata {
|
||||||
struct mnt_idmap *old_mnt_idmap;
|
struct mnt_idmap *mnt_idmap;
|
||||||
struct dentry *old_parent;
|
struct dentry *old_parent;
|
||||||
struct dentry *old_dentry;
|
struct dentry *old_dentry;
|
||||||
struct mnt_idmap *new_mnt_idmap;
|
|
||||||
struct dentry *new_parent;
|
struct dentry *new_parent;
|
||||||
struct dentry *new_dentry;
|
struct dentry *new_dentry;
|
||||||
struct inode **delegated_inode;
|
struct inode **delegated_inode;
|
||||||
|
|||||||
@@ -57,13 +57,17 @@ struct dentry *lookup_one_qstr_excl(const struct qstr *name,
|
|||||||
struct dentry *base,
|
struct dentry *base,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
extern int kern_path(const char *, unsigned, struct path *);
|
extern int kern_path(const char *, unsigned, struct path *);
|
||||||
|
struct dentry *kern_path_parent(const char *name, struct path *parent);
|
||||||
|
|
||||||
extern struct dentry *kern_path_create(int, const char *, struct path *, unsigned int);
|
extern struct dentry *start_creating_path(int, const char *, struct path *, unsigned int);
|
||||||
extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int);
|
extern struct dentry *start_creating_user_path(int, const char __user *, struct path *, unsigned int);
|
||||||
extern void done_path_create(struct path *, struct dentry *);
|
extern void end_creating_path(struct path *, struct dentry *);
|
||||||
extern struct dentry *kern_path_locked(const char *, struct path *);
|
extern struct dentry *start_removing_path(const char *, struct path *);
|
||||||
extern struct dentry *kern_path_locked_negative(const char *, struct path *);
|
extern struct dentry *start_removing_user_path_at(int , const char __user *, struct path *);
|
||||||
extern struct dentry *user_path_locked_at(int , const char __user *, struct path *);
|
static inline void end_removing_path(struct path *path , struct dentry *dentry)
|
||||||
|
{
|
||||||
|
end_creating_path(path, dentry);
|
||||||
|
}
|
||||||
int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
|
int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
|
||||||
struct path *parent, struct qstr *last, int *type,
|
struct path *parent, struct qstr *last, int *type,
|
||||||
const struct path *root);
|
const struct path *root);
|
||||||
@@ -80,6 +84,9 @@ struct dentry *lookup_one_unlocked(struct mnt_idmap *idmap,
|
|||||||
struct dentry *lookup_one_positive_unlocked(struct mnt_idmap *idmap,
|
struct dentry *lookup_one_positive_unlocked(struct mnt_idmap *idmap,
|
||||||
struct qstr *name,
|
struct qstr *name,
|
||||||
struct dentry *base);
|
struct dentry *base);
|
||||||
|
struct dentry *lookup_one_positive_killable(struct mnt_idmap *idmap,
|
||||||
|
struct qstr *name,
|
||||||
|
struct dentry *base);
|
||||||
|
|
||||||
extern int follow_down_one(struct path *);
|
extern int follow_down_one(struct path *);
|
||||||
extern int follow_down(struct path *path, unsigned int flags);
|
extern int follow_down(struct path *path, unsigned int flags);
|
||||||
|
|||||||
@@ -76,17 +76,18 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pa
|
|||||||
struct audit_fsnotify_mark *audit_mark;
|
struct audit_fsnotify_mark *audit_mark;
|
||||||
struct path path;
|
struct path path;
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
struct inode *inode;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (pathname[0] != '/' || pathname[len-1] == '/')
|
if (pathname[0] != '/' || pathname[len-1] == '/')
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
dentry = kern_path_locked(pathname, &path);
|
dentry = kern_path_parent(pathname, &path);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return ERR_CAST(dentry); /* returning an error */
|
return ERR_CAST(dentry); /* returning an error */
|
||||||
inode = path.dentry->d_inode;
|
if (d_really_is_negative(dentry)) {
|
||||||
inode_unlock(inode);
|
audit_mark = ERR_PTR(-ENOENT);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL);
|
audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL);
|
||||||
if (unlikely(!audit_mark)) {
|
if (unlikely(!audit_mark)) {
|
||||||
@@ -100,7 +101,7 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pa
|
|||||||
audit_update_mark(audit_mark, dentry->d_inode);
|
audit_update_mark(audit_mark, dentry->d_inode);
|
||||||
audit_mark->rule = krule;
|
audit_mark->rule = krule;
|
||||||
|
|
||||||
ret = fsnotify_add_inode_mark(&audit_mark->mark, inode, 0);
|
ret = fsnotify_add_inode_mark(&audit_mark->mark, path.dentry->d_inode, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
audit_mark->path = NULL;
|
audit_mark->path = NULL;
|
||||||
fsnotify_put_mark(&audit_mark->mark);
|
fsnotify_put_mark(&audit_mark->mark);
|
||||||
|
|||||||
@@ -349,7 +349,7 @@ static int audit_get_nd(struct audit_watch *watch, struct path *parent)
|
|||||||
{
|
{
|
||||||
struct dentry *d;
|
struct dentry *d;
|
||||||
|
|
||||||
d = kern_path_locked_negative(watch->path, parent);
|
d = kern_path_parent(watch->path, parent);
|
||||||
if (IS_ERR(d))
|
if (IS_ERR(d))
|
||||||
return PTR_ERR(d);
|
return PTR_ERR(d);
|
||||||
|
|
||||||
@@ -359,7 +359,6 @@ static int audit_get_nd(struct audit_watch *watch, struct path *parent)
|
|||||||
watch->ino = d_backing_inode(d)->i_ino;
|
watch->ino = d_backing_inode(d)->i_ino;
|
||||||
}
|
}
|
||||||
|
|
||||||
inode_unlock(d_backing_inode(parent->dentry));
|
|
||||||
dput(d);
|
dput(d);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -442,7 +442,7 @@ static int bpf_obj_do_pin(int path_fd, const char __user *pathname, void *raw,
|
|||||||
umode_t mode;
|
umode_t mode;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dentry = user_path_create(path_fd, pathname, &path, 0);
|
dentry = start_creating_user_path(path_fd, pathname, &path, 0);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
|
|
||||||
@@ -471,7 +471,7 @@ static int bpf_obj_do_pin(int path_fd, const char __user *pathname, void *raw,
|
|||||||
ret = -EPERM;
|
ret = -EPERM;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
done_path_create(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1387,7 +1387,7 @@ static int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr,
|
|||||||
* Get the parent directory, calculate the hash for last
|
* Get the parent directory, calculate the hash for last
|
||||||
* component.
|
* component.
|
||||||
*/
|
*/
|
||||||
dentry = kern_path_create(AT_FDCWD, addr->name->sun_path, &parent, 0);
|
dentry = start_creating_path(AT_FDCWD, addr->name->sun_path, &parent, 0);
|
||||||
if (IS_ERR(dentry)) {
|
if (IS_ERR(dentry)) {
|
||||||
err = PTR_ERR(dentry);
|
err = PTR_ERR(dentry);
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1417,7 +1417,7 @@ static int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr,
|
|||||||
unix_table_double_unlock(net, old_hash, new_hash);
|
unix_table_double_unlock(net, old_hash, new_hash);
|
||||||
unix_insert_bsd_socket(sk);
|
unix_insert_bsd_socket(sk);
|
||||||
mutex_unlock(&u->bindlock);
|
mutex_unlock(&u->bindlock);
|
||||||
done_path_create(&parent, dentry);
|
end_creating_path(&parent, dentry);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
@@ -1427,7 +1427,7 @@ out_unlink:
|
|||||||
/* failed after successful mknod? unlink what we'd created... */
|
/* failed after successful mknod? unlink what we'd created... */
|
||||||
vfs_unlink(idmap, d_inode(parent.dentry), dentry, NULL);
|
vfs_unlink(idmap, d_inode(parent.dentry), dentry, NULL);
|
||||||
out_path:
|
out_path:
|
||||||
done_path_create(&parent, dentry);
|
end_creating_path(&parent, dentry);
|
||||||
out:
|
out:
|
||||||
unix_release_addr(addr);
|
unix_release_addr(addr);
|
||||||
return err == -EEXIST ? -EADDRINUSE : err;
|
return err == -EEXIST ? -EADDRINUSE : err;
|
||||||
|
|||||||
Reference in New Issue
Block a user