diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 101 |
1 files changed, 51 insertions, 50 deletions
diff --git a/fs/namei.c b/fs/namei.c index 6dbbd42d8b95..33fb5bd34a81 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/syscalls.h> | 28 | #include <linux/syscalls.h> |
29 | #include <linux/mount.h> | 29 | #include <linux/mount.h> |
30 | #include <linux/audit.h> | 30 | #include <linux/audit.h> |
31 | #include <linux/capability.h> | ||
31 | #include <linux/file.h> | 32 | #include <linux/file.h> |
32 | #include <asm/namei.h> | 33 | #include <asm/namei.h> |
33 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
@@ -112,7 +113,7 @@ | |||
112 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). | 113 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). |
113 | * PATH_MAX includes the nul terminator --RR. | 114 | * PATH_MAX includes the nul terminator --RR. |
114 | */ | 115 | */ |
115 | static inline int do_getname(const char __user *filename, char *page) | 116 | static int do_getname(const char __user *filename, char *page) |
116 | { | 117 | { |
117 | int retval; | 118 | int retval; |
118 | unsigned long len = PATH_MAX; | 119 | unsigned long len = PATH_MAX; |
@@ -395,7 +396,7 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, | |||
395 | * short-cut DAC fails, then call permission() to do more | 396 | * short-cut DAC fails, then call permission() to do more |
396 | * complete permission check. | 397 | * complete permission check. |
397 | */ | 398 | */ |
398 | static inline int exec_permission_lite(struct inode *inode, | 399 | static int exec_permission_lite(struct inode *inode, |
399 | struct nameidata *nd) | 400 | struct nameidata *nd) |
400 | { | 401 | { |
401 | umode_t mode = inode->i_mode; | 402 | umode_t mode = inode->i_mode; |
@@ -438,7 +439,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s | |||
438 | struct dentry * result; | 439 | struct dentry * result; |
439 | struct inode *dir = parent->d_inode; | 440 | struct inode *dir = parent->d_inode; |
440 | 441 | ||
441 | down(&dir->i_sem); | 442 | mutex_lock(&dir->i_mutex); |
442 | /* | 443 | /* |
443 | * First re-do the cached lookup just in case it was created | 444 | * First re-do the cached lookup just in case it was created |
444 | * while we waited for the directory semaphore.. | 445 | * while we waited for the directory semaphore.. |
@@ -464,7 +465,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s | |||
464 | else | 465 | else |
465 | result = dentry; | 466 | result = dentry; |
466 | } | 467 | } |
467 | up(&dir->i_sem); | 468 | mutex_unlock(&dir->i_mutex); |
468 | return result; | 469 | return result; |
469 | } | 470 | } |
470 | 471 | ||
@@ -472,7 +473,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s | |||
472 | * Uhhuh! Nasty case: the cache was re-populated while | 473 | * Uhhuh! Nasty case: the cache was re-populated while |
473 | * we waited on the semaphore. Need to revalidate. | 474 | * we waited on the semaphore. Need to revalidate. |
474 | */ | 475 | */ |
475 | up(&dir->i_sem); | 476 | mutex_unlock(&dir->i_mutex); |
476 | if (result->d_op && result->d_op->d_revalidate) { | 477 | if (result->d_op && result->d_op->d_revalidate) { |
477 | if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) { | 478 | if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) { |
478 | dput(result); | 479 | dput(result); |
@@ -485,7 +486,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s | |||
485 | static int __emul_lookup_dentry(const char *, struct nameidata *); | 486 | static int __emul_lookup_dentry(const char *, struct nameidata *); |
486 | 487 | ||
487 | /* SMP-safe */ | 488 | /* SMP-safe */ |
488 | static inline int | 489 | static __always_inline int |
489 | walk_init_root(const char *name, struct nameidata *nd) | 490 | walk_init_root(const char *name, struct nameidata *nd) |
490 | { | 491 | { |
491 | read_lock(¤t->fs->lock); | 492 | read_lock(¤t->fs->lock); |
@@ -503,7 +504,7 @@ walk_init_root(const char *name, struct nameidata *nd) | |||
503 | return 1; | 504 | return 1; |
504 | } | 505 | } |
505 | 506 | ||
506 | static inline int __vfs_follow_link(struct nameidata *nd, const char *link) | 507 | static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link) |
507 | { | 508 | { |
508 | int res = 0; | 509 | int res = 0; |
509 | char *name; | 510 | char *name; |
@@ -543,7 +544,7 @@ struct path { | |||
543 | struct dentry *dentry; | 544 | struct dentry *dentry; |
544 | }; | 545 | }; |
545 | 546 | ||
546 | static inline int __do_follow_link(struct path *path, struct nameidata *nd) | 547 | static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) |
547 | { | 548 | { |
548 | int error; | 549 | int error; |
549 | void *cookie; | 550 | void *cookie; |
@@ -689,7 +690,7 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry) | |||
689 | return 0; | 690 | return 0; |
690 | } | 691 | } |
691 | 692 | ||
692 | static inline void follow_dotdot(struct nameidata *nd) | 693 | static __always_inline void follow_dotdot(struct nameidata *nd) |
693 | { | 694 | { |
694 | while(1) { | 695 | while(1) { |
695 | struct vfsmount *parent; | 696 | struct vfsmount *parent; |
@@ -1293,7 +1294,7 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) | |||
1293 | * 10. We don't allow removal of NFS sillyrenamed files; it's handled by | 1294 | * 10. We don't allow removal of NFS sillyrenamed files; it's handled by |
1294 | * nfs_async_unlink(). | 1295 | * nfs_async_unlink(). |
1295 | */ | 1296 | */ |
1296 | static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir) | 1297 | static int may_delete(struct inode *dir,struct dentry *victim,int isdir) |
1297 | { | 1298 | { |
1298 | int error; | 1299 | int error; |
1299 | 1300 | ||
@@ -1366,7 +1367,7 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) | |||
1366 | struct dentry *p; | 1367 | struct dentry *p; |
1367 | 1368 | ||
1368 | if (p1 == p2) { | 1369 | if (p1 == p2) { |
1369 | down(&p1->d_inode->i_sem); | 1370 | mutex_lock(&p1->d_inode->i_mutex); |
1370 | return NULL; | 1371 | return NULL; |
1371 | } | 1372 | } |
1372 | 1373 | ||
@@ -1374,30 +1375,30 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) | |||
1374 | 1375 | ||
1375 | for (p = p1; p->d_parent != p; p = p->d_parent) { | 1376 | for (p = p1; p->d_parent != p; p = p->d_parent) { |
1376 | if (p->d_parent == p2) { | 1377 | if (p->d_parent == p2) { |
1377 | down(&p2->d_inode->i_sem); | 1378 | mutex_lock(&p2->d_inode->i_mutex); |
1378 | down(&p1->d_inode->i_sem); | 1379 | mutex_lock(&p1->d_inode->i_mutex); |
1379 | return p; | 1380 | return p; |
1380 | } | 1381 | } |
1381 | } | 1382 | } |
1382 | 1383 | ||
1383 | for (p = p2; p->d_parent != p; p = p->d_parent) { | 1384 | for (p = p2; p->d_parent != p; p = p->d_parent) { |
1384 | if (p->d_parent == p1) { | 1385 | if (p->d_parent == p1) { |
1385 | down(&p1->d_inode->i_sem); | 1386 | mutex_lock(&p1->d_inode->i_mutex); |
1386 | down(&p2->d_inode->i_sem); | 1387 | mutex_lock(&p2->d_inode->i_mutex); |
1387 | return p; | 1388 | return p; |
1388 | } | 1389 | } |
1389 | } | 1390 | } |
1390 | 1391 | ||
1391 | down(&p1->d_inode->i_sem); | 1392 | mutex_lock(&p1->d_inode->i_mutex); |
1392 | down(&p2->d_inode->i_sem); | 1393 | mutex_lock(&p2->d_inode->i_mutex); |
1393 | return NULL; | 1394 | return NULL; |
1394 | } | 1395 | } |
1395 | 1396 | ||
1396 | void unlock_rename(struct dentry *p1, struct dentry *p2) | 1397 | void unlock_rename(struct dentry *p1, struct dentry *p2) |
1397 | { | 1398 | { |
1398 | up(&p1->d_inode->i_sem); | 1399 | mutex_unlock(&p1->d_inode->i_mutex); |
1399 | if (p1 != p2) { | 1400 | if (p1 != p2) { |
1400 | up(&p2->d_inode->i_sem); | 1401 | mutex_unlock(&p2->d_inode->i_mutex); |
1401 | up(&p1->d_inode->i_sb->s_vfs_rename_sem); | 1402 | up(&p1->d_inode->i_sb->s_vfs_rename_sem); |
1402 | } | 1403 | } |
1403 | } | 1404 | } |
@@ -1491,7 +1492,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1491 | if (!error) { | 1492 | if (!error) { |
1492 | DQUOT_INIT(inode); | 1493 | DQUOT_INIT(inode); |
1493 | 1494 | ||
1494 | error = do_truncate(dentry, 0, NULL); | 1495 | error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL); |
1495 | } | 1496 | } |
1496 | put_write_access(inode); | 1497 | put_write_access(inode); |
1497 | if (error) | 1498 | if (error) |
@@ -1563,14 +1564,14 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) | |||
1563 | 1564 | ||
1564 | dir = nd->dentry; | 1565 | dir = nd->dentry; |
1565 | nd->flags &= ~LOOKUP_PARENT; | 1566 | nd->flags &= ~LOOKUP_PARENT; |
1566 | down(&dir->d_inode->i_sem); | 1567 | mutex_lock(&dir->d_inode->i_mutex); |
1567 | path.dentry = lookup_hash(nd); | 1568 | path.dentry = lookup_hash(nd); |
1568 | path.mnt = nd->mnt; | 1569 | path.mnt = nd->mnt; |
1569 | 1570 | ||
1570 | do_last: | 1571 | do_last: |
1571 | error = PTR_ERR(path.dentry); | 1572 | error = PTR_ERR(path.dentry); |
1572 | if (IS_ERR(path.dentry)) { | 1573 | if (IS_ERR(path.dentry)) { |
1573 | up(&dir->d_inode->i_sem); | 1574 | mutex_unlock(&dir->d_inode->i_mutex); |
1574 | goto exit; | 1575 | goto exit; |
1575 | } | 1576 | } |
1576 | 1577 | ||
@@ -1579,7 +1580,7 @@ do_last: | |||
1579 | if (!IS_POSIXACL(dir->d_inode)) | 1580 | if (!IS_POSIXACL(dir->d_inode)) |
1580 | mode &= ~current->fs->umask; | 1581 | mode &= ~current->fs->umask; |
1581 | error = vfs_create(dir->d_inode, path.dentry, mode, nd); | 1582 | error = vfs_create(dir->d_inode, path.dentry, mode, nd); |
1582 | up(&dir->d_inode->i_sem); | 1583 | mutex_unlock(&dir->d_inode->i_mutex); |
1583 | dput(nd->dentry); | 1584 | dput(nd->dentry); |
1584 | nd->dentry = path.dentry; | 1585 | nd->dentry = path.dentry; |
1585 | if (error) | 1586 | if (error) |
@@ -1593,7 +1594,7 @@ do_last: | |||
1593 | /* | 1594 | /* |
1594 | * It already exists. | 1595 | * It already exists. |
1595 | */ | 1596 | */ |
1596 | up(&dir->d_inode->i_sem); | 1597 | mutex_unlock(&dir->d_inode->i_mutex); |
1597 | 1598 | ||
1598 | error = -EEXIST; | 1599 | error = -EEXIST; |
1599 | if (flag & O_EXCL) | 1600 | if (flag & O_EXCL) |
@@ -1665,7 +1666,7 @@ do_link: | |||
1665 | goto exit; | 1666 | goto exit; |
1666 | } | 1667 | } |
1667 | dir = nd->dentry; | 1668 | dir = nd->dentry; |
1668 | down(&dir->d_inode->i_sem); | 1669 | mutex_lock(&dir->d_inode->i_mutex); |
1669 | path.dentry = lookup_hash(nd); | 1670 | path.dentry = lookup_hash(nd); |
1670 | path.mnt = nd->mnt; | 1671 | path.mnt = nd->mnt; |
1671 | __putname(nd->last.name); | 1672 | __putname(nd->last.name); |
@@ -1680,13 +1681,13 @@ do_link: | |||
1680 | * Simple function to lookup and return a dentry and create it | 1681 | * Simple function to lookup and return a dentry and create it |
1681 | * if it doesn't exist. Is SMP-safe. | 1682 | * if it doesn't exist. Is SMP-safe. |
1682 | * | 1683 | * |
1683 | * Returns with nd->dentry->d_inode->i_sem locked. | 1684 | * Returns with nd->dentry->d_inode->i_mutex locked. |
1684 | */ | 1685 | */ |
1685 | struct dentry *lookup_create(struct nameidata *nd, int is_dir) | 1686 | struct dentry *lookup_create(struct nameidata *nd, int is_dir) |
1686 | { | 1687 | { |
1687 | struct dentry *dentry = ERR_PTR(-EEXIST); | 1688 | struct dentry *dentry = ERR_PTR(-EEXIST); |
1688 | 1689 | ||
1689 | down(&nd->dentry->d_inode->i_sem); | 1690 | mutex_lock(&nd->dentry->d_inode->i_mutex); |
1690 | /* | 1691 | /* |
1691 | * Yucky last component or no last component at all? | 1692 | * Yucky last component or no last component at all? |
1692 | * (foo/., foo/.., /////) | 1693 | * (foo/., foo/.., /////) |
@@ -1784,7 +1785,7 @@ asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev) | |||
1784 | } | 1785 | } |
1785 | dput(dentry); | 1786 | dput(dentry); |
1786 | } | 1787 | } |
1787 | up(&nd.dentry->d_inode->i_sem); | 1788 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
1788 | path_release(&nd); | 1789 | path_release(&nd); |
1789 | out: | 1790 | out: |
1790 | putname(tmp); | 1791 | putname(tmp); |
@@ -1836,7 +1837,7 @@ asmlinkage long sys_mkdir(const char __user * pathname, int mode) | |||
1836 | error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); | 1837 | error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); |
1837 | dput(dentry); | 1838 | dput(dentry); |
1838 | } | 1839 | } |
1839 | up(&nd.dentry->d_inode->i_sem); | 1840 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
1840 | path_release(&nd); | 1841 | path_release(&nd); |
1841 | out: | 1842 | out: |
1842 | putname(tmp); | 1843 | putname(tmp); |
@@ -1885,7 +1886,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1885 | 1886 | ||
1886 | DQUOT_INIT(dir); | 1887 | DQUOT_INIT(dir); |
1887 | 1888 | ||
1888 | down(&dentry->d_inode->i_sem); | 1889 | mutex_lock(&dentry->d_inode->i_mutex); |
1889 | dentry_unhash(dentry); | 1890 | dentry_unhash(dentry); |
1890 | if (d_mountpoint(dentry)) | 1891 | if (d_mountpoint(dentry)) |
1891 | error = -EBUSY; | 1892 | error = -EBUSY; |
@@ -1897,7 +1898,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1897 | dentry->d_inode->i_flags |= S_DEAD; | 1898 | dentry->d_inode->i_flags |= S_DEAD; |
1898 | } | 1899 | } |
1899 | } | 1900 | } |
1900 | up(&dentry->d_inode->i_sem); | 1901 | mutex_unlock(&dentry->d_inode->i_mutex); |
1901 | if (!error) { | 1902 | if (!error) { |
1902 | d_delete(dentry); | 1903 | d_delete(dentry); |
1903 | } | 1904 | } |
@@ -1932,14 +1933,14 @@ asmlinkage long sys_rmdir(const char __user * pathname) | |||
1932 | error = -EBUSY; | 1933 | error = -EBUSY; |
1933 | goto exit1; | 1934 | goto exit1; |
1934 | } | 1935 | } |
1935 | down(&nd.dentry->d_inode->i_sem); | 1936 | mutex_lock(&nd.dentry->d_inode->i_mutex); |
1936 | dentry = lookup_hash(&nd); | 1937 | dentry = lookup_hash(&nd); |
1937 | error = PTR_ERR(dentry); | 1938 | error = PTR_ERR(dentry); |
1938 | if (!IS_ERR(dentry)) { | 1939 | if (!IS_ERR(dentry)) { |
1939 | error = vfs_rmdir(nd.dentry->d_inode, dentry); | 1940 | error = vfs_rmdir(nd.dentry->d_inode, dentry); |
1940 | dput(dentry); | 1941 | dput(dentry); |
1941 | } | 1942 | } |
1942 | up(&nd.dentry->d_inode->i_sem); | 1943 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
1943 | exit1: | 1944 | exit1: |
1944 | path_release(&nd); | 1945 | path_release(&nd); |
1945 | exit: | 1946 | exit: |
@@ -1959,7 +1960,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1959 | 1960 | ||
1960 | DQUOT_INIT(dir); | 1961 | DQUOT_INIT(dir); |
1961 | 1962 | ||
1962 | down(&dentry->d_inode->i_sem); | 1963 | mutex_lock(&dentry->d_inode->i_mutex); |
1963 | if (d_mountpoint(dentry)) | 1964 | if (d_mountpoint(dentry)) |
1964 | error = -EBUSY; | 1965 | error = -EBUSY; |
1965 | else { | 1966 | else { |
@@ -1967,7 +1968,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1967 | if (!error) | 1968 | if (!error) |
1968 | error = dir->i_op->unlink(dir, dentry); | 1969 | error = dir->i_op->unlink(dir, dentry); |
1969 | } | 1970 | } |
1970 | up(&dentry->d_inode->i_sem); | 1971 | mutex_unlock(&dentry->d_inode->i_mutex); |
1971 | 1972 | ||
1972 | /* We don't d_delete() NFS sillyrenamed files--they still exist. */ | 1973 | /* We don't d_delete() NFS sillyrenamed files--they still exist. */ |
1973 | if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { | 1974 | if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { |
@@ -1979,7 +1980,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1979 | 1980 | ||
1980 | /* | 1981 | /* |
1981 | * Make sure that the actual truncation of the file will occur outside its | 1982 | * Make sure that the actual truncation of the file will occur outside its |
1982 | * directory's i_sem. Truncate can take a long time if there is a lot of | 1983 | * directory's i_mutex. Truncate can take a long time if there is a lot of |
1983 | * writeout happening, and we don't want to prevent access to the directory | 1984 | * writeout happening, and we don't want to prevent access to the directory |
1984 | * while waiting on the I/O. | 1985 | * while waiting on the I/O. |
1985 | */ | 1986 | */ |
@@ -2001,7 +2002,7 @@ asmlinkage long sys_unlink(const char __user * pathname) | |||
2001 | error = -EISDIR; | 2002 | error = -EISDIR; |
2002 | if (nd.last_type != LAST_NORM) | 2003 | if (nd.last_type != LAST_NORM) |
2003 | goto exit1; | 2004 | goto exit1; |
2004 | down(&nd.dentry->d_inode->i_sem); | 2005 | mutex_lock(&nd.dentry->d_inode->i_mutex); |
2005 | dentry = lookup_hash(&nd); | 2006 | dentry = lookup_hash(&nd); |
2006 | error = PTR_ERR(dentry); | 2007 | error = PTR_ERR(dentry); |
2007 | if (!IS_ERR(dentry)) { | 2008 | if (!IS_ERR(dentry)) { |
@@ -2015,7 +2016,7 @@ asmlinkage long sys_unlink(const char __user * pathname) | |||
2015 | exit2: | 2016 | exit2: |
2016 | dput(dentry); | 2017 | dput(dentry); |
2017 | } | 2018 | } |
2018 | up(&nd.dentry->d_inode->i_sem); | 2019 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
2019 | if (inode) | 2020 | if (inode) |
2020 | iput(inode); /* truncate the inode here */ | 2021 | iput(inode); /* truncate the inode here */ |
2021 | exit1: | 2022 | exit1: |
@@ -2075,7 +2076,7 @@ asmlinkage long sys_symlink(const char __user * oldname, const char __user * new | |||
2075 | error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO); | 2076 | error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO); |
2076 | dput(dentry); | 2077 | dput(dentry); |
2077 | } | 2078 | } |
2078 | up(&nd.dentry->d_inode->i_sem); | 2079 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
2079 | path_release(&nd); | 2080 | path_release(&nd); |
2080 | out: | 2081 | out: |
2081 | putname(to); | 2082 | putname(to); |
@@ -2113,10 +2114,10 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de | |||
2113 | if (error) | 2114 | if (error) |
2114 | return error; | 2115 | return error; |
2115 | 2116 | ||
2116 | down(&old_dentry->d_inode->i_sem); | 2117 | mutex_lock(&old_dentry->d_inode->i_mutex); |
2117 | DQUOT_INIT(dir); | 2118 | DQUOT_INIT(dir); |
2118 | error = dir->i_op->link(old_dentry, dir, new_dentry); | 2119 | error = dir->i_op->link(old_dentry, dir, new_dentry); |
2119 | up(&old_dentry->d_inode->i_sem); | 2120 | mutex_unlock(&old_dentry->d_inode->i_mutex); |
2120 | if (!error) | 2121 | if (!error) |
2121 | fsnotify_create(dir, new_dentry->d_name.name); | 2122 | fsnotify_create(dir, new_dentry->d_name.name); |
2122 | return error; | 2123 | return error; |
@@ -2157,7 +2158,7 @@ asmlinkage long sys_link(const char __user * oldname, const char __user * newnam | |||
2157 | error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); | 2158 | error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); |
2158 | dput(new_dentry); | 2159 | dput(new_dentry); |
2159 | } | 2160 | } |
2160 | up(&nd.dentry->d_inode->i_sem); | 2161 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
2161 | out_release: | 2162 | out_release: |
2162 | path_release(&nd); | 2163 | path_release(&nd); |
2163 | out: | 2164 | out: |
@@ -2178,7 +2179,7 @@ exit: | |||
2178 | * sb->s_vfs_rename_sem. We might be more accurate, but that's another | 2179 | * sb->s_vfs_rename_sem. We might be more accurate, but that's another |
2179 | * story. | 2180 | * story. |
2180 | * c) we have to lock _three_ objects - parents and victim (if it exists). | 2181 | * c) we have to lock _three_ objects - parents and victim (if it exists). |
2181 | * And that - after we got ->i_sem on parents (until then we don't know | 2182 | * And that - after we got ->i_mutex on parents (until then we don't know |
2182 | * whether the target exists). Solution: try to be smart with locking | 2183 | * whether the target exists). Solution: try to be smart with locking |
2183 | * order for inodes. We rely on the fact that tree topology may change | 2184 | * order for inodes. We rely on the fact that tree topology may change |
2184 | * only under ->s_vfs_rename_sem _and_ that parent of the object we | 2185 | * only under ->s_vfs_rename_sem _and_ that parent of the object we |
@@ -2195,9 +2196,9 @@ exit: | |||
2195 | * stuff into VFS), but the former is not going away. Solution: the same | 2196 | * stuff into VFS), but the former is not going away. Solution: the same |
2196 | * trick as in rmdir(). | 2197 | * trick as in rmdir(). |
2197 | * e) conversion from fhandle to dentry may come in the wrong moment - when | 2198 | * e) conversion from fhandle to dentry may come in the wrong moment - when |
2198 | * we are removing the target. Solution: we will have to grab ->i_sem | 2199 | * we are removing the target. Solution: we will have to grab ->i_mutex |
2199 | * in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on | 2200 | * in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on |
2200 | * ->i_sem on parents, which works but leads to some truely excessive | 2201 | * ->i_mutex on parents, which works but leads to some truely excessive |
2201 | * locking]. | 2202 | * locking]. |
2202 | */ | 2203 | */ |
2203 | static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, | 2204 | static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, |
@@ -2222,7 +2223,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, | |||
2222 | 2223 | ||
2223 | target = new_dentry->d_inode; | 2224 | target = new_dentry->d_inode; |
2224 | if (target) { | 2225 | if (target) { |
2225 | down(&target->i_sem); | 2226 | mutex_lock(&target->i_mutex); |
2226 | dentry_unhash(new_dentry); | 2227 | dentry_unhash(new_dentry); |
2227 | } | 2228 | } |
2228 | if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) | 2229 | if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) |
@@ -2232,7 +2233,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, | |||
2232 | if (target) { | 2233 | if (target) { |
2233 | if (!error) | 2234 | if (!error) |
2234 | target->i_flags |= S_DEAD; | 2235 | target->i_flags |= S_DEAD; |
2235 | up(&target->i_sem); | 2236 | mutex_unlock(&target->i_mutex); |
2236 | if (d_unhashed(new_dentry)) | 2237 | if (d_unhashed(new_dentry)) |
2237 | d_rehash(new_dentry); | 2238 | d_rehash(new_dentry); |
2238 | dput(new_dentry); | 2239 | dput(new_dentry); |
@@ -2255,7 +2256,7 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, | |||
2255 | dget(new_dentry); | 2256 | dget(new_dentry); |
2256 | target = new_dentry->d_inode; | 2257 | target = new_dentry->d_inode; |
2257 | if (target) | 2258 | if (target) |
2258 | down(&target->i_sem); | 2259 | mutex_lock(&target->i_mutex); |
2259 | if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) | 2260 | if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) |
2260 | error = -EBUSY; | 2261 | error = -EBUSY; |
2261 | else | 2262 | else |
@@ -2266,7 +2267,7 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, | |||
2266 | d_move(old_dentry, new_dentry); | 2267 | d_move(old_dentry, new_dentry); |
2267 | } | 2268 | } |
2268 | if (target) | 2269 | if (target) |
2269 | up(&target->i_sem); | 2270 | mutex_unlock(&target->i_mutex); |
2270 | dput(new_dentry); | 2271 | dput(new_dentry); |
2271 | return error; | 2272 | return error; |
2272 | } | 2273 | } |
@@ -2314,7 +2315,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2314 | return error; | 2315 | return error; |
2315 | } | 2316 | } |
2316 | 2317 | ||
2317 | static inline int do_rename(const char * oldname, const char * newname) | 2318 | static int do_rename(const char * oldname, const char * newname) |
2318 | { | 2319 | { |
2319 | int error = 0; | 2320 | int error = 0; |
2320 | struct dentry * old_dir, * new_dir; | 2321 | struct dentry * old_dir, * new_dir; |