Root/fs/nfsd/nfssvc.c

1/*
2 * Central processing for nfsd.
3 *
4 * Authors: Olaf Kirch (okir@monad.swb.de)
5 *
6 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
7 */
8
9#include <linux/sched.h>
10#include <linux/freezer.h>
11#include <linux/fs_struct.h>
12#include <linux/swap.h>
13
14#include <linux/sunrpc/stats.h>
15#include <linux/sunrpc/svcsock.h>
16#include <linux/lockd/bind.h>
17#include <linux/nfsacl.h>
18#include <linux/seq_file.h>
19#include <net/net_namespace.h>
20#include "nfsd.h"
21#include "cache.h"
22#include "vfs.h"
23
24#define NFSDDBG_FACILITY NFSDDBG_SVC
25
26extern struct svc_program nfsd_program;
27static int nfsd(void *vrqstp);
28struct timeval nfssvc_boot;
29
30/*
31 * nfsd_mutex protects nfsd_serv -- both the pointer itself and the members
32 * of the svc_serv struct. In particular, ->sv_nrthreads but also to some
33 * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt
34 *
35 * If (out side the lock) nfsd_serv is non-NULL, then it must point to a
36 * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number
37 * of nfsd threads must exist and each must listed in ->sp_all_threads in each
38 * entry of ->sv_pools[].
39 *
40 * Transitions of the thread count between zero and non-zero are of particular
41 * interest since the svc_serv needs to be created and initialized at that
42 * point, or freed.
43 *
44 * Finally, the nfsd_mutex also protects some of the global variables that are
45 * accessed when nfsd starts and that are settable via the write_* routines in
46 * nfsctl.c. In particular:
47 *
48 * user_recovery_dirname
49 * user_lease_time
50 * nfsd_versions
51 */
52DEFINE_MUTEX(nfsd_mutex);
53struct svc_serv *nfsd_serv;
54
55/*
56 * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used.
57 * nfsd_drc_max_pages limits the total amount of memory available for
58 * version 4.1 DRC caches.
59 * nfsd_drc_pages_used tracks the current version 4.1 DRC memory usage.
60 */
61spinlock_t nfsd_drc_lock;
62unsigned int nfsd_drc_max_mem;
63unsigned int nfsd_drc_mem_used;
64
65#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
66static struct svc_stat nfsd_acl_svcstats;
67static struct svc_version * nfsd_acl_version[] = {
68    [2] = &nfsd_acl_version2,
69    [3] = &nfsd_acl_version3,
70};
71
72#define NFSD_ACL_MINVERS 2
73#define NFSD_ACL_NRVERS ARRAY_SIZE(nfsd_acl_version)
74static struct svc_version *nfsd_acl_versions[NFSD_ACL_NRVERS];
75
76static struct svc_program nfsd_acl_program = {
77    .pg_prog = NFS_ACL_PROGRAM,
78    .pg_nvers = NFSD_ACL_NRVERS,
79    .pg_vers = nfsd_acl_versions,
80    .pg_name = "nfsacl",
81    .pg_class = "nfsd",
82    .pg_stats = &nfsd_acl_svcstats,
83    .pg_authenticate = &svc_set_client,
84};
85
86static struct svc_stat nfsd_acl_svcstats = {
87    .program = &nfsd_acl_program,
88};
89#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
90
91static struct svc_version * nfsd_version[] = {
92    [2] = &nfsd_version2,
93#if defined(CONFIG_NFSD_V3)
94    [3] = &nfsd_version3,
95#endif
96#if defined(CONFIG_NFSD_V4)
97    [4] = &nfsd_version4,
98#endif
99};
100
101#define NFSD_MINVERS 2
102#define NFSD_NRVERS ARRAY_SIZE(nfsd_version)
103static struct svc_version *nfsd_versions[NFSD_NRVERS];
104
105struct svc_program nfsd_program = {
106#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
107    .pg_next = &nfsd_acl_program,
108#endif
109    .pg_prog = NFS_PROGRAM, /* program number */
110    .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
111    .pg_vers = nfsd_versions, /* version table */
112    .pg_name = "nfsd", /* program name */
113    .pg_class = "nfsd", /* authentication class */
114    .pg_stats = &nfsd_svcstats, /* version table */
115    .pg_authenticate = &svc_set_client, /* export authentication */
116
117};
118
119u32 nfsd_supported_minorversion;
120
121int nfsd_vers(int vers, enum vers_op change)
122{
123    if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
124        return 0;
125    switch(change) {
126    case NFSD_SET:
127        nfsd_versions[vers] = nfsd_version[vers];
128#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
129        if (vers < NFSD_ACL_NRVERS)
130            nfsd_acl_versions[vers] = nfsd_acl_version[vers];
131#endif
132        break;
133    case NFSD_CLEAR:
134        nfsd_versions[vers] = NULL;
135#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
136        if (vers < NFSD_ACL_NRVERS)
137            nfsd_acl_versions[vers] = NULL;
138#endif
139        break;
140    case NFSD_TEST:
141        return nfsd_versions[vers] != NULL;
142    case NFSD_AVAIL:
143        return nfsd_version[vers] != NULL;
144    }
145    return 0;
146}
147
148int nfsd_minorversion(u32 minorversion, enum vers_op change)
149{
150    if (minorversion > NFSD_SUPPORTED_MINOR_VERSION)
151        return -1;
152    switch(change) {
153    case NFSD_SET:
154        nfsd_supported_minorversion = minorversion;
155        break;
156    case NFSD_CLEAR:
157        if (minorversion == 0)
158            return -1;
159        nfsd_supported_minorversion = minorversion - 1;
160        break;
161    case NFSD_TEST:
162        return minorversion <= nfsd_supported_minorversion;
163    case NFSD_AVAIL:
164        return minorversion <= NFSD_SUPPORTED_MINOR_VERSION;
165    }
166    return 0;
167}
168
169/*
170 * Maximum number of nfsd processes
171 */
172#define NFSD_MAXSERVS 8192
173
174int nfsd_nrthreads(void)
175{
176    int rv = 0;
177    mutex_lock(&nfsd_mutex);
178    if (nfsd_serv)
179        rv = nfsd_serv->sv_nrthreads;
180    mutex_unlock(&nfsd_mutex);
181    return rv;
182}
183
184static int nfsd_init_socks(int port)
185{
186    int error;
187    if (!list_empty(&nfsd_serv->sv_permsocks))
188        return 0;
189
190    error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port,
191                    SVC_SOCK_DEFAULTS);
192    if (error < 0)
193        return error;
194
195    error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port,
196                    SVC_SOCK_DEFAULTS);
197    if (error < 0)
198        return error;
199
200    return 0;
201}
202
203static bool nfsd_up = false;
204
205static int nfsd_startup(unsigned short port, int nrservs)
206{
207    int ret;
208
209    if (nfsd_up)
210        return 0;
211    /*
212     * Readahead param cache - will no-op if it already exists.
213     * (Note therefore results will be suboptimal if number of
214     * threads is modified after nfsd start.)
215     */
216    ret = nfsd_racache_init(2*nrservs);
217    if (ret)
218        return ret;
219    ret = nfsd_init_socks(port);
220    if (ret)
221        goto out_racache;
222    ret = lockd_up();
223    if (ret)
224        goto out_racache;
225    ret = nfs4_state_start();
226    if (ret)
227        goto out_lockd;
228    nfsd_up = true;
229    return 0;
230out_lockd:
231    lockd_down();
232out_racache:
233    nfsd_racache_shutdown();
234    return ret;
235}
236
237static void nfsd_shutdown(void)
238{
239    /*
240     * write_ports can create the server without actually starting
241     * any threads--if we get shut down before any threads are
242     * started, then nfsd_last_thread will be run before any of this
243     * other initialization has been done.
244     */
245    if (!nfsd_up)
246        return;
247    nfs4_state_shutdown();
248    lockd_down();
249    nfsd_racache_shutdown();
250    nfsd_up = false;
251}
252
253static void nfsd_last_thread(struct svc_serv *serv)
254{
255    /* When last nfsd thread exits we need to do some clean-up */
256    nfsd_serv = NULL;
257    nfsd_shutdown();
258
259    printk(KERN_WARNING "nfsd: last server has exited, flushing export "
260                "cache\n");
261    nfsd_export_flush();
262}
263
264void nfsd_reset_versions(void)
265{
266    int found_one = 0;
267    int i;
268
269    for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
270        if (nfsd_program.pg_vers[i])
271            found_one = 1;
272    }
273
274    if (!found_one) {
275        for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++)
276            nfsd_program.pg_vers[i] = nfsd_version[i];
277#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
278        for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++)
279            nfsd_acl_program.pg_vers[i] =
280                nfsd_acl_version[i];
281#endif
282    }
283}
284
285/*
286 * Each session guarantees a negotiated per slot memory cache for replies
287 * which in turn consumes memory beyond the v2/v3/v4.0 server. A dedicated
288 * NFSv4.1 server might want to use more memory for a DRC than a machine
289 * with mutiple services.
290 *
291 * Impose a hard limit on the number of pages for the DRC which varies
292 * according to the machines free pages. This is of course only a default.
293 *
294 * For now this is a #defined shift which could be under admin control
295 * in the future.
296 */
297static void set_max_drc(void)
298{
299    #define NFSD_DRC_SIZE_SHIFT 10
300    nfsd_drc_max_mem = (nr_free_buffer_pages()
301                    >> NFSD_DRC_SIZE_SHIFT) * PAGE_SIZE;
302    nfsd_drc_mem_used = 0;
303    spin_lock_init(&nfsd_drc_lock);
304    dprintk("%s nfsd_drc_max_mem %u \n", __func__, nfsd_drc_max_mem);
305}
306
307int nfsd_create_serv(void)
308{
309    int err = 0;
310
311    WARN_ON(!mutex_is_locked(&nfsd_mutex));
312    if (nfsd_serv) {
313        svc_get(nfsd_serv);
314        return 0;
315    }
316    if (nfsd_max_blksize == 0) {
317        /* choose a suitable default */
318        struct sysinfo i;
319        si_meminfo(&i);
320        /* Aim for 1/4096 of memory per thread
321         * This gives 1MB on 4Gig machines
322         * But only uses 32K on 128M machines.
323         * Bottom out at 8K on 32M and smaller.
324         * Of course, this is only a default.
325         */
326        nfsd_max_blksize = NFSSVC_MAXBLKSIZE;
327        i.totalram <<= PAGE_SHIFT - 12;
328        while (nfsd_max_blksize > i.totalram &&
329               nfsd_max_blksize >= 8*1024*2)
330            nfsd_max_blksize /= 2;
331    }
332    nfsd_reset_versions();
333
334    nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
335                      nfsd_last_thread, nfsd, THIS_MODULE);
336    if (nfsd_serv == NULL)
337        return -ENOMEM;
338
339    set_max_drc();
340    do_gettimeofday(&nfssvc_boot); /* record boot time */
341    return err;
342}
343
344int nfsd_nrpools(void)
345{
346    if (nfsd_serv == NULL)
347        return 0;
348    else
349        return nfsd_serv->sv_nrpools;
350}
351
352int nfsd_get_nrthreads(int n, int *nthreads)
353{
354    int i = 0;
355
356    if (nfsd_serv != NULL) {
357        for (i = 0; i < nfsd_serv->sv_nrpools && i < n; i++)
358            nthreads[i] = nfsd_serv->sv_pools[i].sp_nrthreads;
359    }
360
361    return 0;
362}
363
364int nfsd_set_nrthreads(int n, int *nthreads)
365{
366    int i = 0;
367    int tot = 0;
368    int err = 0;
369
370    WARN_ON(!mutex_is_locked(&nfsd_mutex));
371
372    if (nfsd_serv == NULL || n <= 0)
373        return 0;
374
375    if (n > nfsd_serv->sv_nrpools)
376        n = nfsd_serv->sv_nrpools;
377
378    /* enforce a global maximum number of threads */
379    tot = 0;
380    for (i = 0; i < n; i++) {
381        if (nthreads[i] > NFSD_MAXSERVS)
382            nthreads[i] = NFSD_MAXSERVS;
383        tot += nthreads[i];
384    }
385    if (tot > NFSD_MAXSERVS) {
386        /* total too large: scale down requested numbers */
387        for (i = 0; i < n && tot > 0; i++) {
388                int new = nthreads[i] * NFSD_MAXSERVS / tot;
389            tot -= (nthreads[i] - new);
390            nthreads[i] = new;
391        }
392        for (i = 0; i < n && tot > 0; i++) {
393            nthreads[i]--;
394            tot--;
395        }
396    }
397
398    /*
399     * There must always be a thread in pool 0; the admin
400     * can't shut down NFS completely using pool_threads.
401     */
402    if (nthreads[0] == 0)
403        nthreads[0] = 1;
404
405    /* apply the new numbers */
406    svc_get(nfsd_serv);
407    for (i = 0; i < n; i++) {
408        err = svc_set_num_threads(nfsd_serv, &nfsd_serv->sv_pools[i],
409                          nthreads[i]);
410        if (err)
411            break;
412    }
413    svc_destroy(nfsd_serv);
414
415    return err;
416}
417
418/*
419 * Adjust the number of threads and return the new number of threads.
420 * This is also the function that starts the server if necessary, if
421 * this is the first time nrservs is nonzero.
422 */
423int
424nfsd_svc(unsigned short port, int nrservs)
425{
426    int error;
427    bool nfsd_up_before;
428
429    mutex_lock(&nfsd_mutex);
430    dprintk("nfsd: creating service\n");
431    if (nrservs <= 0)
432        nrservs = 0;
433    if (nrservs > NFSD_MAXSERVS)
434        nrservs = NFSD_MAXSERVS;
435    error = 0;
436    if (nrservs == 0 && nfsd_serv == NULL)
437        goto out;
438
439    error = nfsd_create_serv();
440    if (error)
441        goto out;
442
443    nfsd_up_before = nfsd_up;
444
445    error = nfsd_startup(port, nrservs);
446    if (error)
447        goto out_destroy;
448    error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
449    if (error)
450        goto out_shutdown;
451    /* We are holding a reference to nfsd_serv which
452     * we don't want to count in the return value,
453     * so subtract 1
454     */
455    error = nfsd_serv->sv_nrthreads - 1;
456out_shutdown:
457    if (error < 0 && !nfsd_up_before)
458        nfsd_shutdown();
459out_destroy:
460    svc_destroy(nfsd_serv); /* Release server */
461out:
462    mutex_unlock(&nfsd_mutex);
463    return error;
464}
465
466
467/*
468 * This is the NFS server kernel thread
469 */
470static int
471nfsd(void *vrqstp)
472{
473    struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
474    int err, preverr = 0;
475
476    /* Lock module and set up kernel thread */
477    mutex_lock(&nfsd_mutex);
478
479    /* At this point, the thread shares current->fs
480     * with the init process. We need to create files with a
481     * umask of 0 instead of init's umask. */
482    if (unshare_fs_struct() < 0) {
483        printk("Unable to start nfsd thread: out of memory\n");
484        goto out;
485    }
486
487    current->fs->umask = 0;
488
489    /*
490     * thread is spawned with all signals set to SIG_IGN, re-enable
491     * the ones that will bring down the thread
492     */
493    allow_signal(SIGKILL);
494    allow_signal(SIGHUP);
495    allow_signal(SIGINT);
496    allow_signal(SIGQUIT);
497
498    nfsdstats.th_cnt++;
499    mutex_unlock(&nfsd_mutex);
500
501    /*
502     * We want less throttling in balance_dirty_pages() so that nfs to
503     * localhost doesn't cause nfsd to lock up due to all the client's
504     * dirty pages.
505     */
506    current->flags |= PF_LESS_THROTTLE;
507    set_freezable();
508
509    /*
510     * The main request loop
511     */
512    for (;;) {
513        /*
514         * Find a socket with data available and call its
515         * recvfrom routine.
516         */
517        while ((err = svc_recv(rqstp, 60*60*HZ)) == -EAGAIN)
518            ;
519        if (err == -EINTR)
520            break;
521        else if (err < 0) {
522            if (err != preverr) {
523                printk(KERN_WARNING "%s: unexpected error "
524                    "from svc_recv (%d)\n", __func__, -err);
525                preverr = err;
526            }
527            schedule_timeout_uninterruptible(HZ);
528            continue;
529        }
530
531
532        /* Lock the export hash tables for reading. */
533        exp_readlock();
534
535        validate_process_creds();
536        svc_process(rqstp);
537        validate_process_creds();
538
539        /* Unlock export hash tables */
540        exp_readunlock();
541    }
542
543    /* Clear signals before calling svc_exit_thread() */
544    flush_signals(current);
545
546    mutex_lock(&nfsd_mutex);
547    nfsdstats.th_cnt --;
548
549out:
550    /* Release the thread */
551    svc_exit_thread(rqstp);
552
553    /* Release module */
554    mutex_unlock(&nfsd_mutex);
555    module_put_and_exit(0);
556    return 0;
557}
558
559static __be32 map_new_errors(u32 vers, __be32 nfserr)
560{
561    if (nfserr == nfserr_jukebox && vers == 2)
562        return nfserr_dropit;
563    if (nfserr == nfserr_wrongsec && vers < 4)
564        return nfserr_acces;
565    return nfserr;
566}
567
568int
569nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
570{
571    struct svc_procedure *proc;
572    kxdrproc_t xdr;
573    __be32 nfserr;
574    __be32 *nfserrp;
575
576    dprintk("nfsd_dispatch: vers %d proc %d\n",
577                rqstp->rq_vers, rqstp->rq_proc);
578    proc = rqstp->rq_procinfo;
579
580    /* Check whether we have this call in the cache. */
581    switch (nfsd_cache_lookup(rqstp, proc->pc_cachetype)) {
582    case RC_INTR:
583    case RC_DROPIT:
584        return 0;
585    case RC_REPLY:
586        return 1;
587    case RC_DOIT:;
588        /* do it */
589    }
590
591    /* Decode arguments */
592    xdr = proc->pc_decode;
593    if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base,
594            rqstp->rq_argp)) {
595        dprintk("nfsd: failed to decode arguments!\n");
596        nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
597        *statp = rpc_garbage_args;
598        return 1;
599    }
600
601    /* need to grab the location to store the status, as
602     * nfsv4 does some encoding while processing
603     */
604    nfserrp = rqstp->rq_res.head[0].iov_base
605        + rqstp->rq_res.head[0].iov_len;
606    rqstp->rq_res.head[0].iov_len += sizeof(__be32);
607
608    /* Now call the procedure handler, and encode NFS status. */
609    nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
610    nfserr = map_new_errors(rqstp->rq_vers, nfserr);
611    if (nfserr == nfserr_dropit || rqstp->rq_dropme) {
612        dprintk("nfsd: Dropping request; may be revisited later\n");
613        nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
614        return 0;
615    }
616
617    if (rqstp->rq_proc != 0)
618        *nfserrp++ = nfserr;
619
620    /* Encode result.
621     * For NFSv2, additional info is never returned in case of an error.
622     */
623    if (!(nfserr && rqstp->rq_vers == 2)) {
624        xdr = proc->pc_encode;
625        if (xdr && !xdr(rqstp, nfserrp,
626                rqstp->rq_resp)) {
627            /* Failed to encode result. Release cache entry */
628            dprintk("nfsd: failed to encode result!\n");
629            nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
630            *statp = rpc_system_err;
631            return 1;
632        }
633    }
634
635    /* Store reply in cache. */
636    nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1);
637    return 1;
638}
639
640int nfsd_pool_stats_open(struct inode *inode, struct file *file)
641{
642    int ret;
643    mutex_lock(&nfsd_mutex);
644    if (nfsd_serv == NULL) {
645        mutex_unlock(&nfsd_mutex);
646        return -ENODEV;
647    }
648    /* bump up the psudo refcount while traversing */
649    svc_get(nfsd_serv);
650    ret = svc_pool_stats_open(nfsd_serv, file);
651    mutex_unlock(&nfsd_mutex);
652    return ret;
653}
654
655int nfsd_pool_stats_release(struct inode *inode, struct file *file)
656{
657    int ret = seq_release(inode, file);
658    mutex_lock(&nfsd_mutex);
659    /* this function really, really should have been called svc_put() */
660    svc_destroy(nfsd_serv);
661    mutex_unlock(&nfsd_mutex);
662    return ret;
663}
664

Archive Download this file



interactive