#include <linux/slab.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/stats.h>
#define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE)
#define ALLOWED_SIGS (sigmask(SIGKILL))
-extern struct svc_program nlmsvc_program;
+static struct svc_program nlmsvc_program;
struct nlmsvc_binding * nlmsvc_ops;
EXPORT_SYMBOL(nlmsvc_ops);
-static DECLARE_MUTEX(nlmsvc_sema);
+static DEFINE_MUTEX(nlmsvc_mutex);
static unsigned int nlmsvc_users;
static pid_t nlmsvc_pid;
int nlmsvc_grace_period;
unsigned long nlmsvc_timeout;
-static DECLARE_MUTEX_LOCKED(lockd_start);
+static DECLARE_COMPLETION(lockd_start_done);
static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
/*
* Let our maker know we're running.
*/
nlmsvc_pid = current->pid;
- up(&lockd_start);
+ complete(&lockd_start_done);
daemonize("lockd");
}
+ flush_signals(current);
+
/*
* Check whether there's a new lockd process before
* shutting down the hosts and clearing the slot.
printk(KERN_DEBUG
"lockd: new process, skipping host shutdown\n");
wake_up(&lockd_exit);
-
+
/* Exit the RPC thread */
svc_exit_thread(rqstp);
struct svc_serv * serv;
int error = 0;
- down(&nlmsvc_sema);
+ mutex_lock(&nlmsvc_mutex);
/*
* Unconditionally increment the user count ... this is
* the number of clients who _want_ a lockd process.
"lockd_up: create thread failed, error=%d\n", error);
goto destroy_and_out;
}
- down(&lockd_start);
+ wait_for_completion(&lockd_start_done);
/*
* Note: svc_serv structures have an initial use count of 1,
destroy_and_out:
svc_destroy(serv);
out:
- up(&nlmsvc_sema);
+ mutex_unlock(&nlmsvc_mutex);
return error;
}
EXPORT_SYMBOL(lockd_up);
lockd_down(void)
{
static int warned;
- wait_queue_t __wait;
- int retries=0;
- down(&nlmsvc_sema);
+ mutex_lock(&nlmsvc_mutex);
if (nlmsvc_users) {
if (--nlmsvc_users)
goto out;
warned = 0;
kill_proc(nlmsvc_pid, SIGKILL, 1);
-
- init_waitqueue_entry(&__wait, current);
- add_wait_queue(&lockd_exit, &__wait);
-
/*
* Wait for the lockd process to exit, but since we're holding
* the lockd semaphore, we can't wait around forever ...
*/
clear_thread_flag(TIF_SIGPENDING);
- set_current_state(TASK_UNINTERRUPTIBLE);
- while (nlmsvc_pid) {
-
- schedule_timeout(HZ);
- if (retries++ < 3)
- continue;
-
+ wait_event_timeout(lockd_exit, nlmsvc_pid == 0, HZ);
+ if (nlmsvc_pid) {
printk(KERN_WARNING
"lockd_down: lockd failed to exit, clearing pid\n");
nlmsvc_pid = 0;
}
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&lockd_exit, &__wait);
-
spin_lock_irq(¤t->sighand->siglock);
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
-
out:
- up(&nlmsvc_sema);
+ mutex_unlock(&nlmsvc_mutex);
}
EXPORT_SYMBOL(lockd_down);
.ctl_name = CTL_UNNUMBERED,
.procname = "nlm_grace_period",
.data = &nlm_grace_period,
- .maxlen = sizeof(int),
+ .maxlen = sizeof(unsigned long),
.mode = 0644,
.proc_handler = &proc_doulongvec_minmax,
.extra1 = (unsigned long *) &nlm_grace_period_min,
.ctl_name = CTL_UNNUMBERED,
.procname = "nlm_timeout",
.data = &nlm_timeout,
- .maxlen = sizeof(int),
+ .maxlen = sizeof(unsigned long),
.mode = 0644,
.proc_handler = &proc_doulongvec_minmax,
.extra1 = (unsigned long *) &nlm_timeout_min,
return 0; \
}
+static inline int is_callback(u32 proc)
+{
+ return proc == NLMPROC_GRANTED
+ || proc == NLMPROC_GRANTED_MSG
+ || proc == NLMPROC_TEST_RES
+ || proc == NLMPROC_LOCK_RES
+ || proc == NLMPROC_CANCEL_RES
+ || proc == NLMPROC_UNLOCK_RES
+ || proc == NLMPROC_NSM_NOTIFY;
+}
+
+
+static int lockd_authenticate(struct svc_rqst *rqstp)
+{
+ rqstp->rq_client = NULL;
+ switch (rqstp->rq_authop->flavour) {
+ case RPC_AUTH_NULL:
+ case RPC_AUTH_UNIX:
+ if (rqstp->rq_proc == 0)
+ return SVC_OK;
+ if (is_callback(rqstp->rq_proc)) {
+ /* Leave it to individual procedures to
+ * call nlmsvc_lookup_host(rqstp)
+ */
+ return SVC_OK;
+ }
+ return svc_set_client(rqstp);
+ }
+ return SVC_DENIED;
+}
+
+
param_set_min_max(port, int, simple_strtol, 0, 65535)
param_set_min_max(grace_period, unsigned long, simple_strtoul,
nlm_grace_period_min, nlm_grace_period_max)
static struct svc_stat nlmsvc_stats;
-#define NLM_NRVERS (sizeof(nlmsvc_version)/sizeof(nlmsvc_version[0]))
-struct svc_program nlmsvc_program = {
- .pg_prog = NLM_PROGRAM, /* program number */
- .pg_nvers = NLM_NRVERS, /* number of entries in nlmsvc_version */
- .pg_vers = nlmsvc_version, /* version table */
- .pg_name = "lockd", /* service name */
- .pg_class = "nfsd", /* share authentication with nfsd */
- .pg_stats = &nlmsvc_stats, /* stats table */
+#define NLM_NRVERS ARRAY_SIZE(nlmsvc_version)
+static struct svc_program nlmsvc_program = {
+ .pg_prog = NLM_PROGRAM, /* program number */
+ .pg_nvers = NLM_NRVERS, /* number of entries in nlmsvc_version */
+ .pg_vers = nlmsvc_version, /* version table */
+ .pg_name = "lockd", /* service name */
+ .pg_class = "nfsd", /* share authentication with nfsd */
+ .pg_stats = &nlmsvc_stats, /* stats table */
+ .pg_authenticate = &lockd_authenticate /* export authentication */
};