libmultipath: resolve hash collisions in pgcmp()
authorHannes Reinecke <hare@suse.de>
Tue, 3 May 2011 11:45:49 +0000 (13:45 +0200)
committerHannes Reinecke <hare@suse.de>
Tue, 3 May 2011 11:45:49 +0000 (13:45 +0200)
pgcmp() is using a simple xor algorithm for hashing. Main intention
here is to have a quick comparison if two paths are identical.
However, this algorithm is prone to hash collisions, so even if
two hashes match we should still check the individual paths to
avoid collisions.

Signed-off-by: Hannes Reinecke <hare@suse.de>
libmultipath/configure.c
libmultipath/structs.c
libmultipath/structs.h

index d512a1ab79701f24ea006ceff8f102b1a9d72fba..95406a516a373dc6db03c1f716321a03442f5bff 100644 (file)
@@ -132,7 +132,8 @@ pgcmp (struct multipath * mpp, struct multipath * cmpp)
                compute_pgid(pgp);
 
                vector_foreach_slot (cmpp->pg, cpgp, j) {
-                       if (pgp->id == cpgp->id) {
+                       if (pgp->id == cpgp->id &&
+                           !pathcmp(pgp, cpgp)) {
                                r = 0;
                                break;
                        }
index 82df68085a3cff6fb2ed33c568d70dce3117d158..25a5a0e4b06c23351be9961b20e4c30cb7447cde 100644 (file)
@@ -371,6 +371,26 @@ pathcount (struct multipath * mpp, int state)
        return count;
 }
 
+extern int
+pathcmp (struct pathgroup *pgp, struct pathgroup *cpgp)
+{
+       int i, j;
+       struct path *pp, *cpp;
+       int pnum = 0, found = 0;
+
+       vector_foreach_slot(pgp->paths, pp, i) {
+               pnum++;
+               vector_foreach_slot(cpgp->paths, cpp, j) {
+                       if ((long)pp == (long)cpp) {
+                               found++;
+                               break;
+                       }
+               }
+       }
+
+       return pnum - found;
+}
+
 struct path *
 first_path (struct multipath * mpp)
 {
index e7930282681eb4ba79e2945b4a25e448854a657d..cab98288f2a306f0efe88cb0092681cfc75f17dc 100644 (file)
@@ -251,6 +251,7 @@ struct path * first_path (struct multipath * mpp);
 
 int pathcountgr (struct pathgroup *, int);
 int pathcount (struct multipath *, int);
+int pathcmp (struct pathgroup *, struct pathgroup *);
 void setup_feature(struct multipath *, char *);
 
 extern char sysfs_path[PATH_SIZE];