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

Commit 713404d6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

* 'for-2.6.29' of git://linux-nfs.org/~bfields/linux: (67 commits)
  nfsd: get rid of NFSD_VERSION
  nfsd: last_byte_offset
  nfsd: delete wrong file comment from nfsd/nfs4xdr.c
  nfsd: git rid of nfs4_cb_null_ops declaration
  nfsd: dprint each op status in nfsd4_proc_compound
  nfsd: add etoosmall to nfserrno
  NFSD: FIDs need to take precedence over UUIDs
  SUNRPC: The sunrpc server code should not be used by out-of-tree modules
  svc: Clean up deferred requests on transport destruction
  nfsd: fix double-locks of directory mutex
  svc: Move kfree of deferral record to common code
  CRED: Fix NFSD regression
  NLM: Clean up flow of control in make_socks() function
  NLM: Refactor make_socks() function
  nfsd: Ensure nfsv4 calls the underlying filesystem on LOCKT
  SUNRPC: Ensure the server closes sockets in a timely fashion
  NFSD: Add documenting comments for nfsctl interface
  NFSD: Replace open-coded integer with macro
  NFSD: Fix a handful of coding style issues in write_filehandle()
  NFSD: clean up failover sysctl function naming
  ...
parents d599edca db43910c
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/lockd/lockd.h>
#include <linux/lockd/sm_inter.h>

#define NLMDBG_FACILITY		NLMDBG_CLIENT
#define NLMCLNT_GRACE_WAIT	(5*HZ)
@@ -518,11 +517,9 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
	unsigned char fl_type;
	int status = -ENOLCK;

	if (nsm_monitor(host) < 0) {
		printk(KERN_NOTICE "lockd: failed to monitor %s\n",
					host->h_name);
	if (nsm_monitor(host) < 0)
		goto out;
	}

	fl->fl_flags |= FL_ACCESS;
	status = do_vfs_lock(fl);
	fl->fl_flags = fl_flags;
+17 −153
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/lockd/lockd.h>
#include <linux/lockd/sm_inter.h>
#include <linux/mutex.h>

#include <net/ipv6.h>
@@ -32,11 +31,6 @@ static int nrhosts;
static DEFINE_MUTEX(nlm_host_mutex);

static void			nlm_gc_hosts(void);
static struct nsm_handle	*nsm_find(const struct sockaddr *sap,
						const size_t salen,
						const char *hostname,
						const size_t hostname_len,
						const int create);

struct nlm_lookup_host_info {
	const int		server;		/* search for server|client */
@@ -105,32 +99,6 @@ static void nlm_clear_port(struct sockaddr *sap)
	}
}

static void nlm_display_address(const struct sockaddr *sap,
				char *buf, const size_t len)
{
	const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
	const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;

	switch (sap->sa_family) {
	case AF_UNSPEC:
		snprintf(buf, len, "unspecified");
		break;
	case AF_INET:
		snprintf(buf, len, "%pI4", &sin->sin_addr.s_addr);
		break;
	case AF_INET6:
		if (ipv6_addr_v4mapped(&sin6->sin6_addr))
			snprintf(buf, len, "%pI4",
				 &sin6->sin6_addr.s6_addr32[3]);
		else
			snprintf(buf, len, "%pI6", &sin6->sin6_addr);
		break;
	default:
		snprintf(buf, len, "unsupported address family");
		break;
	}
}

/*
 * Common host lookup routine for server & client
 */
