Re: [PATCH] Bug 11061, NFS mounts dropped

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2009-02-03 at 17:16 -0500, Chuck Lever wrote: 
> On Feb 3, 2009, at Feb 3, 2009, 4:56 PM, Ian Dall wrote:
> > OK here is version 2 of the patch. It is half the size of version 1,
> > although the resultant client.c is slightly bigger and IMO slightly
> > inferior than for version 1, but certainly it is around the margin.
> 
> Why do you think this is inferior?  This way we are checking exactly  
> the fields in each sockaddr that need to be checked, and using the  
> same equality test that most other parts of the NFS client use.

There is duplicated code, namely the function headers for 
nfs_sockaddr_match_ipaddr() and nfs_sockaddr_match_port().

Granted this doesn't add to the executable size in any way because of
the conditional compilation, but it is still a potential source of
trouble down the track when one function definition gets changed and
another doesn't and further more, it won't show up unless you test both
IPV6 and non IPV6 configurations. Having function headers in two places
makes following the code with etags more confusing. And even without
etags you have to scroll up and down to see the two versions of the same
function.

Also nfs_sockaddr_match_ipaddr4() is trivial, taking 7 lines of code
(counting the call and the function definition) to do what can be
expressed in 2 and has additional overhead, albeit small.

None of these are a big deal, which is way I said *slightly* inferior.

I'm not exactly sure what you didn't like about my first patch. Maybe it
was just too big (fair enough, more to go wrong), or maybe you didn't
like the  test return; test return; ... style, or maybe you didn't like
the use of a port_match flag.

See if you like this one :-) It is small, but not quite minimal. It
doesn't change the style of logic, it doesn't use a flag. It does
address my concerns about duplicated code, it includes Trond's
suggestions and the resulting code is smallest so far (in SLOC). Granted
that less SLOC isn't always better, but in this case it is done by
removing duplication and not by making more complicated lines, so IMHO
it is a good thing!

Log:
======================
Don't compare sock_addr structures using memcmp(). Reduce conditionally
compiled address comparison code.

Signed-off-by: Ian Dall <ian@xxxxxxxxxxxxxxxxxxxxx>
======================
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 9b728f3..1c2a319 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -238,10 +238,12 @@ static const struct in6_addr *nfs_map_ipv4_addr(const struct sockaddr *sa, struc
 			return addr_mapped;
 	}
 }
+#endif
 
 static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
 		const struct sockaddr *sa2)
 {
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	const struct in6_addr *addr1;
 	const struct in6_addr *addr2;
 	struct in6_addr addr1_mapped;
@@ -254,23 +256,32 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
 			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 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 (((const struct sockaddr_in *)sa1)->sin_addr.s_addr ==
+		((const struct sockaddr_in *)sa2)->sin_addr.s_addr))
+#endif
 }
+
+static int nfs_sockaddr_match_port(const struct sockaddr *sa1,
+				   const struct sockaddr *sa2)
+{
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	switch (sa1->sa_family) {
+	case AF_INET:
+		return (((const struct sockaddr_in *)sa1)->sin_port ==
+			((const struct sockaddr_in *)sa2)->sin_port);
+	case AF_INET6:
+		return (((const struct sockaddr_in6 *)sa1)->sin6_port ==
+			((const struct sockaddr_in6 *)sa2)->sin6_port);
+	}
+	return 0;
+#else
+	return (((const struct sockaddr_in *)sa1)->sin_port ==
+		((const struct sockaddr_in *)sa2)->sin_port);
 #endif
+}
 
 /*
  * Find a client by IP address and protocol version
@@ -344,8 +355,10 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
 static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data)
 {
 	struct nfs_client *clp;
+	const struct sockaddr *sap = data->addr;
 
 	list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
+	        const struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
 		/* Don't match clients that failed to initialise properly */
 		if (clp->cl_cons_state < 0)
 			continue;
@@ -358,8 +371,12 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
 			continue;
 
 		/* Match the full socket address */
-		if (memcmp(&clp->cl_addr, data->addr, sizeof(clp->cl_addr)) != 0)
+		if (!nfs_sockaddr_match_ipaddr(sap, clap))
 			continue;
+		/* including the port number */
+		if (!nfs_sockaddr_match_port(sap, clap))
+			continue;
+
 
 		atomic_inc(&clp->cl_count);
 		return clp;

-- 
Ian Dall <ian@xxxxxxxxxxxxxxxxxxxxx>

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux