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 d512a1a..95406a5 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 82df680..25a5a0e 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 e793028..cab9828 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];