aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c45
1 files changed, 23 insertions, 22 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 4a27eb798118..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);
@@ -1801,7 +1804,6 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
1801 } 1804 }
1802 up(&dentry->d_inode->i_sem); 1805 up(&dentry->d_inode->i_sem);
1803 if (!error) { 1806 if (!error) {
1804 fsnotify_rmdir(dentry, dentry->d_inode, dir);
1805 d_delete(dentry); 1807 d_delete(dentry);
1806 } 1808 }
1807 dput(dentry); 1809 dput(dentry);
@@ -1874,7 +1876,6 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
1874 1876
1875 /* We don't d_delete() NFS sillyrenamed files--they still exist. */ 1877 /* We don't d_delete() NFS sillyrenamed files--they still exist. */
1876 if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { 1878 if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
1877 fsnotify_unlink(dentry, dir);
1878 d_delete(dentry); 1879 d_delete(dentry);
1879 } 1880 }
1880 1881
@@ -2218,7 +2219,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
2218 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);
2219 if (!error) { 2220 if (!error) {
2220 const char *new_name = old_dentry->d_name.name; 2221 const char *new_name = old_dentry->d_name.name;
2221 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);
2222 } 2224 }
2223 fsnotify_oldname_free(old_name); 2225 fsnotify_oldname_free(old_name);
2224 2226
@@ -2345,15 +2347,17 @@ out:
2345int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) 2347int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
2346{ 2348{
2347 struct nameidata nd; 2349 struct nameidata nd;
2348 int res; 2350 void *cookie;
2351
2349 nd.depth = 0; 2352 nd.depth = 0;
2350 res = dentry->d_inode->i_op->follow_link(dentry, &nd); 2353 cookie = dentry->d_inode->i_op->follow_link(dentry, &nd);
2351 if (!res) { 2354 if (!IS_ERR(cookie)) {
2352 res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); 2355 int res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd));
2353 if (dentry->d_inode->i_op->put_link) 2356 if (dentry->d_inode->i_op->put_link)
2354 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);
2355 } 2359 }
2356 return res; 2360 return PTR_ERR(cookie);
2357} 2361}
2358 2362
2359int vfs_follow_link(struct nameidata *nd, const char *link) 2363int vfs_follow_link(struct nameidata *nd, const char *link)
@@ -2396,23 +2400,20 @@ int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
2396 return res; 2400 return res;
2397} 2401}
2398 2402
2399int page_follow_link_light(struct dentry *dentry, struct nameidata *nd) 2403void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd)
2400{ 2404{
2401 struct page *page; 2405 struct page *page = NULL;
2402 nd_set_link(nd, page_getlink(dentry, &page)); 2406 nd_set_link(nd, page_getlink(dentry, &page));
2403 return 0; 2407 return page;
2404} 2408}
2405 2409
2406void page_put_link(struct dentry *dentry, struct nameidata *nd) 2410void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
2407{ 2411{
2408 if (!IS_ERR(nd_get_link(nd))) { 2412 struct page *page = cookie;
2409 struct page *page; 2413
2410 page = find_get_page(dentry->d_inode->i_mapping, 0); 2414 if (page) {
2411 if (!page)
2412 BUG();
2413 kunmap(page); 2415 kunmap(page);
2414 page_cache_release(page); 2416 page_cache_release(page);
2415 page_cache_release(page);
2416 } 2417 }
2417} 2418}
2418 2419