Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.linux-nfs.org/projects/trondmy/…
Browse files Browse the repository at this point in the history
…nfs-2.6

* 'for-linus' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6: (58 commits)
  SUNRPC: Ensure IPV6_V6ONLY is set on the socket before binding to a port
  NSM: Fix unaligned accesses in nsm_init_private()
  NFS: Simplify logic to compare socket addresses in client.c
  NFS: Start PF_INET6 callback listener only if IPv6 support is available
  lockd: Start PF_INET6 listener only if IPv6 support is available
  SUNRPC: Remove CONFIG_SUNRPC_REGISTER_V4
  SUNRPC: rpcb_register() should handle errors silently
  SUNRPC: Simplify kernel RPC service registration
  SUNRPC: Simplify svc_unregister()
  SUNRPC: Allow callers to pass rpcb_v4_register a NULL address
  SUNRPC: rpcbind actually interprets r_owner string
  SUNRPC: Clean up address type casts in rpcb_v4_register()
  SUNRPC: Don't return EPROTONOSUPPORT in svc_register()'s helpers
  SUNRPC: Use IPv4 loopback for registering AF_INET6 kernel RPC services
  SUNRPC: Set IPV6ONLY flag on PF_INET6 RPC listener sockets
  NFS: Revert creation of IPv6 listeners for lockd and NFSv4 callbacks
  SUNRPC: Remove @family argument from svc_create() and svc_create_pooled()
  SUNRPC: Change svc_create_xprt() to take a @family argument
  SUNRPC: svc_setup_socket() gets protocol family from socket
  SUNRPC: Pass a family argument to svc_register()
  ...
  • Loading branch information
Linus Torvalds committed Apr 1, 2009
2 parents 395d734 + cc85906 commit 4fe7041
Show file tree
Hide file tree
Showing 39 changed files with 1,178 additions and 845 deletions.
51 changes: 1 addition & 50 deletions fs/lockd/clntlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,55 +139,6 @@ int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout)
return 0;
}

#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static const struct in6_addr *nlmclnt_map_v4addr(const struct sockaddr *sap,
struct in6_addr *addr_mapped)
{
const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;

switch (sap->sa_family) {
case AF_INET6:
return &((const struct sockaddr_in6 *)sap)->sin6_addr;
case AF_INET:
ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, addr_mapped);
return addr_mapped;
}

return NULL;
}

/*
* If lockd is using a PF_INET6 listener, all incoming requests appear
* to come from AF_INET6 remotes. The address of AF_INET remotes are
* mapped to AF_INET6 automatically by the network layer. In case the
* user passed an AF_INET server address at mount time, ensure both
* addresses are AF_INET6 before comparing them.
*/
static int nlmclnt_cmp_addr(const struct nlm_host *host,
const struct sockaddr *sap)
{
const struct in6_addr *addr1;
const struct in6_addr *addr2;
struct in6_addr addr1_mapped;
struct in6_addr addr2_mapped;

addr1 = nlmclnt_map_v4addr(nlm_addr(host), &addr1_mapped);
if (likely(addr1 != NULL)) {
addr2 = nlmclnt_map_v4addr(sap, &addr2_mapped);
if (likely(addr2 != NULL))
return ipv6_addr_equal(addr1, addr2);
}

return 0;
}
#else /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
static int nlmclnt_cmp_addr(const struct nlm_host *host,
const struct sockaddr *sap)
{
return nlm_cmp_addr(nlm_addr(host), sap);
}
#endif /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */

/*
* The server lockd has called us back to tell us the lock was granted
*/
Expand Down Expand Up @@ -215,7 +166,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
*/
if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid)
continue;
if (!nlmclnt_cmp_addr(block->b_host, addr))
if (!nlm_cmp_addr(nlm_addr(block->b_host), addr))
continue;
if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0)
continue;
Expand Down
8 changes: 6 additions & 2 deletions fs/lockd/mon.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include <linux/sunrpc/svc.h>
#include <linux/lockd/lockd.h>

#include <asm/unaligned.h>

#define NLMDBG_FACILITY NLMDBG_MONITOR
#define NSM_PROGRAM 100024
#define NSM_VERSION 1
Expand Down Expand Up @@ -274,10 +276,12 @@ static void nsm_init_private(struct nsm_handle *nsm)
{
u64 *p = (u64 *)&nsm->sm_priv.data;
struct timespec ts;
s64 ns;

ktime_get_ts(&ts);
*p++ = timespec_to_ns(&ts);
*p = (unsigned long)nsm;
ns = timespec_to_ns(&ts);
put_unaligned(ns, p);
put_unaligned((unsigned long)nsm, p + 1);
}

static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap,
Expand Down
42 changes: 22 additions & 20 deletions fs/lockd/svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,6 @@ 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
Expand Down Expand Up @@ -204,19 +193,30 @@ lockd(void *vrqstp)
return 0;
}

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

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

return svc_create_xprt(serv, name, family, port,
SVC_SOCK_DEFAULTS);
svc_xprt_put(xprt);
return 0;
}

static int create_lockd_family(struct svc_serv *serv, const int family)
{
int err;

err = create_lockd_listener(serv, "udp", family, nlm_udpport);
if (err < 0)
return err;

return create_lockd_listener(serv, "tcp", family, nlm_tcpport);
}

/*
* Ensure there are active UDP and TCP listeners for lockd.
*
Expand All @@ -232,13 +232,15 @@ static int make_socks(struct svc_serv *serv)
static int warned;
int err;

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

err = create_lockd_listener(serv, "tcp", nlm_tcpport);
if (err < 0)
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
err = create_lockd_family(serv, PF_INET6);
if (err < 0 && err != -EAFNOSUPPORT)
goto out_err;
#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */

