diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 67 |
1 files changed, 29 insertions, 38 deletions
diff --git a/fs/namei.c b/fs/namei.c index 43a97ee1d4c8..dc984fee5532 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -600,14 +600,10 @@ static int complete_walk(struct nameidata *nd) | |||
600 | if (likely(!(nd->flags & LOOKUP_JUMPED))) | 600 | if (likely(!(nd->flags & LOOKUP_JUMPED))) |
601 | return 0; | 601 | return 0; |
602 | 602 | ||
603 | if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE))) | 603 | if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE))) |
604 | return 0; | 604 | return 0; |
605 | 605 | ||
606 | if (likely(!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT))) | 606 | status = dentry->d_op->d_weak_revalidate(dentry, nd->flags); |
607 | return 0; | ||
608 | |||
609 | /* Note: we do not d_invalidate() */ | ||
610 | status = d_revalidate(dentry, nd->flags); | ||
611 | if (status > 0) | 607 | if (status > 0) |
612 | return 0; | 608 | return 0; |
613 | 609 | ||
@@ -1342,7 +1338,7 @@ static struct dentry *__lookup_hash(struct qstr *name, | |||
1342 | * small and for now I'd prefer to have fast path as straight as possible. | 1338 | * small and for now I'd prefer to have fast path as straight as possible. |
1343 | * It _is_ time-critical. | 1339 | * It _is_ time-critical. |
1344 | */ | 1340 | */ |
1345 | static int lookup_fast(struct nameidata *nd, struct qstr *name, | 1341 | static int lookup_fast(struct nameidata *nd, |
1346 | struct path *path, struct inode **inode) | 1342 | struct path *path, struct inode **inode) |
1347 | { | 1343 | { |
1348 | struct vfsmount *mnt = nd->path.mnt; | 1344 | struct vfsmount *mnt = nd->path.mnt; |
@@ -1358,7 +1354,7 @@ static int lookup_fast(struct nameidata *nd, struct qstr *name, | |||
1358 | */ | 1354 | */ |
1359 | if (nd->flags & LOOKUP_RCU) { | 1355 | if (nd->flags & LOOKUP_RCU) { |
1360 | unsigned seq; | 1356 | unsigned seq; |
1361 | dentry = __d_lookup_rcu(parent, name, &seq, nd->inode); | 1357 | dentry = __d_lookup_rcu(parent, &nd->last, &seq, nd->inode); |
1362 | if (!dentry) | 1358 | if (!dentry) |
1363 | goto unlazy; | 1359 | goto unlazy; |
1364 | 1360 | ||
@@ -1400,7 +1396,7 @@ unlazy: | |||
1400 | if (unlazy_walk(nd, dentry)) | 1396 | if (unlazy_walk(nd, dentry)) |
1401 | return -ECHILD; | 1397 | return -ECHILD; |
1402 | } else { | 1398 | } else { |
1403 | dentry = __d_lookup(parent, name); | 1399 | dentry = __d_lookup(parent, &nd->last); |
1404 | } | 1400 | } |
1405 | 1401 | ||
1406 | if (unlikely(!dentry)) | 1402 | if (unlikely(!dentry)) |
@@ -1436,8 +1432,7 @@ need_lookup: | |||
1436 | } | 1432 | } |
1437 | 1433 | ||
1438 | /* Fast lookup failed, do it the slow way */ | 1434 | /* Fast lookup failed, do it the slow way */ |
1439 | static int lookup_slow(struct nameidata *nd, struct qstr *name, | 1435 | static int lookup_slow(struct nameidata *nd, struct path *path) |
1440 | struct path *path) | ||
1441 | { | 1436 | { |
1442 | struct dentry *dentry, *parent; | 1437 | struct dentry *dentry, *parent; |
1443 | int err; | 1438 | int err; |
@@ -1446,7 +1441,7 @@ static int lookup_slow(struct nameidata *nd, struct qstr *name, | |||
1446 | BUG_ON(nd->inode != parent->d_inode); | 1441 | BUG_ON(nd->inode != parent->d_inode); |
1447 | 1442 | ||
1448 | mutex_lock(&parent->d_inode->i_mutex); | 1443 | mutex_lock(&parent->d_inode->i_mutex); |
1449 | dentry = __lookup_hash(name, parent, nd->flags); | 1444 | dentry = __lookup_hash(&nd->last, parent, nd->flags); |
1450 | mutex_unlock(&parent->d_inode->i_mutex); | 1445 | mutex_unlock(&parent->d_inode->i_mutex); |
1451 | if (IS_ERR(dentry)) | 1446 | if (IS_ERR(dentry)) |
1452 | return PTR_ERR(dentry); | 1447 | return PTR_ERR(dentry); |
@@ -1519,7 +1514,7 @@ static inline int should_follow_link(struct inode *inode, int follow) | |||
1519 | } | 1514 | } |
1520 | 1515 | ||
1521 | static inline int walk_component(struct nameidata *nd, struct path *path, | 1516 | static inline int walk_component(struct nameidata *nd, struct path *path, |
1522 | struct qstr *name, int type, int follow) | 1517 | int follow) |
1523 | { | 1518 | { |
1524 | struct inode *inode; | 1519 | struct inode *inode; |
1525 | int err; | 1520 | int err; |
@@ -1528,14 +1523,14 @@ static inline int walk_component(struct nameidata *nd, struct path *path, | |||
1528 | * to be able to know about the current root directory and | 1523 | * to be able to know about the current root directory and |
1529 | * parent relationships. | 1524 | * parent relationships. |
1530 | */ | 1525 | */ |
1531 | if (unlikely(type != LAST_NORM)) | 1526 | if (unlikely(nd->last_type != LAST_NORM)) |
1532 | return handle_dots(nd, type); | 1527 | return handle_dots(nd, nd->last_type); |
1533 | err = lookup_fast(nd, name, path, &inode); | 1528 | err = lookup_fast(nd, path, &inode); |
1534 | if (unlikely(err)) { | 1529 | if (unlikely(err)) { |
1535 | if (err < 0) | 1530 | if (err < 0) |
1536 | goto out_err; | 1531 | goto out_err; |
1537 | 1532 | ||
1538 | err = lookup_slow(nd, name, path); | 1533 | err = lookup_slow(nd, path); |
1539 | if (err < 0) | 1534 | if (err < 0) |
1540 | goto out_err; | 1535 | goto out_err; |
1541 | 1536 | ||
@@ -1594,8 +1589,7 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd) | |||
1594 | res = follow_link(&link, nd, &cookie); | 1589 | res = follow_link(&link, nd, &cookie); |
1595 | if (res) | 1590 | if (res) |
1596 | break; | 1591 | break; |
1597 | res = walk_component(nd, path, &nd->last, | 1592 | res = walk_component(nd, path, LOOKUP_FOLLOW); |
1598 | nd->last_type, LOOKUP_FOLLOW); | ||
1599 | put_link(nd, &link, cookie); | 1593 | put_link(nd, &link, cookie); |
1600 | } while (res > 0); | 1594 | } while (res > 0); |
1601 | 1595 | ||
@@ -1802,8 +1796,11 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1802 | } | 1796 | } |
1803 | } | 1797 | } |
1804 | 1798 | ||
1799 | nd->last = this; | ||
1800 | nd->last_type = type; | ||
1801 | |||
1805 | if (!name[len]) | 1802 | if (!name[len]) |
1806 | goto last_component; | 1803 | return 0; |
1807 | /* | 1804 | /* |
1808 | * If it wasn't NUL, we know it was '/'. Skip that | 1805 | * If it wasn't NUL, we know it was '/'. Skip that |
1809 | * slash, and continue until no more slashes. | 1806 | * slash, and continue until no more slashes. |
@@ -1812,10 +1809,11 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1812 | len++; | 1809 | len++; |
1813 | } while (unlikely(name[len] == '/')); | 1810 | } while (unlikely(name[len] == '/')); |
1814 | if (!name[len]) | 1811 | if (!name[len]) |
1815 | goto last_component; | 1812 | return 0; |
1813 | |||
1816 | name += len; | 1814 | name += len; |
1817 | 1815 | ||
1818 | err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW); | 1816 | err = walk_component(nd, &next, LOOKUP_FOLLOW); |
1819 | if (err < 0) | 1817 | if (err < 0) |
1820 | return err; | 1818 | return err; |
1821 | 1819 | ||
@@ -1824,16 +1822,10 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1824 | if (err) | 1822 | if (err) |
1825 | return err; | 1823 | return err; |
1826 | } | 1824 | } |
1827 | if (can_lookup(nd->inode)) | 1825 | if (!can_lookup(nd->inode)) { |
1828 | continue; | 1826 | err = -ENOTDIR; |
1829 | err = -ENOTDIR; | 1827 | break; |
1830 | break; | 1828 | } |
1831 | /* here ends the main loop */ | ||
1832 | |||
1833 | last_component: | ||
1834 | nd->last = this; | ||
1835 | nd->last_type = type; | ||
1836 | return 0; | ||
1837 | } | 1829 | } |
1838 | terminate_walk(nd); | 1830 | terminate_walk(nd); |
1839 | return err; | 1831 | return err; |
@@ -1932,8 +1924,7 @@ static inline int lookup_last(struct nameidata *nd, struct path *path) | |||
1932 | nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; | 1924 | nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; |
1933 | 1925 | ||
1934 | nd->flags &= ~LOOKUP_PARENT; | 1926 | nd->flags &= ~LOOKUP_PARENT; |
1935 | return walk_component(nd, path, &nd->last, nd->last_type, | 1927 | return walk_component(nd, path, nd->flags & LOOKUP_FOLLOW); |
1936 | nd->flags & LOOKUP_FOLLOW); | ||
1937 | } | 1928 | } |
1938 | 1929 | ||
1939 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ | 1930 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ |
@@ -2732,7 +2723,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
2732 | if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW)) | 2723 | if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW)) |
2733 | symlink_ok = true; | 2724 | symlink_ok = true; |
2734 | /* we _can_ be in RCU mode here */ | 2725 | /* we _can_ be in RCU mode here */ |
2735 | error = lookup_fast(nd, &nd->last, path, &inode); | 2726 | error = lookup_fast(nd, path, &inode); |
2736 | if (likely(!error)) | 2727 | if (likely(!error)) |
2737 | goto finish_lookup; | 2728 | goto finish_lookup; |
2738 | 2729 | ||
@@ -2778,7 +2769,7 @@ retry_lookup: | |||
2778 | goto out; | 2769 | goto out; |
2779 | 2770 | ||
2780 | if ((*opened & FILE_CREATED) || | 2771 | if ((*opened & FILE_CREATED) || |
2781 | !S_ISREG(file->f_path.dentry->d_inode->i_mode)) | 2772 | !S_ISREG(file_inode(file)->i_mode)) |
2782 | will_truncate = false; | 2773 | will_truncate = false; |
2783 | 2774 | ||
2784 | audit_inode(name, file->f_path.dentry, 0); | 2775 | audit_inode(name, file->f_path.dentry, 0); |
@@ -2941,8 +2932,8 @@ static struct file *path_openat(int dfd, struct filename *pathname, | |||
2941 | int error; | 2932 | int error; |
2942 | 2933 | ||
2943 | file = get_empty_filp(); | 2934 | file = get_empty_filp(); |
2944 | if (!file) | 2935 | if (IS_ERR(file)) |
2945 | return ERR_PTR(-ENFILE); | 2936 | return file; |
2946 | 2937 | ||
2947 | file->f_flags = op->open_flag; | 2938 | file->f_flags = op->open_flag; |
2948 | 2939 | ||