aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c43
1 files changed, 23 insertions, 20 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 57046d98a746..6ec1f0fefc5b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -501,6 +501,7 @@ struct path {
501static inline int __do_follow_link(struct path *path, struct nameidata *nd) 501static 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);
@@ -2216,7 +2219,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
2216 error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry); 2219 error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
2217 if (!error) { 2220 if (!error) {
2218 const char *new_name = old_dentry->d_name.name; 2221 const char *new_name = old_dentry->d_name.name;
2219 fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, new_dentry->d_inode); 2222 fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
2223 new_dentry->d_inode, old_dentry->d_inode);
2220 } 2224 }
2221 fsnotify_oldname_free(old_name); 2225 fsnotify_oldname_free(old_name);
2222 2226
@@ -2343,15 +2347,17 @@ out:
2343int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) 2347int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
2344{ 2348{
2345 struct nameidata nd; 2349 struct nameidata nd;
2346 int res; 2350 void *cookie;
2351
2347 nd.depth = 0; 2352 nd.depth = 0;
2348 res = dentry->d_inode->i_op->follow_link(dentry, &nd); 2353 cookie = dentry->d_inode->i_op->follow_link(dentry, &nd);
2349 if (!res) { 2354 if (!IS_ERR(cookie)) {
2350 res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); 2355 int res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd));
2351 if (dentry->d_inode->i_op->put_link) 2356 if (dentry->d_inode->i_op->put_link)
2352 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);
2353 } 2359 }
2354 return res; 2360 return PTR_ERR(cookie);
2355} 2361}
2356 2362
2357int vfs_follow_link(struct nameidata *nd, const char *link) 2363int vfs_follow_link(struct nameidata *nd, const char *link)
@@ -2394,23 +2400,20 @@ int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
2394 return res; 2400 return res;
2395} 2401}
2396 2402
2397int page_follow_link_light(struct dentry *dentry, struct nameidata *nd) 2403void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd)
2398{ 2404{
2399 struct page *page; 2405 struct page *page = NULL;
2400 nd_set_link(nd, page_getlink(dentry, &page)); 2406 nd_set_link(nd, page_getlink(dentry, &page));
2401 return 0; 2407 return page;
2402} 2408}
2403 2409
2404void page_put_link(struct dentry *dentry, struct nameidata *nd) 2410void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
2405{ 2411{
2406 if (!IS_ERR(nd_get_link(nd))) { 2412 struct page *page = cookie;
2407 struct page *page; 2413
2408 page = find_get_page(dentry->d_inode->i_mapping, 0); 2414 if (page) {
2409 if (!page)
2410 BUG();
2411 kunmap(page); 2415 kunmap(page);
2412 page_cache_release(page); 2416 page_cache_release(page);
2413 page_cache_release(page);
2414 } 2417 }
2415} 2418}
2416 2419