Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f57fa1d6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.linux-nfs.org/projects/trondmy/nfs-2.6: (70 commits)
  fs/nfs/nfs4proc.c: make nfs4_map_errors() static
  rpc: add service field to new upcall
  rpc: add target field to new upcall
  nfsd: support callbacks with gss flavors
  rpc: allow gss callbacks to client
  rpc: pass target name down to rpc level on callbacks
  nfsd: pass client principal name in rsc downcall
  rpc: implement new upcall
  rpc: store pointer to pipe inode in gss upcall message
  rpc: use count of pipe openers to wait for first open
  rpc: track number of users of the gss upcall pipe
  rpc: call release_pipe only on last close
  rpc: add an rpc_pipe_open method
  rpc: minor gss_alloc_msg cleanup
  rpc: factor out warning code from gss_pipe_destroy_msg
  rpc: remove unnecessary assignment
  NFS: remove unused status from encode routines
  NFS: increment number of operations in each encode routine
  NFS: fix comment placement in nfs4xdr.c
  NFS: fix tabs in nfs4xdr.c
  ...
parents 6094c85a 08cc36cb
Loading
Loading
Loading
Loading
+16 −7
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/sunrpc/svc.h>
#include <linux/lockd/lockd.h>
#include <linux/smp_lock.h>
#include <linux/kthread.h>

#define NLMDBG_FACILITY		NLMDBG_CLIENT

@@ -60,7 +61,7 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)

	host = nlmclnt_lookup_host(nlm_init->address, nlm_init->addrlen,
				   nlm_init->protocol, nlm_version,
				   nlm_init->hostname);
				   nlm_init->hostname, nlm_init->noresvport);
	if (host == NULL) {
		lockd_down();
		return ERR_PTR(-ENOLCK);
@@ -191,11 +192,15 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
void
nlmclnt_recovery(struct nlm_host *host)
{
	struct task_struct *task;

	if (!host->h_reclaiming++) {
		nlm_get_host(host);
		__module_get(THIS_MODULE);
		if (kernel_thread(reclaimer, host, CLONE_FS | CLONE_FILES) < 0)
			module_put(THIS_MODULE);
		task = kthread_run(reclaimer, host, "%s-reclaim", host->h_name);
		if (IS_ERR(task))
			printk(KERN_ERR "lockd: unable to spawn reclaimer "
				"thread. Locks for %s won't be reclaimed! "
				"(%ld)\n", host->h_name, PTR_ERR(task));
	}
}

@@ -207,7 +212,6 @@ reclaimer(void *ptr)
	struct file_lock *fl, *next;
	u32 nsmstate;

	daemonize("%s-reclaim", host->h_name);
	allow_signal(SIGKILL);

	down_write(&host->h_rwsem);
@@ -233,7 +237,12 @@ restart:
	list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) {
		list_del_init(&fl->fl_u.nfs_fl.list);

		/* Why are we leaking memory here? --okir */
		/*
		 * sending this thread a SIGKILL will result in any unreclaimed
		 * locks being removed from the h_granted list. This means that
		 * the kernel will not attempt to reclaim them again if a new
		 * reclaimer thread is spawned for this host.
		 */
		if (signalled())
			continue;
		if (nlmclnt_reclaim(host, fl) != 0)
@@ -261,5 +270,5 @@ restart:
	nlm_release_host(host);
	lockd_down();
	unlock_kernel();
	module_put_and_exit(0);
	return 0;
}
+9 −1
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ struct nlm_lookup_host_info {
	const size_t		hostname_len;	/* it's length */
	const struct sockaddr	*src_sap;	/* our address (optional) */
	const size_t		src_len;	/* it's length */
	const int		noresvport;	/* use non-priv port */
};

/*
@@ -222,6 +223,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
	host->h_nsmstate   = 0;			/* real NSM state */
	host->h_nsmhandle  = nsm;
	host->h_server	   = ni->server;
	host->h_noresvport = ni->noresvport;
	hlist_add_head(&host->h_hash, chain);
	INIT_LIST_HEAD(&host->h_lockowners);
	spin_lock_init(&host->h_lock);
@@ -272,6 +274,7 @@ nlm_destroy_host(struct nlm_host *host)
 * @protocol: transport protocol to use
 * @version: NLM protocol version
 * @hostname: '\0'-terminated hostname of server
 * @noresvport: 1 if non-privileged port should be used
 *
 * Returns an nlm_host structure that matches the passed-in
 * [server address, transport protocol, NLM version, server hostname].
