Commit 419f4319 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-3.5' of git://linux-nfs.org/~bfields/linux

Pull the rest of the nfsd commits from Bruce Fields:
 "... and then I cherry-picked the remainder of the patches from the
  head of my previous branch"

This is the rest of the original nfsd branch, rebased without the
delegation stuff that I thought really needed to be redone.

I don't like rebasing things like this in general, but in this situation
this was the lesser of two evils.

* 'for-3.5' of git://linux-nfs.org/~bfields/linux: (50 commits)
  nfsd4: fix, consolidate client_has_state
  nfsd4: don't remove rebooted client record until confirmation
  nfsd4: remove some dprintk's and a comment
  nfsd4: return "real" sequence id in confirmed case
  nfsd4: fix exchange_id to return confirm flag
  nfsd4: clarify that renewing expired client is a bug
  nfsd4: simpler ordering of setclientid_confirm checks
  nfsd4: setclientid: remove pointless assignment
  nfsd4: fix error return in non-matching-creds case
  nfsd4: fix setclientid_confirm same_cred check
  nfsd4: merge 3 setclientid cases to 2
  nfsd4: pull out common code from setclientid cases
  nfsd4: merge last two setclientid cases
  nfsd4: setclientid/confirm comment cleanup
  nfsd4: setclientid remove unnecessary terms from a logical expression
  nfsd4: move rq_flavor into svc_cred
  nfsd4: stricter cred comparison for setclientid/exchange_id
  nfsd4: move principal name into svc_cred
  nfsd4: allow removing clients not holding state
  nfsd4: rearrange exchange_id logic to simplify
  ...
parents fb21affa 6eccece9
Loading
Loading
Loading
Loading
+90 −55
Original line number Diff line number Diff line
@@ -251,39 +251,40 @@ out_err:
	return err;
}

static int lockd_up_net(struct net *net)
static int lockd_up_net(struct svc_serv *serv, struct net *net)
{
	struct lockd_net *ln = net_generic(net, lockd_net_id);
	struct svc_serv *serv = nlmsvc_rqst->rq_server;
	int error;

	if (ln->nlmsvc_users)
	if (ln->nlmsvc_users++)
		return 0;

	error = svc_rpcb_setup(serv, net);
	error = svc_bind(serv, net);
	if (error)
		goto err_rpcb;
		goto err_bind;

	error = make_socks(serv, net);
	if (error < 0)
		goto err_socks;
	dprintk("lockd_up_net: per-net data created; net=%p\n", net);
	return 0;

err_socks:
	svc_rpcb_cleanup(serv, net);
err_rpcb:
err_bind:
	ln->nlmsvc_users--;
	return error;
}

static void lockd_down_net(struct net *net)
static void lockd_down_net(struct svc_serv *serv, struct net *net)
{
	struct lockd_net *ln = net_generic(net, lockd_net_id);
	struct svc_serv *serv = nlmsvc_rqst->rq_server;

	if (ln->nlmsvc_users) {
		if (--ln->nlmsvc_users == 0) {
			nlm_shutdown_hosts_net(net);
			svc_shutdown_net(serv, net);
			dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net);
		}
	} else {
		printk(KERN_ERR "lockd_down_net: no users! task=%p, net=%p\n",
@@ -292,21 +293,60 @@ static void lockd_down_net(struct net *net)
	}
}

static int lockd_start_svc(struct svc_serv *serv)
{
	int error;

	if (nlmsvc_rqst)
		return 0;

	/*
 * Bring up the lockd process if it's not already up.
	 * Create the kernel thread and wait for it to start.
	 */
int lockd_up(struct net *net)
	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_run(lockd, nlmsvc_rqst, 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;
	}
	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;
}

static struct svc_serv *lockd_create_svc(void)
{
	struct svc_serv *serv;
	int		error = 0;

	mutex_lock(&nlmsvc_mutex);
	/*
	 * Check whether we're already up and running.
	 */
	if (nlmsvc_rqst) {
		error = lockd_up_net(net);
		goto out;
		/*
		 * Note: increase service usage, because later in case of error
		 * svc_destroy() will be called.
		 */
		svc_get(nlmsvc_rqst->rq_server);
		return nlmsvc_rqst->rq_server;
	}

	/*
@@ -317,59 +357,53 @@ int lockd_up(struct net *net)
		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;
		return ERR_PTR(-ENOMEM);
	}
	dprintk("lockd_up: service created\n");
	return serv;
}

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

/*
	 * Create the kernel thread and wait for it to start.
 * Bring up the lockd process if it's not already up.
 */
	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 destroy_and_out;
	}
