OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [LINUX_2_4_26_OR32/] [linux/] [linux-2.4/] [fs/] [lockd/] [svc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/fs/lockd/svc.c
3
 *
4
 * This is the central lockd service.
5
 *
6
 * FIXME: Separate the lockd NFS server functionality from the lockd NFS
7
 *        client functionality. Oh why didn't Sun create two separate
8
 *        services in the first place?
9
 *
10
 * Authors:     Olaf Kirch (okir@monad.swb.de)
11
 *
12
 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
13
 */
14
 
15
#define __KERNEL_SYSCALLS__
16
#include <linux/config.h>
17
#include <linux/module.h>
18
#include <linux/init.h>
19
 
20
#include <linux/sched.h>
21
#include <linux/errno.h>
22
#include <linux/in.h>
23
#include <linux/uio.h>
24
#include <linux/version.h>
25
#include <linux/unistd.h>
26
#include <linux/slab.h>
27
#include <linux/smp.h>
28
#include <linux/smp_lock.h>
29
 
30
#include <linux/sunrpc/types.h>
31
#include <linux/sunrpc/stats.h>
32
#include <linux/sunrpc/clnt.h>
33
#include <linux/sunrpc/svc.h>
34
#include <linux/sunrpc/svcsock.h>
35
#include <linux/lockd/lockd.h>
36
#include <linux/nfs.h>
37
 
38
#define NLMDBG_FACILITY         NLMDBG_SVC
39
#define LOCKD_BUFSIZE           (1024 + NLMSSVC_XDRSIZE)
40
#define ALLOWED_SIGS            (sigmask(SIGKILL))
41
 
42
extern struct svc_program       nlmsvc_program;
43
struct nlmsvc_binding *         nlmsvc_ops;
44
static DECLARE_MUTEX(nlmsvc_sema);
45
static unsigned int             nlmsvc_users;
46
static pid_t                    nlmsvc_pid;
47
int                             nlmsvc_grace_period;
48
unsigned long                   nlmsvc_timeout;
49
 
50
static DECLARE_MUTEX_LOCKED(lockd_start);
51
static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
52
 
53
/*
54
 * Currently the following can be set only at insmod time.
55
 * Ideally, they would be accessible through the sysctl interface.
56
 */
57
unsigned long                   nlm_grace_period;
58
unsigned long                   nlm_timeout = LOCKD_DFLT_TIMEO;
59
unsigned long                   nlm_udpport, nlm_tcpport;
60
 
61
static unsigned long set_grace_period(void)
62
{
63
        unsigned long grace_period;
64
 
65
        /* Note: nlm_timeout should always be nonzero */
66
        if (nlm_grace_period)
67
                grace_period = ((nlm_grace_period + nlm_timeout - 1)
68
                                / nlm_timeout) * nlm_timeout * HZ;
69
        else
70
                grace_period = nlm_timeout * 5 * HZ;
71
        nlmsvc_grace_period = 1;
72
        return grace_period + jiffies;
73
}
74
 
75
/*
76
 * This is the lockd kernel thread
77
 */
78
static void
79
lockd(struct svc_rqst *rqstp)
80
{
81
        struct svc_serv *serv = rqstp->rq_server;
82
        int             err = 0;
83
        unsigned long grace_period_expire;
84
 
85
        /* Lock module and set up kernel thread */
86
        MOD_INC_USE_COUNT;
87
        lock_kernel();
88
 
89
        /*
90
         * Let our maker know we're running.
91
         */
92
        nlmsvc_pid = current->pid;
93
        up(&lockd_start);
94
 
95
        daemonize();
96
        reparent_to_init();
97
        sprintf(current->comm, "lockd");
98
 
99
        /* Process request with signals blocked.  */
100
        spin_lock_irq(&current->sigmask_lock);
101
        siginitsetinv(&current->blocked, sigmask(SIGKILL));
102
        recalc_sigpending(current);
103
        spin_unlock_irq(&current->sigmask_lock);
104
 
105
        /* kick rpciod */
106
        rpciod_up();
107
 
108
        dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
109
 
110
        if (!nlm_timeout)
111
                nlm_timeout = LOCKD_DFLT_TIMEO;
112
        nlmsvc_timeout = nlm_timeout * HZ;
113
 
114
        grace_period_expire = set_grace_period();
115
 
116
        /*
117
         * The main request loop. We don't terminate until the last
118
         * NFS mount or NFS daemon has gone away, and we've been sent a
119
         * signal, or else another process has taken over our job.
120
         */
121
        while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid)
122
        {
123
                long timeout = MAX_SCHEDULE_TIMEOUT;
124
                if (signalled()) {
125
                        spin_lock_irq(&current->sigmask_lock);
126
                        flush_signals(current);
127
                        spin_unlock_irq(&current->sigmask_lock);
128
                        if (nlmsvc_ops) {
129
                                nlmsvc_ops->detach();
130
                                grace_period_expire = set_grace_period();
131
                        }
132
                }
133
 
134
                /*
135
                 * Retry any blocked locks that have been notified by
136
                 * the VFS. Don't do this during grace period.
137
                 * (Theoretically, there shouldn't even be blocked locks
138
                 * during grace period).
139
                 */
140
                if (!nlmsvc_grace_period)
141
                        timeout = nlmsvc_retry_blocked();
142
 
143
                /*
144
                 * Find a socket with data available and call its
145
                 * recvfrom routine.
146
                 */
147
                err = svc_recv(serv, rqstp, timeout);
148
                if (err == -EAGAIN || err == -EINTR)
149
                        continue;
150
                if (err < 0) {
151
                        printk(KERN_WARNING
152
                               "lockd: terminating on error %d\n",
153
                               -err);
154
                        break;
155
                }
156
 
157
                dprintk("lockd: request from %08x\n",
158
                        (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
159
 
160
                /*
161
                 * Look up the NFS client handle. The handle is needed for
162
                 * all but the GRANTED callback RPCs.
163
                 */
164
                rqstp->rq_client = NULL;
165
                if (nlmsvc_ops) {
166
                        nlmsvc_ops->exp_readlock();
167
                        rqstp->rq_client =
168
                                nlmsvc_ops->exp_getclient(&rqstp->rq_addr);
169
                }
170
 
171
                if (nlmsvc_grace_period &&
172
                    time_before(grace_period_expire, jiffies))
173
                        nlmsvc_grace_period = 0;
174
                svc_process(serv, rqstp);
175
 
176
                /* Unlock export hash tables */
177
                if (nlmsvc_ops)
178
                        nlmsvc_ops->exp_unlock();
179
        }
180
 
181
        /*
182
         * Check whether there's a new lockd process before
183
         * shutting down the hosts and clearing the slot.
184
         */
185
        if (!nlmsvc_pid || current->pid == nlmsvc_pid) {
186
                if (nlmsvc_ops)
187
                        nlmsvc_ops->detach();
188
                nlm_shutdown_hosts();
189
                nlmsvc_pid = 0;
190
        } else
191
                printk(KERN_DEBUG
192
                        "lockd: new process, skipping host shutdown\n");
193
        wake_up(&lockd_exit);
194
 
195
        /* Exit the RPC thread */
196
        svc_exit_thread(rqstp);
197
 
198
        /* release rpciod */
199
        rpciod_down();
200
 
201
        /* Release module */
202
        MOD_DEC_USE_COUNT;
203
}
204
 
205
/*
206
 * Bring up the lockd process if it's not already up.
207
 */
208
int
209
lockd_up(void)
210
{
211
        static int              warned = 0;
212
        struct svc_serv *       serv;
213
        int                     error = 0;
214
 
215
        down(&nlmsvc_sema);
216
        /*
217
         * Unconditionally increment the user count ... this is
218
         * the number of clients who _want_ a lockd process.
219
         */
220
        nlmsvc_users++;
221
        /*
222
         * Check whether we're already up and running.
223
         */
224
        if (nlmsvc_pid)
225
                goto out;
226
 
227
        /*
228
         * Sanity check: if there's no pid,
229
         * we should be the first user ...
230
         */
231
        if (nlmsvc_users > 1)
232
                printk(KERN_WARNING
233
                        "lockd_up: no pid, %d users??\n", nlmsvc_users);
234
 
235
        error = -ENOMEM;
236
        serv = svc_create(&nlmsvc_program, 0, NLMSVC_XDRSIZE);
237
        if (!serv) {
238
                printk(KERN_WARNING "lockd_up: create service failed\n");
239
                goto out;
240
        }
241
 
242
        if ((error = svc_makesock(serv, IPPROTO_UDP, nlm_udpport)) < 0
243
#ifdef CONFIG_NFSD_TCP
244
         || (error = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport)) < 0
245
#endif
246
                ) {
247
                if (warned++ == 0)
248
                        printk(KERN_WARNING
249
                                "lockd_up: makesock failed, error=%d\n", error);
250
                goto destroy_and_out;
251
        }
252
        warned = 0;
253
 
254
        /*
255
         * Create the kernel thread and wait for it to start.
256
         */
257
        error = svc_create_thread(lockd, serv);
258
        if (error) {
259
                printk(KERN_WARNING
260
                        "lockd_up: create thread failed, error=%d\n", error);
261
                goto destroy_and_out;
262
        }
263
        down(&lockd_start);
264
 
265
        /*
266
         * Note: svc_serv structures have an initial use count of 1,
267
         * so we exit through here on both success and failure.
268
         */
269
destroy_and_out:
270
        svc_destroy(serv);
271
out:
272
        up(&nlmsvc_sema);
273
        return error;
274
}
275
 
276
/*
277
 * Decrement the user count and bring down lockd if we're the last.
278
 */
279
void
280
lockd_down(void)
281
{
282
        static int warned = 0;
283
 
284
        down(&nlmsvc_sema);
285
        if (nlmsvc_users) {
286
                if (--nlmsvc_users)
287
                        goto out;
288
        } else
289
                printk(KERN_WARNING "lockd_down: no users! pid=%d\n", nlmsvc_pid);
290
 
291
        if (!nlmsvc_pid) {
292
                if (warned++ == 0)
293
                        printk(KERN_WARNING "lockd_down: no lockd running.\n");
294
                goto out;
295
        }
296
        warned = 0;
297
 
298
        kill_proc(nlmsvc_pid, SIGKILL, 1);
299
        /*
300
         * Wait for the lockd process to exit, but since we're holding
301
         * the lockd semaphore, we can't wait around forever ...
302
         */
303
        current->sigpending = 0;
304
        interruptible_sleep_on_timeout(&lockd_exit, HZ);
305
        if (nlmsvc_pid) {
306
                printk(KERN_WARNING
307
                        "lockd_down: lockd failed to exit, clearing pid\n");
308
                nlmsvc_pid = 0;
309
        }
310
        spin_lock_irq(&current->sigmask_lock);
311
        recalc_sigpending(current);
312
        spin_unlock_irq(&current->sigmask_lock);
313
out:
314
        up(&nlmsvc_sema);
315
}
316
 
317
#ifdef MODULE
318
/* New module support in 2.1.18 */
319
 
320
MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
321
MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
322
MODULE_LICENSE("GPL");
323
MODULE_PARM(nlm_grace_period, "10-240l");
324
MODULE_PARM(nlm_timeout, "3-20l");
325
MODULE_PARM(nlm_udpport, "0-65535l");
326
MODULE_PARM(nlm_tcpport, "0-65535l");
327
 
328
int
329
init_module(void)
330
{
331
        /* Init the static variables */
332
        init_MUTEX(&nlmsvc_sema);
333
        nlmsvc_users = 0;
334
        nlmsvc_pid = 0;
335
        return 0;
336
}
337
 
338
void
339
cleanup_module(void)
340
{
341
        /* FIXME: delete all NLM clients */
342
        nlm_shutdown_hosts();
343
}
344
#else
345
/* not a module, so process bootargs
346
 * lockd.udpport and lockd.tcpport
347
 */
348
 
349
static int __init udpport_set(char *str)
350
{
351
        nlm_udpport = simple_strtoul(str, NULL, 0);
352
        return 1;
353
}
354
static int __init tcpport_set(char *str)
355
{
356
        nlm_tcpport = simple_strtoul(str, NULL, 0);
357
        return 1;
358
}
359
__setup("lockd.udpport=", udpport_set);
360
__setup("lockd.tcpport=", tcpport_set);
361
 
362
#endif
363
 
364
/*
365
 * Define NLM program and procedures
366
 */
367
static struct svc_version       nlmsvc_version1 = {
368
        1, 17, nlmsvc_procedures, NULL
369
};
370
static struct svc_version       nlmsvc_version3 = {
371
        3, 24, nlmsvc_procedures, NULL
372
};
373
#ifdef CONFIG_LOCKD_V4
374
static struct svc_version       nlmsvc_version4 = {
375
        4, 24, nlmsvc_procedures4, NULL
376
};
377
#endif
378
static struct svc_version *     nlmsvc_version[] = {
379
        NULL,
380
        &nlmsvc_version1,
381
        NULL,
382
        &nlmsvc_version3,
383
#ifdef CONFIG_LOCKD_V4
384
        &nlmsvc_version4,
385
#endif
386
};
387
 
388
static struct svc_stat          nlmsvc_stats;
389
 
390
#define NLM_NRVERS      (sizeof(nlmsvc_version)/sizeof(nlmsvc_version[0]))
391
struct svc_program              nlmsvc_program = {
392
        NLM_PROGRAM,            /* program number */
393
        1, NLM_NRVERS-1,        /* version range */
394
        NLM_NRVERS,             /* number of entries in nlmsvc_version */
395
        nlmsvc_version,         /* version table */
396
        "lockd",                /* service name */
397
        &nlmsvc_stats,          /* stats table */
398
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.