Commit 051d381259eb57d6074d02a6ba6e90e744f1a29f

Authored by Ian Kent
Committed by Linus Torvalds
1 parent f75ba3ade8

[PATCH] autofs4: nameidata needs to be up to date for follow_link

In order to be able to trigger a mount using the follow_link inode method the
nameidata struct that is passed in needs to have the vfsmount of the autofs
trigger not its parent.

During a path walk if an autofs trigger is mounted on a dentry, when the
follow_link method is called, the nameidata struct contains the vfsmount and
mountpoint dentry of the parent mount while the dentry that is passed in is
the root of the autofs trigger mount.  I believe it is impossible to get the
vfsmount of the trigger mount, within the follow_link method, when only the
parent vfsmount and the root dentry of the trigger mount are known.

This patch updates the nameidata struct on entry to __do_follow_link if it
detects that it is out of date.  It moves the path_to_nameidata to above
__do_follow_link to facilitate calling it from there.  The dput_path is moved
as well as that seemed sensible.  No changes are made to these two functions.

Signed-off-by: Ian Kent <raven@themaw.net>
Cc: Al Viro <viro@ftp.linux.org.uk>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 1 changed file with 21 additions and 18 deletions Side-by-side Diff

... ... @@ -546,6 +546,22 @@
546 546 struct dentry *dentry;
547 547 };
548 548  
  549 +static inline void dput_path(struct path *path, struct nameidata *nd)
  550 +{
  551 + dput(path->dentry);
  552 + if (path->mnt != nd->mnt)
  553 + mntput(path->mnt);
  554 +}
  555 +
  556 +static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
  557 +{
  558 + dput(nd->dentry);
  559 + if (nd->mnt != path->mnt)
  560 + mntput(nd->mnt);
  561 + nd->mnt = path->mnt;
  562 + nd->dentry = path->dentry;
  563 +}
  564 +
549 565 static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
550 566 {
551 567 int error;
... ... @@ -555,8 +571,11 @@
555 571 touch_atime(path->mnt, dentry);
556 572 nd_set_link(nd, NULL);
557 573  
558   - if (path->mnt == nd->mnt)
559   - mntget(path->mnt);
  574 + if (path->mnt != nd->mnt) {
  575 + path_to_nameidata(path, nd);
  576 + dget(dentry);
  577 + }
  578 + mntget(path->mnt);
560 579 cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
561 580 error = PTR_ERR(cookie);
562 581 if (!IS_ERR(cookie)) {
... ... @@ -571,22 +590,6 @@
571 590 mntput(path->mnt);
572 591  
573 592 return error;
574   -}
575   -
576   -static inline void dput_path(struct path *path, struct nameidata *nd)
577   -{
578   - dput(path->dentry);
579   - if (path->mnt != nd->mnt)
580   - mntput(path->mnt);
581   -}
582   -
583   -static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
584   -{
585   - dput(nd->dentry);
586   - if (nd->mnt != path->mnt)
587   - mntput(nd->mnt);
588   - nd->mnt = path->mnt;
589   - nd->dentry = path->dentry;
590 593 }
591 594  
592 595 /*