int lockd_up(struct net *net)
{
	struct svc_serv *serv;
	int error;

	svc_sock_update_bufs(serv);
	serv->sv_maxconn = nlm_max_connections;
	mutex_lock(&nlmsvc_mutex);

	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;
	serv = lockd_create_svc();
	if (IS_ERR(serv)) {
		error = PTR_ERR(serv);
		goto err_create;
	}

	error = lockd_up_net(serv, net);
	if (error < 0)
		goto err_net;

	error = lockd_start_svc(serv);
	if (error < 0)
		goto err_start;

	nlmsvc_users++;
	/*
	 * Note: svc_serv structures have an initial use count of 1,
	 * so we exit through here on both success and failure.
	 */
destroy_and_out:
err_net:
	svc_destroy(serv);
out:
	if (!error) {
		struct lockd_net *ln = net_generic(net, lockd_net_id);

		ln->nlmsvc_users++;
		nlmsvc_users++;
	}
err_create:
	mutex_unlock(&nlmsvc_mutex);
	return error;

err_start:
	lockd_down_net(serv, net);
	goto err_net;
}
EXPORT_SYMBOL_GPL(lockd_up);

@@ -380,11 +414,10 @@ void
lockd_down(struct net *net)
{
	mutex_lock(&nlmsvc_mutex);
	lockd_down_net(nlmsvc_rqst->rq_server, net);
	if (nlmsvc_users) {
		if (--nlmsvc_users) {
			lockd_down_net(net);
		if (--nlmsvc_users)
			goto out;
		}
	} else {
		printk(KERN_ERR "lockd_down: no users! task=%p\n",
			nlmsvc_task);
@@ -396,7 +429,9 @@ lockd_down(struct net *net)
		BUG();
	}
	kthread_stop(nlmsvc_task);
	dprintk("lockd_down: service stopped\n");
	svc_exit_thread(nlmsvc_rqst);
	dprintk("lockd_down: service destroyed\n");
	nlmsvc_task = NULL;
	nlmsvc_rqst = NULL;
out:
+12 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/kthread.h>
#include <linux/sunrpc/svcauth_gss.h>
#include <linux/sunrpc/bc_xprt.h>
#include <linux/nsproxy.h>

#include <net/inet_sock.h>

@@ -253,6 +254,7 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
	char svc_name[12];
	int ret = 0;
	int minorversion_setup;
	struct net *net = current->nsproxy->net_ns;

	mutex_lock(&nfs_callback_mutex);
	if (cb_info->users++ || cb_info->task != NULL) {
@@ -265,6 +267,12 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
		goto out_err;
	}

	ret = svc_bind(serv, net);
	if (ret < 0) {
		printk(KERN_WARNING "NFS: bind callback service failed\n");
		goto out_err;
	}

	minorversion_setup =  nfs_minorversion_callback_svc_setup(minorversion,
					serv, xprt, &rqstp, &callback_svc);
	if (!minorversion_setup) {
@@ -306,6 +314,8 @@ out_err:
	dprintk("NFS: Couldn't create callback socket or server thread; "
		"err = %d\n", ret);
	cb_info->users--;
	if (serv)
		svc_shutdown_net(serv, net);
	goto out;
}

@@ -320,6 +330,7 @@ void nfs_callback_down(int minorversion)
	cb_info->users--;
	if (cb_info->users == 0 && cb_info->task != NULL) {
		kthread_stop(cb_info->task);
		svc_shutdown_net(cb_info->serv, current->nsproxy->net_ns);
		svc_exit_thread(cb_info->rqst);
		cb_info->serv = NULL;
		cb_info->rqst = NULL;
@@ -332,7 +343,7 @@ void nfs_callback_down(int minorversion)
int
check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)
{
	char *p = svc_gss_principal(rqstp);
	char *p = rqstp->rq_cred.cr_principal;

	if (rqstp->rq_authop->flavour != RPC_AUTH_GSS)
		return 1;
+1 −1
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;

	for (f = exp->ex_flavors; f < end; f++) {
		if (f->pseudoflavor == rqstp->rq_flavor)
		if (f->pseudoflavor == rqstp->rq_cred.cr_flavor)
			return f->flags;
	}
	return exp->ex_flags;
+4 −4
Original line number Diff line number Diff line
@@ -706,7 +706,7 @@ static struct cache_head *svc_export_alloc(void)
		return NULL;
}

struct cache_detail svc_export_cache_template = {
static struct cache_detail svc_export_cache_template = {
	.owner		= THIS_MODULE,
	.hash_size	= EXPORT_HASHMAX,
	.name		= "nfsd.export",
@@ -904,13 +904,13 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
		return 0;
	/* ip-address based client; check sec= export option: */
	for (f = exp->ex_flavors; f < end; f++) {
		if (f->pseudoflavor == rqstp->rq_flavor)
		if (f->pseudoflavor == rqstp->rq_cred.cr_flavor)
			return 0;
	}
	/* defaults in absence of sec= options: */
	if (exp->ex_nflavors == 0) {
		if (rqstp->rq_flavor == RPC_AUTH_NULL ||
		    rqstp->rq_flavor == RPC_AUTH_UNIX)
		if (rqstp->rq_cred.cr_flavor == RPC_AUTH_NULL ||
		    rqstp->rq_cred.cr_flavor == RPC_AUTH_UNIX)
			return 0;
	}
	return nfserr_wrongsec;
+1 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ static int nfsd_inject_set(void *op_ptr, u64 val)

static int nfsd_inject_get(void *data, u64 *val)
{
	*val = 0;
	return 0;
}

Loading