diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-04 17:03:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-04 17:03:05 -0400 |
commit | 7df934526c0b3775613502dcd19ab6d2da8cce1e (patch) | |
tree | 01e6a4ea20c676228f4acefc6ae776d2e52072db | |
parent | 3c83e61e67256e0bb08c46cc2db43b58fd617251 (diff) | |
parent | bd42998a6bcb9b1708dac9ca9876e3d304c16f3d (diff) |
Merge branch 'cross-rename' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull renameat2 system call from Miklos Szeredi:
"This adds a new syscall, renameat2(), which is the same as renameat()
but with a flags argument.
The purpose of extending rename is to add cross-rename, a symmetric
variant of rename, which exchanges the two files. This allows
interesting things, which were not possible before, for example
atomically replacing a directory tree with a symlink, etc... This
also allows overlayfs and friends to operate on whiteouts atomically.
Andy Lutomirski also suggested a "noreplace" flag, which disables the
overwriting behavior of rename.
These two flags, RENAME_EXCHANGE and RENAME_NOREPLACE are only
implemented for ext4 as an example and for testing"
* 'cross-rename' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
ext4: add cross rename support
ext4: rename: split out helper functions
ext4: rename: move EMLINK check up
ext4: rename: create ext4_renament structure for local vars
vfs: add cross-rename
vfs: lock_two_nondirectories: allow directory args
security: add flags to rename hooks
vfs: add RENAME_NOREPLACE flag
vfs: add renameat2 syscall
vfs: rename: use common code for dir and non-dir
vfs: rename: move d_move() up
vfs: add d_is_dir()
-rw-r--r-- | Documentation/filesystems/Locking | 6 | ||||
-rw-r--r-- | Documentation/filesystems/vfs.txt | 16 | ||||
-rw-r--r-- | arch/x86/syscalls/syscall_64.tbl | 1 | ||||
-rw-r--r-- | drivers/staging/lustre/lustre/include/linux/lustre_compat25.h | 4 | ||||
-rw-r--r-- | drivers/staging/lustre/lustre/lvfs/lvfs_linux.c | 2 | ||||
-rw-r--r-- | fs/cachefiles/namei.c | 4 | ||||
-rw-r--r-- | fs/dcache.c | 50 | ||||
-rw-r--r-- | fs/ecryptfs/inode.c | 2 | ||||
-rw-r--r-- | fs/ext4/namei.c | 480 | ||||
-rw-r--r-- | fs/inode.c | 25 | ||||
-rw-r--r-- | fs/namei.c | 315 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 2 | ||||
-rw-r--r-- | include/linux/dcache.h | 8 | ||||
-rw-r--r-- | include/linux/fs.h | 4 | ||||
-rw-r--r-- | include/linux/security.h | 12 | ||||
-rw-r--r-- | include/uapi/linux/fs.h | 3 | ||||
-rw-r--r-- | security/security.c | 22 |
17 files changed, 643 insertions, 313 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 5b0c083d7c0e..f424e0e5b46b 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
@@ -47,6 +47,8 @@ prototypes: | |||
47 | int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); | 47 | int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); |
48 | int (*rename) (struct inode *, struct dentry *, | 48 | int (*rename) (struct inode *, struct dentry *, |
49 | struct inode *, struct dentry *); | 49 | struct inode *, struct dentry *); |
50 | int (*rename2) (struct inode *, struct dentry *, | ||
51 | struct inode *, struct dentry *, unsigned int); | ||
50 | int (*readlink) (struct dentry *, char __user *,int); | 52 | int (*readlink) (struct dentry *, char __user *,int); |
51 | void * (*follow_link) (struct dentry *, struct nameidata *); | 53 | void * (*follow_link) (struct dentry *, struct nameidata *); |
52 | void (*put_link) (struct dentry *, struct nameidata *, void *); | 54 | void (*put_link) (struct dentry *, struct nameidata *, void *); |
@@ -78,6 +80,7 @@ mkdir: yes | |||
78 | unlink: yes (both) | 80 | unlink: yes (both) |
79 | rmdir: yes (both) (see below) | 81 | rmdir: yes (both) (see below) |
80 | rename: yes (all) (see below) | 82 | rename: yes (all) (see below) |
83 | rename2: yes (all) (see below) | ||
81 | readlink: no | 84 | readlink: no |
82 | follow_link: no | 85 | follow_link: no |
83 | put_link: no | 86 | put_link: no |
@@ -96,7 +99,8 @@ tmpfile: no | |||
96 | 99 | ||
97 | Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on | 100 | Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on |
98 | victim. | 101 | victim. |
99 | cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. | 102 | cross-directory ->rename() and rename2() has (per-superblock) |
103 | ->s_vfs_rename_sem. | ||
100 | 104 | ||
101 | See Documentation/filesystems/directory-locking for more detailed discussion | 105 | See Documentation/filesystems/directory-locking for more detailed discussion |
102 | of the locking scheme for directory operations. | 106 | of the locking scheme for directory operations. |
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index c53784c119c8..94eb86287bcb 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
@@ -347,6 +347,8 @@ struct inode_operations { | |||
347 | int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); | 347 | int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); |
348 | int (*rename) (struct inode *, struct dentry *, | 348 | int (*rename) (struct inode *, struct dentry *, |
349 | struct inode *, struct dentry *); | 349 | struct inode *, struct dentry *); |
350 | int (*rename2) (struct inode *, struct dentry *, | ||
351 | struct inode *, struct dentry *, unsigned int); | ||
350 | int (*readlink) (struct dentry *, char __user *,int); | 352 | int (*readlink) (struct dentry *, char __user *,int); |
351 | void * (*follow_link) (struct dentry *, struct nameidata *); | 353 | void * (*follow_link) (struct dentry *, struct nameidata *); |
352 | void (*put_link) (struct dentry *, struct nameidata *, void *); | 354 | void (*put_link) (struct dentry *, struct nameidata *, void *); |
@@ -414,6 +416,20 @@ otherwise noted. | |||
414 | rename: called by the rename(2) system call to rename the object to | 416 | rename: called by the rename(2) system call to rename the object to |
415 | have the parent and name given by the second inode and dentry. | 417 | have the parent and name given by the second inode and dentry. |
416 | 418 | ||
419 | rename2: this has an additional flags argument compared to rename. | ||
420 | If no flags are supported by the filesystem then this method | ||
421 | need not be implemented. If some flags are supported then the | ||
422 | filesystem must return -EINVAL for any unsupported or unknown | ||
423 | flags. Currently the following flags are implemented: | ||
424 | (1) RENAME_NOREPLACE: this flag indicates that if the target | ||
425 | of the rename exists the rename should fail with -EEXIST | ||
426 | instead of replacing the target. The VFS already checks for | ||
427 | existence, so for local filesystems the RENAME_NOREPLACE | ||
428 | implementation is equivalent to plain rename. | ||
429 | (2) RENAME_EXCHANGE: exchange source and target. Both must | ||
430 | exist; this is checked by the VFS. Unlike plain rename, | ||
431 | source and target may be of different type. | ||
432 | |||
417 | readlink: called by the readlink(2) system call. Only required if | 433 | readlink: called by the readlink(2) system call. Only required if |
418 | you want to support reading symbolic links | 434 | you want to support reading symbolic links |
419 | 435 | ||
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index a12bddc7ccea..04376ac3d9ef 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl | |||
@@ -322,6 +322,7 @@ | |||
322 | 313 common finit_module sys_finit_module | 322 | 313 common finit_module sys_finit_module |
323 | 314 common sched_setattr sys_sched_setattr | 323 | 314 common sched_setattr sys_sched_setattr |
324 | 315 common sched_getattr sys_sched_getattr | 324 | 315 common sched_getattr sys_sched_getattr |
325 | 316 common renameat2 sys_renameat2 | ||
325 | 326 | ||
326 | # | 327 | # |
327 | # x32-specific system call numbers start at 512 to avoid cache impact | 328 | # x32-specific system call numbers start at 512 to avoid cache impact |
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h index eefdb8d061b1..81cc7a0134bb 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h | |||
@@ -105,8 +105,8 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, | |||
105 | #define ll_vfs_unlink(inode,entry,mnt) vfs_unlink(inode,entry) | 105 | #define ll_vfs_unlink(inode,entry,mnt) vfs_unlink(inode,entry) |
106 | #define ll_vfs_mknod(dir,entry,mnt,mode,dev) vfs_mknod(dir,entry,mode,dev) | 106 | #define ll_vfs_mknod(dir,entry,mnt,mode,dev) vfs_mknod(dir,entry,mode,dev) |
107 | #define ll_security_inode_unlink(dir,entry,mnt) security_inode_unlink(dir,entry) | 107 | #define ll_security_inode_unlink(dir,entry,mnt) security_inode_unlink(dir,entry) |
108 | #define ll_vfs_rename(old,old_dir,mnt,new,new_dir,mnt1,delegated_inode) \ | 108 | #define ll_vfs_rename(old, old_dir, mnt, new, new_dir, mnt1) \ |
109 | vfs_rename(old,old_dir,new,new_dir,delegated_inode) | 109 | vfs_rename(old, old_dir, new, new_dir, NULL, 0) |
110 | 110 | ||
111 | #define cfs_bio_io_error(a,b) bio_io_error((a)) | 111 | #define cfs_bio_io_error(a,b) bio_io_error((a)) |
112 | #define cfs_bio_endio(a,b,c) bio_endio((a),(c)) | 112 | #define cfs_bio_endio(a,b,c) bio_endio((a),(c)) |
diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c index e44b7a532de7..374a9b78e1d2 100644 --- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c +++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c | |||
@@ -223,7 +223,7 @@ int lustre_rename(struct dentry *dir, struct vfsmount *mnt, | |||
223 | GOTO(put_old, err = PTR_ERR(dchild_new)); | 223 | GOTO(put_old, err = PTR_ERR(dchild_new)); |
224 | 224 | ||
225 | err = ll_vfs_rename(dir->d_inode, dchild_old, mnt, | 225 | err = ll_vfs_rename(dir->d_inode, dchild_old, mnt, |
226 | dir->d_inode, dchild_new, mnt, NULL); | 226 | dir->d_inode, dchild_new, mnt); |
227 | 227 | ||
228 | dput(dchild_new); | 228 | dput(dchild_new); |
229 | put_old: | 229 | put_old: |
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index ca65f39dc8dc..6494d9f673aa 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c | |||
@@ -391,12 +391,12 @@ try_again: | |||
391 | path.dentry = dir; | 391 | path.dentry = dir; |
392 | path_to_graveyard.mnt = cache->mnt; | 392 | path_to_graveyard.mnt = cache->mnt; |
393 | path_to_graveyard.dentry = cache->graveyard; | 393 | path_to_graveyard.dentry = cache->graveyard; |
394 | ret = security_path_rename(&path, rep, &path_to_graveyard, grave); | 394 | ret = security_path_rename(&path, rep, &path_to_graveyard, grave, 0); |
395 | if (ret < 0) { | 395 | if (ret < 0) { |
396 | cachefiles_io_error(cache, "Rename security error %d", ret); | 396 | cachefiles_io_error(cache, "Rename security error %d", ret); |
397 | } else { | 397 | } else { |
398 | ret = vfs_rename(dir->d_inode, rep, | 398 | ret = vfs_rename(dir->d_inode, rep, |
399 | cache->graveyard->d_inode, grave, NULL); | 399 | cache->graveyard->d_inode, grave, NULL, 0); |
400 | if (ret != 0 && ret != -ENOMEM) | 400 | if (ret != 0 && ret != -ENOMEM) |
401 | cachefiles_io_error(cache, | 401 | cachefiles_io_error(cache, |
402 | "Rename failed with error %d", ret); | 402 | "Rename failed with error %d", ret); |
diff --git a/fs/dcache.c b/fs/dcache.c index ca02c13a84aa..66cba5a8a346 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -2483,12 +2483,14 @@ static void switch_names(struct dentry *dentry, struct dentry *target) | |||
2483 | dentry->d_name.name = dentry->d_iname; | 2483 | dentry->d_name.name = dentry->d_iname; |
2484 | } else { | 2484 | } else { |
2485 | /* | 2485 | /* |
2486 | * Both are internal. Just copy target to dentry | 2486 | * Both are internal. |
2487 | */ | 2487 | */ |
2488 | memcpy(dentry->d_iname, target->d_name.name, | 2488 | unsigned int i; |
2489 | target->d_name.len + 1); | 2489 | BUILD_BUG_ON(!IS_ALIGNED(DNAME_INLINE_LEN, sizeof(long))); |
2490 | dentry->d_name.len = target->d_name.len; | 2490 | for (i = 0; i < DNAME_INLINE_LEN / sizeof(long); i++) { |
2491 | return; | 2491 | swap(((long *) &dentry->d_iname)[i], |
2492 | ((long *) &target->d_iname)[i]); | ||
2493 | } | ||
2492 | } | 2494 | } |
2493 | } | 2495 | } |
2494 | swap(dentry->d_name.len, target->d_name.len); | 2496 | swap(dentry->d_name.len, target->d_name.len); |
@@ -2545,13 +2547,15 @@ static void dentry_unlock_parents_for_move(struct dentry *dentry, | |||
2545 | * __d_move - move a dentry | 2547 | * __d_move - move a dentry |
2546 | * @dentry: entry to move | 2548 | * @dentry: entry to move |
2547 | * @target: new dentry | 2549 | * @target: new dentry |
2550 | * @exchange: exchange the two dentries | ||
2548 | * | 2551 | * |
2549 | * Update the dcache to reflect the move of a file name. Negative | 2552 | * Update the dcache to reflect the move of a file name. Negative |
2550 | * dcache entries should not be moved in this way. Caller must hold | 2553 | * dcache entries should not be moved in this way. Caller must hold |
2551 | * rename_lock, the i_mutex of the source and target directories, | 2554 | * rename_lock, the i_mutex of the source and target directories, |
2552 | * and the sb->s_vfs_rename_mutex if they differ. See lock_rename(). | 2555 | * and the sb->s_vfs_rename_mutex if they differ. See lock_rename(). |
2553 | */ | 2556 | */ |
2554 | static void __d_move(struct dentry * dentry, struct dentry * target) | 2557 | static void __d_move(struct dentry *dentry, struct dentry *target, |
2558 | bool exchange) | ||
2555 | { | 2559 | { |
2556 | if (!dentry->d_inode) | 2560 | if (!dentry->d_inode) |
2557 | printk(KERN_WARNING "VFS: moving negative dcache entry\n"); | 2561 | printk(KERN_WARNING "VFS: moving negative dcache entry\n"); |
@@ -2573,8 +2577,15 @@ static void __d_move(struct dentry * dentry, struct dentry * target) | |||
2573 | __d_drop(dentry); | 2577 | __d_drop(dentry); |
2574 | __d_rehash(dentry, d_hash(target->d_parent, target->d_name.hash)); | 2578 | __d_rehash(dentry, d_hash(target->d_parent, target->d_name.hash)); |
2575 | 2579 | ||
2576 | /* Unhash the target: dput() will then get rid of it */ | 2580 | /* |
2581 | * Unhash the target (d_delete() is not usable here). If exchanging | ||
2582 | * the two dentries, then rehash onto the other's hash queue. | ||
2583 | */ | ||
2577 | __d_drop(target); | 2584 | __d_drop(target); |
2585 | if (exchange) { | ||
2586 | __d_rehash(target, | ||
2587 | d_hash(dentry->d_parent, dentry->d_name.hash)); | ||
2588 | } | ||
2578 | 2589 | ||
2579 | list_del(&dentry->d_u.d_child); | 2590 | list_del(&dentry->d_u.d_child); |
2580 | list_del(&target->d_u.d_child); | 2591 | list_del(&target->d_u.d_child); |
@@ -2601,6 +2612,8 @@ static void __d_move(struct dentry * dentry, struct dentry * target) | |||
2601 | write_seqcount_end(&dentry->d_seq); | 2612 | write_seqcount_end(&dentry->d_seq); |
2602 | 2613 | ||
2603 | dentry_unlock_parents_for_move(dentry, target); | 2614 | dentry_unlock_parents_for_move(dentry, target); |
2615 | if (exchange) | ||
2616 | fsnotify_d_move(target); | ||
2604 | spin_unlock(&target->d_lock); | 2617 | spin_unlock(&target->d_lock); |
2605 | fsnotify_d_move(dentry); | 2618 | fsnotify_d_move(dentry); |
2606 | spin_unlock(&dentry->d_lock); | 2619 | spin_unlock(&dentry->d_lock); |
@@ -2618,11 +2631,30 @@ static void __d_move(struct dentry * dentry, struct dentry * target) | |||
2618 | void d_move(struct dentry *dentry, struct dentry *target) | 2631 | void d_move(struct dentry *dentry, struct dentry *target) |
2619 | { | 2632 | { |
2620 | write_seqlock(&rename_lock); | 2633 | write_seqlock(&rename_lock); |
2621 | __d_move(dentry, target); | 2634 | __d_move(dentry, target, false); |
2622 | write_sequnlock(&rename_lock); | 2635 | write_sequnlock(&rename_lock); |
2623 | } | 2636 | } |
2624 | EXPORT_SYMBOL(d_move); | 2637 | EXPORT_SYMBOL(d_move); |
2625 | 2638 | ||
2639 | /* | ||
2640 | * d_exchange - exchange two dentries | ||
2641 | * @dentry1: first dentry | ||
2642 | * @dentry2: second dentry | ||
2643 | */ | ||
2644 | void d_exchange(struct dentry *dentry1, struct dentry *dentry2) | ||
2645 | { | ||
2646 | write_seqlock(&rename_lock); | ||
2647 | |||
2648 | WARN_ON(!dentry1->d_inode); | ||
2649 | WARN_ON(!dentry2->d_inode); | ||
2650 | WARN_ON(IS_ROOT(dentry1)); | ||
2651 | WARN_ON(IS_ROOT(dentry2)); | ||
2652 | |||
2653 | __d_move(dentry1, dentry2, true); | ||
2654 | |||
2655 | write_sequnlock(&rename_lock); | ||
2656 | } | ||
2657 | |||
2626 | /** | 2658 | /** |
2627 | * d_ancestor - search for an ancestor | 2659 | * d_ancestor - search for an ancestor |
2628 | * @p1: ancestor dentry | 2660 | * @p1: ancestor dentry |
@@ -2670,7 +2702,7 @@ static struct dentry *__d_unalias(struct inode *inode, | |||
2670 | m2 = &alias->d_parent->d_inode->i_mutex; | 2702 | m2 = &alias->d_parent->d_inode->i_mutex; |
2671 | out_unalias: | 2703 | out_unalias: |
2672 | if (likely(!d_mountpoint(alias))) { | 2704 | if (likely(!d_mountpoint(alias))) { |
2673 | __d_move(alias, dentry); | 2705 | __d_move(alias, dentry, false); |
2674 | ret = alias; | 2706 | ret = alias; |
2675 | } | 2707 | } |
2676 | out_err: | 2708 | out_err: |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index b167ca48b8ee..d4a9431ec73c 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -641,7 +641,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
641 | } | 641 | } |
642 | rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, | 642 | rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, |
643 | lower_new_dir_dentry->d_inode, lower_new_dentry, | 643 | lower_new_dir_dentry->d_inode, lower_new_dentry, |
644 | NULL); | 644 | NULL, 0); |
645 | if (rc) | 645 | if (rc) |
646 | goto out_lock; | 646 | goto out_lock; |
647 | if (target_inode) | 647 | if (target_inode) |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index d050e043e884..1cb84f78909e 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -3000,6 +3000,154 @@ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle, | |||
3000 | return ext4_get_first_inline_block(inode, parent_de, retval); | 3000 | return ext4_get_first_inline_block(inode, parent_de, retval); |
3001 | } | 3001 | } |
3002 | 3002 | ||
3003 | struct ext4_renament { | ||
3004 | struct inode *dir; | ||
3005 | struct dentry *dentry; | ||
3006 | struct inode *inode; | ||
3007 | bool is_dir; | ||
3008 | int dir_nlink_delta; | ||
3009 | |||
3010 | /* entry for "dentry" */ | ||
3011 | struct buffer_head *bh; | ||
3012 | struct ext4_dir_entry_2 *de; | ||
3013 | int inlined; | ||
3014 | |||
3015 | /* entry for ".." in inode if it's a directory */ | ||
3016 | struct buffer_head *dir_bh; | ||
3017 | struct ext4_dir_entry_2 *parent_de; | ||
3018 | int dir_inlined; | ||
3019 | }; | ||
3020 | |||
3021 | static int ext4_rename_dir_prepare(handle_t *handle, struct ext4_renament *ent) | ||
3022 | { | ||
3023 | int retval; | ||
3024 | |||
3025 | ent->dir_bh = ext4_get_first_dir_block(handle, ent->inode, | ||
3026 | &retval, &ent->parent_de, | ||
3027 | &ent->dir_inlined); | ||
3028 | if (!ent->dir_bh) | ||
3029 | return retval; | ||
3030 | if (le32_to_cpu(ent->parent_de->inode) != ent->dir->i_ino) | ||
3031 | return -EIO; | ||
3032 | BUFFER_TRACE(ent->dir_bh, "get_write_access"); | ||
3033 | return ext4_journal_get_write_access(handle, ent->dir_bh); | ||
3034 | } | ||
3035 | |||
3036 | static int ext4_rename_dir_finish(handle_t *handle, struct ext4_renament *ent, | ||
3037 | unsigned dir_ino) | ||
3038 | { | ||
3039 | int retval; | ||
3040 | |||
3041 | ent->parent_de->inode = cpu_to_le32(dir_ino); | ||
3042 | BUFFER_TRACE(ent->dir_bh, "call ext4_handle_dirty_metadata"); | ||
3043 | if (!ent->dir_inlined) { | ||
3044 | if (is_dx(ent->inode)) { | ||
3045 | retval = ext4_handle_dirty_dx_node(handle, | ||
3046 | ent->inode, | ||
3047 | ent->dir_bh); | ||
3048 | } else { | ||
3049 | retval = ext4_handle_dirty_dirent_node(handle, | ||
3050 | ent->inode, | ||
3051 | ent->dir_bh); | ||
3052 | } | ||
3053 | } else { | ||
3054 | retval = ext4_mark_inode_dirty(handle, ent->inode); | ||
3055 | } | ||
3056 | if (retval) { | ||
3057 | ext4_std_error(ent->dir->i_sb, retval); | ||
3058 | return retval; | ||
3059 | } | ||
3060 | return 0; | ||
3061 | } | ||
3062 | |||
3063 | static int ext4_setent(handle_t *handle, struct ext4_renament *ent, | ||
3064 | unsigned ino, unsigned file_type) | ||
3065 | { | ||
3066 | int retval; | ||
3067 | |||
3068 | BUFFER_TRACE(ent->bh, "get write access"); | ||
3069 | retval = ext4_journal_get_write_access(handle, ent->bh); | ||
3070 | if (retval) | ||
3071 | return retval; | ||
3072 | ent->de->inode = cpu_to_le32(ino); | ||
3073 | if (EXT4_HAS_INCOMPAT_FEATURE(ent->dir->i_sb, | ||
3074 | EXT4_FEATURE_INCOMPAT_FILETYPE)) | ||
3075 | ent->de->file_type = file_type; | ||
3076 | ent->dir->i_version++; | ||
3077 | ent->dir->i_ctime = ent->dir->i_mtime = | ||
3078 | ext4_current_time(ent->dir); | ||
3079 | ext4_mark_inode_dirty(handle, ent->dir); | ||
3080 | BUFFER_TRACE(ent->bh, "call ext4_handle_dirty_metadata"); | ||
3081 | if (!ent->inlined) { | ||
3082 | retval = ext4_handle_dirty_dirent_node(handle, | ||
3083 | ent->dir, ent->bh); | ||
3084 | if (unlikely(retval)) { | ||
3085 | ext4_std_error(ent->dir->i_sb, retval); | ||
3086 | return retval; | ||
3087 | } | ||
3088 | } | ||
3089 | brelse(ent->bh); | ||
3090 | ent->bh = NULL; | ||
3091 | |||
3092 | return 0; | ||
3093 | } | ||
3094 | |||
3095 | static int ext4_find_delete_entry(handle_t *handle, struct inode *dir, | ||
3096 | const struct qstr *d_name) | ||
3097 | { | ||
3098 | int retval = -ENOENT; | ||
3099 | struct buffer_head *bh; | ||
3100 | struct ext4_dir_entry_2 *de; | ||
3101 | |||
3102 | bh = ext4_find_entry(dir, d_name, &de, NULL); | ||
3103 | if (bh) { | ||
3104 | retval = ext4_delete_entry(handle, dir, de, bh); | ||
3105 | brelse(bh); | ||
3106 | } | ||
3107 | return retval; | ||
3108 | } | ||
3109 | |||
3110 | static void ext4_rename_delete(handle_t *handle, struct ext4_renament *ent) | ||
3111 | { | ||
3112 | int retval; | ||
3113 | /* | ||
3114 | * ent->de could have moved from under us during htree split, so make | ||
3115 | * sure that we are deleting the right entry. We might also be pointing | ||
3116 | * to a stale entry in the unused part of ent->bh so just checking inum | ||
3117 | * and the name isn't enough. | ||
3118 | */ | ||
3119 | if (le32_to_cpu(ent->de->inode) != ent->inode->i_ino || | ||
3120 | ent->de->name_len != ent->dentry->d_name.len || | ||
3121 | strncmp(ent->de->name, ent->dentry->d_name.name, | ||
3122 | ent->de->name_len)) { | ||
3123 | retval = ext4_find_delete_entry(handle, ent->dir, | ||
3124 | &ent->dentry->d_name); | ||
3125 | } else { | ||
3126 | retval = ext4_delete_entry(handle, ent->dir, ent->de, ent->bh); | ||
3127 | if (retval == -ENOENT) { | ||
3128 | retval = ext4_find_delete_entry(handle, ent->dir, | ||
3129 | &ent->dentry->d_name); | ||
3130 | } | ||
3131 | } | ||
3132 | |||
3133 | if (retval) { | ||
3134 | ext4_warning(ent->dir->i_sb, | ||
3135 | "Deleting old file (%lu), %d, error=%d", | ||
3136 | ent->dir->i_ino, ent->dir->i_nlink, retval); | ||
3137 | } | ||
3138 | } | ||
3139 | |||
3140 | static void ext4_update_dir_count(handle_t *handle, struct ext4_renament *ent) | ||
3141 | { | ||
3142 | if (ent->dir_nlink_delta) { | ||
3143 | if (ent->dir_nlink_delta == -1) | ||
3144 | ext4_dec_count(handle, ent->dir); | ||
3145 | else | ||
3146 | ext4_inc_count(handle, ent->dir); | ||
3147 | ext4_mark_inode_dirty(handle, ent->dir); | ||
3148 | } | ||
3149 | } | ||
3150 | |||
3003 | /* | 3151 | /* |
3004 | * Anybody can rename anything with this: the permission checks are left to the | 3152 | * Anybody can rename anything with this: the permission checks are left to the |
3005 | * higher-level routines. | 3153 | * higher-level routines. |
@@ -3012,198 +3160,267 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
3012 | struct inode *new_dir, struct dentry *new_dentry) | 3160 | struct inode *new_dir, struct dentry *new_dentry) |
3013 | { | 3161 | { |
3014 | handle_t *handle = NULL; | 3162 | handle_t *handle = NULL; |
3015 | struct inode *old_inode, *new_inode; | 3163 | struct ext4_renament old = { |
3016 | struct buffer_head *old_bh, *new_bh, *dir_bh; | 3164 | .dir = old_dir, |
3017 | struct ext4_dir_entry_2 *old_de, *new_de; | 3165 | .dentry = old_dentry, |
3166 | .inode = old_dentry->d_inode, | ||
3167 | }; | ||
3168 | struct ext4_renament new = { | ||
3169 | .dir = new_dir, | ||
3170 | .dentry = new_dentry, | ||
3171 | .inode = new_dentry->d_inode, | ||
3172 | }; | ||
3018 | int retval; | 3173 | int retval; |
3019 | int inlined = 0, new_inlined = 0; | ||
3020 | struct ext4_dir_entry_2 *parent_de; | ||
3021 | 3174 | ||
3022 | dquot_initialize(old_dir); | 3175 | dquot_initialize(old.dir); |
3023 | dquot_initialize(new_dir); | 3176 | dquot_initialize(new.dir); |
3024 | |||
3025 | old_bh = new_bh = dir_bh = NULL; | ||
3026 | 3177 | ||
3027 | /* Initialize quotas before so that eventual writes go | 3178 | /* Initialize quotas before so that eventual writes go |
3028 | * in separate transaction */ | 3179 | * in separate transaction */ |
3029 | if (new_dentry->d_inode) | 3180 | if (new.inode) |
3030 | dquot_initialize(new_dentry->d_inode); | 3181 | dquot_initialize(new.inode); |
3031 | 3182 | ||
3032 | old_bh = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de, NULL); | 3183 | old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL); |
3033 | /* | 3184 | /* |
3034 | * Check for inode number is _not_ due to possible IO errors. | 3185 | * Check for inode number is _not_ due to possible IO errors. |
3035 | * We might rmdir the source, keep it as pwd of some process | 3186 | * We might rmdir the source, keep it as pwd of some process |
3036 | * and merrily kill the link to whatever was created under the | 3187 | * and merrily kill the link to whatever was created under the |
3037 | * same name. Goodbye sticky bit ;-< | 3188 | * same name. Goodbye sticky bit ;-< |
3038 | */ | 3189 | */ |
3039 | old_inode = old_dentry->d_inode; | ||
3040 | retval = -ENOENT; | 3190 | retval = -ENOENT; |
3041 | if (!old_bh || le32_to_cpu(old_de->inode) != old_inode->i_ino) | 3191 | if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino) |
3042 | goto end_rename; | 3192 | goto end_rename; |
3043 | 3193 | ||
3044 | new_inode = new_dentry->d_inode; | 3194 | new.bh = ext4_find_entry(new.dir, &new.dentry->d_name, |
3045 | new_bh = ext4_find_entry(new_dir, &new_dentry->d_name, | 3195 | &new.de, &new.inlined); |
3046 | &new_de, &new_inlined); | 3196 | if (new.bh) { |
3047 | if (new_bh) { | 3197 | if (!new.inode) { |
3048 | if (!new_inode) { | 3198 | brelse(new.bh); |
3049 | brelse(new_bh); | 3199 | new.bh = NULL; |
3050 | new_bh = NULL; | ||
3051 | } | 3200 | } |
3052 | } | 3201 | } |
3053 | if (new_inode && !test_opt(new_dir->i_sb, NO_AUTO_DA_ALLOC)) | 3202 | if (new.inode && !test_opt(new.dir->i_sb, NO_AUTO_DA_ALLOC)) |
3054 | ext4_alloc_da_blocks(old_inode); | 3203 | ext4_alloc_da_blocks(old.inode); |
3055 | 3204 | ||
3056 | handle = ext4_journal_start(old_dir, EXT4_HT_DIR, | 3205 | handle = ext4_journal_start(old.dir, EXT4_HT_DIR, |
3057 | (2 * EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) + | 3206 | (2 * EXT4_DATA_TRANS_BLOCKS(old.dir->i_sb) + |
3058 | EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2)); | 3207 | EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2)); |
3059 | if (IS_ERR(handle)) | 3208 | if (IS_ERR(handle)) |
3060 | return PTR_ERR(handle); | 3209 | return PTR_ERR(handle); |
3061 | 3210 | ||
3062 | if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) | 3211 | if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir)) |
3063 | ext4_handle_sync(handle); | 3212 | ext4_handle_sync(handle); |
3064 | 3213 | ||
3065 | if (S_ISDIR(old_inode->i_mode)) { | 3214 | if (S_ISDIR(old.inode->i_mode)) { |
3066 | if (new_inode) { | 3215 | if (new.inode) { |
3067 | retval = -ENOTEMPTY; | 3216 | retval = -ENOTEMPTY; |
3068 | if (!empty_dir(new_inode)) | 3217 | if (!empty_dir(new.inode)) |
3218 | goto end_rename; | ||
3219 | } else { | ||
3220 | retval = -EMLINK; | ||
3221 | if (new.dir != old.dir && EXT4_DIR_LINK_MAX(new.dir)) | ||
3069 | goto end_rename; | 3222 | goto end_rename; |
3070 | } | 3223 | } |
3071 | retval = -EIO; | 3224 | retval = ext4_rename_dir_prepare(handle, &old); |
3072 | dir_bh = ext4_get_first_dir_block(handle, old_inode, | ||
3073 | &retval, &parent_de, | ||
3074 | &inlined); | ||
3075 | if (!dir_bh) | ||
3076 | goto end_rename; | ||
3077 | if (le32_to_cpu(parent_de->inode) != old_dir->i_ino) | ||
3078 | goto end_rename; | ||
3079 | retval = -EMLINK; | ||
3080 | if (!new_inode && new_dir != old_dir && | ||
3081 | EXT4_DIR_LINK_MAX(new_dir)) | ||
3082 | goto end_rename; | ||
3083 | BUFFER_TRACE(dir_bh, "get_write_access"); | ||
3084 | retval = ext4_journal_get_write_access(handle, dir_bh); | ||
3085 | if (retval) | 3225 | if (retval) |
3086 | goto end_rename; | 3226 | goto end_rename; |
3087 | } | 3227 | } |
3088 | if (!new_bh) { | 3228 | if (!new.bh) { |
3089 | retval = ext4_add_entry(handle, new_dentry, old_inode); | 3229 | retval = ext4_add_entry(handle, new.dentry, old.inode); |
3090 | if (retval) | 3230 | if (retval) |
3091 | goto end_rename; | 3231 | goto end_rename; |
3092 | } else { | 3232 | } else { |
3093 | BUFFER_TRACE(new_bh, "get write access"); | 3233 | retval = ext4_setent(handle, &new, |
3094 | retval = ext4_journal_get_write_access(handle, new_bh); | 3234 | old.inode->i_ino, old.de->file_type); |
3095 | if (retval) | 3235 | if (retval) |
3096 | goto end_rename; | 3236 | goto end_rename; |
3097 | new_de->inode = cpu_to_le32(old_inode->i_ino); | ||
3098 | if (EXT4_HAS_INCOMPAT_FEATURE(new_dir->i_sb, | ||
3099 | EXT4_FEATURE_INCOMPAT_FILETYPE)) | ||
3100 | new_de->file_type = old_de->file_type; | ||
3101 | new_dir->i_version++; | ||
3102 | new_dir->i_ctime = new_dir->i_mtime = | ||
3103 | ext4_current_time(new_dir); | ||
3104 | ext4_mark_inode_dirty(handle, new_dir); | ||
3105 | BUFFER_TRACE(new_bh, "call ext4_handle_dirty_metadata"); | ||
3106 | if (!new_inlined) { | ||
3107 | retval = ext4_handle_dirty_dirent_node(handle, | ||
3108 | new_dir, new_bh); | ||
3109 | if (unlikely(retval)) { | ||
3110 | ext4_std_error(new_dir->i_sb, retval); | ||
3111 | goto end_rename; | ||
3112 | } | ||
3113 | } | ||
3114 | brelse(new_bh); | ||
3115 | new_bh = NULL; | ||
3116 | } | 3237 | } |
3117 | 3238 | ||
3118 | /* | 3239 | /* |
3119 | * Like most other Unix systems, set the ctime for inodes on a | 3240 | * Like most other Unix systems, set the ctime for inodes on a |
3120 | * rename. | 3241 | * rename. |
3121 | */ | 3242 | */ |
3122 | old_inode->i_ctime = ext4_current_time(old_inode); | 3243 | old.inode->i_ctime = ext4_current_time(old.inode); |
3123 | ext4_mark_inode_dirty(handle, old_inode); | 3244 | ext4_mark_inode_dirty(handle, old.inode); |
3124 | 3245 | ||
3125 | /* | 3246 | /* |
3126 | * ok, that's it | 3247 | * ok, that's it |
3127 | */ | 3248 | */ |
3128 | if (le32_to_cpu(old_de->inode) != old_inode->i_ino || | 3249 | ext4_rename_delete(handle, &old); |
3129 | old_de->name_len != old_dentry->d_name.len || | 3250 | |
3130 | strncmp(old_de->name, old_dentry->d_name.name, old_de->name_len) || | 3251 | if (new.inode) { |
3131 | (retval = ext4_delete_entry(handle, old_dir, | 3252 | ext4_dec_count(handle, new.inode); |
3132 | old_de, old_bh)) == -ENOENT) { | 3253 | new.inode->i_ctime = ext4_current_time(new.inode); |
3133 | /* old_de could have moved from under us during htree split, so | ||
3134 | * make sure that we are deleting the right entry. We might | ||
3135 | * also be pointing to a stale entry in the unused part of | ||
3136 | * old_bh so just checking inum and the name isn't enough. */ | ||
3137 | struct buffer_head *old_bh2; | ||
3138 | struct ext4_dir_entry_2 *old_de2; | ||
3139 | |||
3140 | old_bh2 = ext4_find_entry(old_dir, &old_dentry->d_name, | ||
3141 | &old_de2, NULL); | ||
3142 | if (old_bh2) { | ||
3143 | retval = ext4_delete_entry(handle, old_dir, | ||
3144 | old_de2, old_bh2); | ||
3145 | brelse(old_bh2); | ||
3146 | } | ||
3147 | } | 3254 | } |
3148 | if (retval) { | 3255 | old.dir->i_ctime = old.dir->i_mtime = ext4_current_time(old.dir); |
3149 | ext4_warning(old_dir->i_sb, | 3256 | ext4_update_dx_flag(old.dir); |
3150 | "Deleting old file (%lu), %d, error=%d", | 3257 | if (old.dir_bh) { |
3151 | old_dir->i_ino, old_dir->i_nlink, retval); | 3258 | retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino); |
3152 | } | 3259 | if (retval) |
3153 | |||
3154 | if (new_inode) { | ||
3155 | ext4_dec_count(handle, new_inode); | ||
3156 | new_inode->i_ctime = ext4_current_time(new_inode); | ||
3157 | } | ||
3158 | old_dir->i_ctime = old_dir->i_mtime = ext4_current_time(old_dir); | ||
3159 | ext4_update_dx_flag(old_dir); | ||
3160 | if (dir_bh) { | ||
3161 | parent_de->inode = cpu_to_le32(new_dir->i_ino); | ||
3162 | BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); | ||
3163 | if (!inlined) { | ||
3164 | if (is_dx(old_inode)) { | ||
3165 | retval = ext4_handle_dirty_dx_node(handle, | ||
3166 | old_inode, | ||
3167 | dir_bh); | ||
3168 | } else { | ||
3169 | retval = ext4_handle_dirty_dirent_node(handle, | ||
3170 | old_inode, dir_bh); | ||
3171 | } | ||
3172 | } else { | ||
3173 | retval = ext4_mark_inode_dirty(handle, old_inode); | ||
3174 | } | ||
3175 | if (retval) { | ||
3176 | ext4_std_error(old_dir->i_sb, retval); | ||
3177 | goto end_rename; | 3260 | goto end_rename; |
3178 | } | 3261 | |
3179 | ext4_dec_count(handle, old_dir); | 3262 | ext4_dec_count(handle, old.dir); |
3180 | if (new_inode) { | 3263 | if (new.inode) { |
3181 | /* checked empty_dir above, can't have another parent, | 3264 | /* checked empty_dir above, can't have another parent, |
3182 | * ext4_dec_count() won't work for many-linked dirs */ | 3265 | * ext4_dec_count() won't work for many-linked dirs */ |
3183 | clear_nlink(new_inode); | 3266 | clear_nlink(new.inode); |
3184 | } else { | 3267 | } else { |
3185 | ext4_inc_count(handle, new_dir); | 3268 | ext4_inc_count(handle, new.dir); |
3186 | ext4_update_dx_flag(new_dir); | 3269 | ext4_update_dx_flag(new.dir); |
3187 | ext4_mark_inode_dirty(handle, new_dir); | 3270 | ext4_mark_inode_dirty(handle, new.dir); |
3188 | } | 3271 | } |
3189 | } | 3272 | } |
3190 | ext4_mark_inode_dirty(handle, old_dir); | 3273 | ext4_mark_inode_dirty(handle, old.dir); |
3191 | if (new_inode) { | 3274 | if (new.inode) { |
3192 | ext4_mark_inode_dirty(handle, new_inode); | 3275 | ext4_mark_inode_dirty(handle, new.inode); |
3193 | if (!new_inode->i_nlink) | 3276 | if (!new.inode->i_nlink) |
3194 | ext4_orphan_add(handle, new_inode); | 3277 | ext4_orphan_add(handle, new.inode); |
3195 | } | 3278 | } |
3196 | retval = 0; | 3279 | retval = 0; |
3197 | 3280 | ||
3198 | end_rename: | 3281 | end_rename: |
3199 | brelse(dir_bh); | 3282 | brelse(old.dir_bh); |
3200 | brelse(old_bh); | 3283 | brelse(old.bh); |
3201 | brelse(new_bh); | 3284 | brelse(new.bh); |
3202 | if (handle) | 3285 | if (handle) |
3203 | ext4_journal_stop(handle); | 3286 | ext4_journal_stop(handle); |
3204 | return retval; | 3287 | return retval; |
3205 | } | 3288 | } |
3206 | 3289 | ||
3290 | static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry, | ||
3291 | struct inode *new_dir, struct dentry *new_dentry) | ||
3292 | { | ||
3293 | handle_t *handle = NULL; | ||
3294 | struct ext4_renament old = { | ||
3295 | .dir = old_dir, | ||
3296 | .dentry = old_dentry, | ||
3297 | .inode = old_dentry->d_inode, | ||
3298 | }; | ||
3299 | struct ext4_renament new = { | ||
3300 | .dir = new_dir, | ||
3301 | .dentry = new_dentry, | ||
3302 | .inode = new_dentry->d_inode, | ||
3303 | }; | ||
3304 | u8 new_file_type; | ||
3305 | int retval; | ||
3306 | |||
3307 | dquot_initialize(old.dir); | ||
3308 | dquot_initialize(new.dir); | ||
3309 | |||
3310 | old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, | ||
3311 | &old.de, &old.inlined); | ||
3312 | /* | ||
3313 | * Check for inode number is _not_ due to possible IO errors. | ||
3314 | * We might rmdir the source, keep it as pwd of some process | ||
3315 | * and merrily kill the link to whatever was created under the | ||
3316 | * same name. Goodbye sticky bit ;-< | ||
3317 | */ | ||
3318 | retval = -ENOENT; | ||
3319 | if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino) | ||
3320 | goto end_rename; | ||
3321 | |||
3322 | new.bh = ext4_find_entry(new.dir, &new.dentry->d_name, | ||
3323 | &new.de, &new.inlined); | ||
3324 | |||
3325 | /* RENAME_EXCHANGE case: old *and* new must both exist */ | ||
3326 | if (!new.bh || le32_to_cpu(new.de->inode) != new.inode->i_ino) | ||
3327 | goto end_rename; | ||
3328 | |||
3329 | handle = ext4_journal_start(old.dir, EXT4_HT_DIR, | ||
3330 | (2 * EXT4_DATA_TRANS_BLOCKS(old.dir->i_sb) + | ||
3331 | 2 * EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2)); | ||
3332 | if (IS_ERR(handle)) | ||
3333 | return PTR_ERR(handle); | ||
3334 | |||
3335 | if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir)) | ||
3336 | ext4_handle_sync(handle); | ||
3337 | |||
3338 | if (S_ISDIR(old.inode->i_mode)) { | ||
3339 | old.is_dir = true; | ||
3340 | retval = ext4_rename_dir_prepare(handle, &old); | ||
3341 | if (retval) | ||
3342 | goto end_rename; | ||
3343 | } | ||
3344 | if (S_ISDIR(new.inode->i_mode)) { | ||
3345 | new.is_dir = true; | ||
3346 | retval = ext4_rename_dir_prepare(handle, &new); | ||
3347 | if (retval) | ||
3348 | goto end_rename; | ||
3349 | } | ||
3350 | |||
3351 | /* | ||
3352 | * Other than the special case of overwriting a directory, parents' | ||
3353 | * nlink only needs to be modified if this is a cross directory rename. | ||
3354 | */ | ||
3355 | if (old.dir != new.dir && old.is_dir != new.is_dir) { | ||
3356 | old.dir_nlink_delta = old.is_dir ? -1 : 1; | ||
3357 | new.dir_nlink_delta = -old.dir_nlink_delta; | ||
3358 | retval = -EMLINK; | ||
3359 | if ((old.dir_nlink_delta > 0 && EXT4_DIR_LINK_MAX(old.dir)) || | ||
3360 | (new.dir_nlink_delta > 0 && EXT4_DIR_LINK_MAX(new.dir))) | ||
3361 | goto end_rename; | ||
3362 | } | ||
3363 | |||
3364 | new_file_type = new.de->file_type; | ||
3365 | retval = ext4_setent(handle, &new, old.inode->i_ino, old.de->file_type); | ||
3366 | if (retval) | ||
3367 | goto end_rename; | ||
3368 | |||
3369 | retval = ext4_setent(handle, &old, new.inode->i_ino, new_file_type); | ||
3370 | if (retval) | ||
3371 | goto end_rename; | ||
3372 | |||
3373 | /* | ||
3374 | * Like most other Unix systems, set the ctime for inodes on a | ||
3375 | * rename. | ||
3376 | */ | ||
3377 | old.inode->i_ctime = ext4_current_time(old.inode); | ||
3378 | new.inode->i_ctime = ext4_current_time(new.inode); | ||
3379 | ext4_mark_inode_dirty(handle, old.inode); | ||
3380 | ext4_mark_inode_dirty(handle, new.inode); | ||
3381 | |||
3382 | if (old.dir_bh) { | ||
3383 | retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino); | ||
3384 | if (retval) | ||
3385 | goto end_rename; | ||
3386 | } | ||
3387 | if (new.dir_bh) { | ||
3388 | retval = ext4_rename_dir_finish(handle, &new, old.dir->i_ino); | ||
3389 | if (retval) | ||
3390 | goto end_rename; | ||
3391 | } | ||
3392 | ext4_update_dir_count(handle, &old); | ||
3393 | ext4_update_dir_count(handle, &new); | ||
3394 | retval = 0; | ||
3395 | |||
3396 | end_rename: | ||
3397 | brelse(old.dir_bh); | ||
3398 | brelse(new.dir_bh); | ||
3399 | brelse(old.bh); | ||
3400 | brelse(new.bh); | ||
3401 | if (handle) | ||
3402 | ext4_journal_stop(handle); | ||
3403 | return retval; | ||
3404 | } | ||
3405 | |||
3406 | static int ext4_rename2(struct inode *old_dir, struct dentry *old_dentry, | ||
3407 | struct inode *new_dir, struct dentry *new_dentry, | ||
3408 | unsigned int flags) | ||
3409 | { | ||
3410 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) | ||
3411 | return -EINVAL; | ||
3412 | |||
3413 | if (flags & RENAME_EXCHANGE) { | ||
3414 | return ext4_cross_rename(old_dir, old_dentry, | ||
3415 | new_dir, new_dentry); | ||
3416 | } | ||
3417 | /* | ||
3418 | * Existence checking was done by the VFS, otherwise "RENAME_NOREPLACE" | ||
3419 | * is equivalent to regular rename. | ||
3420 | */ | ||
3421 | return ext4_rename(old_dir, old_dentry, new_dir, new_dentry); | ||
3422 | } | ||
3423 | |||
3207 | /* | 3424 | /* |
3208 | * directories can handle most operations... | 3425 | * directories can handle most operations... |
3209 | */ | 3426 | */ |
@@ -3218,6 +3435,7 @@ const struct inode_operations ext4_dir_inode_operations = { | |||
3218 | .mknod = ext4_mknod, | 3435 | .mknod = ext4_mknod, |
3219 | .tmpfile = ext4_tmpfile, | 3436 | .tmpfile = ext4_tmpfile, |
3220 | .rename = ext4_rename, | 3437 | .rename = ext4_rename, |
3438 | .rename2 = ext4_rename2, | ||
3221 | .setattr = ext4_setattr, | 3439 | .setattr = ext4_setattr, |
3222 | .setxattr = generic_setxattr, | 3440 | .setxattr = generic_setxattr, |
3223 | .getxattr = generic_getxattr, | 3441 | .getxattr = generic_getxattr, |
diff --git a/fs/inode.c b/fs/inode.c index e6905152c39f..fb59ba7967f1 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -944,24 +944,22 @@ EXPORT_SYMBOL(unlock_new_inode); | |||
944 | 944 | ||
945 | /** | 945 | /** |
946 | * lock_two_nondirectories - take two i_mutexes on non-directory objects | 946 | * lock_two_nondirectories - take two i_mutexes on non-directory objects |
947 | * | ||
948 | * Lock any non-NULL argument that is not a directory. | ||
949 | * Zero, one or two objects may be locked by this function. | ||
950 | * | ||
947 | * @inode1: first inode to lock | 951 | * @inode1: first inode to lock |
948 | * @inode2: second inode to lock | 952 | * @inode2: second inode to lock |
949 | */ | 953 | */ |
950 | void lock_two_nondirectories(struct inode *inode1, struct inode *inode2) | 954 | void lock_two_nondirectories(struct inode *inode1, struct inode *inode2) |
951 | { | 955 | { |
952 | WARN_ON_ONCE(S_ISDIR(inode1->i_mode)); | 956 | if (inode1 > inode2) |
953 | if (inode1 == inode2 || !inode2) { | 957 | swap(inode1, inode2); |
954 | mutex_lock(&inode1->i_mutex); | 958 | |
955 | return; | 959 | if (inode1 && !S_ISDIR(inode1->i_mode)) |
956 | } | ||
957 | WARN_ON_ONCE(S_ISDIR(inode2->i_mode)); | ||
958 | if (inode1 < inode2) { | ||
959 | mutex_lock(&inode1->i_mutex); | 960 | mutex_lock(&inode1->i_mutex); |
961 | if (inode2 && !S_ISDIR(inode2->i_mode) && inode2 != inode1) | ||
960 | mutex_lock_nested(&inode2->i_mutex, I_MUTEX_NONDIR2); | 962 | mutex_lock_nested(&inode2->i_mutex, I_MUTEX_NONDIR2); |
961 | } else { | ||
962 | mutex_lock(&inode2->i_mutex); | ||
963 | mutex_lock_nested(&inode1->i_mutex, I_MUTEX_NONDIR2); | ||
964 | } | ||
965 | } | 963 | } |
966 | EXPORT_SYMBOL(lock_two_nondirectories); | 964 | EXPORT_SYMBOL(lock_two_nondirectories); |
967 | 965 | ||
@@ -972,8 +970,9 @@ EXPORT_SYMBOL(lock_two_nondirectories); | |||
972 | */ | 970 | */ |
973 | void unlock_two_nondirectories(struct inode *inode1, struct inode *inode2) | 971 | void unlock_two_nondirectories(struct inode *inode1, struct inode *inode2) |
974 | { | 972 | { |
975 | mutex_unlock(&inode1->i_mutex); | 973 | if (inode1 && !S_ISDIR(inode1->i_mode)) |
976 | if (inode2 && inode2 != inode1) | 974 | mutex_unlock(&inode1->i_mutex); |
975 | if (inode2 && !S_ISDIR(inode2->i_mode) && inode2 != inode1) | ||
977 | mutex_unlock(&inode2->i_mutex); | 976 | mutex_unlock(&inode2->i_mutex); |
978 | } | 977 | } |
979 | EXPORT_SYMBOL(unlock_two_nondirectories); | 978 | EXPORT_SYMBOL(unlock_two_nondirectories); |
diff --git a/fs/namei.c b/fs/namei.c index 4b491b431990..c1178880f23c 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1796,7 +1796,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1796 | if (err) | 1796 | if (err) |
1797 | return err; | 1797 | return err; |
1798 | } | 1798 | } |
1799 | if (!d_is_directory(nd->path.dentry)) { | 1799 | if (!d_can_lookup(nd->path.dentry)) { |
1800 | err = -ENOTDIR; | 1800 | err = -ENOTDIR; |
1801 | break; | 1801 | break; |
1802 | } | 1802 | } |
@@ -1817,7 +1817,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1817 | struct dentry *root = nd->root.dentry; | 1817 | struct dentry *root = nd->root.dentry; |
1818 | struct inode *inode = root->d_inode; | 1818 | struct inode *inode = root->d_inode; |
1819 | if (*name) { | 1819 | if (*name) { |
1820 | if (!d_is_directory(root)) | 1820 | if (!d_can_lookup(root)) |
1821 | return -ENOTDIR; | 1821 | return -ENOTDIR; |
1822 | retval = inode_permission(inode, MAY_EXEC); | 1822 | retval = inode_permission(inode, MAY_EXEC); |
1823 | if (retval) | 1823 | if (retval) |
@@ -1873,7 +1873,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1873 | dentry = f.file->f_path.dentry; | 1873 | dentry = f.file->f_path.dentry; |
1874 | 1874 | ||
1875 | if (*name) { | 1875 | if (*name) { |
1876 | if (!d_is_directory(dentry)) { | 1876 | if (!d_can_lookup(dentry)) { |
1877 | fdput(f); | 1877 | fdput(f); |
1878 | return -ENOTDIR; | 1878 | return -ENOTDIR; |
1879 | } | 1879 | } |
@@ -1955,7 +1955,7 @@ static int path_lookupat(int dfd, const char *name, | |||
1955 | err = complete_walk(nd); | 1955 | err = complete_walk(nd); |
1956 | 1956 | ||
1957 | if (!err && nd->flags & LOOKUP_DIRECTORY) { | 1957 | if (!err && nd->flags & LOOKUP_DIRECTORY) { |
1958 | if (!d_is_directory(nd->path.dentry)) { | 1958 | if (!d_can_lookup(nd->path.dentry)) { |
1959 | path_put(&nd->path); | 1959 | path_put(&nd->path); |
1960 | err = -ENOTDIR; | 1960 | err = -ENOTDIR; |
1961 | } | 1961 | } |
@@ -2414,11 +2414,11 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) | |||
2414 | IS_IMMUTABLE(inode) || IS_SWAPFILE(inode)) | 2414 | IS_IMMUTABLE(inode) || IS_SWAPFILE(inode)) |
2415 | return -EPERM; | 2415 | return -EPERM; |
2416 | if (isdir) { | 2416 | if (isdir) { |
2417 | if (!d_is_directory(victim) && !d_is_autodir(victim)) | 2417 | if (!d_is_dir(victim)) |
2418 | return -ENOTDIR; | 2418 | return -ENOTDIR; |
2419 | if (IS_ROOT(victim)) | 2419 | if (IS_ROOT(victim)) |
2420 | return -EBUSY; | 2420 | return -EBUSY; |
2421 | } else if (d_is_directory(victim) || d_is_autodir(victim)) | 2421 | } else if (d_is_dir(victim)) |
2422 | return -EISDIR; | 2422 | return -EISDIR; |
2423 | if (IS_DEADDIR(dir)) | 2423 | if (IS_DEADDIR(dir)) |
2424 | return -ENOENT; | 2424 | return -ENOENT; |
@@ -3016,11 +3016,10 @@ finish_open: | |||
3016 | } | 3016 | } |
3017 | audit_inode(name, nd->path.dentry, 0); | 3017 | audit_inode(name, nd->path.dentry, 0); |
3018 | error = -EISDIR; | 3018 | error = -EISDIR; |
3019 | if ((open_flag & O_CREAT) && | 3019 | if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry)) |
3020 | (d_is_directory(nd->path.dentry) || d_is_autodir(nd->path.dentry))) | ||
3021 | goto out; | 3020 | goto out; |
3022 | error = -ENOTDIR; | 3021 | error = -ENOTDIR; |
3023 | if ((nd->flags & LOOKUP_DIRECTORY) && !d_is_directory(nd->path.dentry)) | 3022 | if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry)) |
3024 | goto out; | 3023 | goto out; |
3025 | if (!S_ISREG(nd->inode->i_mode)) | 3024 | if (!S_ISREG(nd->inode->i_mode)) |
3026 | will_truncate = false; | 3025 | will_truncate = false; |
@@ -3744,7 +3743,7 @@ exit1: | |||
3744 | slashes: | 3743 | slashes: |
3745 | if (d_is_negative(dentry)) | 3744 | if (d_is_negative(dentry)) |
3746 | error = -ENOENT; | 3745 | error = -ENOENT; |
3747 | else if (d_is_directory(dentry) || d_is_autodir(dentry)) | 3746 | else if (d_is_dir(dentry)) |
3748 | error = -EISDIR; | 3747 | error = -EISDIR; |
3749 | else | 3748 | else |
3750 | error = -ENOTDIR; | 3749 | error = -ENOTDIR; |
@@ -3974,7 +3973,28 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname | |||
3974 | return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0); | 3973 | return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0); |
3975 | } | 3974 | } |
3976 | 3975 | ||
3977 | /* | 3976 | /** |
3977 | * vfs_rename - rename a filesystem object | ||
3978 | * @old_dir: parent of source | ||
3979 | * @old_dentry: source | ||
3980 | * @new_dir: parent of destination | ||
3981 | * @new_dentry: destination | ||
3982 | * @delegated_inode: returns an inode needing a delegation break | ||
3983 | * @flags: rename flags | ||
3984 | * | ||
3985 | * The caller must hold multiple mutexes--see lock_rename()). | ||
3986 | * | ||
3987 | * If vfs_rename discovers a delegation in need of breaking at either | ||
3988 | * the source or destination, it will return -EWOULDBLOCK and return a | ||
3989 | * reference to the inode in delegated_inode. The caller should then | ||
3990 | * break the delegation and retry. Because breaking a delegation may | ||
3991 | * take a long time, the caller should drop all locks before doing | ||
3992 | * so. | ||
3993 | * | ||
3994 | * Alternatively, a caller may pass NULL for delegated_inode. This may | ||
3995 | * be appropriate for callers that expect the underlying filesystem not | ||
3996 | * to be NFS exported. | ||
3997 | * | ||
3978 | * The worst of all namespace operations - renaming directory. "Perverted" | 3998 | * The worst of all namespace operations - renaming directory. "Perverted" |
3979 | * doesn't even start to describe it. Somebody in UCB had a heck of a trip... | 3999 | * doesn't even start to describe it. Somebody in UCB had a heck of a trip... |
3980 | * Problems: | 4000 | * Problems: |
@@ -4002,163 +4022,139 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname | |||
4002 | * ->i_mutex on parents, which works but leads to some truly excessive | 4022 | * ->i_mutex on parents, which works but leads to some truly excessive |
4003 | * locking]. | 4023 | * locking]. |
4004 | */ | 4024 | */ |
4005 | static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, | 4025 | int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
4006 | struct inode *new_dir, struct dentry *new_dentry) | 4026 | struct inode *new_dir, struct dentry *new_dentry, |
4027 | struct inode **delegated_inode, unsigned int flags) | ||
4007 | { | 4028 | { |
4008 | int error = 0; | 4029 | int error; |
4030 | bool is_dir = d_is_dir(old_dentry); | ||
4031 | const unsigned char *old_name; | ||
4032 | struct inode *source = old_dentry->d_inode; | ||
4009 | struct inode *target = new_dentry->d_inode; | 4033 | struct inode *target = new_dentry->d_inode; |
4034 | bool new_is_dir = false; | ||
4010 | unsigned max_links = new_dir->i_sb->s_max_links; | 4035 | unsigned max_links = new_dir->i_sb->s_max_links; |
4011 | 4036 | ||
4037 | if (source == target) | ||
4038 | return 0; | ||
4039 | |||
4040 | error = may_delete(old_dir, old_dentry, is_dir); | ||
4041 | if (error) | ||
4042 | return error; | ||
4043 | |||
4044 | if (!target) { | ||
4045 | error = may_create(new_dir, new_dentry); | ||
4046 | } else { | ||
4047 | new_is_dir = d_is_dir(new_dentry); | ||
4048 | |||
4049 | if (!(flags & RENAME_EXCHANGE)) | ||
4050 | error = may_delete(new_dir, new_dentry, is_dir); | ||
4051 | else | ||
4052 | error = may_delete(new_dir, new_dentry, new_is_dir); | ||
4053 | } | ||
4054 | if (error) | ||
4055 | return error; | ||
4056 | |||
4057 | if (!old_dir->i_op->rename) | ||
4058 | return -EPERM; | ||
4059 | |||
4060 | if (flags && !old_dir->i_op->rename2) | ||
4061 | return -EINVAL; | ||
4062 | |||
4012 | /* | 4063 | /* |
4013 | * If we are going to change the parent - check write permissions, | 4064 | * If we are going to change the parent - check write permissions, |
4014 | * we'll need to flip '..'. | 4065 | * we'll need to flip '..'. |
4015 | */ | 4066 | */ |
4016 | if (new_dir != old_dir) { | 4067 | if (new_dir != old_dir) { |
4017 | error = inode_permission(old_dentry->d_inode, MAY_WRITE); | 4068 | if (is_dir) { |
4018 | if (error) | 4069 | error = inode_permission(source, MAY_WRITE); |
4019 | return error; | 4070 | if (error) |
4071 | return error; | ||
4072 | } | ||
4073 | if ((flags & RENAME_EXCHANGE) && new_is_dir) { | ||
4074 | error = inode_permission(target, MAY_WRITE); | ||
4075 | if (error) | ||
4076 | return error; | ||
4077 | } | ||
4020 | } | 4078 | } |
4021 | 4079 | ||
4022 | error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry); | 4080 | error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry, |
4081 | flags); | ||
4023 | if (error) | 4082 | if (error) |
4024 | return error; | 4083 | return error; |
4025 | 4084 | ||
4085 | old_name = fsnotify_oldname_init(old_dentry->d_name.name); | ||
4026 | dget(new_dentry); | 4086 | dget(new_dentry); |
4027 | if (target) | 4087 | if (!is_dir || (flags & RENAME_EXCHANGE)) |
4088 | lock_two_nondirectories(source, target); | ||
4089 | else if (target) | ||
4028 | mutex_lock(&target->i_mutex); | 4090 | mutex_lock(&target->i_mutex); |
4029 | 4091 | ||
4030 | error = -EBUSY; | 4092 | error = -EBUSY; |
4031 | if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry)) | 4093 | if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry)) |
4032 | goto out; | 4094 | goto out; |
4033 | 4095 | ||
4034 | error = -EMLINK; | 4096 | if (max_links && new_dir != old_dir) { |
4035 | if (max_links && !target && new_dir != old_dir && | 4097 | error = -EMLINK; |
4036 | new_dir->i_nlink >= max_links) | 4098 | if (is_dir && !new_is_dir && new_dir->i_nlink >= max_links) |
4037 | goto out; | 4099 | goto out; |
4038 | 4100 | if ((flags & RENAME_EXCHANGE) && !is_dir && new_is_dir && | |
4039 | if (target) | 4101 | old_dir->i_nlink >= max_links) |
4102 | goto out; | ||
4103 | } | ||
4104 | if (is_dir && !(flags & RENAME_EXCHANGE) && target) | ||
4040 | shrink_dcache_parent(new_dentry); | 4105 | shrink_dcache_parent(new_dentry); |
4041 | error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); | 4106 | if (!is_dir) { |
4042 | if (error) | 4107 | error = try_break_deleg(source, delegated_inode); |
4043 | goto out; | 4108 | if (error) |
4044 | 4109 | goto out; | |
4045 | if (target) { | ||
4046 | target->i_flags |= S_DEAD; | ||
4047 | dont_mount(new_dentry); | ||
4048 | } | 4110 | } |
4049 | out: | 4111 | if (target && !new_is_dir) { |
4050 | if (target) | ||
4051 | mutex_unlock(&target->i_mutex); | ||
4052 | dput(new_dentry); | ||
4053 | if (!error) | ||
4054 | if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) | ||
4055 | d_move(old_dentry,new_dentry); | ||
4056 | return error; | ||
4057 | } | ||
4058 | |||
4059 | static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, | ||
4060 | struct inode *new_dir, struct dentry *new_dentry, | ||
4061 | struct inode **delegated_inode) | ||
4062 | { | ||
4063 | struct inode *target = new_dentry->d_inode; | ||
4064 | struct inode *source = old_dentry->d_inode; | ||
4065 | int error; | ||
4066 | |||
4067 | error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry); | ||
4068 | if (error) | ||
4069 | return error; | ||
4070 | |||
4071 | dget(new_dentry); | ||
4072 | lock_two_nondirectories(source, target); | ||
4073 | |||
4074 | error = -EBUSY; | ||
4075 | if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) | ||
4076 | goto out; | ||
4077 | |||
4078 | error = try_break_deleg(source, delegated_inode); | ||
4079 | if (error) | ||
4080 | goto out; | ||
4081 | if (target) { | ||
4082 | error = try_break_deleg(target, delegated_inode); | 4112 | error = try_break_deleg(target, delegated_inode); |
4083 | if (error) | 4113 | if (error) |
4084 | goto out; | 4114 | goto out; |
4085 | } | 4115 | } |
4086 | error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); | 4116 | if (!flags) { |
4117 | error = old_dir->i_op->rename(old_dir, old_dentry, | ||
4118 | new_dir, new_dentry); | ||
4119 | } else { | ||
4120 | error = old_dir->i_op->rename2(old_dir, old_dentry, | ||
4121 | new_dir, new_dentry, flags); | ||
4122 | } | ||
4087 | if (error) | 4123 | if (error) |
4088 | goto out; | 4124 | goto out; |
4089 | 4125 | ||
4090 | if (target) | 4126 | if (!(flags & RENAME_EXCHANGE) && target) { |
4127 | if (is_dir) | ||
4128 | target->i_flags |= S_DEAD; | ||
4091 | dont_mount(new_dentry); | 4129 | dont_mount(new_dentry); |
4092 | if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) | 4130 | } |
4093 | d_move(old_dentry, new_dentry); | 4131 | if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) { |
4132 | if (!(flags & RENAME_EXCHANGE)) | ||
4133 | d_move(old_dentry, new_dentry); | ||
4134 | else | ||
4135 | d_exchange(old_dentry, new_dentry); | ||
4136 | } | ||
4094 | out: | 4137 | out: |
4095 | unlock_two_nondirectories(source, target); | 4138 | if (!is_dir || (flags & RENAME_EXCHANGE)) |
4139 | unlock_two_nondirectories(source, target); | ||
4140 | else if (target) | ||
4141 | mutex_unlock(&target->i_mutex); | ||
4096 | dput(new_dentry); | 4142 | dput(new_dentry); |
4097 | return error; | 4143 | if (!error) { |
4098 | } | ||
4099 | |||
4100 | /** | ||
4101 | * vfs_rename - rename a filesystem object | ||
4102 | * @old_dir: parent of source | ||
4103 | * @old_dentry: source | ||
4104 | * @new_dir: parent of destination | ||
4105 | * @new_dentry: destination | ||
4106 | * @delegated_inode: returns an inode needing a delegation break | ||
4107 | * | ||
4108 | * The caller must hold multiple mutexes--see lock_rename()). | ||
4109 | * | ||
4110 | * If vfs_rename discovers a delegation in need of breaking at either | ||
4111 | * the source or destination, it will return -EWOULDBLOCK and return a | ||
4112 | * reference to the inode in delegated_inode. The caller should then | ||
4113 | * break the delegation and retry. Because breaking a delegation may | ||
4114 | * take a long time, the caller should drop all locks before doing | ||
4115 | * so. | ||
4116 | * | ||
4117 | * Alternatively, a caller may pass NULL for delegated_inode. This may | ||
4118 | * be appropriate for callers that expect the underlying filesystem not | ||
4119 | * to be NFS exported. | ||
4120 | */ | ||
4121 | int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | ||
4122 | struct inode *new_dir, struct dentry *new_dentry, | ||
4123 | struct inode **delegated_inode) | ||
4124 | { | ||
4125 | int error; | ||
4126 | int is_dir = d_is_directory(old_dentry) || d_is_autodir(old_dentry); | ||
4127 | const unsigned char *old_name; | ||
4128 | |||
4129 | if (old_dentry->d_inode == new_dentry->d_inode) | ||
4130 | return 0; | ||
4131 | |||
4132 | error = may_delete(old_dir, old_dentry, is_dir); | ||
4133 | if (error) | ||
4134 | return error; | ||
4135 | |||
4136 | if (!new_dentry->d_inode) | ||
4137 | error = may_create(new_dir, new_dentry); | ||
4138 | else | ||
4139 | error = may_delete(new_dir, new_dentry, is_dir); | ||
4140 | if (error) | ||
4141 | return error; | ||
4142 | |||
4143 | if (!old_dir->i_op->rename) | ||
4144 | return -EPERM; | ||
4145 | |||
4146 | old_name = fsnotify_oldname_init(old_dentry->d_name.name); | ||
4147 | |||
4148 | if (is_dir) | ||
4149 | error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry); | ||
4150 | else | ||
4151 | error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,delegated_inode); | ||
4152 | if (!error) | ||
4153 | fsnotify_move(old_dir, new_dir, old_name, is_dir, | 4144 | fsnotify_move(old_dir, new_dir, old_name, is_dir, |
4154 | new_dentry->d_inode, old_dentry); | 4145 | !(flags & RENAME_EXCHANGE) ? target : NULL, old_dentry); |
4146 | if (flags & RENAME_EXCHANGE) { | ||
4147 | fsnotify_move(new_dir, old_dir, old_dentry->d_name.name, | ||
4148 | new_is_dir, NULL, new_dentry); | ||
4149 | } | ||
4150 | } | ||
4155 | fsnotify_oldname_free(old_name); | 4151 | fsnotify_oldname_free(old_name); |
4156 | 4152 | ||
4157 | return error; | 4153 | return error; |
4158 | } | 4154 | } |
4159 | 4155 | ||
4160 | SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | 4156 | SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname, |
4161 | int, newdfd, const char __user *, newname) | 4157 | int, newdfd, const char __user *, newname, unsigned int, flags) |
4162 | { | 4158 | { |
4163 | struct dentry *old_dir, *new_dir; | 4159 | struct dentry *old_dir, *new_dir; |
4164 | struct dentry *old_dentry, *new_dentry; | 4160 | struct dentry *old_dentry, *new_dentry; |
@@ -4170,6 +4166,13 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | |||
4170 | unsigned int lookup_flags = 0; | 4166 | unsigned int lookup_flags = 0; |
4171 | bool should_retry = false; | 4167 | bool should_retry = false; |
4172 | int error; | 4168 | int error; |
4169 | |||
4170 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) | ||
4171 | return -EINVAL; | ||
4172 | |||
4173 | if ((flags & RENAME_NOREPLACE) && (flags & RENAME_EXCHANGE)) | ||
4174 | return -EINVAL; | ||
4175 | |||
4173 | retry: | 4176 | retry: |
4174 | from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags); | 4177 | from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags); |
4175 | if (IS_ERR(from)) { | 4178 | if (IS_ERR(from)) { |
@@ -4193,6 +4196,8 @@ retry: | |||
4193 | goto exit2; | 4196 | goto exit2; |
4194 | 4197 | ||
4195 | new_dir = newnd.path.dentry; | 4198 | new_dir = newnd.path.dentry; |
4199 | if (flags & RENAME_NOREPLACE) | ||
4200 | error = -EEXIST; | ||
4196 | if (newnd.last_type != LAST_NORM) | 4201 | if (newnd.last_type != LAST_NORM) |
4197 | goto exit2; | 4202 | goto exit2; |
4198 | 4203 | ||
@@ -4202,7 +4207,8 @@ retry: | |||
4202 | 4207 | ||
4203 | oldnd.flags &= ~LOOKUP_PARENT; | 4208 | oldnd.flags &= ~LOOKUP_PARENT; |
4204 | newnd.flags &= ~LOOKUP_PARENT; | 4209 | newnd.flags &= ~LOOKUP_PARENT; |
4205 | newnd.flags |= LOOKUP_RENAME_TARGET; | 4210 | if (!(flags & RENAME_EXCHANGE)) |
4211 | newnd.flags |= LOOKUP_RENAME_TARGET; | ||
4206 | 4212 | ||
4207 | retry_deleg: | 4213 | retry_deleg: |
4208 | trap = lock_rename(new_dir, old_dir); | 4214 | trap = lock_rename(new_dir, old_dir); |
@@ -4215,34 +4221,49 @@ retry_deleg: | |||
4215 | error = -ENOENT; | 4221 | error = -ENOENT; |
4216 | if (d_is_negative(old_dentry)) | 4222 | if (d_is_negative(old_dentry)) |
4217 | goto exit4; | 4223 | goto exit4; |
4224 | new_dentry = lookup_hash(&newnd); | ||
4225 | error = PTR_ERR(new_dentry); | ||
4226 | if (IS_ERR(new_dentry)) | ||
4227 | goto exit4; | ||
4228 | error = -EEXIST; | ||
4229 | if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) | ||
4230 | goto exit5; | ||
4231 | if (flags & RENAME_EXCHANGE) { | ||
4232 | error = -ENOENT; | ||
4233 | if (d_is_negative(new_dentry)) | ||
4234 | goto exit5; | ||
4235 | |||
4236 | if (!d_is_dir(new_dentry)) { | ||
4237 | error = -ENOTDIR; | ||
4238 | if (newnd.last.name[newnd.last.len]) | ||
4239 | goto exit5; | ||
4240 | } | ||
4241 | } | ||
4218 | /* unless the source is a directory trailing slashes give -ENOTDIR */ | 4242 | /* unless the source is a directory trailing slashes give -ENOTDIR */ |
4219 | if (!d_is_directory(old_dentry) && !d_is_autodir(old_dentry)) { | 4243 | if (!d_is_dir(old_dentry)) { |
4220 | error = -ENOTDIR; | 4244 | error = -ENOTDIR; |
4221 | if (oldnd.last.name[oldnd.last.len]) | 4245 | if (oldnd.last.name[oldnd.last.len]) |
4222 | goto exit4; | 4246 | goto exit5; |
4223 | if (newnd.last.name[newnd.last.len]) | 4247 | if (!(flags & RENAME_EXCHANGE) && newnd.last.name[newnd.last.len]) |
4224 | goto exit4; | 4248 | goto exit5; |
4225 | } | 4249 | } |
4226 | /* source should not be ancestor of target */ | 4250 | /* source should not be ancestor of target */ |
4227 | error = -EINVAL; | 4251 | error = -EINVAL; |
4228 | if (old_dentry == trap) | 4252 | if (old_dentry == trap) |
4229 | goto exit4; | 4253 | goto exit5; |
4230 | new_dentry = lookup_hash(&newnd); | ||
4231 | error = PTR_ERR(new_dentry); | ||
4232 | if (IS_ERR(new_dentry)) | ||
4233 | goto exit4; | ||
4234 | /* target should not be an ancestor of source */ | 4254 | /* target should not be an ancestor of source */ |
4235 | error = -ENOTEMPTY; | 4255 | if (!(flags & RENAME_EXCHANGE)) |
4256 | error = -ENOTEMPTY; | ||
4236 | if (new_dentry == trap) | 4257 | if (new_dentry == trap) |
4237 | goto exit5; | 4258 | goto exit5; |
4238 | 4259 | ||
4239 | error = security_path_rename(&oldnd.path, old_dentry, | 4260 | error = security_path_rename(&oldnd.path, old_dentry, |
4240 | &newnd.path, new_dentry); | 4261 | &newnd.path, new_dentry, flags); |
4241 | if (error) | 4262 | if (error) |
4242 | goto exit5; | 4263 | goto exit5; |
4243 | error = vfs_rename(old_dir->d_inode, old_dentry, | 4264 | error = vfs_rename(old_dir->d_inode, old_dentry, |
4244 | new_dir->d_inode, new_dentry, | 4265 | new_dir->d_inode, new_dentry, |
4245 | &delegated_inode); | 4266 | &delegated_inode, flags); |
4246 | exit5: | 4267 | exit5: |
4247 | dput(new_dentry); | 4268 | dput(new_dentry); |
4248 | exit4: | 4269 | exit4: |
@@ -4272,9 +4293,15 @@ exit: | |||
4272 | return error; | 4293 | return error; |
4273 | } | 4294 | } |
4274 | 4295 | ||
4296 | SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | ||
4297 | int, newdfd, const char __user *, newname) | ||
4298 | { | ||
4299 | return sys_renameat2(olddfd, oldname, newdfd, newname, 0); | ||
4300 | } | ||
4301 | |||
4275 | SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname) | 4302 | SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname) |
4276 | { | 4303 | { |
4277 | return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname); | 4304 | return sys_renameat2(AT_FDCWD, oldname, AT_FDCWD, newname, 0); |
4278 | } | 4305 | } |
4279 | 4306 | ||
4280 | int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) | 4307 | int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 6d7be3f80356..915808b36df7 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1694,7 +1694,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1694 | if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry) | 1694 | if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry) |
1695 | goto out_dput_new; | 1695 | goto out_dput_new; |
1696 | 1696 | ||
1697 | host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); | 1697 | host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL, 0); |
1698 | if (!host_err) { | 1698 | if (!host_err) { |
1699 | host_err = commit_metadata(tfhp); | 1699 | host_err = commit_metadata(tfhp); |
1700 | if (!host_err) | 1700 | if (!host_err) |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index bf72e9ac6de0..3b9bfdb83ba6 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -308,6 +308,7 @@ extern void dentry_update_name_case(struct dentry *, struct qstr *); | |||
308 | 308 | ||
309 | /* used for rename() and baskets */ | 309 | /* used for rename() and baskets */ |
310 | extern void d_move(struct dentry *, struct dentry *); | 310 | extern void d_move(struct dentry *, struct dentry *); |
311 | extern void d_exchange(struct dentry *, struct dentry *); | ||
311 | extern struct dentry *d_ancestor(struct dentry *, struct dentry *); | 312 | extern struct dentry *d_ancestor(struct dentry *, struct dentry *); |
312 | 313 | ||
313 | /* appendix may either be NULL or be used for transname suffixes */ | 314 | /* appendix may either be NULL or be used for transname suffixes */ |
@@ -429,7 +430,7 @@ static inline unsigned __d_entry_type(const struct dentry *dentry) | |||
429 | return dentry->d_flags & DCACHE_ENTRY_TYPE; | 430 | return dentry->d_flags & DCACHE_ENTRY_TYPE; |
430 | } | 431 | } |
431 | 432 | ||
432 | static inline bool d_is_directory(const struct dentry *dentry) | 433 | static inline bool d_can_lookup(const struct dentry *dentry) |
433 | { | 434 | { |
434 | return __d_entry_type(dentry) == DCACHE_DIRECTORY_TYPE; | 435 | return __d_entry_type(dentry) == DCACHE_DIRECTORY_TYPE; |
435 | } | 436 | } |
@@ -439,6 +440,11 @@ static inline bool d_is_autodir(const struct dentry *dentry) | |||
439 | return __d_entry_type(dentry) == DCACHE_AUTODIR_TYPE; | 440 | return __d_entry_type(dentry) == DCACHE_AUTODIR_TYPE; |
440 | } | 441 | } |
441 | 442 | ||
443 | static inline bool d_is_dir(const struct dentry *dentry) | ||
444 | { | ||
445 | return d_can_lookup(dentry) || d_is_autodir(dentry); | ||
446 | } | ||
447 | |||
442 | static inline bool d_is_symlink(const struct dentry *dentry) | 448 | static inline bool d_is_symlink(const struct dentry *dentry) |
443 | { | 449 | { |
444 | return __d_entry_type(dentry) == DCACHE_SYMLINK_TYPE; | 450 | return __d_entry_type(dentry) == DCACHE_SYMLINK_TYPE; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 3ca9420f627e..215cb1b09f47 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1461,7 +1461,7 @@ extern int vfs_symlink(struct inode *, struct dentry *, const char *); | |||
1461 | extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct inode **); | 1461 | extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct inode **); |
1462 | extern int vfs_rmdir(struct inode *, struct dentry *); | 1462 | extern int vfs_rmdir(struct inode *, struct dentry *); |
1463 | extern int vfs_unlink(struct inode *, struct dentry *, struct inode **); | 1463 | extern int vfs_unlink(struct inode *, struct dentry *, struct inode **); |
1464 | extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **); | 1464 | extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int); |
1465 | 1465 | ||
1466 | /* | 1466 | /* |
1467 | * VFS dentry helper functions. | 1467 | * VFS dentry helper functions. |
@@ -1572,6 +1572,8 @@ struct inode_operations { | |||
1572 | int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); | 1572 | int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); |
1573 | int (*rename) (struct inode *, struct dentry *, | 1573 | int (*rename) (struct inode *, struct dentry *, |
1574 | struct inode *, struct dentry *); | 1574 | struct inode *, struct dentry *); |
1575 | int (*rename2) (struct inode *, struct dentry *, | ||
1576 | struct inode *, struct dentry *, unsigned int); | ||
1575 | int (*setattr) (struct dentry *, struct iattr *); | 1577 | int (*setattr) (struct dentry *, struct iattr *); |
1576 | int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); | 1578 | int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); |
1577 | int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); | 1579 | int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); |
diff --git a/include/linux/security.h b/include/linux/security.h index 2fc42d191f79..6478ce3252c7 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -1793,7 +1793,8 @@ int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
1793 | int security_inode_rmdir(struct inode *dir, struct dentry *dentry); | 1793 | int security_inode_rmdir(struct inode *dir, struct dentry *dentry); |
1794 | int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev); | 1794 | int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev); |
1795 | int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, | 1795 | int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, |
1796 | struct inode *new_dir, struct dentry *new_dentry); | 1796 | struct inode *new_dir, struct dentry *new_dentry, |
1797 | unsigned int flags); | ||
1797 | int security_inode_readlink(struct dentry *dentry); | 1798 | int security_inode_readlink(struct dentry *dentry); |
1798 | int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd); | 1799 | int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd); |
1799 | int security_inode_permission(struct inode *inode, int mask); | 1800 | int security_inode_permission(struct inode *inode, int mask); |
@@ -2161,7 +2162,8 @@ static inline int security_inode_mknod(struct inode *dir, | |||
2161 | static inline int security_inode_rename(struct inode *old_dir, | 2162 | static inline int security_inode_rename(struct inode *old_dir, |
2162 | struct dentry *old_dentry, | 2163 | struct dentry *old_dentry, |
2163 | struct inode *new_dir, | 2164 | struct inode *new_dir, |
2164 | struct dentry *new_dentry) | 2165 | struct dentry *new_dentry, |
2166 | unsigned int flags) | ||
2165 | { | 2167 | { |
2166 | return 0; | 2168 | return 0; |
2167 | } | 2169 | } |
@@ -2955,7 +2957,8 @@ int security_path_symlink(struct path *dir, struct dentry *dentry, | |||
2955 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, | 2957 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, |
2956 | struct dentry *new_dentry); | 2958 | struct dentry *new_dentry); |
2957 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, | 2959 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, |
2958 | struct path *new_dir, struct dentry *new_dentry); | 2960 | struct path *new_dir, struct dentry *new_dentry, |
2961 | unsigned int flags); | ||
2959 | int security_path_chmod(struct path *path, umode_t mode); | 2962 | int security_path_chmod(struct path *path, umode_t mode); |
2960 | int security_path_chown(struct path *path, kuid_t uid, kgid_t gid); | 2963 | int security_path_chown(struct path *path, kuid_t uid, kgid_t gid); |
2961 | int security_path_chroot(struct path *path); | 2964 | int security_path_chroot(struct path *path); |
@@ -3003,7 +3006,8 @@ static inline int security_path_link(struct dentry *old_dentry, | |||
3003 | static inline int security_path_rename(struct path *old_dir, | 3006 | static inline int security_path_rename(struct path *old_dir, |
3004 | struct dentry *old_dentry, | 3007 | struct dentry *old_dentry, |
3005 | struct path *new_dir, | 3008 | struct path *new_dir, |
3006 | struct dentry *new_dentry) | 3009 | struct dentry *new_dentry, |
3010 | unsigned int flags) | ||
3007 | { | 3011 | { |
3008 | return 0; | 3012 | return 0; |
3009 | } | 3013 | } |
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 6c28b61bb690..ca1a11bb4443 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h | |||
@@ -35,6 +35,9 @@ | |||
35 | #define SEEK_HOLE 4 /* seek to the next hole */ | 35 | #define SEEK_HOLE 4 /* seek to the next hole */ |
36 | #define SEEK_MAX SEEK_HOLE | 36 | #define SEEK_MAX SEEK_HOLE |
37 | 37 | ||
38 | #define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */ | ||
39 | #define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */ | ||
40 | |||
38 | struct fstrim_range { | 41 | struct fstrim_range { |
39 | __u64 start; | 42 | __u64 start; |
40 | __u64 len; | 43 | __u64 len; |
diff --git a/security/security.c b/security/security.c index 919cad93ac82..8b774f362a3d 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -433,11 +433,20 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir, | |||
433 | } | 433 | } |
434 | 434 | ||
435 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, | 435 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, |
436 | struct path *new_dir, struct dentry *new_dentry) | 436 | struct path *new_dir, struct dentry *new_dentry, |
437 | unsigned int flags) | ||
437 | { | 438 | { |
438 | if (unlikely(IS_PRIVATE(old_dentry->d_inode) || | 439 | if (unlikely(IS_PRIVATE(old_dentry->d_inode) || |
439 | (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) | 440 | (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) |
440 | return 0; | 441 | return 0; |
442 | |||
443 | if (flags & RENAME_EXCHANGE) { | ||
444 | int err = security_ops->path_rename(new_dir, new_dentry, | ||
445 | old_dir, old_dentry); | ||
446 | if (err) | ||
447 | return err; | ||
448 | } | ||
449 | |||
441 | return security_ops->path_rename(old_dir, old_dentry, new_dir, | 450 | return security_ops->path_rename(old_dir, old_dentry, new_dir, |
442 | new_dentry); | 451 | new_dentry); |
443 | } | 452 | } |
@@ -524,11 +533,20 @@ int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
524 | } | 533 | } |
525 | 534 | ||
526 | int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, | 535 | int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, |
527 | struct inode *new_dir, struct dentry *new_dentry) | 536 | struct inode *new_dir, struct dentry *new_dentry, |
537 | unsigned int flags) | ||
528 | { | 538 | { |
529 | if (unlikely(IS_PRIVATE(old_dentry->d_inode) || | 539 | if (unlikely(IS_PRIVATE(old_dentry->d_inode) || |
530 | (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) | 540 | (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) |
531 | return 0; | 541 | return 0; |
542 | |||
543 | if (flags & RENAME_EXCHANGE) { | ||
544 | int err = security_ops->inode_rename(new_dir, new_dentry, | ||
545 | old_dir, old_dentry); | ||
546 | if (err) | ||
547 | return err; | ||
548 | } | ||
549 | |||
532 | return security_ops->inode_rename(old_dir, old_dentry, | 550 | return security_ops->inode_rename(old_dir, old_dentry, |
533 | new_dir, new_dentry); | 551 | new_dir, new_dentry); |
534 | } | 552 | } |