diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/fs/namei.c b/fs/namei.c index 6e888dd10461..56e9f0f7e761 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1577,19 +1577,35 @@ do_link: | |||
1577 | * | 1577 | * |
1578 | * Simple function to lookup and return a dentry and create it | 1578 | * Simple function to lookup and return a dentry and create it |
1579 | * if it doesn't exist. Is SMP-safe. | 1579 | * if it doesn't exist. Is SMP-safe. |
1580 | * | ||
1581 | * Returns with nd->dentry->d_inode->i_sem locked. | ||
1580 | */ | 1582 | */ |
1581 | struct dentry *lookup_create(struct nameidata *nd, int is_dir) | 1583 | struct dentry *lookup_create(struct nameidata *nd, int is_dir) |
1582 | { | 1584 | { |
1583 | struct dentry *dentry; | 1585 | struct dentry *dentry = ERR_PTR(-EEXIST); |
1584 | 1586 | ||
1585 | down(&nd->dentry->d_inode->i_sem); | 1587 | down(&nd->dentry->d_inode->i_sem); |
1586 | dentry = ERR_PTR(-EEXIST); | 1588 | /* |
1589 | * Yucky last component or no last component at all? | ||
1590 | * (foo/., foo/.., /////) | ||
1591 | */ | ||
1587 | if (nd->last_type != LAST_NORM) | 1592 | if (nd->last_type != LAST_NORM) |
1588 | goto fail; | 1593 | goto fail; |
1589 | nd->flags &= ~LOOKUP_PARENT; | 1594 | nd->flags &= ~LOOKUP_PARENT; |
1595 | |||
1596 | /* | ||
1597 | * Do the final lookup. | ||
1598 | */ | ||
1590 | dentry = lookup_hash(&nd->last, nd->dentry); | 1599 | dentry = lookup_hash(&nd->last, nd->dentry); |
1591 | if (IS_ERR(dentry)) | 1600 | if (IS_ERR(dentry)) |
1592 | goto fail; | 1601 | goto fail; |
1602 | |||
1603 | /* | ||
1604 | * Special case - lookup gave negative, but... we had foo/bar/ | ||
1605 | * From the vfs_mknod() POV we just have a negative dentry - | ||
1606 | * all is fine. Let's be bastards - you had / on the end, you've | ||
1607 | * been asking for (non-existent) directory. -ENOENT for you. | ||
1608 | */ | ||
1593 | if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) | 1609 | if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) |
1594 | goto enoent; | 1610 | goto enoent; |
1595 | return dentry; | 1611 | return dentry; |