#include <linux/sunrpc/svcsock.h>
#include <linux/nfs_fs.h>
#include <linux/mutex.h>
+#include <linux/freezer.h>
#include <net/inet_sock.h>
*/
static void nfs_callback_svc(struct svc_rqst *rqstp)
{
- struct svc_serv *serv = rqstp->rq_server;
int err;
__module_get(THIS_MODULE);
daemonize("nfsv4-svc");
/* Process request with signals blocked, but allow SIGKILL. */
allow_signal(SIGKILL);
+ set_freezable();
complete(&nfs_callback_info.started);
/*
* Listen for a request on the socket
*/
- err = svc_recv(serv, rqstp, MAX_SCHEDULE_TIMEOUT);
+ err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT);
if (err == -EAGAIN || err == -EINTR)
continue;
if (err < 0) {
__FUNCTION__, -err);
break;
}
- dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__,
- NIPQUAD(rqstp->rq_addr.sin_addr.s_addr));
- svc_process(serv, rqstp);
+ svc_process(rqstp);
}
+ flush_signals(current);
svc_exit_thread(rqstp);
nfs_callback_info.pid = 0;
complete(&nfs_callback_info.stopped);
*/
int nfs_callback_up(void)
{
- struct svc_serv *serv;
- struct svc_sock *svsk;
+ struct svc_serv *serv = NULL;
int ret = 0;
lock_kernel();
goto out;
init_completion(&nfs_callback_info.started);
init_completion(&nfs_callback_info.stopped);
- serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE);
+ serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
ret = -ENOMEM;
if (!serv)
goto out_err;
- /* FIXME: We don't want to register this socket with the portmapper */
- ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport);
- if (ret < 0)
- goto out_destroy;
- if (!list_empty(&serv->sv_permsocks)) {
- svsk = list_entry(serv->sv_permsocks.next,
- struct svc_sock, sk_list);
- nfs_callback_tcpport = ntohs(inet_sk(svsk->sk_sk)->sport);
- dprintk ("Callback port = 0x%x\n", nfs_callback_tcpport);
- } else
- BUG();
+
+ ret = svc_create_xprt(serv, "tcp", nfs_callback_set_tcpport,
+ SVC_SOCK_ANONYMOUS);
+ if (ret <= 0)
+ goto out_err;
+ nfs_callback_tcpport = ret;
+ dprintk("Callback port = 0x%x\n", nfs_callback_tcpport);
+
ret = svc_create_thread(nfs_callback_svc, serv);
if (ret < 0)
- goto out_destroy;
+ goto out_err;
nfs_callback_info.serv = serv;
wait_for_completion(&nfs_callback_info.started);
out:
+ /*
+ * svc_create creates the svc_serv with sv_nrthreads == 1, and then
+ * svc_create_thread increments that. So we need to call svc_destroy
+ * on both success and failure so that the refcount is 1 when the
+ * thread exits.
+ */
+ if (serv)
+ svc_destroy(serv);
mutex_unlock(&nfs_callback_mutex);
unlock_kernel();
return ret;
-out_destroy:
- svc_destroy(serv);
out_err:
+ dprintk("Couldn't create callback socket or server thread; err = %d\n",
+ ret);
nfs_callback_info.users--;
goto out;
}
static int nfs_callback_authenticate(struct svc_rqst *rqstp)
{
- struct sockaddr_in *addr = &rqstp->rq_addr;
struct nfs_client *clp;
+ RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
/* Don't talk to strangers */
- clp = nfs_find_client(addr, 4);
+ clp = nfs_find_client(svc_addr(rqstp), 4);
if (clp == NULL)
return SVC_DROP;
- dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr->sin_addr));
+
+ dprintk("%s: %s NFSv4 callback!\n", __FUNCTION__,
+ svc_print_addr(rqstp, buf, sizeof(buf)));
nfs_put_client(clp);
+
switch (rqstp->rq_authop->flavour) {
case RPC_AUTH_NULL:
if (rqstp->rq_proc != CB_NULL)