split __lookup_mnt() in two functions
authorAl Viro <viro@zeniv.linux.org.uk>
Tue, 1 Oct 2013 20:11:26 +0000 (16:11 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 25 Oct 2013 03:35:00 +0000 (23:35 -0400)
Instead of passing the direction as argument (and checking it on every
step through the hash chain), just have separate __lookup_mnt() and
__lookup_mnt_last().  And use the standard iterators...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/mount.h
fs/namei.c
fs/namespace.c
fs/pnode.c

index 7076f25af35d939e4d0b6ca721b15d227203a82c..f0866076de6ebf889505166d910c2fddcf18b6fb 100644 (file)
@@ -77,7 +77,8 @@ static inline int is_mounted(struct vfsmount *mnt)
        return !IS_ERR_OR_NULL(real_mount(mnt));
 }
 
-extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
+extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *);
+extern struct mount *__lookup_mnt_last(struct vfsmount *, struct dentry *);
 
 static inline void get_mnt_ns(struct mnt_namespace *ns)
 {
index 645268f23eb64cb8c2931ce33391beb2d0080c36..1f844fbfce7286f4b65e260a3a6603baaf329477 100644 (file)
@@ -1111,7 +1111,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
                if (!d_mountpoint(path->dentry))
                        break;
 
-               mounted = __lookup_mnt(path->mnt, path->dentry, 1);
+               mounted = __lookup_mnt(path->mnt, path->dentry);
                if (!mounted)
                        break;
                path->mnt = &mounted->mnt;
@@ -1132,7 +1132,7 @@ static void follow_mount_rcu(struct nameidata *nd)
 {
        while (d_mountpoint(nd->path.dentry)) {
                struct mount *mounted;
-               mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry, 1);
+               mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry);
                if (!mounted)
                        break;
                nd->path.mnt = &mounted->mnt;
index 5cbe8cefadb59cfad53e411b0cd2c378c4d3652a..500202ce10dbf0a7b10ebd0b5d418fe1e52470c6 100644 (file)
@@ -548,29 +548,33 @@ static void free_vfsmnt(struct mount *mnt)
 }
 
 /*
- * find the first or last mount at @dentry on vfsmount @mnt depending on
- * @dir. If @dir is set return the first mount else return the last mount.
+ * find the first mount at @dentry on vfsmount @mnt.
  * vfsmount_lock must be held for read or write.
  */
-struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry,
-                             int dir)
+struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
 {
        struct list_head *head = mount_hashtable + hash(mnt, dentry);
-       struct list_head *tmp = head;
-       struct mount *p, *found = NULL;
+       struct mount *p;
 
-       for (;;) {
-               tmp = dir ? tmp->next : tmp->prev;
-               p = NULL;
-               if (tmp == head)
-                       break;
-               p = list_entry(tmp, struct mount, mnt_hash);
-               if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry) {
-                       found = p;
-                       break;
-               }
-       }
-       return found;
+       list_for_each_entry(p, head, mnt_hash)
+               if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry)
+                       return p;
+       return NULL;
+}
+
+/*
+ * find the last mount at @dentry on vfsmount @mnt.
+ * vfsmount_lock must be held for read or write.
+ */
+struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry)
+{
+       struct list_head *head = mount_hashtable + hash(mnt, dentry);
+       struct mount *p;
+
+       list_for_each_entry_reverse(p, head, mnt_hash)
+               if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry)
+                       return p;
+       return NULL;
 }
 
 /*
@@ -594,7 +598,7 @@ struct vfsmount *lookup_mnt(struct path *path)
        struct mount *child_mnt;
 
        br_read_lock(&vfsmount_lock);
-       child_mnt = __lookup_mnt(path->mnt, path->dentry, 1);
+       child_mnt = __lookup_mnt(path->mnt, path->dentry);
        if (child_mnt) {
                mnt_add_count(child_mnt, 1);
                br_read_unlock(&vfsmount_lock);
index 58933fd149ad3cfcebbdcff7f08614aea61bf696..c7221bb19801e6b6251ad1ed3cea6f4f79dcf876 100644 (file)
@@ -310,7 +310,7 @@ int propagate_mount_busy(struct mount *mnt, int refcnt)
 
        for (m = propagation_next(parent, parent); m;
                        m = propagation_next(m, parent)) {
-               child = __lookup_mnt(&m->mnt, mnt->mnt_mountpoint, 0);
+               child = __lookup_mnt_last(&m->mnt, mnt->mnt_mountpoint);
                if (child && list_empty(&child->mnt_mounts) &&
                    (ret = do_refcount_check(child, 1)))
                        break;
@@ -332,8 +332,8 @@ static void __propagate_umount(struct mount *mnt)
        for (m = propagation_next(parent, parent); m;
                        m = propagation_next(m, parent)) {
 
-               struct mount *child = __lookup_mnt(&m->mnt,
-                                       mnt->mnt_mountpoint, 0);
+               struct mount *child = __lookup_mnt_last(&m->mnt,
+                                               mnt->mnt_mountpoint);
                /*
                 * umount the child only if the child has no
                 * other children