|
@@ -546,6 +546,22 @@ struct path {
|
|
|
struct dentry *dentry;
|
|
|
};
|
|
|
|
|
|
+static inline void dput_path(struct path *path, struct nameidata *nd)
|
|
|
+{
|
|
|
+ dput(path->dentry);
|
|
|
+ if (path->mnt != nd->mnt)
|
|
|
+ mntput(path->mnt);
|
|
|
+}
|
|
|
+
|
|
|
+static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
|
|
|
+{
|
|
|
+ dput(nd->dentry);
|
|
|
+ if (nd->mnt != path->mnt)
|
|
|
+ mntput(nd->mnt);
|
|
|
+ nd->mnt = path->mnt;
|
|
|
+ nd->dentry = path->dentry;
|
|
|
+}
|
|
|
+
|
|
|
static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
|
|
|
{
|
|
|
int error;
|
|
@@ -555,8 +571,11 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
|
|
|
touch_atime(path->mnt, dentry);
|
|
|
nd_set_link(nd, NULL);
|
|
|
|
|
|
- if (path->mnt == nd->mnt)
|
|
|
- mntget(path->mnt);
|
|
|
+ if (path->mnt != nd->mnt) {
|
|
|
+ path_to_nameidata(path, nd);
|
|
|
+ dget(dentry);
|
|
|
+ }
|
|
|
+ mntget(path->mnt);
|
|
|
cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
|
|
|
error = PTR_ERR(cookie);
|
|
|
if (!IS_ERR(cookie)) {
|
|
@@ -573,22 +592,6 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
-static inline void dput_path(struct path *path, struct nameidata *nd)
|
|
|
-{
|
|
|
- dput(path->dentry);
|
|
|
- if (path->mnt != nd->mnt)
|
|
|
- mntput(path->mnt);
|
|
|
-}
|
|
|
-
|
|
|
-static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
|
|
|
-{
|
|
|
- dput(nd->dentry);
|
|
|
- if (nd->mnt != path->mnt)
|
|
|
- mntput(nd->mnt);
|
|
|
- nd->mnt = path->mnt;
|
|
|
- nd->dentry = path->dentry;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* This limits recursive symlink follows to 8, while
|
|
|
* limiting consecutive symlinks to 40.
|