summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/internal.h2
-rw-r--r--fs/mount.h2
-rw-r--r--fs/namei.c13
-rw-r--r--fs/namespace.c23
-rw-r--r--fs/pnode.c13
5 files changed, 31 insertions, 22 deletions
diff --git a/fs/internal.h b/fs/internal.h
index 7b1cb1528ac2..6aab61a4f36f 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -15,6 +15,7 @@ struct super_block;
struct file_system_type;
struct linux_binprm;
struct path;
+struct mount;
/*
* block_dev.c
@@ -46,7 +47,6 @@ extern void __init chrdev_init(void);
extern int copy_mount_options(const void __user *, unsigned long *);
extern int copy_mount_string(const void __user *, char **);
-extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
extern struct vfsmount *lookup_mnt(struct path *);
extern int finish_automount(struct vfsmount *, struct path *);
diff --git a/fs/mount.h b/fs/mount.h
index 47da8163e1f4..44e5b6f54b7e 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -13,3 +13,5 @@ static inline int mnt_has_parent(struct vfsmount *mnt)
{
return mnt != mnt->mnt_parent;
}
+
+extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
diff --git a/fs/namei.c b/fs/namei.c
index 5008f01787f5..d1c6a559f8f0 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -36,6 +36,7 @@
#include <asm/uaccess.h>
#include "internal.h"
+#include "mount.h"
/* [Feb-1997 T. Schoebel-Theuer]
* Fundamental changes in the pathname lookup mechanisms (namei)
@@ -884,7 +885,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
struct inode **inode)
{
for (;;) {
- struct vfsmount *mounted;
+ struct mount *mounted;
/*
* Don't forget we might have a non-mountpoint managed dentry
* that wants to block transit.
@@ -898,8 +899,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
mounted = __lookup_mnt(path->mnt, path->dentry, 1);
if (!mounted)
break;
- path->mnt = mounted;
- path->dentry = mounted->mnt_root;
+ path->mnt = &mounted->mnt;
+ path->dentry = mounted->mnt.mnt_root;
nd->flags |= LOOKUP_JUMPED;
nd->seq = read_seqcount_begin(&path->dentry->d_seq);
/*
@@ -915,12 +916,12 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
static void follow_mount_rcu(struct nameidata *nd)
{
while (d_mountpoint(nd->path.dentry)) {
- struct vfsmount *mounted;
+ struct mount *mounted;
mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry, 1);
if (!mounted)
break;
- nd->path.mnt = mounted;
- nd->path.dentry = mounted->mnt_root;
+ nd->path.mnt = &mounted->mnt;
+ nd->path.dentry = mounted->mnt.mnt_root;
nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
}
}
diff --git a/fs/namespace.c b/fs/namespace.c
index dda47fee6fdf..398eb2421494 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -464,20 +464,20 @@ static void free_vfsmnt(struct vfsmount *mnt)
* @dir. If @dir is set return the first mount else return the last mount.
* vfsmount_lock must be held for read or write.
*/
-struct vfsmount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry,
+struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry,
int dir)
{
struct list_head *head = mount_hashtable + hash(mnt, dentry);
struct list_head *tmp = head;
- struct vfsmount *p, *found = NULL;
+ struct mount *p, *found = NULL;
for (;;) {
tmp = dir ? tmp->next : tmp->prev;
p = NULL;
if (tmp == head)
break;
- p = list_entry(tmp, struct vfsmount, mnt_hash);
- if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) {
+ p = list_entry(tmp, struct mount, mnt.mnt_hash);
+ if (p->mnt.mnt_parent == mnt && p->mnt.mnt_mountpoint == dentry) {
found = p;
break;
}
@@ -491,13 +491,18 @@ struct vfsmount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry,
*/
struct vfsmount *lookup_mnt(struct path *path)
{
- struct vfsmount *child_mnt;
+ struct mount *child_mnt;
br_read_lock(vfsmount_lock);
- if ((child_mnt = __lookup_mnt(path->mnt, path->dentry, 1)))
- mntget(child_mnt);
- br_read_unlock(vfsmount_lock);
- return child_mnt;
+ child_mnt = __lookup_mnt(path->mnt, path->dentry, 1);
+ if (child_mnt) {
+ mnt_add_count(child_mnt, 1);
+ br_read_unlock(vfsmount_lock);
+ return &child_mnt->mnt;
+ } else {
+ br_read_unlock(vfsmount_lock);
+ return NULL;
+ }
}
static inline int check_mnt(struct vfsmount *mnt)
diff --git a/fs/pnode.c b/fs/pnode.c
index 4d5a06ea57a2..e996d039c0f2 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -289,7 +289,8 @@ static inline int do_refcount_check(struct vfsmount *mnt, int count)
*/
int propagate_mount_busy(struct vfsmount *mnt, int refcnt)
{
- struct vfsmount *m, *child;
+ struct vfsmount *m;
+ struct mount *child;
struct vfsmount *parent = mnt->mnt_parent;
int ret = 0;
@@ -307,8 +308,8 @@ int propagate_mount_busy(struct vfsmount *mnt, int refcnt)
for (m = propagation_next(parent, parent); m;
m = propagation_next(m, parent)) {
child = __lookup_mnt(m, mnt->mnt_mountpoint, 0);
- if (child && list_empty(&child->mnt_mounts) &&
- (ret = do_refcount_check(child, 1)))
+ if (child && list_empty(&child->mnt.mnt_mounts) &&
+ (ret = do_refcount_check(&child->mnt, 1)))
break;
}
return ret;
@@ -328,14 +329,14 @@ static void __propagate_umount(struct vfsmount *mnt)
for (m = propagation_next(parent, parent); m;
m = propagation_next(m, parent)) {
- struct vfsmount *child = __lookup_mnt(m,
+ struct mount *child = __lookup_mnt(m,
mnt->mnt_mountpoint, 0);
/*
* umount the child only if the child has no
* other children
*/
- if (child && list_empty(&child->mnt_mounts))
- list_move_tail(&child->mnt_hash, &mnt->mnt_hash);
+ if (child && list_empty(&child->mnt.mnt_mounts))
+ list_move_tail(&child->mnt.mnt_hash, &mnt->mnt_hash);
}
}