summaryrefslogtreecommitdiffstats
path: root/fs/autofs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/autofs')
-rw-r--r--fs/autofs/.cvsignore1
-rw-r--r--fs/autofs/Makefile29
-rw-r--r--fs/autofs/autofs_i.h175
-rw-r--r--fs/autofs/dir.c2
-rw-r--r--fs/autofs/dirhash.c49
-rw-r--r--fs/autofs/init.c27
-rw-r--r--fs/autofs/inode.c11
-rw-r--r--fs/autofs/root.c106
-rw-r--r--fs/autofs/symlink.c2
-rw-r--r--fs/autofs/waitq.c18
10 files changed, 375 insertions, 45 deletions
diff --git a/fs/autofs/.cvsignore b/fs/autofs/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/autofs/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/autofs/Makefile b/fs/autofs/Makefile
index 12f302635..1681c3d31 100644
--- a/fs/autofs/Makefile
+++ b/fs/autofs/Makefile
@@ -1,11 +1,7 @@
#
# Makefile for the linux autofs-filesystem routines.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...
+# We can build this either out of the kernel tree or the autofs tools tree.
#
O_TARGET := autofs.o
@@ -13,4 +9,27 @@ O_OBJS := dir.o dirhash.o init.o inode.o root.o symlink.o waitq.o
M_OBJS := $(O_TARGET)
+ifdef TOPDIR
+#
+# Part of the kernel code
+#
include $(TOPDIR)/Rules.make
+else
+#
+# Standalone (handy for development)
+#
+include ../Makefile.rules
+
+CFLAGS += -D__KERNEL__ -DMODULE $(KFLAGS) -I../include -I$(KINCLUDE) $(MODFLAGS)
+
+all: $(O_TARGET)
+
+$(O_TARGET): $(O_OBJS)
+ $(LD) -r -o $(O_TARGET) $(O_OBJS)
+
+install: $(O_TARGET)
+ install -c $(O_TARGET) /lib/modules/`uname -r`/fs
+
+clean:
+ rm -f *.o *.s
+endif
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
new file mode 100644
index 000000000..d3b6e484f
--- /dev/null
+++ b/fs/autofs/autofs_i.h
@@ -0,0 +1,175 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * linux/fs/autofs/autofs_i.h
+ *
+ * Copyright 1997 Transmeta Corporation - All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/* Internal header file for autofs */
+
+#include <linux/auto_fs.h>
+
+/* This is the range of ioctl() numbers we claim as ours */
+#define AUTOFS_IOC_FIRST AUTOFS_IOC_READY
+#define AUTOFS_IOC_COUNT 32
+
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+
+#define kver(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+
+#if LINUX_VERSION_CODE < kver(2,1,0)
+
+/* Segmentation stuff for pre-2.1 kernels */
+#include <asm/segment.h>
+
+static inline int copy_to_user(void *dst, void *src, unsigned long len)
+{
+ int rv = verify_area(VERIFY_WRITE, dst, len);
+ if ( rv )
+ return -1;
+ memcpy_tofs(dst,src,len);
+ return 0;
+}
+
+static inline int copy_from_user(void *dst, void *src, unsigned long len)
+{
+ int rv = verify_area(VERIFY_READ, src, len);
+ if ( rv )
+ return -1;
+ memcpy_fromfs(dst,src,len);
+ return 0;
+}
+
+#else
+
+/* Segmentation stuff for post-2.1 kernels */
+#include <asm/uaccess.h>
+#define register_symtab(x) ((void)0)
+
+#endif
+
+#ifdef DEBUG
+#define DPRINTK(D) printk D;
+#else
+#define DPRINTK(D)
+#endif
+
+#define AUTOFS_SUPER_MAGIC 0x0187
+
+/* Structures associated with the root directory hash */
+
+#define AUTOFS_HASH_SIZE 67
+
+typedef u32 autofs_hash_t; /* Type returned by autofs_hash() */
+
+struct autofs_dir_ent {
+ autofs_hash_t hash;
+ struct autofs_dir_ent *next;
+ struct autofs_dir_ent **back;
+ char *name;
+ int len;
+ ino_t ino;
+ /* The following entries are for the expiry system */
+ unsigned long last_usage;
+ struct autofs_dir_ent *exp_next;
+ struct autofs_dir_ent *exp_prev;
+};
+
+struct autofs_dirhash {
+ struct autofs_dir_ent *h[AUTOFS_HASH_SIZE];
+ struct autofs_dir_ent expiry_head;
+};
+
+struct autofs_wait_queue {
+ unsigned long wait_queue_token;
+ struct wait_queue *queue;
+ struct autofs_wait_queue *next;
+ /* We use the following to see what we are waiting for */
+ autofs_hash_t hash;
+ int len;
+ char *name;
+ /* This is for status reporting upon return */
+ int status;
+ int wait_ctr;
+};
+
+struct autofs_symlink {
+ int len;
+ char *data;
+ time_t mtime;
+};
+
+#define AUTOFS_MAX_SYMLINKS 256
+
+#define AUTOFS_ROOT_INO 1
+#define AUTOFS_FIRST_SYMLINK 2
+#define AUTOFS_FIRST_DIR_INO (AUTOFS_FIRST_SYMLINK+AUTOFS_MAX_SYMLINKS)
+
+#define AUTOFS_SYMLINK_BITMAP_LEN ((AUTOFS_MAX_SYMLINKS+31)/32)
+
+#ifndef END_OF_TIME
+#define END_OF_TIME ((time_t)((unsigned long)((time_t)(~0UL)) >> 1))
+#endif
+
+struct autofs_sb_info {
+ struct file *pipe;
+ pid_t oz_pgrp;
+ int catatonic;
+ unsigned long exp_timeout;
+ ino_t next_dir_ino;
+ struct autofs_wait_queue *queues; /* Wait queue pointer */
+ struct autofs_dirhash dirhash; /* Root directory hash */
+ struct autofs_symlink symlink[AUTOFS_MAX_SYMLINKS];
+ u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN];
+};
+
+/* autofs_oz_mode(): do we see the man behind the curtain? */
+static inline int autofs_oz_mode(struct autofs_sb_info *sbi) {
+ return sbi->catatonic || current->pgrp == sbi->oz_pgrp;
+}
+
+/* Hash operations */
+
+autofs_hash_t autofs_hash(const char *,int);
+void autofs_initialize_hash(struct autofs_dirhash *);
+struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *,autofs_hash_t,const char *,int);
+void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *);
+void autofs_hash_delete(struct autofs_dir_ent *);
+struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *);
+void autofs_hash_nuke(struct autofs_dirhash *);
+
+/* Expiration-handling functions */
+
+void autofs_update_usage(struct autofs_dirhash *,struct autofs_dir_ent *);
+struct autofs_dir_ent *autofs_expire(struct autofs_dirhash *,unsigned long);
+
+/* Operations structures */
+
+extern struct inode_operations autofs_root_inode_operations;
+extern struct inode_operations autofs_symlink_inode_operations;
+extern struct inode_operations autofs_dir_inode_operations;
+
+/* Initializing function */
+
+struct super_block *autofs_read_super(struct super_block *, void *,int);
+
+/* Queue management functions */
+
+int autofs_wait(struct autofs_sb_info *,autofs_hash_t,const char *,int);
+int autofs_wait_release(struct autofs_sb_info *,unsigned long,int);
+void autofs_catatonic_mode(struct autofs_sb_info *);
+
+#ifdef DEBUG
+void autofs_say(const char *name, int len);
+#else
+#define autofs_say(n,l)
+#endif
diff --git a/fs/autofs/dir.c b/fs/autofs/dir.c
index 22081d1a7..461688e9f 100644
--- a/fs/autofs/dir.c
+++ b/fs/autofs/dir.c
@@ -10,7 +10,7 @@
*
* ------------------------------------------------------------------------- */
-#include <linux/auto_fs.h>
+#include "autofs_i.h"
static int autofs_dir_readdir(struct inode *inode, struct file *filp,
void *dirent, filldir_t filldir)
diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c
index 8ea5325c4..90c18695a 100644
--- a/fs/autofs/dirhash.c
+++ b/fs/autofs/dirhash.c
@@ -10,9 +10,43 @@
*
* ------------------------------------------------------------------------- */
-#include <linux/string.h>
-#include <linux/malloc.h>
-#include <linux/auto_fs.h>
+#include "autofs_i.h"
+
+/* Functions for maintenance of expiry queue */
+
+static void autofs_init_usage(struct autofs_dirhash *dh,
+ struct autofs_dir_ent *ent)
+{
+ ent->exp_next = &dh->expiry_head;
+ ent->exp_prev = dh->expiry_head.exp_prev;
+ dh->expiry_head.exp_prev->exp_next = ent;
+ dh->expiry_head.exp_prev = ent;
+ ent->last_usage = jiffies;
+}
+
+static void autofs_delete_usage(struct autofs_dir_ent *ent)
+{
+ ent->exp_prev->exp_next = ent->exp_next;
+ ent->exp_next->exp_prev = ent->exp_prev;
+}
+
+void autofs_update_usage(struct autofs_dirhash *dh,
+ struct autofs_dir_ent *ent)
+{
+ autofs_delete_usage(ent); /* Unlink from current position */
+ autofs_init_usage(dh,ent); /* Relink at queue tail */
+}
+
+struct autofs_dir_ent *autofs_expire(struct autofs_dirhash *dh,
+ unsigned long timeout)
+{
+ struct autofs_dir_ent *ent;
+
+ ent = dh->expiry_head.exp_next;
+
+ if ( ent == &(dh->expiry_head) ) return NULL;
+ return (jiffies - ent->last_usage >= timeout) ? ent : NULL;
+}
/* Adapted from the Dragon Book, page 436 */
/* This particular hashing algorithm requires autofs_hash_t == u32 */
@@ -28,6 +62,8 @@ autofs_hash_t autofs_hash(const char *name, int len)
void autofs_initialize_hash(struct autofs_dirhash *dh) {
memset(&dh->h, 0, AUTOFS_HASH_SIZE*sizeof(struct autofs_dir_ent *));
+ dh->expiry_head.exp_next = dh->expiry_head.exp_prev =
+ &dh->expiry_head;
}
struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *dh, autofs_hash_t hash, const char *name, int len)
@@ -54,6 +90,8 @@ void autofs_hash_insert(struct autofs_dirhash *dh, struct autofs_dir_ent *ent)
DPRINTK(("autofs_hash_insert: hash = 0x%08x, name = ", ent->hash));
autofs_say(ent->name,ent->len);
+ autofs_init_usage(dh,ent);
+
dhnp = &dh->h[ent->hash % AUTOFS_HASH_SIZE];
ent->next = *dhnp;
ent->back = dhnp;
@@ -63,6 +101,9 @@ void autofs_hash_insert(struct autofs_dirhash *dh, struct autofs_dir_ent *ent)
void autofs_hash_delete(struct autofs_dir_ent *ent)
{
*(ent->back) = ent->next;
+
+ autofs_delete_usage(ent);
+
kfree(ent->name);
kfree(ent);
}
@@ -114,6 +155,8 @@ struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *dh, off_t *
return ent;
}
+/* Delete everything. This is used on filesystem destruction, so we
+ make no attempt to keep the pointers valid */
void autofs_hash_nuke(struct autofs_dirhash *dh)
{
int i;
diff --git a/fs/autofs/init.c b/fs/autofs/init.c
index a4857cb99..1b3f6f165 100644
--- a/fs/autofs/init.c
+++ b/fs/autofs/init.c
@@ -11,23 +11,24 @@
* ------------------------------------------------------------------------- */
#include <linux/module.h>
-#include <linux/auto_fs.h>
+#include "autofs_i.h"
-struct file_system_type autofs_fs_type = {
+#if LINUX_VERSION_CODE < kver(2,1,36)
+#define __initfunc(X) X
+#else
+#include <linux/init.h>
+#endif
+
+static struct file_system_type autofs_fs_type = {
autofs_read_super, "autofs", 0, NULL
};
-int init_autofs_fs(void)
-{
- return register_filesystem(&autofs_fs_type);
-}
-
#ifdef MODULE
int init_module(void)
{
int status;
- if ((status = init_autofs_fs()) == 0)
+ if ((status = register_filesystem(&autofs_fs_type)) == 0)
register_symtab(0);
return status;
}
@@ -36,7 +37,15 @@ void cleanup_module(void)
{
unregister_filesystem(&autofs_fs_type);
}
-#endif
+
+#else /* MODULE */
+
+__initfunc(int init_autofs_fs(void))
+{
+ return register_filesystem(&autofs_fs_type);
+}
+
+#endif /* !MODULE */
#ifdef DEBUG
void autofs_say(const char *name, int len)
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index 60b805a07..a8c176a02 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -15,7 +15,7 @@
#include <linux/file.h>
#include <linux/locks.h>
#include <asm/bitops.h>
-#include <linux/auto_fs.h>
+#include "autofs_i.h"
#define __NO_VERSION__
#include <linux/module.h>
@@ -28,17 +28,19 @@ static void autofs_put_inode(struct inode *inode)
static void autofs_put_super(struct super_block *sb)
{
- struct autofs_sb_info *sbi;
+ struct autofs_sb_info *sbi =
+ (struct autofs_sb_info *) sb->u.generic_sbp;
unsigned int n;
+ if ( !sbi->catatonic )
+ autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
+
lock_super(sb);
- sbi = (struct autofs_sb_info *) sb->u.generic_sbp;
autofs_hash_nuke(&sbi->dirhash);
for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) {
if ( test_bit(n, sbi->symlink_bitmap) )
kfree(sbi->symlink[n].data);
}
- fput(sbi->pipe, sbi->pipe->f_inode);
sb->s_dev = 0;
kfree(sb->u.generic_sbp);
@@ -149,6 +151,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
s->u.generic_sbp = sbi;
sbi->catatonic = 0;
+ sbi->exp_timeout = 0;
sbi->oz_pgrp = current->pgrp;
autofs_initialize_hash(&sbi->dirhash);
sbi->queues = NULL;
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index d9056dcb1..57449e816 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -12,9 +12,8 @@
#include <linux/errno.h>
#include <linux/stat.h>
-#include <linux/malloc.h>
-#include <linux/ioctl.h>
-#include <linux/auto_fs.h>
+#include <linux/param.h>
+#include "autofs_i.h"
static int autofs_root_readdir(struct inode *,struct file *,void *,filldir_t);
static int autofs_root_lookup(struct inode *,const char *,int,struct inode **);
@@ -171,7 +170,8 @@ static int autofs_root_lookup(struct inode *dir, const char *name, int len,
}
}
} while(!res);
-
+ autofs_update_usage(&sbi->dirhash,ent);
+
*result = res;
iput(dir);
return 0;
@@ -229,7 +229,6 @@ static int autofs_root_symlink(struct inode *dir, const char *name, int len, con
ent->ino = AUTOFS_FIRST_SYMLINK + n;
ent->hash = hash;
memcpy(ent->name,name,ent->len = len);
- ent->expiry = END_OF_TIME;
autofs_hash_insert(dh,ent);
@@ -322,7 +321,6 @@ static int autofs_root_mkdir(struct inode *dir, const char *name, int len, int m
ent->hash = hash;
memcpy(ent->name, name, ent->len = len);
ent->ino = sbi->next_dir_ino++;
- ent->expiry = END_OF_TIME;
autofs_hash_insert(dh,ent);
dir->i_nlink++;
iput(dir);
@@ -330,6 +328,75 @@ static int autofs_root_mkdir(struct inode *dir, const char *name, int len, int m
return 0;
}
+/* Get/set timeout ioctl() operation */
+static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi,
+ unsigned long *p)
+{
+ int rv;
+ unsigned long ntimeout;
+
+#if LINUX_VERSION_CODE < kver(2,1,0)
+ if ( (rv = verify_area(VERIFY_WRITE, p, sizeof(unsigned long))) )
+ return rv;
+ ntimeout = get_user(p);
+ put_user(sbi->exp_timeout/HZ, p);
+#else
+ if ( (rv = get_user(ntimeout, p)) ||
+ (rv = put_user(sbi->exp_timeout/HZ, p)) )
+ return rv;
+#endif
+
+ if ( ntimeout > ULONG_MAX/HZ )
+ sbi->exp_timeout = 0;
+ else
+ sbi->exp_timeout = ntimeout * HZ;
+
+ return 0;
+}
+
+/* Return protocol version */
+static inline int autofs_get_protover(int *p)
+{
+#if LINUX_VERSION_CODE < kver(2,1,0)
+ int rv;
+ if ( (rv = verify_area(VERIFY_WRITE, p, sizeof(int))) )
+ return rv;
+ put_user(AUTOFS_PROTO_VERSION, p);
+ return 0;
+#else
+ return put_user(AUTOFS_PROTO_VERSION, p);
+#endif
+}
+
+/* Perform an expiry operation */
+static inline int autofs_expire_run(struct autofs_sb_info *sbi,
+ struct autofs_packet_expire *pkt_p)
+{
+ struct autofs_dir_ent *ent;
+ struct autofs_packet_expire pkt;
+ struct autofs_dirhash *dh = &(sbi->dirhash);
+
+ memset(&pkt,0,sizeof pkt);
+
+ pkt.hdr.proto_version = AUTOFS_PROTO_VERSION;
+ pkt.hdr.type = autofs_ptype_expire;
+
+ if ( !sbi->exp_timeout ||
+ !(ent = autofs_expire(dh,sbi->exp_timeout)) )
+ return -EAGAIN;
+
+ pkt.len = ent->len;
+ memcpy(pkt.name, ent->name, pkt.len);
+ pkt.name[pkt.len] = '\0';
+
+ if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
+ return -EFAULT;
+
+ autofs_update_usage(dh,ent);
+
+ return 0;
+}
+
/*
* ioctl()'s on the root directory is the chief method for the daemon to
* generate kernel reactions
@@ -337,26 +404,33 @@ static int autofs_root_mkdir(struct inode *dir, const char *name, int len, int m
static int autofs_root_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- struct autofs_sb_info *sbi = (struct autofs_sb_info *)inode->i_sb->u.generic_sbp;
+ struct autofs_sb_info *sbi =
+ (struct autofs_sb_info *)inode->i_sb->u.generic_sbp;
- DPRINTK(("autofs_ioctl: cmd = %04x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp));
+ DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp));
+ if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
+ _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT )
+ return -ENOTTY;
+
+ if ( !autofs_oz_mode(sbi) && !fsuser() )
+ return -EPERM;
+
switch(cmd) {
case AUTOFS_IOC_READY: /* Wait queue: go ahead and retry */
- if ( !autofs_oz_mode(sbi) && !fsuser() )
- return -EPERM;
return autofs_wait_release(sbi,arg,0);
case AUTOFS_IOC_FAIL: /* Wait queue: fail with ENOENT */
- /* Optional: add to failure cache */
- if ( !autofs_oz_mode(sbi) && !fsuser() )
- return -EPERM;
return autofs_wait_release(sbi,arg,-ENOENT);
case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */
- if ( !autofs_oz_mode(sbi) && !fsuser() )
- return -EPERM;
autofs_catatonic_mode(sbi);
return 0;
+ case AUTOFS_IOC_PROTOVER: /* Get protocol version */
+ return autofs_get_protover((int *)arg);
+ case AUTOFS_IOC_SETTIMEOUT:
+ return autofs_get_set_timeout(sbi,(unsigned long *)arg);
+ case AUTOFS_IOC_EXPIRE:
+ return autofs_expire_run(sbi,(struct autofs_packet_expire *)arg);
default:
- return -ENOTTY; /* Should this be ENOSYS? */
+ return -ENOSYS;
}
}
diff --git a/fs/autofs/symlink.c b/fs/autofs/symlink.c
index 0e932c169..46c333103 100644
--- a/fs/autofs/symlink.c
+++ b/fs/autofs/symlink.c
@@ -12,7 +12,7 @@
#include <linux/string.h>
#include <linux/sched.h>
-#include <linux/auto_fs.h>
+#include "autofs_i.h"
static int autofs_follow_link(struct inode *dir, struct inode *inode,
int flag, int mode, struct inode **res_inode)
diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c
index 6dc6d0b13..b37745f19 100644
--- a/fs/autofs/waitq.c
+++ b/fs/autofs/waitq.c
@@ -11,9 +11,10 @@
* ------------------------------------------------------------------------- */
#include <linux/malloc.h>
-#include <linux/signal.h>
#include <linux/sched.h>
-#include <linux/auto_fs.h>
+#include <linux/signal.h>
+#include <linux/file.h>
+#include "autofs_i.h"
/* We make this a static variable rather than a part of the superblock; it
is better if we don't reassign numbers easily even across filesystems */
@@ -36,6 +37,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi)
wake_up(&wq->queue);
wq = nwq;
}
+ fput(sbi->pipe, sbi->pipe->f_inode); /* Close the pipe */
}
static int autofs_write(struct file *file, const void *addr, int bytes)
@@ -43,7 +45,7 @@ static int autofs_write(struct file *file, const void *addr, int bytes)
unsigned short fs;
unsigned long old_signal;
const char *data = (const char *)addr;
- int written;
+ int written = 0;
/** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/
@@ -75,6 +77,8 @@ static void autofs_notify_daemon(struct autofs_sb_info *sbi, struct autofs_wait_
DPRINTK(("autofs_wait: wait id = 0x%08lx, name = ", wq->wait_queue_token));
autofs_say(wq->name,wq->len);
+ memset(&pkt,0,sizeof pkt); /* For security reasons */
+
pkt.hdr.proto_version = AUTOFS_PROTO_VERSION;
pkt.hdr.type = autofs_ptype_missing;
pkt.wait_queue_token = wq->wait_queue_token;
@@ -94,7 +98,7 @@ int autofs_wait(struct autofs_sb_info *sbi, autofs_hash_t hash, const char *name
for ( wq = sbi->queues ; wq ; wq = wq->next ) {
if ( wq->hash == hash &&
wq->len == len &&
- !memcmp(wq->name,name,len) )
+ wq->name && !memcmp(wq->name,name,len) )
break;
}
@@ -113,12 +117,13 @@ int autofs_wait(struct autofs_sb_info *sbi, autofs_hash_t hash, const char *name
init_waitqueue(&wq->queue);
wq->hash = hash;
wq->len = len;
+ wq->status = -EINTR; /* Status return if interrupted */
memcpy(wq->name, name, len);
wq->next = sbi->queues;
sbi->queues = wq;
/* autofs_notify_daemon() may block */
- wq->wait_ctr++;
+ wq->wait_ctr = 1;
autofs_notify_daemon(sbi,wq);
} else
wq->wait_ctr++;
@@ -130,7 +135,8 @@ int autofs_wait(struct autofs_sb_info *sbi, autofs_hash_t hash, const char *name
DPRINTK(("autofs_wait: skipped sleeping\n"));
}
- status = (current->signal & ~current->blocked) ? -EINTR : wq->status;
+ status = wq->status;
+
if ( ! --wq->wait_ctr ) /* Are we the last process to need status? */
kfree(wq);