|
@@ -45,6 +45,8 @@
|
|
#include <linux/nfs_idmap.h>
|
|
#include <linux/nfs_idmap.h>
|
|
#include <linux/vfs.h>
|
|
#include <linux/vfs.h>
|
|
#include <linux/inet.h>
|
|
#include <linux/inet.h>
|
|
|
|
+#include <linux/in6.h>
|
|
|
|
+#include <net/ipv6.h>
|
|
#include <linux/nfs_xdr.h>
|
|
#include <linux/nfs_xdr.h>
|
|
#include <linux/magic.h>
|
|
#include <linux/magic.h>
|
|
#include <linux/parser.h>
|
|
#include <linux/parser.h>
|
|
@@ -1326,15 +1328,50 @@ static int nfs_set_super(struct super_block *s, void *data)
|
|
return ret;
|
|
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)
|
|
static int nfs_compare_super(struct super_block *sb, void *data)
|
|
{
|
|
{
|
|
struct nfs_sb_mountdata *sb_mntdata = data;
|
|
struct nfs_sb_mountdata *sb_mntdata = data;
|
|
struct nfs_server *server = sb_mntdata->server, *old = NFS_SB(sb);
|
|
struct nfs_server *server = sb_mntdata->server, *old = NFS_SB(sb);
|
|
int mntflags = sb_mntdata->mntflags;
|
|
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;
|
|
return 0;
|
|
/* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
|
|
/* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
|
|
if (old->flags & NFS_MOUNT_UNSHARED)
|
|
if (old->flags & NFS_MOUNT_UNSHARED)
|