+static struct dentry *autofs4_lookup_active(struct dentry *dentry)
+{
+ struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct dentry *parent = dentry->d_parent;
+ struct qstr *name = &dentry->d_name;
+ unsigned int len = name->len;
+ unsigned int hash = name->hash;
+ const unsigned char *str = name->name;
+ struct list_head *p, *head;
+
+ spin_lock(&dcache_lock);
+ spin_lock(&sbi->lookup_lock);
+ head = &sbi->active_list;
+ list_for_each(p, head) {
+ struct autofs_info *ino;
+ struct dentry *active;
+ struct qstr *qstr;
+
+ ino = list_entry(p, struct autofs_info, active);
+ active = ino->dentry;
+
+ spin_lock(&active->d_lock);
+
+ /* Already gone? */
+ if (atomic_read(&active->d_count) == 0)
+ goto next;
+
+ qstr = &active->d_name;
+
+ if (active->d_name.hash != hash)
+ goto next;
+ if (active->d_parent != parent)
+ goto next;
+
+ if (qstr->len != len)
+ goto next;
+ if (memcmp(qstr->name, str, len))
+ goto next;
+
+ if (d_unhashed(active)) {
+ dget(active);
+ spin_unlock(&active->d_lock);
+ spin_unlock(&sbi->lookup_lock);
+ spin_unlock(&dcache_lock);
+ return active;
+ }
+next:
+ spin_unlock(&active->d_lock);
+ }
+ spin_unlock(&sbi->lookup_lock);
+ spin_unlock(&dcache_lock);
+
+ return NULL;
+}
+
+static struct dentry *autofs4_lookup_expiring(struct dentry *dentry)
+{
+ struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct dentry *parent = dentry->d_parent;
+ struct qstr *name = &dentry->d_name;
+ unsigned int len = name->len;
+ unsigned int hash = name->hash;
+ const unsigned char *str = name->name;
+ struct list_head *p, *head;
+
+ spin_lock(&dcache_lock);
+ spin_lock(&sbi->lookup_lock);
+ head = &sbi->expiring_list;
+ list_for_each(p, head) {
+ struct autofs_info *ino;
+ struct dentry *expiring;
+ struct qstr *qstr;
+
+ ino = list_entry(p, struct autofs_info, expiring);
+ expiring = ino->dentry;
+
+ spin_lock(&expiring->d_lock);
+
+ /* Bad luck, we've already been dentry_iput */
+ if (!expiring->d_inode)
+ goto next;
+
+ qstr = &expiring->d_name;
+
+ if (expiring->d_name.hash != hash)
+ goto next;
+ if (expiring->d_parent != parent)
+ goto next;
+
+ if (qstr->len != len)
+ goto next;
+ if (memcmp(qstr->name, str, len))
+ goto next;
+
+ if (d_unhashed(expiring)) {
+ dget(expiring);
+ spin_unlock(&expiring->d_lock);
+ spin_unlock(&sbi->lookup_lock);
+ spin_unlock(&dcache_lock);
+ return expiring;
+ }
+next:
+ spin_unlock(&expiring->d_lock);
+ }
+ spin_unlock(&sbi->lookup_lock);
+ spin_unlock(&dcache_lock);
+
+ return NULL;
+}
+