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 | ||