warned = 0;
return 0;
Expand Down Expand Up @@ -274,7 +276,7 @@ int lockd_up(void)
"lockd_up: no pid, %d users??\n", nlmsvc_users);

error = -ENOMEM;
serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, nlmsvc_family, NULL);
serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL);
if (!serv) {
printk(KERN_WARNING "lockd_up: create service failed\n");
goto out;
Expand Down
31 changes: 16 additions & 15 deletions fs/nfs/callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,10 @@ static struct svc_program nfs4_callback_program;

unsigned int nfs_callback_set_tcpport;
unsigned short nfs_callback_tcpport;
unsigned short nfs_callback_tcpport6;
static const int nfs_set_port_min = 0;
static const int nfs_set_port_max = 65535;

/*
* 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)
static const sa_family_t nfs_callback_family = AF_INET6;
#else
static const sa_family_t nfs_callback_family = AF_INET;
#endif

static int param_set_port(const char *val, struct kernel_param *kp)
{
char *endp;
Expand Down Expand Up @@ -116,19 +107,29 @@ int nfs_callback_up(void)
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);
serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
ret = -ENOMEM;
if (!serv)
goto out_err;

ret = svc_create_xprt(serv, "tcp", nfs_callback_set_tcpport,
SVC_SOCK_ANONYMOUS);
ret = svc_create_xprt(serv, "tcp", 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, nfs_callback_family);
nfs_callback_tcpport, PF_INET);

#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
ret = svc_create_xprt(serv, "tcp", 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)
goto out_err;
#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */

nfs_callback_info.rqst = svc_prepare_thread(serv, &serv->sv_pools[0]);
if (IS_ERR(nfs_callback_info.rqst)) {
Expand Down
1 change: 1 addition & 0 deletions fs/nfs/callback.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,6 @@ extern void nfs_callback_down(void);

extern unsigned int nfs_callback_set_tcpport;
extern unsigned short nfs_callback_tcpport;
extern unsigned short nfs_callback_tcpport6;

#endif /* __LINUX_FS_NFS_CALLBACK_H */
116 changes: 52 additions & 64 deletions fs/nfs/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,38 +224,6 @@ void nfs_put_client(struct nfs_client *clp)
}

#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)
{
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_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;
}

/*
* Test if two ip6 socket addresses refer to the same socket by
* comparing relevant fields. The padding bytes specifically, are not
Expand All @@ -267,38 +235,21 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
*
* The caller should ensure both socket addresses are AF_INET6.
*/
static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1,
const struct sockaddr *sa2)
static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1,
const struct sockaddr *sa2)
{
const struct sockaddr_in6 *saddr1 = (const struct sockaddr_in6 *)sa1;
const struct sockaddr_in6 *saddr2 = (const struct sockaddr_in6 *)sa2;
const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1;
const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2;

if (!ipv6_addr_equal(&saddr1->sin6_addr,
&saddr1->sin6_addr))
if (ipv6_addr_scope(&sin1->sin6_addr) == IPV6_ADDR_SCOPE_LINKLOCAL &&
sin1->sin6_scope_id != sin2->sin6_scope_id)
return 0;
if (ipv6_addr_scope(&saddr1->sin6_addr) == IPV6_ADDR_SCOPE_LINKLOCAL &&
saddr1->sin6_scope_id != saddr2->sin6_scope_id)
return 0;
return saddr1->sin6_port == saddr2->sin6_port;
}
#else
static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1,
const struct sockaddr_in *sa2)
{
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)
{
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);
return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr);
}

static int nfs_sockaddr_cmp_ip6(const struct sockaddr * sa1,
const struct sockaddr * sa2)
#else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */
static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1,
const struct sockaddr *sa2)
{
return 0;
}
Expand All @@ -311,20 +262,57 @@ static int nfs_sockaddr_cmp_ip6(const struct sockaddr * sa1,
*
* The caller should ensure both socket addresses are AF_INET.
*/
static int nfs_sockaddr_match_ipaddr4(const struct sockaddr *sa1,
const struct sockaddr *sa2)
{
const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1;
const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2;

return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
}

static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1,
const struct sockaddr *sa2)
{
const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1;
const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2;

return nfs_sockaddr_match_ipaddr6(sa1, sa2) &&
(sin1->sin6_port == sin2->sin6_port);
}

static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1,
const struct sockaddr *sa2)
{
const struct sockaddr_in *saddr1 = (const struct sockaddr_in *)sa1;
const struct sockaddr_in *saddr2 = (const struct sockaddr_in *)sa2;
const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1;
const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2;

if (saddr1->sin_addr.s_addr != saddr2->sin_addr.s_addr)
return nfs_sockaddr_match_ipaddr4(sa1, sa2) &&
(sin1->sin_port == sin2->sin_port);
}

/*
* Test if two socket addresses represent the same actual socket,
* by comparing (only) relevant fields, excluding the port number.
*/
static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
const struct sockaddr *sa2)
{
if (sa1->sa_family != sa2->sa_family)
return 0;
return saddr1->sin_port == saddr2->sin_port;

switch (sa1->sa_family) {
case AF_INET:
return nfs_sockaddr_match_ipaddr4(sa1, sa2);
case AF_INET6:
return nfs_sockaddr_match_ipaddr6(sa1, sa2);
}
return 0;
}

/*
* Test if two socket addresses represent the same actual socket,
* by comparing (only) relevant fields.
* by comparing (only) relevant fields, including the port number.
*/
static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
const struct sockaddr *sa2)
Expand Down
Loading

0 comments on commit 4fe7041

Please sign in to comment.