aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c44
1 files changed, 17 insertions, 27 deletions
diff --git a/fs/namei.c b/fs/namei.c
index a4855af776a8..0741c69b3319 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -689,33 +689,20 @@ static __always_inline void follow_dotdot(struct nameidata *nd)
689 set_root(nd); 689 set_root(nd);
690 690
691 while(1) { 691 while(1) {
692 struct vfsmount *parent;
693 struct dentry *old = nd->path.dentry; 692 struct dentry *old = nd->path.dentry;
694 693
695 if (nd->path.dentry == nd->root.dentry && 694 if (nd->path.dentry == nd->root.dentry &&
696 nd->path.mnt == nd->root.mnt) { 695 nd->path.mnt == nd->root.mnt) {
697 break; 696 break;
698 } 697 }
699 spin_lock(&dcache_lock);
700 if (nd->path.dentry != nd->path.mnt->mnt_root) { 698 if (nd->path.dentry != nd->path.mnt->mnt_root) {
701 nd->path.dentry = dget(nd->path.dentry->d_parent); 699 /* rare case of legitimate dget_parent()... */
702 spin_unlock(&dcache_lock); 700 nd->path.dentry = dget_parent(nd->path.dentry);
703 dput(old); 701 dput(old);
704 break; 702 break;
705 } 703 }
706 spin_unlock(&dcache_lock); 704 if (!follow_up(&nd->path))
707 spin_lock(&vfsmount_lock);
708 parent = nd->path.mnt->mnt_parent;
709 if (parent == nd->path.mnt) {
710 spin_unlock(&vfsmount_lock);
711 break; 705 break;
712 }
713 mntget(parent);
714 nd->path.dentry = dget(nd->path.mnt->mnt_mountpoint);
715 spin_unlock(&vfsmount_lock);
716 dput(old);
717 mntput(nd->path.mnt);
718 nd->path.mnt = parent;
719 } 706 }
720 follow_mount(&nd->path); 707 follow_mount(&nd->path);
721} 708}
@@ -1347,7 +1334,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
1347 return -ENOENT; 1334 return -ENOENT;
1348 1335
1349 BUG_ON(victim->d_parent->d_inode != dir); 1336 BUG_ON(victim->d_parent->d_inode != dir);
1350 audit_inode_child(victim->d_name.name, victim, dir); 1337 audit_inode_child(victim, dir);
1351 1338
1352 error = inode_permission(dir, MAY_WRITE | MAY_EXEC); 1339 error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
1353 if (error) 1340 if (error)
@@ -1503,7 +1490,7 @@ int may_open(struct path *path, int acc_mode, int flag)
1503 * An append-only file must be opened in append mode for writing. 1490 * An append-only file must be opened in append mode for writing.
1504 */ 1491 */
1505 if (IS_APPEND(inode)) { 1492 if (IS_APPEND(inode)) {
1506 if ((flag & FMODE_WRITE) && !(flag & O_APPEND)) 1493 if ((flag & O_ACCMODE) != O_RDONLY && !(flag & O_APPEND))
1507 return -EPERM; 1494 return -EPERM;
1508 if (flag & O_TRUNC) 1495 if (flag & O_TRUNC)
1509 return -EPERM; 1496 return -EPERM;
@@ -1547,7 +1534,7 @@ static int handle_truncate(struct path *path)
1547 * what get passed to sys_open(). 1534 * what get passed to sys_open().
1548 */ 1535 */
1549static int __open_namei_create(struct nameidata *nd, struct path *path, 1536static int __open_namei_create(struct nameidata *nd, struct path *path,
1550 int flag, int mode) 1537 int open_flag, int mode)
1551{ 1538{
1552 int error; 1539 int error;
1553 struct dentry *dir = nd->path.dentry; 1540 struct dentry *dir = nd->path.dentry;
@@ -1565,7 +1552,7 @@ out_unlock:
1565 if (error) 1552 if (error)
1566 return error; 1553 return error;
1567 /* Don't check for write permission, don't truncate */ 1554 /* Don't check for write permission, don't truncate */
1568 return may_open(&nd->path, 0, flag & ~O_TRUNC); 1555 return may_open(&nd->path, 0, open_flag & ~O_TRUNC);
1569} 1556}
1570 1557
1571/* 1558/*
@@ -1736,7 +1723,7 @@ do_last:
1736 error = mnt_want_write(nd.path.mnt); 1723 error = mnt_want_write(nd.path.mnt);
1737 if (error) 1724 if (error)
1738 goto exit_mutex_unlock; 1725 goto exit_mutex_unlock;
1739 error = __open_namei_create(&nd, &path, flag, mode); 1726 error = __open_namei_create(&nd, &path, open_flag, mode);
1740 if (error) { 1727 if (error) {
1741 mnt_drop_write(nd.path.mnt); 1728 mnt_drop_write(nd.path.mnt);
1742 goto exit; 1729 goto exit;
@@ -1798,7 +1785,7 @@ ok:
1798 if (error) 1785 if (error)
1799 goto exit; 1786 goto exit;
1800 } 1787 }
1801 error = may_open(&nd.path, acc_mode, flag); 1788 error = may_open(&nd.path, acc_mode, open_flag);
1802 if (error) { 1789 if (error) {
1803 if (will_truncate) 1790 if (will_truncate)
1804 mnt_drop_write(nd.path.mnt); 1791 mnt_drop_write(nd.path.mnt);
@@ -2275,8 +2262,11 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
2275 error = -EBUSY; 2262 error = -EBUSY;
2276 else { 2263 else {
2277 error = security_inode_unlink(dir, dentry); 2264 error = security_inode_unlink(dir, dentry);
2278 if (!error) 2265 if (!error) {
2279 error = dir->i_op->unlink(dir, dentry); 2266 error = dir->i_op->unlink(dir, dentry);
2267 if (!error)
2268 dentry->d_inode->i_flags |= S_DEAD;
2269 }
2280 } 2270 }
2281 mutex_unlock(&dentry->d_inode->i_mutex); 2271 mutex_unlock(&dentry->d_inode->i_mutex);
2282 2272
@@ -2629,6 +2619,8 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
2629 else 2619 else
2630 error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); 2620 error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
2631 if (!error) { 2621 if (!error) {
2622 if (target)
2623 target->i_flags |= S_DEAD;
2632 if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) 2624 if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))
2633 d_move(old_dentry, new_dentry); 2625 d_move(old_dentry, new_dentry);
2634 } 2626 }
@@ -2671,11 +2663,9 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
2671 error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry); 2663 error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
2672 else 2664 else
2673 error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry); 2665 error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
2674 if (!error) { 2666 if (!error)
2675 const char *new_name = old_dentry->d_name.name; 2667 fsnotify_move(old_dir, new_dir, old_name, is_dir,
2676 fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
2677 new_dentry->d_inode, old_dentry); 2668 new_dentry->d_inode, old_dentry);
2678 }
2679 fsnotify_oldname_free(old_name); 2669 fsnotify_oldname_free(old_name);
2680 2670
2681 return error; 2671 return error;