Author: pjd
Date: Sun Sep 13 10:12:29 2009
New Revision: 197150
URL: http://svn.freebsd.org/changeset/base/197150

Log:
  There is a bug where mze_insert() can trigger an assert() of inserting
  the same entry twice. This bug is not fixed yet, but leads to situation
  where when try to access corrupted directory the kernel will panic.
  Until the bug is properly fixed, try to recover from it and log that it
  happened.
  
  Reported by:  marck
  OpenSolaris bug:      6709336
  MFC after:    3 days

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c     Sun Sep 
13 10:04:08 2009        (r197149)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c     Sun Sep 
13 10:12:29 2009        (r197150)
@@ -181,10 +181,11 @@ mze_compare(const void *arg1, const void
        return (0);
 }
 
-static void
+static int
 mze_insert(zap_t *zap, int chunkid, uint64_t hash, mzap_ent_phys_t *mzep)
 {
        mzap_ent_t *mze;
+       avl_index_t idx;
 
        ASSERT(zap->zap_ismicro);
        ASSERT(RW_WRITE_HELD(&zap->zap_rwlock));
@@ -194,7 +195,12 @@ mze_insert(zap_t *zap, int chunkid, uint
        mze->mze_chunkid = chunkid;
        mze->mze_hash = hash;
        mze->mze_phys = *mzep;
-       avl_add(&zap->zap_m.zap_avl, mze);
+       if (avl_find(&zap->zap_m.zap_avl, mze, &idx) != NULL) {
+               kmem_free(mze, sizeof (mzap_ent_t));
+               return (EEXIST);
+       }
+       avl_insert(&zap->zap_m.zap_avl, mze, idx);
+       return (0);
 }
 
 static mzap_ent_t *
@@ -329,10 +335,15 @@ mzap_open(objset_t *os, uint64_t obj, dm
                        if (mze->mze_name[0]) {
                                zap_name_t *zn;
 
-                               zap->zap_m.zap_num_entries++;
                                zn = zap_name_alloc(zap, mze->mze_name,
                                    MT_EXACT);
-                               mze_insert(zap, i, zn->zn_hash, mze);
+                               if (mze_insert(zap, i, zn->zn_hash, mze) == 0)
+                                       zap->zap_m.zap_num_entries++;
+                               else {
+                                       printf("ZFS WARNING: Duplicated ZAP "
+                                           "entry detected (%s).",
+                                           mze->mze_name);
+                               }
                                zap_name_free(zn);
                        }
                }
@@ -771,7 +782,7 @@ again:
                        if (zap->zap_m.zap_alloc_next ==
                            zap->zap_m.zap_num_chunks)
                                zap->zap_m.zap_alloc_next = 0;
-                       mze_insert(zap, i, zn->zn_hash, mze);
+                       VERIFY(0 == mze_insert(zap, i, zn->zn_hash, mze));
                        return;
                }
        }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to