linux/fs/nfsd/nfssvc.c
<<
>>
Prefs
   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/module.h>
  12#include <linux/fs_struct.h>
  13#include <linux/swap.h>
  14
  15#include <linux/sunrpc/stats.h>
  16#include <linux/sunrpc/svcsock.h>
  17#include <linux/sunrpc/svc_xprt.h>
  18#include <linux/lockd/bind.h>
  19#include <linux/nfsacl.h>
  20#include <linux/seq_file.h>
  21#include <linux/inetdevice.h>
  22#include <net/addrconf.h>
  23#include <net/ipv6.h>
  24#include <net/net_namespace.h>
  25#include "nfsd.h"
  26#include "cache.h"
  27#include "vfs.h"
  28#include "netns.h"
  29
  30#define NFSDDBG_FACILITY        NFSDDBG_SVC
  31
  32extern struct svc_program       nfsd_program;
  33static int                      nfsd(void *vrqstp);
  34
  35/*
  36 * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members
  37 * of the svc_serv struct. In particular, ->sv_nrthreads but also to some
  38 * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt
  39 *
  40 * If (out side the lock) nn->nfsd_serv is non-NULL, then it must point to a
  41 * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number
  42 * of nfsd threads must exist and each must listed in ->sp_all_threads in each
  43 * entry of ->sv_pools[].
  44 *
  45 * Transitions of the thread count between zero and non-zero are of particular
  46 * interest since the svc_serv needs to be created and initialized at that
  47 * point, or freed.
  48 *
  49 * Finally, the nfsd_mutex also protects some of the global variables that are
  50 * accessed when nfsd starts and that are settable via the write_* routines in
  51 * nfsctl.c. In particular:
  52 *
  53 *      user_recovery_dirname
  54 *      user_lease_time
  55 *      nfsd_versions
  56 */
  57DEFINE_MUTEX(nfsd_mutex);
  58
  59/*
  60 * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used.
  61 * nfsd_drc_max_pages limits the total amount of memory available for
  62 * version 4.1 DRC caches.
  63 * nfsd_drc_pages_used tracks the current version 4.1 DRC memory usage.
  64 */
  65spinlock_t      nfsd_drc_lock;
  66unsigned long   nfsd_drc_max_mem;
  67unsigned long   nfsd_drc_mem_used;
  68
  69#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
  70static struct svc_stat  nfsd_acl_svcstats;
  71static struct svc_version *     nfsd_acl_version[] = {
  72        [2] = &nfsd_acl_version2,
  73        [3] = &nfsd_acl_version3,
  74};
  75
  76#define NFSD_ACL_MINVERS            2
  77#define NFSD_ACL_NRVERS         ARRAY_SIZE(nfsd_acl_version)
  78static struct svc_version *nfsd_acl_versions[NFSD_ACL_NRVERS];
  79
  80static struct svc_program       nfsd_acl_program = {
  81        .pg_prog                = NFS_ACL_PROGRAM,
  82        .pg_nvers               = NFSD_ACL_NRVERS,
  83        .pg_vers                = nfsd_acl_versions,
  84        .pg_name                = "nfsacl",
  85        .pg_class               = "nfsd",
  86        .pg_stats               = &nfsd_acl_svcstats,
  87        .pg_authenticate        = &svc_set_client,
  88};
  89
  90static struct svc_stat  nfsd_acl_svcstats = {
  91        .program        = &nfsd_acl_program,
  92};
  93#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
  94
  95static struct svc_version *     nfsd_version[] = {
  96        [2] = &nfsd_version2,
  97#if defined(CONFIG_NFSD_V3)
  98        [3] = &nfsd_version3,
  99#endif
 100#if defined(CONFIG_NFSD_V4)
 101        [4] = &nfsd_version4,
 102#endif
 103};
 104
 105#define NFSD_MINVERS            2
 106#define NFSD_NRVERS             ARRAY_SIZE(nfsd_version)
 107static struct svc_version *nfsd_versions[NFSD_NRVERS];
 108
 109struct svc_program              nfsd_program = {
 110#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 111        .pg_next                = &nfsd_acl_program,
 112#endif
 113        .pg_prog                = NFS_PROGRAM,          /* program number */
 114        .pg_nvers               = NFSD_NRVERS,          /* nr of entries in nfsd_version */
 115        .pg_vers                = nfsd_versions,        /* version table */
 116        .pg_name                = "nfsd",               /* program name */
 117        .pg_class               = "nfsd",               /* authentication class */
 118        .pg_stats               = &nfsd_svcstats,       /* version table */
 119        .pg_authenticate        = &svc_set_client,      /* export authentication */
 120
 121};
 122
 123static bool nfsd_supported_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1] = {
 124        [0] = 1,
 125        [1] = 1,
 126        [2] = 1,
 127};
 128
 129int nfsd_vers(int vers, enum vers_op change)
 130{
 131        if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
 132                return 0;
 133        switch(change) {
 134        case NFSD_SET:
 135                nfsd_versions[vers] = nfsd_version[vers];
 136#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 137                if (vers < NFSD_ACL_NRVERS)
 138                        nfsd_acl_versions[vers] = nfsd_acl_version[vers];
 139#endif
 140                break;
 141        case NFSD_CLEAR:
 142                nfsd_versions[vers] = NULL;
 143#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 144                if (vers < NFSD_ACL_NRVERS)
 145                        nfsd_acl_versions[vers] = NULL;
 146#endif
 147                break;
 148        case NFSD_TEST:
 149                return nfsd_versions[vers] != NULL;
 150        case NFSD_AVAIL:
 151                return nfsd_version[vers] != NULL;
 152        }
 153        return 0;
 154}
 155
 156int nfsd_minorversion(u32 minorversion, enum vers_op change)
 157{
 158        if (minorversion > NFSD_SUPPORTED_MINOR_VERSION)
 159                return -1;
 160        switch(change) {
 161        case NFSD_SET:
 162                nfsd_supported_minorversions[minorversion] = true;
 163                break;
 164        case NFSD_CLEAR:
 165                nfsd_supported_minorversions[minorversion] = false;
 166                break;
 167        case NFSD_TEST:
 168                return nfsd_supported_minorversions[minorversion];
 169        case NFSD_AVAIL:
 170                return minorversion <= NFSD_SUPPORTED_MINOR_VERSION;
 171        }
 172        return 0;
 173}
 174
 175/*
 176 * Maximum number of nfsd processes
 177 */
 178#define NFSD_MAXSERVS           8192
 179
 180int nfsd_nrthreads(struct net *net)
 181{
 182        int rv = 0;
 183        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 184
 185        mutex_lock(&nfsd_mutex);
 186        if (nn->nfsd_serv)
 187                rv = nn->nfsd_serv->sv_nrthreads;
 188        mutex_unlock(&nfsd_mutex);
 189        return rv;
 190}
 191
 192static int nfsd_init_socks(struct net *net)
 193{
 194        int error;
 195        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 196
 197        if (!list_empty(&nn->nfsd_serv->sv_permsocks))
 198                return 0;
 199
 200        error = svc_create_xprt(nn->nfsd_serv, "udp", net, PF_INET, NFS_PORT,
 201                                        SVC_SOCK_DEFAULTS);
 202        if (error < 0)
 203                return error;
 204
 205        error = svc_create_xprt(nn->nfsd_serv, "tcp", net, PF_INET, NFS_PORT,
 206                                        SVC_SOCK_DEFAULTS);
 207        if (error < 0)
 208                return error;
 209
 210        return 0;
 211}
 212
 213static int nfsd_users = 0;
 214
 215static int nfsd_startup_generic(int nrservs)
 216{
 217        int ret;
 218
 219        if (nfsd_users++)
 220                return 0;
 221
 222        /*
 223         * Readahead param cache - will no-op if it already exists.
 224         * (Note therefore results will be suboptimal if number of
 225         * threads is modified after nfsd start.)
 226         */
 227        ret = nfsd_racache_init(2*nrservs);
 228        if (ret)
 229                goto dec_users;
 230
 231        ret = nfs4_state_start();
 232        if (ret)
 233                goto out_racache;
 234        return 0;
 235
 236out_racache:
 237        nfsd_racache_shutdown();
 238dec_users:
 239        nfsd_users--;
 240        return ret;
 241}
 242
 243static void nfsd_shutdown_generic(void)
 244{
 245        if (--nfsd_users)
 246                return;
 247
 248        nfs4_state_shutdown();
 249        nfsd_racache_shutdown();
 250}
 251
 252static bool nfsd_needs_lockd(void)
 253{
 254#if defined(CONFIG_NFSD_V3)
 255        return (nfsd_versions[2] != NULL) || (nfsd_versions[3] != NULL);
 256#else
 257        return (nfsd_versions[2] != NULL);
 258#endif
 259}
 260
 261static int nfsd_startup_net(int nrservs, struct net *net)
 262{
 263        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 264        int ret;
 265
 266        if (nn->nfsd_net_up)
 267                return 0;
 268
 269        ret = nfsd_startup_generic(nrservs);
 270        if (ret)
 271                return ret;
 272        ret = nfsd_init_socks(net);
 273        if (ret)
 274                goto out_socks;
 275
 276        if (nfsd_needs_lockd() && !nn->lockd_up) {
 277                ret = lockd_up(net);
 278                if (ret)
 279                        goto out_socks;
 280                nn->lockd_up = 1;
 281        }
 282
 283        ret = nfs4_state_start_net(net);
 284        if (ret)
 285                goto out_lockd;
 286
 287        nn->nfsd_net_up = true;
 288        return 0;
 289
 290out_lockd:
 291        if (nn->lockd_up) {
 292                lockd_down(net);
 293                nn->lockd_up = 0;
 294        }
 295out_socks:
 296        nfsd_shutdown_generic();
 297        return ret;
 298}
 299
 300static void nfsd_shutdown_net(struct net *net)
 301{
 302        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 303
 304        nfs4_state_shutdown_net(net);
 305        if (nn->lockd_up) {
 306                lockd_down(net);
 307                nn->lockd_up = 0;
 308        }
 309        nn->nfsd_net_up = false;
 310        nfsd_shutdown_generic();
 311}
 312
 313static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event,
 314        void *ptr)
 315{
 316        struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
 317        struct net_device *dev = ifa->ifa_dev->dev;
 318        struct net *net = dev_net(dev);
 319        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 320        struct sockaddr_in sin;
 321
 322        if (event != NETDEV_DOWN)
 323                goto out;
 324
 325        if (nn->nfsd_serv) {
 326                dprintk("nfsd_inetaddr_event: removed %pI4\n", &ifa->ifa_local);
 327                sin.sin_family = AF_INET;
 328                sin.sin_addr.s_addr = ifa->ifa_local;
 329                svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin);
 330        }
 331
 332out:
 333        return NOTIFY_DONE;
 334}
 335
 336static struct notifier_block nfsd_inetaddr_notifier = {
 337        .notifier_call = nfsd_inetaddr_event,
 338};
 339
 340#if IS_ENABLED(CONFIG_IPV6)
 341static int nfsd_inet6addr_event(struct notifier_block *this,
 342        unsigned long event, void *ptr)
 343{
 344        struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
 345        struct net_device *dev = ifa->idev->dev;
 346        struct net *net = dev_net(dev);
 347        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 348        struct sockaddr_in6 sin6;
 349
 350        if (event != NETDEV_DOWN)
 351                goto out;
 352
 353        if (nn->nfsd_serv) {
 354                dprintk("nfsd_inet6addr_event: removed %pI6\n", &ifa->addr);
 355                sin6.sin6_family = AF_INET6;
 356                sin6.sin6_addr = ifa->addr;
 357                svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin6);
 358        }
 359
 360out:
 361        return NOTIFY_DONE;
 362}
 363
 364static struct notifier_block nfsd_inet6addr_notifier = {
 365        .notifier_call = nfsd_inet6addr_event,
 366};
 367#endif
 368
 369static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
 370{
 371        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 372
 373        unregister_inetaddr_notifier(&nfsd_inetaddr_notifier);
 374#if IS_ENABLED(CONFIG_IPV6)
 375        unregister_inet6addr_notifier(&nfsd_inet6addr_notifier);
 376#endif
 377        /*
 378         * write_ports can create the server without actually starting
 379         * any threads--if we get shut down before any threads are
 380         * started, then nfsd_last_thread will be run before any of this
 381         * other initialization has been done except the rpcb information.
 382         */
 383        svc_rpcb_cleanup(serv, net);
 384        if (!nn->nfsd_net_up)
 385                return;
 386
 387        nfsd_shutdown_net(net);
 388        printk(KERN_WARNING "nfsd: last server has exited, flushing export "
 389                            "cache\n");
 390        nfsd_export_flush(net);
 391}
 392
 393void nfsd_reset_versions(void)
 394{
 395        int found_one = 0;
 396        int i;
 397
 398        for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
 399                if (nfsd_program.pg_vers[i])
 400                        found_one = 1;
 401        }
 402
 403        if (!found_one) {
 404                for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++)
 405                        nfsd_program.pg_vers[i] = nfsd_version[i];
 406#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 407                for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++)
 408                        nfsd_acl_program.pg_vers[i] =
 409                                nfsd_acl_version[i];
 410#endif
 411        }
 412}
 413
 414/*
 415 * Each session guarantees a negotiated per slot memory cache for replies
 416 * which in turn consumes memory beyond the v2/v3/v4.0 server. A dedicated
 417 * NFSv4.1 server might want to use more memory for a DRC than a machine
 418 * with mutiple services.
 419 *
 420 * Impose a hard limit on the number of pages for the DRC which varies
 421 * according to the machines free pages. This is of course only a default.
 422 *
 423 * For now this is a #defined shift which could be under admin control
 424 * in the future.
 425 */
 426static void set_max_drc(void)
 427{
 428        #define NFSD_DRC_SIZE_SHIFT     10
 429        nfsd_drc_max_mem = (nr_free_buffer_pages()
 430                                        >> NFSD_DRC_SIZE_SHIFT) * PAGE_SIZE;
 431        nfsd_drc_mem_used = 0;
 432        spin_lock_init(&nfsd_drc_lock);
 433        dprintk("%s nfsd_drc_max_mem %lu \n", __func__, nfsd_drc_max_mem);
 434}
 435
 436static int nfsd_get_default_max_blksize(void)
 437{
 438        struct sysinfo i;
 439        unsigned long long target;
 440        unsigned long ret;
 441
 442        si_meminfo(&i);
 443        target = (i.totalram - i.totalhigh) << PAGE_SHIFT;
 444        /*
 445         * Aim for 1/4096 of memory per thread This gives 1MB on 4Gig
 446         * machines, but only uses 32K on 128M machines.  Bottom out at
 447         * 8K on 32M and smaller.  Of course, this is only a default.
 448         */
 449        target >>= 12;
 450
 451        ret = NFSSVC_MAXBLKSIZE;
 452        while (ret > target && ret >= 8*1024*2)
 453                ret /= 2;
 454        return ret;
 455}
 456
 457static struct svc_serv_ops nfsd_thread_sv_ops = {
 458        .svo_shutdown           = nfsd_last_thread,
 459        .svo_function           = nfsd,
 460        .svo_enqueue_xprt       = svc_xprt_do_enqueue,
 461        .svo_setup              = svc_set_num_threads,
 462        .svo_module             = THIS_MODULE,
 463};
 464
 465int nfsd_create_serv(struct net *net)
 466{
 467        int error;
 468        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 469
 470        WARN_ON(!mutex_is_locked(&nfsd_mutex));
 471        if (nn->nfsd_serv) {
 472                svc_get(nn->nfsd_serv);
 473                return 0;
 474        }
 475        if (nfsd_max_blksize == 0)
 476                nfsd_max_blksize = nfsd_get_default_max_blksize();
 477        nfsd_reset_versions();
 478        nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
 479                                                &nfsd_thread_sv_ops);
 480        if (nn->nfsd_serv == NULL)
 481                return -ENOMEM;
 482
 483        nn->nfsd_serv->sv_maxconn = nn->max_connections;
 484        error = svc_bind(nn->nfsd_serv, net);
 485        if (error < 0) {
 486                svc_destroy(nn->nfsd_serv);
 487                return error;
 488        }
 489
 490        set_max_drc();
 491        register_inetaddr_notifier(&nfsd_inetaddr_notifier);
 492#if IS_ENABLED(CONFIG_IPV6)
 493        register_inet6addr_notifier(&nfsd_inet6addr_notifier);
 494#endif
 495        do_gettimeofday(&nn->nfssvc_boot);              /* record boot time */
 496        return 0;
 497}
 498
 499int nfsd_nrpools(struct net *net)
 500{
 501        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 502
 503        if (nn->nfsd_serv == NULL)
 504                return 0;
 505        else
 506                return nn->nfsd_serv->sv_nrpools;
 507}
 508
 509int nfsd_get_nrthreads(int n, int *nthreads, struct net *net)
 510{
 511        int i = 0;
 512        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 513
 514        if (nn->nfsd_serv != NULL) {
 515                for (i = 0; i < nn->nfsd_serv->sv_nrpools && i < n; i++)
 516                        nthreads[i] = nn->nfsd_serv->sv_pools[i].sp_nrthreads;
 517        }
 518
 519        return 0;
 520}
 521
 522void nfsd_destroy(struct net *net)
 523{
 524        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 525        int destroy = (nn->nfsd_serv->sv_nrthreads == 1);
 526
 527        if (destroy)
 528                svc_shutdown_net(nn->nfsd_serv, net);
 529        svc_destroy(nn->nfsd_serv);
 530        if (destroy)
 531                nn->nfsd_serv = NULL;
 532}
 533
 534int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
 535{
 536        int i = 0;
 537        int tot = 0;
 538        int err = 0;
 539        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 540
 541        WARN_ON(!mutex_is_locked(&nfsd_mutex));
 542
 543        if (nn->nfsd_serv == NULL || n <= 0)
 544                return 0;
 545
 546        if (n > nn->nfsd_serv->sv_nrpools)
 547                n = nn->nfsd_serv->sv_nrpools;
 548
 549        /* enforce a global maximum number of threads */
 550        tot = 0;
 551        for (i = 0; i < n; i++) {
 552                nthreads[i] = min(nthreads[i], NFSD_MAXSERVS);
 553                tot += nthreads[i];
 554        }
 555        if (tot > NFSD_MAXSERVS) {
 556                /* total too large: scale down requested numbers */
 557                for (i = 0; i < n && tot > 0; i++) {
 558                        int new = nthreads[i] * NFSD_MAXSERVS / tot;
 559                        tot -= (nthreads[i] - new);
 560                        nthreads[i] = new;
 561                }
 562                for (i = 0; i < n && tot > 0; i++) {
 563                        nthreads[i]--;
 564                        tot--;
 565                }
 566        }
 567
 568        /*
 569         * There must always be a thread in pool 0; the admin
 570         * can't shut down NFS completely using pool_threads.
 571         */
 572        if (nthreads[0] == 0)
 573                nthreads[0] = 1;
 574
 575        /* apply the new numbers */
 576        svc_get(nn->nfsd_serv);
 577        for (i = 0; i < n; i++) {
 578                err = nn->nfsd_serv->sv_ops->svo_setup(nn->nfsd_serv,
 579                                &nn->nfsd_serv->sv_pools[i], nthreads[i]);
 580                if (err)
 581                        break;
 582        }
 583        nfsd_destroy(net);
 584        return err;
 585}
 586
 587/*
 588 * Adjust the number of threads and return the new number of threads.
 589 * This is also the function that starts the server if necessary, if
 590 * this is the first time nrservs is nonzero.
 591 */
 592int
 593nfsd_svc(int nrservs, struct net *net)
 594{
 595        int     error;
 596        bool    nfsd_up_before;
 597        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 598
 599        mutex_lock(&nfsd_mutex);
 600        dprintk("nfsd: creating service\n");
 601
 602        nrservs = max(nrservs, 0);
 603        nrservs = min(nrservs, NFSD_MAXSERVS);
 604        error = 0;
 605
 606        if (nrservs == 0 && nn->nfsd_serv == NULL)
 607                goto out;
 608
 609        error = nfsd_create_serv(net);
 610        if (error)
 611                goto out;
 612
 613        nfsd_up_before = nn->nfsd_net_up;
 614
 615        error = nfsd_startup_net(nrservs, net);
 616        if (error)
 617                goto out_destroy;
 618        error = nn->nfsd_serv->sv_ops->svo_setup(nn->nfsd_serv,
 619                        NULL, nrservs);
 620        if (error)
 621                goto out_shutdown;
 622        /* We are holding a reference to nn->nfsd_serv which
 623         * we don't want to count in the return value,
 624         * so subtract 1
 625         */
 626        error = nn->nfsd_serv->sv_nrthreads - 1;
 627out_shutdown:
 628        if (error < 0 && !nfsd_up_before)
 629                nfsd_shutdown_net(net);
 630out_destroy:
 631        nfsd_destroy(net);              /* Release server */
 632out:
 633        mutex_unlock(&nfsd_mutex);
 634        return error;
 635}
 636
 637
 638/*
 639 * This is the NFS server kernel thread
 640 */
 641static int
 642nfsd(void *vrqstp)
 643{
 644        struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
 645        struct svc_xprt *perm_sock = list_entry(rqstp->rq_server->sv_permsocks.next, typeof(struct svc_xprt), xpt_list);
 646        struct net *net = perm_sock->xpt_net;
 647        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 648        int err;
 649
 650        /* Lock module and set up kernel thread */
 651        mutex_lock(&nfsd_mutex);
 652
 653        /* At this point, the thread shares current->fs
 654         * with the init process. We need to create files with a
 655         * umask of 0 instead of init's umask. */
 656        if (unshare_fs_struct() < 0) {
 657                printk("Unable to start nfsd thread: out of memory\n");
 658                goto out;
 659        }
 660
 661        current->fs->umask = 0;
 662
 663        /*
 664         * thread is spawned with all signals set to SIG_IGN, re-enable
 665         * the ones that will bring down the thread
 666         */
 667        allow_signal(SIGKILL);
 668        allow_signal(SIGHUP);
 669        allow_signal(SIGINT);
 670        allow_signal(SIGQUIT);
 671
 672        nfsdstats.th_cnt++;
 673        mutex_unlock(&nfsd_mutex);
 674
 675        set_freezable();
 676
 677        /*
 678         * The main request loop
 679         */
 680        for (;;) {
 681                /* Update sv_maxconn if it has changed */
 682                rqstp->rq_server->sv_maxconn = nn->max_connections;
 683
 684                /*
 685                 * Find a socket with data available and call its
 686                 * recvfrom routine.
 687                 */
 688                while ((err = svc_recv(rqstp, 60*60*HZ)) == -EAGAIN)
 689                        ;
 690                if (err == -EINTR)
 691                        break;
 692                validate_process_creds();
 693                svc_process(rqstp);
 694                validate_process_creds();
 695        }
 696
 697        /* Clear signals before calling svc_exit_thread() */
 698        flush_signals(current);
 699
 700        mutex_lock(&nfsd_mutex);
 701        nfsdstats.th_cnt --;
 702
 703out:
 704        rqstp->rq_server = NULL;
 705
 706        /* Release the thread */
 707        svc_exit_thread(rqstp);
 708
 709        nfsd_destroy(net);
 710
 711        /* Release module */
 712        mutex_unlock(&nfsd_mutex);
 713        module_put_and_exit(0);
 714        return 0;
 715}
 716
 717static __be32 map_new_errors(u32 vers, __be32 nfserr)
 718{
 719        if (nfserr == nfserr_jukebox && vers == 2)
 720                return nfserr_dropit;
 721        if (nfserr == nfserr_wrongsec && vers < 4)
 722                return nfserr_acces;
 723        return nfserr;
 724}
 725
 726int
 727nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 728{
 729        struct svc_procedure    *proc;
 730        kxdrproc_t              xdr;
 731        __be32                  nfserr;
 732        __be32                  *nfserrp;
 733
 734        dprintk("nfsd_dispatch: vers %d proc %d\n",
 735                                rqstp->rq_vers, rqstp->rq_proc);
 736        proc = rqstp->rq_procinfo;
 737
 738        /*
 739         * Give the xdr decoder a chance to change this if it wants
 740         * (necessary in the NFSv4.0 compound case)
 741         */
 742        rqstp->rq_cachetype = proc->pc_cachetype;
 743        /* Decode arguments */
 744        xdr = proc->pc_decode;
 745        if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base,
 746                        rqstp->rq_argp)) {
 747                dprintk("nfsd: failed to decode arguments!\n");
 748                *statp = rpc_garbage_args;
 749                return 1;
 750        }
 751
 752        /* Check whether we have this call in the cache. */
 753        switch (nfsd_cache_lookup(rqstp)) {
 754        case RC_DROPIT:
 755                return 0;
 756        case RC_REPLY:
 757                return 1;
 758        case RC_DOIT:;
 759                /* do it */
 760        }
 761
 762        /* need to grab the location to store the status, as
 763         * nfsv4 does some encoding while processing 
 764         */
 765        nfserrp = rqstp->rq_res.head[0].iov_base
 766                + rqstp->rq_res.head[0].iov_len;
 767        rqstp->rq_res.head[0].iov_len += sizeof(__be32);
 768
 769        /* Now call the procedure handler, and encode NFS status. */
 770        nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
 771        nfserr = map_new_errors(rqstp->rq_vers, nfserr);
 772        if (nfserr == nfserr_dropit || test_bit(RQ_DROPME, &rqstp->rq_flags)) {
 773                dprintk("nfsd: Dropping request; may be revisited later\n");
 774                nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
 775                return 0;
 776        }
 777
 778        if (rqstp->rq_proc != 0)
 779                *nfserrp++ = nfserr;
 780
 781        /* Encode result.
 782         * For NFSv2, additional info is never returned in case of an error.
 783         */
 784        if (!(nfserr && rqstp->rq_vers == 2)) {
 785                xdr = proc->pc_encode;
 786                if (xdr && !xdr(rqstp, nfserrp,
 787                                rqstp->rq_resp)) {
 788                        /* Failed to encode result. Release cache entry */
 789                        dprintk("nfsd: failed to encode result!\n");
 790                        nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
 791                        *statp = rpc_system_err;
 792                        return 1;
 793                }
 794        }
 795
 796        /* Store reply in cache. */
 797        nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
 798        return 1;
 799}
 800
 801int nfsd_pool_stats_open(struct inode *inode, struct file *file)
 802{
 803        int ret;
 804        struct nfsd_net *nn = net_generic(inode->i_sb->s_fs_info, nfsd_net_id);
 805
 806        mutex_lock(&nfsd_mutex);
 807        if (nn->nfsd_serv == NULL) {
 808                mutex_unlock(&nfsd_mutex);
 809                return -ENODEV;
 810        }
 811        /* bump up the psudo refcount while traversing */
 812        svc_get(nn->nfsd_serv);
 813        ret = svc_pool_stats_open(nn->nfsd_serv, file);
 814        mutex_unlock(&nfsd_mutex);
 815        return ret;
 816}
 817
 818int nfsd_pool_stats_release(struct inode *inode, struct file *file)
 819{
 820        int ret = seq_release(inode, file);
 821        struct net *net = inode->i_sb->s_fs_info;
 822
 823        mutex_lock(&nfsd_mutex);
 824        /* this function really, really should have been called svc_put() */
 825        nfsd_destroy(net);
 826        mutex_unlock(&nfsd_mutex);
 827        return ret;
 828}
 829