@@ -190,8 +158,8 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
		atomic_inc(&nsm->sm_count);
	else {
		host = NULL;
		nsm = nsm_find(ni->sap, ni->salen,
				ni->hostname, ni->hostname_len, 1);
		nsm = nsm_get_handle(ni->sap, ni->salen,
					ni->hostname, ni->hostname_len);
		if (!nsm) {
			dprintk("lockd: nlm_lookup_host failed; "
				"no nsm handle\n");
@@ -206,6 +174,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
		goto out;
	}
	host->h_name	   = nsm->sm_name;
	host->h_addrbuf    = nsm->sm_addrbuf;
	memcpy(nlm_addr(host), ni->sap, ni->salen);
	host->h_addrlen = ni->salen;
	nlm_clear_port(nlm_addr(host));
@@ -232,11 +201,6 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)

	nrhosts++;

	nlm_display_address((struct sockaddr *)&host->h_addr,
				host->h_addrbuf, sizeof(host->h_addrbuf));
	nlm_display_address((struct sockaddr *)&host->h_srcaddr,
				host->h_srcaddrbuf, sizeof(host->h_srcaddrbuf));

	dprintk("lockd: nlm_lookup_host created host %s\n",
			host->h_name);

@@ -256,10 +220,8 @@ nlm_destroy_host(struct nlm_host *host)
	BUG_ON(!list_empty(&host->h_lockowners));
	BUG_ON(atomic_read(&host->h_count));

	/*
	 * Release NSM handle and unmonitor host.
	 */
	nsm_unmonitor(host);
	nsm_release(host->h_nsmhandle);

	clnt = host->h_rpcclnt;
	if (clnt != NULL)
@@ -378,8 +340,8 @@ nlm_bind_host(struct nlm_host *host)
{
	struct rpc_clnt	*clnt;

	dprintk("lockd: nlm_bind_host %s (%s), my addr=%s\n",
			host->h_name, host->h_addrbuf, host->h_srcaddrbuf);
	dprintk("lockd: nlm_bind_host %s (%s)\n",
			host->h_name, host->h_addrbuf);

	/* Lock host handle */
	mutex_lock(&host->h_mutex);
@@ -481,35 +443,23 @@ void nlm_release_host(struct nlm_host *host)
	}
}

/*
 * We were notified that the host indicated by address &sin
 * has rebooted.
 * Release all resources held by that peer.
/**
 * nlm_host_rebooted - Release all resources held by rebooted host
 * @info: pointer to decoded results of NLM_SM_NOTIFY call
 *
 * We were notified that the specified host has rebooted.  Release
 * all resources held by that peer.
 */
void nlm_host_rebooted(const struct sockaddr_in *sin,
				const char *hostname,
				unsigned int hostname_len,
				u32 new_state)