@@ -281,7 +284,9 @@ nlm_destroy_host(struct nlm_host *host)
struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
				     const size_t salen,
				     const unsigned short protocol,
				     const u32 version, const char *hostname)
				     const u32 version,
				     const char *hostname,
				     int noresvport)
{
	const struct sockaddr source = {
		.sa_family	= AF_UNSPEC,
@@ -296,6 +301,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
		.hostname_len	= strlen(hostname),
		.src_sap	= &source,
		.src_len	= sizeof(source),
		.noresvport	= noresvport,
	};

	dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
@@ -417,6 +423,8 @@ nlm_bind_host(struct nlm_host *host)
		 */
		if (!host->h_server)
			args.flags |= RPC_CLNT_CREATE_HARDRTRY;
		if (host->h_noresvport)
			args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;

		clnt = rpc_create(&args);
		if (!IS_ERR(clnt))
+3 −3
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@
static struct svc_program	nlmsvc_program;

struct nlmsvc_binding *		nlmsvc_ops;
EXPORT_SYMBOL(nlmsvc_ops);
EXPORT_SYMBOL_GPL(nlmsvc_ops);

static DEFINE_MUTEX(nlmsvc_mutex);
static unsigned int		nlmsvc_users;
@@ -300,7 +300,7 @@ out:
	mutex_unlock(&nlmsvc_mutex);
	return error;
}
EXPORT_SYMBOL(lockd_up);
EXPORT_SYMBOL_GPL(lockd_up);

/*
 * Decrement the user count and bring down lockd if we're the last.
@@ -329,7 +329,7 @@ lockd_down(void)
out:
	mutex_unlock(&nlmsvc_mutex);
}
EXPORT_SYMBOL(lockd_down);
EXPORT_SYMBOL_GPL(lockd_down);

#ifdef CONFIG_SYSCTL

+31 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/mutex.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/sunrpc/svcauth_gss.h>

#include <net/inet_sock.h>

@@ -182,10 +183,34 @@ void nfs_callback_down(void)
	mutex_unlock(&nfs_callback_mutex);
}

static int check_gss_callback_principal(struct nfs_client *clp,
					struct svc_rqst *rqstp)
{
	struct rpc_clnt *r = clp->cl_rpcclient;
	char *p = svc_gss_principal(rqstp);

	/*
	 * It might just be a normal user principal, in which case
	 * userspace won't bother to tell us the name at all.
	 */
	if (p == NULL)
		return SVC_DENIED;

	/* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */

	if (memcmp(p, "nfs@", 4) != 0)
		return SVC_DENIED;
	p += 4;
	if (strcmp(p, r->cl_server) != 0)
		return SVC_DENIED;
	return SVC_OK;
}

static int nfs_callback_authenticate(struct svc_rqst *rqstp)
{
	struct nfs_client *clp;
	RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
	int ret = SVC_OK;

	/* Don't talk to strangers */
	clp = nfs_find_client(svc_addr(rqstp), 4);
@@ -194,21 +219,22 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp)

	dprintk("%s: %s NFSv4 callback!\n", __func__,
			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)
				return SVC_DENIED;
				ret = SVC_DENIED;
			break;
		case RPC_AUTH_UNIX:
			break;
		case RPC_AUTH_GSS:
			/* FIXME: RPCSEC_GSS handling? */
			ret = check_gss_callback_principal(clp, rqstp);
			break;
		default:
			return SVC_DENIED;
			ret = SVC_DENIED;
	}
	return SVC_OK;
	nfs_put_client(clp);
	return ret;
}

/*
+61 −34
Original line number Diff line number Diff line
@@ -143,7 +143,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
	clp->cl_proto = cl_init->proto;

#ifdef CONFIG_NFS_V4
	init_rwsem(&clp->cl_sem);
	INIT_LIST_HEAD(&clp->cl_delegations);
	spin_lock_init(&clp->cl_lock);
	INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
@@ -224,31 +223,54 @@ void nfs_put_client(struct nfs_client *clp)
	}
}

static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1,
				 const struct sockaddr_in *sa2)
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static const struct in6_addr *nfs_map_ipv4_addr(const struct sockaddr *sa, struct in6_addr *addr_mapped)
{
	return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr;
	switch (sa->sa_family) {
		default:
			return NULL;
		case AF_INET6:
			return &((const struct sockaddr_in6 *)sa)->sin6_addr;
			break;
		case AF_INET:
			ipv6_addr_set_v4mapped(((const struct sockaddr_in *)sa)->sin_addr.s_addr,
					addr_mapped);
			return addr_mapped;
	}
}

static int nfs_sockaddr_match_ipaddr6(const struct sockaddr_in6 *sa1,
				 const struct sockaddr_in6 *sa2)
static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
		const struct sockaddr *sa2)
{
	const struct in6_addr *addr1;
	const struct in6_addr *addr2;
	struct in6_addr addr1_mapped;
	struct in6_addr addr2_mapped;

	addr1 = nfs_map_ipv4_addr(sa1, &addr1_mapped);
	if (likely(addr1 != NULL)) {
		addr2 = nfs_map_ipv4_addr(sa2, &addr2_mapped);
		if (likely(addr2 != NULL))
			return ipv6_addr_equal(addr1, addr2);
	}
	return 0;
}
#else
static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1,
				 const struct sockaddr_in *sa2)
{
	return ipv6_addr_equal(&sa1->sin6_addr, &sa2->sin6_addr);
	return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr;
}

static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
				 const struct sockaddr *sa2)
{
	switch (sa1->sa_family) {
	case AF_INET:
	if (unlikely(sa1->sa_family != AF_INET || sa2->sa_family != AF_INET))
		return 0;
	return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1,
			(const struct sockaddr_in *)sa2);
	case AF_INET6:
		return nfs_sockaddr_match_ipaddr6((const struct sockaddr_in6 *)sa1,
				(const struct sockaddr_in6 *)sa2);
	}
	BUG();
}
#endif

/*
 * Find a client by IP address and protocol version
@@ -270,8 +292,6 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
		if (clp->rpc_ops->version != nfsversion)
			continue;

		if (addr->sa_family != clap->sa_family)
			continue;
		/* Match only the IP address, not the port number */
		if (!nfs_sockaddr_match_ipaddr(addr, clap))
			continue;
