aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2009-12-26 08:37:05 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2010-03-05 09:01:40 -0500
commitdef4af30cf945a3735ffca865788ea84b30b25d9 (patch)
treeadeac07e1675c51e8d9fa42ccf284b7b893041f1 /fs
parent3866248e5f86d74960a3d1592882490ec3021675 (diff)
Get rid of symlink body copying
Now that nd->last stays around until ->put_link() is called, we can just postpone that ->put_link() in do_filp_open() a bit and don't bother with copying. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/namei.c55
1 files changed, 24 insertions, 31 deletions
diff --git a/fs/namei.c b/fs/namei.c
index adfbaf5c04a7..1f5d86d1fbf5 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -498,8 +498,6 @@ static int link_path_walk(const char *, struct nameidata *);
498 498
499static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link) 499static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
500{ 500{
501 int res = 0;
502 char *name;
503 if (IS_ERR(link)) 501 if (IS_ERR(link))
504 goto fail; 502 goto fail;
505 503
@@ -510,22 +508,7 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l
510 path_get(&nd->root); 508 path_get(&nd->root);
511 } 509 }
512 510
513 res = link_path_walk(link, nd); 511 return link_path_walk(link, nd);
514 if (nd->depth || res || nd->last_type!=LAST_NORM)
515 return res;
516 /*
517 * If it is an iterative symlinks resolution in open_namei() we
518 * have to copy the last component. And all that crap because of
519 * bloody create() on broken symlinks. Furrfu...
520 */
521 name = __getname();
522 if (unlikely(!name)) {
523 path_put(&nd->path);
524 return -ENOMEM;
525 }
526 strcpy(name, nd->last.name);
527 nd->last.name = name;
528 return 0;
529fail: 512fail:
530 path_put(&nd->path); 513 path_put(&nd->path);
531 return PTR_ERR(link); 514 return PTR_ERR(link);
@@ -547,10 +530,10 @@ static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
547 nd->path.dentry = path->dentry; 530 nd->path.dentry = path->dentry;
548} 531}
549 532
550static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) 533static __always_inline int
534__do_follow_link(struct path *path, struct nameidata *nd, void **p)
551{ 535{
552 int error; 536 int error;
553 void *cookie;
554 struct dentry *dentry = path->dentry; 537 struct dentry *dentry = path->dentry;
555 538
556 touch_atime(path->mnt, dentry); 539 touch_atime(path->mnt, dentry);
@@ -562,9 +545,9 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
562 } 545 }
563 mntget(path->mnt); 546 mntget(path->mnt);
564 nd->last_type = LAST_BIND; 547 nd->last_type = LAST_BIND;
565 cookie = dentry->d_inode->i_op->follow_link(dentry, nd); 548 *p = dentry->d_inode->i_op->follow_link(dentry, nd);
566 error = PTR_ERR(cookie); 549 error = PTR_ERR(*p);
567 if (!IS_ERR(cookie)) { 550 if (!IS_ERR(*p)) {
568 char *s = nd_get_link(nd); 551 char *s = nd_get_link(nd);
569 error = 0; 552 error = 0;
570 if (s) 553 if (s)
@@ -574,8 +557,6 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
574 if (error) 557 if (error)
575 path_put(&nd->path); 558 path_put(&nd->path);
576 } 559 }
577 if (dentry->d_inode->i_op->put_link)
578 dentry->d_inode->i_op->put_link(dentry, nd, cookie);
579 } 560 }
580 return error; 561 return error;
581} 562}
@@ -589,6 +570,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
589 */ 570 */
590static inline int do_follow_link(struct path *path, struct nameidata *nd) 571static inline int do_follow_link(struct path *path, struct nameidata *nd)
591{ 572{
573 void *cookie;
592 int err = -ELOOP; 574 int err = -ELOOP;
593 if (current->link_count >= MAX_NESTED_LINKS) 575 if (current->link_count >= MAX_NESTED_LINKS)
594 goto loop; 576 goto loop;
@@ -602,7 +584,9 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd)
602 current->link_count++; 584 current->link_count++;
603 current->total_link_count++; 585 current->total_link_count++;
604 nd->depth++; 586 nd->depth++;
605 err = __do_follow_link(path, nd); 587 err = __do_follow_link(path, nd, &cookie);
588 if (!IS_ERR(cookie) && path->dentry->d_inode->i_op->put_link)
589 path->dentry->d_inode->i_op->put_link(path->dentry, nd, cookie);
606 path_put(path); 590 path_put(path);
607 current->link_count--; 591 current->link_count--;
608 nd->depth--; 592 nd->depth--;
@@ -1847,6 +1831,9 @@ reval:
1847 nd.flags |= LOOKUP_EXCL; 1831 nd.flags |= LOOKUP_EXCL;
1848 filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); 1832 filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
1849 while (unlikely(!filp)) { /* trailing symlink */ 1833 while (unlikely(!filp)) { /* trailing symlink */
1834 struct path holder;
1835 struct inode *inode;
1836 void *cookie;
1850 error = -ELOOP; 1837 error = -ELOOP;
1851 if ((open_flag & O_NOFOLLOW) || count++ == 32) 1838 if ((open_flag & O_NOFOLLOW) || count++ == 32)
1852 goto exit_dput; 1839 goto exit_dput;
@@ -1865,18 +1852,24 @@ reval:
1865 error = security_inode_follow_link(path.dentry, &nd); 1852 error = security_inode_follow_link(path.dentry, &nd);
1866 if (error) 1853 if (error)
1867 goto exit_dput; 1854 goto exit_dput;
1868 error = __do_follow_link(&path, &nd); 1855 error = __do_follow_link(&path, &nd, &cookie);
1869 path_put(&path); 1856 if (unlikely(error)) {
1870 if (error) {
1871 /* nd.path had been dropped */ 1857 /* nd.path had been dropped */
1858 inode = path.dentry->d_inode;
1859 if (!IS_ERR(cookie) && inode->i_op->put_link)
1860 inode->i_op->put_link(path.dentry, &nd, cookie);
1861 path_put(&path);
1872 release_open_intent(&nd); 1862 release_open_intent(&nd);
1873 filp = ERR_PTR(error); 1863 filp = ERR_PTR(error);
1874 goto out; 1864 goto out;
1875 } 1865 }
1866 holder = path;
1876 nd.flags &= ~LOOKUP_PARENT; 1867 nd.flags &= ~LOOKUP_PARENT;
1877 filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); 1868 filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
1878 if (nd.last_type == LAST_NORM) 1869 inode = holder.dentry->d_inode;
1879 __putname(nd.last.name); 1870 if (inode->i_op->put_link)
1871 inode->i_op->put_link(holder.dentry, &nd, cookie);
1872 path_put(&holder);
1880 } 1873 }
1881out: 1874out:
1882 if (nd.root.mnt) 1875 if (nd.root.mnt)