예제 #1
0
/*
 * Prepare to bring up the NFSv4 callback service
 */
static struct svc_rqst *
nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
{
    int ret;

    ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET,
                          nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
    if (ret <= 0)
        goto out_err;
    nfs_callback_tcpport = ret;
    dprintk("NFS: Callback listener port = %u (af %u)\n",
            nfs_callback_tcpport, PF_INET);

    ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6,
                          nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
    if (ret > 0) {
        nfs_callback_tcpport6 = ret;
        dprintk("NFS: Callback listener port = %u (af %u)\n",
                nfs_callback_tcpport6, PF_INET6);
    } else if (ret == -EAFNOSUPPORT)
        ret = 0;
    else
        goto out_err;

    return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);

out_err:
    if (ret == 0)
        ret = -ENOMEM;
    return ERR_PTR(ret);
}
예제 #2
0
/*
 * Bring up the callback thread if it is not already up.
 */
int nfs_callback_up(void)
{
	struct svc_serv *serv = NULL;
	int ret = 0;

	mutex_lock(&nfs_callback_mutex);
	if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
		goto out;
	serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE,
				nfs_callback_family, NULL);
	ret = -ENOMEM;
	if (!serv)
		goto out_err;

	ret = svc_create_xprt(serv, "tcp", nfs_callback_set_tcpport,
			      SVC_SOCK_ANONYMOUS);
	if (ret <= 0)
		goto out_err;
	nfs_callback_tcpport = ret;
	dprintk("NFS: Callback listener port = %u (af %u)\n",
			nfs_callback_tcpport, nfs_callback_family);

	nfs_callback_info.rqst = svc_prepare_thread(serv, &serv->sv_pools[0]);
	if (IS_ERR(nfs_callback_info.rqst)) {
		ret = PTR_ERR(nfs_callback_info.rqst);
		nfs_callback_info.rqst = NULL;
		goto out_err;
	}

	svc_sock_update_bufs(serv);

	nfs_callback_info.task = kthread_run(nfs_callback_svc,
					     nfs_callback_info.rqst,
					     "nfsv4-svc");
	if (IS_ERR(nfs_callback_info.task)) {
		ret = PTR_ERR(nfs_callback_info.task);
		svc_exit_thread(nfs_callback_info.rqst);
		nfs_callback_info.rqst = NULL;
		nfs_callback_info.task = NULL;
		goto out_err;
	}
out:
	/*
	 * svc_create creates the svc_serv with sv_nrthreads == 1, and then
	 * svc_prepare_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);
	return ret;
out_err:
	dprintk("NFS: Couldn't create callback socket or server thread; "
		"err = %d\n", ret);
	nfs_callback_info.users--;
	goto out;
}
예제 #3
0
파일: svc.c 프로젝트: BWhitten/linux-stable
/*
 * Create or destroy enough new threads to make the number
 * of threads the given number.  If `pool' is non-NULL, applies
 * only to threads in that pool, otherwise round-robins between
 * all pools.  Caller must ensure that mutual exclusion between this and
 * server startup or shutdown.
 *
 * Destroying threads relies on the service threads filling in
 * rqstp->rq_task, which only the nfs ones do.  Assumes the serv
 * has been created using svc_create_pooled().
 *
 * Based on code that used to be in nfsd_svc() but tweaked
 * to be pool-aware.
 */
int
svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
{
	struct svc_rqst	*rqstp;
	struct task_struct *task;
	struct svc_pool *chosen_pool;
	int error = 0;
	unsigned int state = serv->sv_nrthreads-1;
	int node;

	if (pool == NULL) {
		/* The -1 assumes caller has done a svc_get() */
		nrservs -= (serv->sv_nrthreads-1);
	} else {
		spin_lock_bh(&pool->sp_lock);
		nrservs -= pool->sp_nrthreads;
		spin_unlock_bh(&pool->sp_lock);
	}

	/* create new threads */
	while (nrservs > 0) {
		nrservs--;
		chosen_pool = choose_pool(serv, pool, &state);

		node = svc_pool_map_get_node(chosen_pool->sp_id);
		rqstp = svc_prepare_thread(serv, chosen_pool, node);
		if (IS_ERR(rqstp)) {
			error = PTR_ERR(rqstp);
			break;
		}

		__module_get(serv->sv_ops->svo_module);
		task = kthread_create_on_node(serv->sv_ops->svo_function, rqstp,
					      node, "%s", serv->sv_name);
		if (IS_ERR(task)) {
			error = PTR_ERR(task);
			module_put(serv->sv_ops->svo_module);
			svc_exit_thread(rqstp);
			break;
		}

		rqstp->rq_task = task;
		if (serv->sv_nrpools > 1)
			svc_pool_map_set_cpumask(task, chosen_pool->sp_id);

		svc_sock_update_bufs(serv);
		wake_up_process(task);
	}
	/* destroy old threads */
	while (nrservs < 0 &&
	       (task = choose_victim(serv, pool, &state)) != NULL) {
		send_sig(SIGINT, task, 1);
		nrservs++;
	}

	return error;
}
예제 #4
0
파일: svc.c 프로젝트: 19Dan01/linux
static int lockd_start_svc(struct svc_serv *serv)
{
	int error;

	if (nlmsvc_rqst)
		return 0;

	/*
	 * Create the kernel thread and wait for it to start.
	 */
	nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);
	if (IS_ERR(nlmsvc_rqst)) {
		error = PTR_ERR(nlmsvc_rqst);
		printk(KERN_WARNING
			"lockd_up: svc_rqst allocation failed, error=%d\n",
			error);
		goto out_rqst;
	}

	svc_sock_update_bufs(serv);
	serv->sv_maxconn = nlm_max_connections;

	nlmsvc_task = kthread_create(lockd, nlmsvc_rqst, "%s", serv->sv_name);
	if (IS_ERR(nlmsvc_task)) {
		error = PTR_ERR(nlmsvc_task);
		printk(KERN_WARNING
			"lockd_up: kthread_run failed, error=%d\n", error);
		goto out_task;
	}
	nlmsvc_rqst->rq_task = nlmsvc_task;
	wake_up_process(nlmsvc_task);

	dprintk("lockd_up: service started\n");
	return 0;