@@ -305,8 +325,6 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
		if (clp->rpc_ops->version != nfsvers)
			continue;

		if (sap->sa_family != clap->sa_family)
			continue;
		/* Match only the IP address, not the port number */
		if (!nfs_sockaddr_match_ipaddr(sap, clap))
			continue;
@@ -470,7 +488,7 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
static int nfs_create_rpc_client(struct nfs_client *clp,
				 const struct rpc_timeout *timeparms,
				 rpc_authflavor_t flavor,
				 int flags)
				 int discrtry, int noresvport)
{
	struct rpc_clnt		*clnt = NULL;
	struct rpc_create_args args = {
@@ -482,9 +500,13 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
		.program	= &nfs_program,
		.version	= clp->rpc_ops->version,
		.authflavor	= flavor,
		.flags		= flags,
	};

	if (discrtry)
		args.flags |= RPC_CLNT_CREATE_DISCRTRY;
	if (noresvport)
		args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;

	if (!IS_ERR(clp->cl_rpcclient))
		return 0;

@@ -522,6 +544,8 @@ static int nfs_start_lockd(struct nfs_server *server)
		.protocol	= server->flags & NFS_MOUNT_TCP ?
						IPPROTO_TCP : IPPROTO_UDP,
		.nfs_version	= clp->rpc_ops->version,
		.noresvport	= server->flags & NFS_MOUNT_NORESVPORT ?
					1 : 0,
	};

	if (nlm_init.nfs_version > 3)
@@ -623,7 +647,8 @@ static int nfs_init_client(struct nfs_client *clp,
	 * Create a client RPC handle for doing FSSTAT with UNIX auth only
	 * - RFC 2623, sec 2.3.2
	 */
	error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX, 0);
	error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX,
				      0, data->flags & NFS_MOUNT_NORESVPORT);
	if (error < 0)
		goto error;
	nfs_mark_client_ready(clp, NFS_CS_READY);
@@ -965,7 +990,8 @@ error:
static int nfs4_init_client(struct nfs_client *clp,
		const struct rpc_timeout *timeparms,
		const char *ip_addr,
		rpc_authflavor_t authflavour)
		rpc_authflavor_t authflavour,
		int flags)
{
	int error;

@@ -979,7 +1005,7 @@ static int nfs4_init_client(struct nfs_client *clp,
	clp->rpc_ops = &nfs_v4_clientops;

	error = nfs_create_rpc_client(clp, timeparms, authflavour,
					RPC_CLNT_CREATE_DISCRTRY);
				      1, flags & NFS_MOUNT_NORESVPORT);
	if (error < 0)
		goto error;
	memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
@@ -1030,7 +1056,8 @@ static int nfs4_set_client(struct nfs_server *server,
		error = PTR_ERR(clp);
		goto error;
	}
	error = nfs4_init_client(clp, timeparms, ip_addr, authflavour);
	error = nfs4_init_client(clp, timeparms, ip_addr, authflavour,
					server->flags);
	if (error < 0)
		goto error_put;

@@ -1059,6 +1086,10 @@ static int nfs4_init_server(struct nfs_server *server,
	nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
			data->timeo, data->retrans);

	/* Initialise the client representation from the mount data */
	server->flags = data->flags;
	server->caps |= NFS_CAP_ATOMIC_OPEN;

	/* Get a client record */
	error = nfs4_set_client(server,
			data->nfs_server.hostname,
@@ -1071,10 +1102,6 @@ static int nfs4_init_server(struct nfs_server *server,
	if (error < 0)
		goto error;

	/* Initialise the client representation from the mount data */
	server->flags = data->flags;
	server->caps |= NFS_CAP_ATOMIC_OPEN;

	if (data->rsize)
		server->rsize = nfs_block_size(data->rsize, NULL);
	if (data->wsize)
@@ -1177,6 +1204,10 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
	parent_server = NFS_SB(data->sb);
	parent_client = parent_server->nfs_client;

	/* Initialise the client representation from the parent server */
	nfs_server_copy_userdata(server, parent_server);
	server->caps |= NFS_CAP_ATOMIC_OPEN;

	/* Get a client representation.
	 * Note: NFSv4 always uses TCP, */
	error = nfs4_set_client(server, data->hostname,
@@ -1189,10 +1220,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
	if (error < 0)
		goto error;

	/* Initialise the client representation from the parent server */
	nfs_server_copy_userdata(server, parent_server);
	server->caps |= NFS_CAP_ATOMIC_OPEN;

	error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
	if (error < 0)
		goto error;
Loading