diff options
Diffstat (limited to 'fs/namei.c')
| -rw-r--r-- | fs/namei.c | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/fs/namei.c b/fs/namei.c index b85f158aef0c..6ec1f0fefc5b 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -501,6 +501,7 @@ struct path { | |||
| 501 | static inline int __do_follow_link(struct path *path, struct nameidata *nd) | 501 | static inline int __do_follow_link(struct path *path, struct nameidata *nd) |
| 502 | { | 502 | { |
| 503 | int error; | 503 | int error; |
| 504 | void *cookie; | ||
| 504 | struct dentry *dentry = path->dentry; | 505 | struct dentry *dentry = path->dentry; |
| 505 | 506 | ||
| 506 | touch_atime(path->mnt, dentry); | 507 | touch_atime(path->mnt, dentry); |
| @@ -508,13 +509,15 @@ static inline int __do_follow_link(struct path *path, struct nameidata *nd) | |||
| 508 | 509 | ||
| 509 | if (path->mnt == nd->mnt) | 510 | if (path->mnt == nd->mnt) |
| 510 | mntget(path->mnt); | 511 | mntget(path->mnt); |
| 511 | error = dentry->d_inode->i_op->follow_link(dentry, nd); | 512 | cookie = dentry->d_inode->i_op->follow_link(dentry, nd); |
| 512 | if (!error) { | 513 | error = PTR_ERR(cookie); |
| 514 | if (!IS_ERR(cookie)) { | ||
| 513 | char *s = nd_get_link(nd); | 515 | char *s = nd_get_link(nd); |
| 516 | error = 0; | ||
| 514 | if (s) | 517 | if (s) |
| 515 | error = __vfs_follow_link(nd, s); | 518 | error = __vfs_follow_link(nd, s); |
| 516 | if (dentry->d_inode->i_op->put_link) | 519 | if (dentry->d_inode->i_op->put_link) |
| 517 | dentry->d_inode->i_op->put_link(dentry, nd); | 520 | dentry->d_inode->i_op->put_link(dentry, nd, cookie); |
| 518 | } | 521 | } |
| 519 | dput(dentry); | 522 | dput(dentry); |
| 520 | mntput(path->mnt); | 523 | mntput(path->mnt); |
| @@ -2344,15 +2347,17 @@ out: | |||
| 2344 | int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) | 2347 | int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) |
| 2345 | { | 2348 | { |
| 2346 | struct nameidata nd; | 2349 | struct nameidata nd; |
| 2347 | int res; | 2350 | void *cookie; |
| 2351 | |||
| 2348 | nd.depth = 0; | 2352 | nd.depth = 0; |
| 2349 | res = dentry->d_inode->i_op->follow_link(dentry, &nd); | 2353 | cookie = dentry->d_inode->i_op->follow_link(dentry, &nd); |
| 2350 | if (!res) { | 2354 | if (!IS_ERR(cookie)) { |
| 2351 | res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); | 2355 | int res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); |
| 2352 | if (dentry->d_inode->i_op->put_link) | 2356 | if (dentry->d_inode->i_op->put_link) |
| 2353 | dentry->d_inode->i_op->put_link(dentry, &nd); | 2357 | dentry->d_inode->i_op->put_link(dentry, &nd, cookie); |
| 2358 | cookie = ERR_PTR(res); | ||
| 2354 | } | 2359 | } |
| 2355 | return res; | 2360 | return PTR_ERR(cookie); |
| 2356 | } | 2361 | } |
| 2357 | 2362 | ||
| 2358 | int vfs_follow_link(struct nameidata *nd, const char *link) | 2363 | int vfs_follow_link(struct nameidata *nd, const char *link) |
| @@ -2395,23 +2400,20 @@ int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) | |||
| 2395 | return res; | 2400 | return res; |
| 2396 | } | 2401 | } |
| 2397 | 2402 | ||
| 2398 | int page_follow_link_light(struct dentry *dentry, struct nameidata *nd) | 2403 | void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd) |
| 2399 | { | 2404 | { |
| 2400 | struct page *page; | 2405 | struct page *page = NULL; |
| 2401 | nd_set_link(nd, page_getlink(dentry, &page)); | 2406 | nd_set_link(nd, page_getlink(dentry, &page)); |
| 2402 | return 0; | 2407 | return page; |
| 2403 | } | 2408 | } |
| 2404 | 2409 | ||
| 2405 | void page_put_link(struct dentry *dentry, struct nameidata *nd) | 2410 | void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) |
| 2406 | { | 2411 | { |
| 2407 | if (!IS_ERR(nd_get_link(nd))) { | 2412 | struct page *page = cookie; |
| 2408 | struct page *page; | 2413 | |
| 2409 | page = find_get_page(dentry->d_inode->i_mapping, 0); | 2414 | if (page) { |
| 2410 | if (!page) | ||
| 2411 | BUG(); | ||
| 2412 | kunmap(page); | 2415 | kunmap(page); |
| 2413 | page_cache_release(page); | 2416 | page_cache_release(page); |
| 2414 | page_cache_release(page); | ||
| 2415 | } | 2417 | } |
| 2416 | } | 2418 | } |
| 2417 | 2419 | ||
