NFS: Add support for AF_INET6 addresses in nfs_compare_super()
Refactor nfs_compare_super() and add AF_INET6 support. Replace the generic memcmp() to document explicitly what parts of the addresses must match in this check, and make the comparison independent of the lengths of both addresses. A side benefit is both tests are more computationally efficient than a memcmp(). Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
3f43c6667a
commit
fd00a8ff8e
|
@ -45,6 +45,8 @@
|
|||
#include <linux/nfs_idmap.h>
|
||||
#include <linux/vfs.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/in6.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <linux/nfs_xdr.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/parser.h>
|
||||
|
@ -1326,15 +1328,50 @@ static int nfs_set_super(struct super_block *s, void *data)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int nfs_compare_super_address(struct nfs_server *server1,
|
||||
struct nfs_server *server2)
|
||||
{
|
||||
struct sockaddr *sap1, *sap2;
|
||||
|
||||
sap1 = (struct sockaddr *)&server1->nfs_client->cl_addr;
|
||||
sap2 = (struct sockaddr *)&server2->nfs_client->cl_addr;
|
||||
|
||||
if (sap1->sa_family != sap2->sa_family)
|
||||
return 0;
|
||||
|
||||
switch (sap1->sa_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *sin1 = (struct sockaddr_in *)sap1;
|
||||
struct sockaddr_in *sin2 = (struct sockaddr_in *)sap2;
|
||||
if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr)
|
||||
return 0;
|
||||
if (sin1->sin_port != sin2->sin_port)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *sin1 = (struct sockaddr_in6 *)sap1;
|
||||
struct sockaddr_in6 *sin2 = (struct sockaddr_in6 *)sap2;
|
||||
if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr))
|
||||
return 0;
|
||||
if (sin1->sin6_port != sin2->sin6_port)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nfs_compare_super(struct super_block *sb, void *data)
|
||||
{
|
||||
struct nfs_sb_mountdata *sb_mntdata = data;
|
||||
struct nfs_server *server = sb_mntdata->server, *old = NFS_SB(sb);
|
||||
int mntflags = sb_mntdata->mntflags;
|
||||
|
||||
if (memcmp(&old->nfs_client->cl_addr,
|
||||
&server->nfs_client->cl_addr,
|
||||
sizeof(old->nfs_client->cl_addr)) != 0)
|
||||
if (!nfs_compare_super_address(old, server))
|
||||
return 0;
|
||||
/* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
|
||||
if (old->flags & NFS_MOUNT_UNSHARED)
|
||||
|
|
Loading…
Reference in New Issue