diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 45 |
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 { | |||
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); |
@@ -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: | |||
2345 | int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) | 2347 | int 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 | ||
2359 | int vfs_follow_link(struct nameidata *nd, const char *link) | 2363 | int 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 | ||
2399 | int page_follow_link_light(struct dentry *dentry, struct nameidata *nd) | 2403 | void *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 | ||
2406 | void page_put_link(struct dentry *dentry, struct nameidata *nd) | 2410 | void 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 | ||