static void nfsd_shutdown_generic(void) { if (--nfsd_users) return; nfs4_state_shutdown(); nfsd_racache_shutdown(); }
static void nfsd_last_thread(struct svc_serv *serv) { /* When last nfsd thread exits we need to do some clean-up */ struct svc_xprt *xprt; list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) lockd_down(); nfsd_serv = NULL; nfsd_racache_shutdown(); nfs4_state_shutdown(); printk(KERN_WARNING "nfsd: last server has exited, flushing export " "cache\n"); nfsd_export_flush(); }
static void nfsd_shutdown(void) { /* * write_ports can create the server without actually starting * any threads--if we get shut down before any threads are * started, then nfsd_last_thread will be run before any of this * other initialization has been done. */ if (!nfsd_up) return; nfs4_state_shutdown(); lockd_down(); nfsd_racache_shutdown(); nfsd_up = false; }
static void nfsd_shutdown(void) { /* */ if (!nfsd_up) return; nfs4_state_shutdown(); lockd_down(); nfsd_racache_shutdown(); nfsd_up = false; }
int nfsd_svc(unsigned short port, int nrservs) { int error; int none_left; struct list_head *victim; lock_kernel(); dprintk("nfsd: creating service\n"); error = -EINVAL; if (nrservs <= 0) nrservs = 0; if (nrservs > NFSD_MAXSERVS) nrservs = NFSD_MAXSERVS; /* Readahead param cache - will no-op if it already exists */ error = nfsd_racache_init(2*nrservs); nfs4_state_init(); if (error<0) goto out; if (!nfsd_serv) { atomic_set(&nfsd_busy, 0); error = -ENOMEM; nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE); if (nfsd_serv == NULL) goto out; error = svc_makesock(nfsd_serv, IPPROTO_UDP, port); if (error < 0) goto failure; #ifdef CONFIG_NFSD_TCP error = svc_makesock(nfsd_serv, IPPROTO_TCP, port); if (error < 0) goto failure; #endif do_gettimeofday(&nfssvc_boot); /* record boot time */ } else nfsd_serv->sv_nrthreads++; nrservs -= (nfsd_serv->sv_nrthreads-1); while (nrservs > 0) { nrservs--; __module_get(THIS_MODULE); error = svc_create_thread(nfsd, nfsd_serv); if (error < 0) { module_put(THIS_MODULE); break; } } victim = nfsd_list.next; while (nrservs < 0 && victim != &nfsd_list) { struct nfsd_list *nl = list_entry(victim,struct nfsd_list, list); victim = victim->next; send_sig(SIG_NOCLEAN, nl->task, 1); nrservs++; } failure: none_left = (nfsd_serv->sv_nrthreads == 1); svc_destroy(nfsd_serv); /* Release server */ if (none_left) { nfsd_serv = NULL; nfsd_racache_shutdown(); nfs4_state_shutdown(); } out: unlock_kernel(); return error; }
/* * This is the NFS server kernel thread */ static void nfsd(struct svc_rqst *rqstp) { struct svc_serv *serv = rqstp->rq_server; struct fs_struct *fsp; int err; struct nfsd_list me; sigset_t shutdown_mask, allowed_mask; /* Lock module and set up kernel thread */ lock_kernel(); daemonize("nfsd"); current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; /* After daemonize() this kernel thread shares current->fs * with the init process. We need to create files with a * umask of 0 instead of init's umask. */ fsp = copy_fs_struct(current->fs); if (!fsp) { printk("Unable to start nfsd thread: out of memory\n"); goto out; } exit_fs(current); current->fs = fsp; current->fs->umask = 0; siginitsetinv(&shutdown_mask, SHUTDOWN_SIGS); siginitsetinv(&allowed_mask, ALLOWED_SIGS); nfsdstats.th_cnt++; lockd_up(); /* start lockd */ me.task = current; list_add(&me.list, &nfsd_list); unlock_kernel(); /* * We want less throttling in balance_dirty_pages() so that nfs to * localhost doesn't cause nfsd to lock up due to all the client's * dirty pages. */ current->flags |= PF_LESS_THROTTLE; /* * The main request loop */ for (;;) { /* Block all but the shutdown signals */ sigprocmask(SIG_SETMASK, &shutdown_mask, NULL); /* * Find a socket with data available and call its * recvfrom routine. */ while ((err = svc_recv(serv, rqstp, 60*60*HZ)) == -EAGAIN) ; if (err < 0) break; update_thread_usage(atomic_read(&nfsd_busy)); atomic_inc(&nfsd_busy); /* Lock the export hash tables for reading. */ exp_readlock(); /* Process request with signals blocked. */ sigprocmask(SIG_SETMASK, &allowed_mask, NULL); svc_process(serv, rqstp); /* Unlock export hash tables */ exp_readunlock(); update_thread_usage(atomic_read(&nfsd_busy)); atomic_dec(&nfsd_busy); } if (err != -EINTR) { printk(KERN_WARNING "nfsd: terminating on error %d\n", -err); } else { unsigned int signo; for (signo = 1; signo <= _NSIG; signo++) if (sigismember(¤t->pending.signal, signo) && !sigismember(¤t->blocked, signo)) break; err = signo; } lock_kernel(); /* Release lockd */ lockd_down(); /* Check if this is last thread */ if (serv->sv_nrthreads==1) { printk(KERN_WARNING "nfsd: last server has exited\n"); if (err != SIG_NOCLEAN) { printk(KERN_WARNING "nfsd: unexporting all filesystems\n"); nfsd_export_flush(); } nfsd_serv = NULL; nfsd_racache_shutdown(); /* release read-ahead cache */ nfs4_state_shutdown(); } list_del(&me.list); nfsdstats.th_cnt --; out: /* Release the thread */ svc_exit_thread(rqstp); /* Release module */ module_put_and_exit(0); }