diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/internal.h | 2 | ||||
-rw-r--r-- | fs/mount.h | 2 | ||||
-rw-r--r-- | fs/namei.c | 13 | ||||
-rw-r--r-- | fs/namespace.c | 23 | ||||
-rw-r--r-- | fs/pnode.c | 13 |
5 files changed, 31 insertions, 22 deletions
diff --git a/fs/internal.h b/fs/internal.h index 7b1cb1528ac..6aab61a4f36 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 47da8163e1f..44e5b6f54b7 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 5008f01787f..d1c6a559f8f 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 dda47fee6fd..398eb242149 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 4d5a06ea57a..e996d039c0f 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); } } |