void nlm_host_rebooted(const struct nlm_reboot *info)
{
	struct hlist_head *chain;
	struct hlist_node *pos;
	struct nsm_handle *nsm;
	struct nlm_host	*host;

	nsm = nsm_find((struct sockaddr *)sin, sizeof(*sin),
			hostname, hostname_len, 0);
	if (nsm == NULL) {
		dprintk("lockd: never saw rebooted peer '%.*s' before\n",
				hostname_len, hostname);
	nsm = nsm_reboot_lookup(info);
	if (unlikely(nsm == NULL))
		return;
	}

	dprintk("lockd: nlm_host_rebooted(%.*s, %s)\n",
			hostname_len, hostname, nsm->sm_addrbuf);

	/* When reclaiming locks on this peer, make sure that
	 * we set up a new notification */
	nsm->sm_monitored = 0;

	/* Mark all hosts tied to this NSM state as having rebooted.
	 * We run the loop repeatedly, because we drop the host table
@@ -520,8 +470,8 @@ again: mutex_lock(&nlm_host_mutex);
	for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
		hlist_for_each_entry(host, pos, chain, h_hash) {
			if (host->h_nsmhandle == nsm
			 && host->h_nsmstate != new_state) {
				host->h_nsmstate = new_state;
			 && host->h_nsmstate != info->state) {
				host->h_nsmstate = info->state;
				host->h_state++;

				nlm_get_host(host);
@@ -629,89 +579,3 @@ nlm_gc_hosts(void)

	next_gc = jiffies + NLM_HOST_COLLECT;
}


/*
 * Manage NSM handles
 */
static LIST_HEAD(nsm_handles);
static DEFINE_SPINLOCK(nsm_lock);

static struct nsm_handle *nsm_find(const struct sockaddr *sap,
				   const size_t salen,
				   const char *hostname,
				   const size_t hostname_len,
				   const int create)
{
	struct nsm_handle *nsm = NULL;
	struct nsm_handle *pos;

	if (!sap)
		return NULL;

	if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
		if (printk_ratelimit()) {
			printk(KERN_WARNING "Invalid hostname \"%.*s\" "
					    "in NFS lock request\n",
				(int)hostname_len, hostname);
		}
		return NULL;
	}

retry:
	spin_lock(&nsm_lock);
	list_for_each_entry(pos, &nsm_handles, sm_link) {

		if (hostname && nsm_use_hostnames) {
			if (strlen(pos->sm_name) != hostname_len
			 || memcmp(pos->sm_name, hostname, hostname_len))
				continue;
		} else if (!nlm_cmp_addr(nsm_addr(pos), sap))
			continue;
		atomic_inc(&pos->sm_count);
		kfree(nsm);
		nsm = pos;
		goto found;
	}
	if (nsm) {
		list_add(&nsm->sm_link, &nsm_handles);
		goto found;
	}
	spin_unlock(&nsm_lock);

	if (!create)
		return NULL;

	nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL);
	if (nsm == NULL)
		return NULL;

	memcpy(nsm_addr(nsm), sap, salen);
	nsm->sm_addrlen = salen;
	nsm->sm_name = (char *) (nsm + 1);
	memcpy(nsm->sm_name, hostname, hostname_len);
	nsm->sm_name[hostname_len] = '\0';
	nlm_display_address((struct sockaddr *)&nsm->sm_addr,
				nsm->sm_addrbuf, sizeof(nsm->sm_addrbuf));
	atomic_set(&nsm->sm_count, 1);
	goto retry;

found:
	spin_unlock(&nsm_lock);
	return nsm;
}

/*
 * Release an NSM handle
 */
void
nsm_release(struct nsm_handle *nsm)
{
	if (!nsm)
		return;
	if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
		list_del(&nsm->sm_link);
		spin_unlock(&nsm_lock);
		kfree(nsm);
	}
}
+424 −145

File changed.

Preview size limit exceeded, changes collapsed.

+48 −24
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@
#include <linux/sunrpc/svcsock.h>
#include <net/ip.h>
#include <linux/lockd/lockd.h>
#include <linux/lockd/sm_inter.h>
#include <linux/nfs.h>

#define NLMDBG_FACILITY		NLMDBG_SVC
@@ -53,6 +52,17 @@ static struct task_struct *nlmsvc_task;
static struct svc_rqst		*nlmsvc_rqst;
unsigned long			nlmsvc_timeout;

/*
 * If the kernel has IPv6 support available, always listen for
 * both AF_INET and AF_INET6 requests.
 */
#if (defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)) && \
	defined(CONFIG_SUNRPC_REGISTER_V4)
static const sa_family_t	nlmsvc_family = AF_INET6;
#else	/* (CONFIG_IPV6 || CONFIG_IPV6_MODULE) && CONFIG_SUNRPC_REGISTER_V4 */
static const sa_family_t	nlmsvc_family = AF_INET;
#endif	/* (CONFIG_IPV6 || CONFIG_IPV6_MODULE) && CONFIG_SUNRPC_REGISTER_V4 */

/*
 * These can be set at insmod time (useful for NFS as root filesystem),
 * and also changed through the sysctl interface.  -- Jamie Lokier, Aug 2003
@@ -60,7 +70,9 @@ unsigned long nlmsvc_timeout;
static unsigned long		nlm_grace_period;
static unsigned long		nlm_timeout = LOCKD_DFLT_TIMEO;
static int			nlm_udpport, nlm_tcpport;
int				nsm_use_hostnames = 0;

/* RLIM_NOFILE defaults to 1024. That seems like a reasonable default here. */
static unsigned int		nlm_max_connections = 1024;

