diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 70 |
1 files changed, 47 insertions, 23 deletions
diff --git a/fs/namei.c b/fs/namei.c index 208c6aa4a989..e2ba62820a0f 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1095,8 +1095,10 @@ static struct dentry *d_inode_lookup(struct dentry *parent, struct dentry *dentr | |||
1095 | struct dentry *old; | 1095 | struct dentry *old; |
1096 | 1096 | ||
1097 | /* Don't create child dentry for a dead directory. */ | 1097 | /* Don't create child dentry for a dead directory. */ |
1098 | if (unlikely(IS_DEADDIR(inode))) | 1098 | if (unlikely(IS_DEADDIR(inode))) { |
1099 | dput(dentry); | ||
1099 | return ERR_PTR(-ENOENT); | 1100 | return ERR_PTR(-ENOENT); |
1101 | } | ||
1100 | 1102 | ||
1101 | old = inode->i_op->lookup(inode, dentry, nd); | 1103 | old = inode->i_op->lookup(inode, dentry, nd); |
1102 | if (unlikely(old)) { | 1104 | if (unlikely(old)) { |
@@ -1372,6 +1374,34 @@ static inline int can_lookup(struct inode *inode) | |||
1372 | return 1; | 1374 | return 1; |
1373 | } | 1375 | } |
1374 | 1376 | ||
1377 | unsigned int full_name_hash(const unsigned char *name, unsigned int len) | ||
1378 | { | ||
1379 | unsigned long hash = init_name_hash(); | ||
1380 | while (len--) | ||
1381 | hash = partial_name_hash(*name++, hash); | ||
1382 | return end_name_hash(hash); | ||
1383 | } | ||
1384 | EXPORT_SYMBOL(full_name_hash); | ||
1385 | |||
1386 | /* | ||
1387 | * We know there's a real path component here of at least | ||
1388 | * one character. | ||
1389 | */ | ||
1390 | static inline unsigned long hash_name(const char *name, unsigned int *hashp) | ||
1391 | { | ||
1392 | unsigned long hash = init_name_hash(); | ||
1393 | unsigned long len = 0, c; | ||
1394 | |||
1395 | c = (unsigned char)*name; | ||
1396 | do { | ||
1397 | len++; | ||
1398 | hash = partial_name_hash(c, hash); | ||
1399 | c = (unsigned char)name[len]; | ||
1400 | } while (c && c != '/'); | ||
1401 | *hashp = end_name_hash(hash); | ||
1402 | return len; | ||
1403 | } | ||
1404 | |||
1375 | /* | 1405 | /* |
1376 | * Name resolution. | 1406 | * Name resolution. |
1377 | * This is the basic name resolution function, turning a pathname into | 1407 | * This is the basic name resolution function, turning a pathname into |
@@ -1392,31 +1422,22 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1392 | 1422 | ||
1393 | /* At this point we know we have a real path component. */ | 1423 | /* At this point we know we have a real path component. */ |
1394 | for(;;) { | 1424 | for(;;) { |
1395 | unsigned long hash; | ||
1396 | struct qstr this; | 1425 | struct qstr this; |
1397 | unsigned int c; | 1426 | long len; |
1398 | int type; | 1427 | int type; |
1399 | 1428 | ||
1400 | err = may_lookup(nd); | 1429 | err = may_lookup(nd); |
1401 | if (err) | 1430 | if (err) |
1402 | break; | 1431 | break; |
1403 | 1432 | ||
1433 | len = hash_name(name, &this.hash); | ||
1404 | this.name = name; | 1434 | this.name = name; |
1405 | c = *(const unsigned char *)name; | 1435 | this.len = len; |
1406 | |||
1407 | hash = init_name_hash(); | ||
1408 | do { | ||
1409 | name++; | ||
1410 | hash = partial_name_hash(c, hash); | ||
1411 | c = *(const unsigned char *)name; | ||
1412 | } while (c && (c != '/')); | ||
1413 | this.len = name - (const char *) this.name; | ||
1414 | this.hash = end_name_hash(hash); | ||
1415 | 1436 | ||
1416 | type = LAST_NORM; | 1437 | type = LAST_NORM; |
1417 | if (this.name[0] == '.') switch (this.len) { | 1438 | if (name[0] == '.') switch (len) { |
1418 | case 2: | 1439 | case 2: |
1419 | if (this.name[1] == '.') { | 1440 | if (name[1] == '.') { |
1420 | type = LAST_DOTDOT; | 1441 | type = LAST_DOTDOT; |
1421 | nd->flags |= LOOKUP_JUMPED; | 1442 | nd->flags |= LOOKUP_JUMPED; |
1422 | } | 1443 | } |
@@ -1435,12 +1456,18 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1435 | } | 1456 | } |
1436 | } | 1457 | } |
1437 | 1458 | ||
1438 | /* remove trailing slashes? */ | 1459 | if (!name[len]) |
1439 | if (!c) | ||
1440 | goto last_component; | 1460 | goto last_component; |
1441 | while (*++name == '/'); | 1461 | /* |
1442 | if (!*name) | 1462 | * If it wasn't NUL, we know it was '/'. Skip that |
1463 | * slash, and continue until no more slashes. | ||
1464 | */ | ||
1465 | do { | ||
1466 | len++; | ||
1467 | } while (unlikely(name[len] == '/')); | ||
1468 | if (!name[len]) | ||
1443 | goto last_component; | 1469 | goto last_component; |
1470 | name += len; | ||
1444 | 1471 | ||
1445 | err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW); | 1472 | err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW); |
1446 | if (err < 0) | 1473 | if (err < 0) |
@@ -1773,24 +1800,21 @@ static struct dentry *lookup_hash(struct nameidata *nd) | |||
1773 | struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) | 1800 | struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) |
1774 | { | 1801 | { |
1775 | struct qstr this; | 1802 | struct qstr this; |
1776 | unsigned long hash; | ||
1777 | unsigned int c; | 1803 | unsigned int c; |
1778 | 1804 | ||
1779 | WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex)); | 1805 | WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex)); |
1780 | 1806 | ||
1781 | this.name = name; | 1807 | this.name = name; |
1782 | this.len = len; | 1808 | this.len = len; |
1809 | this.hash = full_name_hash(name, len); | ||
1783 | if (!len) | 1810 | if (!len) |
1784 | return ERR_PTR(-EACCES); | 1811 | return ERR_PTR(-EACCES); |
1785 | 1812 | ||
1786 | hash = init_name_hash(); | ||
1787 | while (len--) { | 1813 | while (len--) { |
1788 | c = *(const unsigned char *)name++; | 1814 | c = *(const unsigned char *)name++; |
1789 | if (c == '/' || c == '\0') | 1815 | if (c == '/' || c == '\0') |
1790 | return ERR_PTR(-EACCES); | 1816 | return ERR_PTR(-EACCES); |
1791 | hash = partial_name_hash(c, hash); | ||
1792 | } | 1817 | } |
1793 | this.hash = end_name_hash(hash); | ||
1794 | /* | 1818 | /* |
1795 | * See if the low-level filesystem might want | 1819 | * See if the low-level filesystem might want |
1796 | * to use its own hash.. | 1820 | * to use its own hash.. |