Deleted Added
sdiffudifftextold (74d016ec..)new (22e111ed6c83dcde3037fc81176012721bc34c0b)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * linux/fs/namei.c
4 *
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 */
7
8/*

--- 2559 unchanged lines hidden (view full) ---

2568static int filename_parentat(int dfd, struct filename *name,
2569 unsigned int flags, struct path *parent,
2570 struct qstr *last, int *type)
2571{
2572 return __filename_parentat(dfd, name, flags, parent, last, type, NULL);
2573}
2574
2575/* does lookup, returns the object with parent locked */
2576static struct dentry *__kern_path_locked(struct filename *name, struct path *path)
2577{
2578 struct dentry *d;
2579 struct qstr last;
2580 int type, error;
2581
2582 error = filename_parentat(AT_FDCWD, name, 0, path, &last, &type);
2583 if (error)
2584 return ERR_PTR(error);
2585 if (unlikely(type != LAST_NORM)) {
2586 path_put(path);
2587 return ERR_PTR(-EINVAL);
2588 }
2589 inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
2590 d = lookup_one_qstr_excl(&last, path->dentry, 0);
2591 if (IS_ERR(d)) {
2592 inode_unlock(path->dentry->d_inode);
2593 path_put(path);
2594 }
2595 return d;
2596}
2597
2598struct dentry *kern_path_locked(const char *name, struct path *path)
2599{
2600 struct filename *filename = getname_kernel(name);
2601 struct dentry *res = __kern_path_locked(filename, path);
2602
2603 putname(filename);
2604 return res;
2605}
2606
2607int kern_path(const char *name, unsigned int flags, struct path *path)
2608{
2609 struct filename *filename = getname_kernel(name);
2610 int ret = filename_lookup(AT_FDCWD, filename, flags, path, NULL);
2611
2612 putname(filename);
2613 return ret;
2614

--- 401 unchanged lines hidden (view full) ---

3016
3017static struct dentry *lock_two_directories(struct dentry *p1, struct dentry *p2)
3018{
3019 struct dentry *p;
3020
3021 p = d_ancestor(p2, p1);
3022 if (p) {
3023 inode_lock_nested(p2->d_inode, I_MUTEX_PARENT);
3024 inode_lock_nested(p1->d_inode, I_MUTEX_PARENT2);
3025 return p;
3026 }
3027
3028 p = d_ancestor(p1, p2);
3029 inode_lock_nested(p1->d_inode, I_MUTEX_PARENT);
3030 inode_lock_nested(p2->d_inode, I_MUTEX_PARENT2);
3031 return p;
3032}
3033
3034/*
3035 * p1 and p2 should be directories on the same fs.
3036 */
3037struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
3038{
3039 if (p1 == p2) {

--- 1665 unchanged lines hidden (view full) ---

4705 * to be NFS exported.
4706 *
4707 * The worst of all namespace operations - renaming directory. "Perverted"
4708 * doesn't even start to describe it. Somebody in UCB had a heck of a trip...
4709 * Problems:
4710 *
4711 * a) we can get into loop creation.
4712 * b) race potential - two innocent renames can create a loop together.
4713 * That's where 4.4BSD screws up. Current fix: serialization on
4714 * sb->s_vfs_rename_mutex. We might be more accurate, but that's another
4715 * story.
4716 * c) we may have to lock up to _four_ objects - parents and victim (if it exists),
4717 * and source (if it's a non-directory or a subdirectory that moves to
4718 * different parent).
4719 * And that - after we got ->i_mutex on parents (until then we don't know
4720 * whether the target exists). Solution: try to be smart with locking
4721 * order for inodes. We rely on the fact that tree topology may change
4722 * only under ->s_vfs_rename_mutex _and_ that parent of the object we
4723 * move will be locked. Thus we can rank directories by the tree
4724 * (ancestors first) and rank all non-directories after them.
4725 * That works since everybody except rename does "lock parent, lookup,
4726 * lock child" and rename is under ->s_vfs_rename_mutex.

--- 15 unchanged lines hidden (view full) ---

4742 struct inode **delegated_inode = rd->delegated_inode;
4743 unsigned int flags = rd->flags;
4744 bool is_dir = d_is_dir(old_dentry);
4745 struct inode *source = old_dentry->d_inode;
4746 struct inode *target = new_dentry->d_inode;
4747 bool new_is_dir = false;
4748 unsigned max_links = new_dir->i_sb->s_max_links;
4749 struct name_snapshot old_name;
4750 bool lock_old_subdir, lock_new_subdir;
4751
4752 if (source == target)
4753 return 0;
4754
4755 error = may_delete(rd->old_mnt_idmap, old_dir, old_dentry, is_dir);
4756 if (error)
4757 return error;
4758

--- 37 unchanged lines hidden (view full) ---

4796 error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry,
4797 flags);
4798 if (error)
4799 return error;
4800
4801 take_dentry_name_snapshot(&old_name, old_dentry);
4802 dget(new_dentry);
4803 /*
4804 * Lock children.
4805 * The source subdirectory needs to be locked on cross-directory
4806 * rename or cross-directory exchange since its parent changes.
4807 * The target subdirectory needs to be locked on cross-directory
4808 * exchange due to parent change and on any rename due to becoming
4809 * a victim.
4810 * Non-directories need locking in all cases (for NFS reasons);
4811 * they get locked after any subdirectories (in inode address order).
4812 *
4813 * NOTE: WE ONLY LOCK UNRELATED DIRECTORIES IN CROSS-DIRECTORY CASE.
4814 * NEVER, EVER DO THAT WITHOUT ->s_vfs_rename_mutex.
4815 */
4816 lock_old_subdir = new_dir != old_dir;
4817 lock_new_subdir = new_dir != old_dir || !(flags & RENAME_EXCHANGE);
4818 if (is_dir) {
4819 if (lock_old_subdir)
4820 inode_lock_nested(source, I_MUTEX_CHILD);
4821 if (target && (!new_is_dir || lock_new_subdir))
4822 inode_lock(target);
4823 } else if (new_is_dir) {
4824 if (lock_new_subdir)
4825 inode_lock_nested(target, I_MUTEX_CHILD);
4826 inode_lock(source);
4827 } else {
4828 lock_two_nondirectories(source, target);
4829 }
4830
4831 error = -EPERM;
4832 if (IS_SWAPFILE(source) || (target && IS_SWAPFILE(target)))
4833 goto out;
4834
4835 error = -EBUSY;
4836 if (is_local_mountpoint(old_dentry) || is_local_mountpoint(new_dentry))
4837 goto out;

--- 31 unchanged lines hidden (view full) ---

4869 }
4870 if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) {
4871 if (!(flags & RENAME_EXCHANGE))
4872 d_move(old_dentry, new_dentry);
4873 else
4874 d_exchange(old_dentry, new_dentry);
4875 }
4876out:
4877 if (!is_dir || lock_old_subdir)
4878 inode_unlock(source);
4879 if (target && (!new_is_dir || lock_new_subdir))
4880 inode_unlock(target);
4881 dput(new_dentry);
4882 if (!error) {
4883 fsnotify_move(old_dir, new_dir, &old_name.name, is_dir,
4884 !(flags & RENAME_EXCHANGE) ? target : NULL, old_dentry);
4885 if (flags & RENAME_EXCHANGE) {
4886 fsnotify_move(new_dir, old_dir, &old_dentry->d_name,
4887 new_is_dir, NULL, new_dentry);

--- 339 unchanged lines hidden ---