summaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorAlex Reece <[email protected]>2015-04-02 02:10:58 +1100
committerBrian Behlendorf <[email protected]>2015-04-28 16:24:49 -0700
commit9925c28cdec943a6ffa81219cb469b727decf111 (patch)
tree219c9802db1a1a145deecd66d9bdfab7606e1b51 /module
parent5aea3644d6aef3fe636053d6924bc0803fbd75b5 (diff)
Illumos 5095 - panic when adding a duplicate dbuf to dn_dbufs
5095 panic when adding a duplicate dbuf to dn_dbufs Author: Alex Reece <[email protected]> Reviewed by: Adam Leventhal <[email protected]> Reviewed by: George Wilson <[email protected]> Reviewed by: Mattew Ahrens <[email protected]> Reviewed by: Dan Kimmel <[email protected]> Reviewed by: Dan McDonald <[email protected]> Reviewed by: Josef Sipek <[email protected]> Approved by: Robert Mustacchi <[email protected]> References: https://www.illumos.org/issues/5095 https://github.com/illumos/illumos-gate/commit/86bb58a Ported-by: Chris Dunlop <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]>
Diffstat (limited to 'module')
-rw-r--r--module/zfs/dbuf.c4
-rw-r--r--module/zfs/dnode.c34
2 files changed, 19 insertions, 19 deletions
diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c
index e9c8580fc..e6e24e0e9 100644
--- a/module/zfs/dbuf.c
+++ b/module/zfs/dbuf.c
@@ -94,8 +94,6 @@ dbuf_cons(void *vdb, void *unused, int kmflag)
cv_init(&db->db_changed, NULL, CV_DEFAULT, NULL);
refcount_create(&db->db_holds);
- db->db_creation = gethrtime();
-
return (0);
}
@@ -884,7 +882,7 @@ dbuf_free_range(dnode_t *dn, uint64_t start_blkid, uint64_t end_blkid,
db_seach = kmem_alloc(sizeof (dmu_buf_impl_t), KM_SLEEP);
db_search->db_level = 0;
db_search->db_blkid = start_blkid;
- db_search->db_creation = 0;
+ db_search->db_state = DB_SEARCH;
mutex_enter(&dn->dn_dbufs_mtx);
if (start_blkid >= dn->dn_unlisted_l0_blkid && !freespill) {
diff --git a/module/zfs/dnode.c b/module/zfs/dnode.c
index 7c28dc64d..2b022860e 100644
--- a/module/zfs/dnode.c
+++ b/module/zfs/dnode.c
@@ -70,33 +70,35 @@ dbuf_compare(const void *x1, const void *x2)
if (d1->db_level < d2->db_level) {
return (-1);
- } else if (d1->db_level > d2->db_level) {
+ }
+ if (d1->db_level > d2->db_level) {
return (1);
}
if (d1->db_blkid < d2->db_blkid) {
return (-1);
- } else if (d1->db_blkid > d2->db_blkid) {
+ }
+ if (d1->db_blkid > d2->db_blkid) {
return (1);
}
- /*
- * If a dbuf is being evicted while dn_dbufs_mutex is not held, we set
- * the db_state to DB_EVICTING but do not remove it from dn_dbufs. If
- * another thread creates a dbuf of the same blkid before the dbuf is
- * removed from dn_dbufs, we can reach a state where there are two
- * dbufs of the same blkid and level in db_dbufs. To maintain the avl
- * invariant that there cannot be duplicate items, we distinguish
- * between these two dbufs based on the time they were created.
- */
- if (d1->db_creation < d2->db_creation) {
+ if (d1->db_state < d2->db_state) {
return (-1);
- } else if (d1->db_creation > d2->db_creation) {
+ }
+ if (d1->db_state > d2->db_state) {
return (1);
- } else {
- ASSERT3P(d1, ==, d2);
- return (0);
}
+
+ ASSERT3S(d1->db_state, !=, DB_SEARCH);
+ ASSERT3S(d2->db_state, !=, DB_SEARCH);
+
+ if ((uintptr_t)d1 < (uintptr_t)d2) {
+ return (-1);
+ }
+ if ((uintptr_t)d1 > (uintptr_t)d2) {
+ return (1);
+ }
+ return (0);
}
/* ARGSUSED */