/*
 * Constants needed for the sysctl interface.
@@ -143,6 +155,9 @@ lockd(void *vrqstp)
		long timeout = MAX_SCHEDULE_TIMEOUT;
		RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);

		/* update sv_maxconn if it has changed */
		rqstp->rq_server->sv_maxconn = nlm_max_connections;

		if (signalled()) {
			flush_signals(current);
			if (nlmsvc_ops) {
@@ -189,6 +204,19 @@ lockd(void *vrqstp)
	return 0;
}

static int create_lockd_listener(struct svc_serv *serv, char *name,
				 unsigned short port)
{
	struct svc_xprt *xprt;

	xprt = svc_find_xprt(serv, name, 0, 0);
	if (xprt == NULL)
		return svc_create_xprt(serv, name, port, SVC_SOCK_DEFAULTS);

	svc_xprt_put(xprt);
	return 0;
}

/*
 * Ensure there are active UDP and TCP listeners for lockd.
 *
@@ -202,27 +230,21 @@ lockd(void *vrqstp)
static int make_socks(struct svc_serv *serv)
{
	static int warned;
	struct svc_xprt *xprt;
	int err = 0;
	int err;

	err = create_lockd_listener(serv, "udp", nlm_udpport);
	if (err < 0)
		goto out_err;

	err = create_lockd_listener(serv, "tcp", nlm_tcpport);
	if (err < 0)
		goto out_err;

	xprt = svc_find_xprt(serv, "udp", 0, 0);
	if (!xprt)
		err = svc_create_xprt(serv, "udp", nlm_udpport,
				      SVC_SOCK_DEFAULTS);
	else
		svc_xprt_put(xprt);
	if (err >= 0) {
		xprt = svc_find_xprt(serv, "tcp", 0, 0);
		if (!xprt)
			err = svc_create_xprt(serv, "tcp", nlm_tcpport,
					      SVC_SOCK_DEFAULTS);
		else
			svc_xprt_put(xprt);
	}
	if (err >= 0) {
	warned = 0;
		err = 0;
	} else if (warned++ == 0)
	return 0;

out_err:
	if (warned++ == 0)
		printk(KERN_WARNING
			"lockd_up: makesock failed, error=%d\n", err);
	return err;
@@ -252,7 +274,7 @@ int lockd_up(void)
			"lockd_up: no pid, %d users??\n", nlmsvc_users);

	error = -ENOMEM;
	serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, AF_INET, NULL);
	serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, nlmsvc_family, NULL);
	if (!serv) {
		printk(KERN_WARNING "lockd_up: create service failed\n");
		goto out;
@@ -276,6 +298,7 @@ int lockd_up(void)
	}

	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)) {
@@ -485,6 +508,7 @@ module_param_call(nlm_udpport, param_set_port, param_get_int,
module_param_call(nlm_tcpport, param_set_port, param_get_int,
		  &nlm_tcpport, 0644);
module_param(nsm_use_hostnames, bool, 0644);
module_param(nlm_max_connections, uint, 0644);

/*
 * Initialising and terminating the module.
+1 −12
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@
#include <linux/nfsd/nfsd.h>
#include <linux/lockd/lockd.h>
#include <linux/lockd/share.h>
#include <linux/lockd/sm_inter.h>


#define NLMDBG_FACILITY		NLMDBG_CLIENT

@@ -419,8 +417,6 @@ static __be32
nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
					      void	        *resp)
{
	struct sockaddr_in	saddr;

	dprintk("lockd: SM_NOTIFY     called\n");

	if (!nlm_privileged_requester(rqstp)) {
@@ -430,14 +426,7 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
		return rpc_system_err;
	}

	/* Obtain the host pointer for this NFS server and try to
	 * reclaim all locks we hold on this server.
	 */
	memset(&saddr, 0, sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_addr.s_addr = argp->addr;
	nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state);

	nlm_host_rebooted(argp);
	return rpc_success;
}

Loading