out_task:
	svc_exit_thread(nlmsvc_rqst);
	nlmsvc_task = NULL;
out_rqst:
	nlmsvc_rqst = NULL;
	return error;
}
예제 #5
0
/*
 * Bring up the lockd process if it's not already up.
 */
int lockd_up(void)
{
	struct svc_serv *serv;
	int		error = 0;

	mutex_lock(&nlmsvc_mutex);
	/*
	 * Check whether we're already up and running.
	 */
	if (nlmsvc_rqst)
		goto out;

	/*
	 * Sanity check: if there's no pid,
	 * we should be the first user ...
	 */
	if (nlmsvc_users)
		printk(KERN_WARNING
			"lockd_up: no pid, %d users??\n", nlmsvc_users);

	error = -ENOMEM;
	serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL);
	if (!serv) {
		printk(KERN_WARNING "lockd_up: create service failed\n");
		goto out;
	}

	error = make_socks(serv);
	if (error < 0)
		goto destroy_and_out;

	/*
	 * Create the kernel thread and wait for it to start.
	 */
	nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0]);
	if (IS_ERR(nlmsvc_rqst)) {
		error = PTR_ERR(nlmsvc_rqst);
		nlmsvc_rqst = NULL;
		printk(KERN_WARNING
			"lockd_up: svc_rqst allocation failed, error=%d\n",
			error);
		goto destroy_and_out;
	}

	svc_sock_update_bufs(serv);
	serv->sv_maxconn = nlm_max_connections;

	nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name);
	if (IS_ERR(nlmsvc_task)) {
		error = PTR_ERR(nlmsvc_task);
		svc_exit_thread(nlmsvc_rqst);
		nlmsvc_task = NULL;
		nlmsvc_rqst = NULL;
		printk(KERN_WARNING
			"lockd_up: kthread_run failed, error=%d\n", error);
		goto destroy_and_out;
	}

	/*
	 * Note: svc_serv structures have an initial use count of 1,
	 * so we exit through here on both success and failure.
	 */
destroy_and_out:
	svc_destroy(serv);
out:
	if (!error)
		nlmsvc_users++;
	mutex_unlock(&nlmsvc_mutex);
	return error;
}
예제 #6
0
파일: callback.c 프로젝트: kyleterry/linux
/*
 * Prepare to bring up the NFSv4 callback service
 */
static struct svc_rqst *
nfs4_callback_up(struct svc_serv *serv)
{
	return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);
}
예제 #7
0
int lockd_up(struct net *net)
{
    struct svc_serv *serv;
    int		error = 0;
    struct lockd_net *ln = net_generic(net, lockd_net_id);

    mutex_lock(&nlmsvc_mutex);
    if (nlmsvc_rqst) {
        error = lockd_up_net(nlmsvc_rqst->rq_server, net);
        goto out;
    }

    if (nlmsvc_users)
        printk(KERN_WARNING
               "lockd_up: no pid, %d users??\n", nlmsvc_users);

    error = -ENOMEM;
    serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL);
    if (!serv) {
        printk(KERN_WARNING "lockd_up: create service failed\n");
        goto out;
    }

    error = svc_bind(serv, net);
    if (error < 0) {
        printk(KERN_WARNING "lockd_up: bind service failed\n");
        goto destroy_and_out;
    }

    ln->nlmsvc_users++;

    error = make_socks(serv, net);
    if (error < 0)
        goto err_start;

    nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);
    if (IS_ERR(nlmsvc_rqst)) {
        error = PTR_ERR(nlmsvc_rqst);
        nlmsvc_rqst = NULL;
        printk(KERN_WARNING
               "lockd_up: svc_rqst allocation failed, error=%d\n",
               error);
        goto err_start;
    }

    svc_sock_update_bufs(serv);
    serv->sv_maxconn = nlm_max_connections;

    nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name);
    if (IS_ERR(nlmsvc_task)) {
        error = PTR_ERR(nlmsvc_task);
        svc_exit_thread(nlmsvc_rqst);
        nlmsvc_task = NULL;
        nlmsvc_rqst = NULL;
        printk(KERN_WARNING
               "lockd_up: kthread_run failed, error=%d\n", error);
        goto err_start;
    }

destroy_and_out:
    svc_destroy(serv);
out:
    if (!error)
        nlmsvc_users++;
    mutex_unlock(&nlmsvc_mutex);
    return error;

err_start:
    lockd_down_net(serv, net);
    goto destroy_and_out;
}