From 9925c28cdec943a6ffa81219cb469b727decf111 Mon Sep 17 00:00:00 2001 From: Alex Reece Date: Thu, 2 Apr 2015 02:10:58 +1100 Subject: Illumos 5095 - panic when adding a duplicate dbuf to dn_dbufs 5095 panic when adding a duplicate dbuf to dn_dbufs Author: Alex Reece Reviewed by: Adam Leventhal Reviewed by: George Wilson Reviewed by: Mattew Ahrens Reviewed by: Dan Kimmel Reviewed by: Dan McDonald Reviewed by: Josef Sipek Approved by: Robert Mustacchi References: https://www.illumos.org/issues/5095 https://github.com/illumos/illumos-gate/commit/86bb58a Ported-by: Chris Dunlop Signed-off-by: Brian Behlendorf --- include/sys/dbuf.h | 8 +++++--- include/sys/dnode.h | 13 ++++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'include/sys') diff --git a/include/sys/dbuf.h b/include/sys/dbuf.h index 2f593bb4d..d253add59 100644 --- a/include/sys/dbuf.h +++ b/include/sys/dbuf.h @@ -66,8 +66,13 @@ extern "C" { * | | * | | * +--------> NOFILL -------+ + * + * DB_SEARCH is an invalid state for a dbuf. It is used by dbuf_free_range + * to find all dbufs in a range of a dnode and must be less than any other + * dbuf_states_t (see comment on dn_dbufs in dnode.h). */ typedef enum dbuf_states { + DB_SEARCH = -1, DB_UNCACHED, DB_FILL, DB_NOFILL, @@ -213,9 +218,6 @@ typedef struct dmu_buf_impl { /* pointer to most recent dirty record for this buffer */ dbuf_dirty_record_t *db_last_dirty; - /* Creation time of dbuf (see comment in dbuf_compare). */ - hrtime_t db_creation; - /* * Our link on the owner dnodes's dn_dbufs list. * Protected by its dn_dbufs_mtx. diff --git a/include/sys/dnode.h b/include/sys/dnode.h index 2974a20dc..90a334ba7 100644 --- a/include/sys/dnode.h +++ b/include/sys/dnode.h @@ -233,7 +233,18 @@ typedef struct dnode { refcount_t dn_holds; kmutex_t dn_dbufs_mtx; - avl_tree_t dn_dbufs; /* descendent dbufs */ + /* + * Descendent dbufs, ordered by dbuf_compare. Note that dn_dbufs + * can contain multiple dbufs of the same (level, blkid) when a + * dbuf is marked DB_EVICTING without being removed from + * dn_dbufs. To maintain the avl invariant that there cannot be + * duplicate entries, we order the dbufs by an arbitrary value - + * their address in memory. This means that dn_dbufs cannot be used to + * directly look up a dbuf. Instead, callers must use avl_walk, have + * a reference to the dbuf, or look up a non-existant node with + * db_state = DB_SEARCH (see dbuf_free_range for an example). + */ + avl_tree_t dn_dbufs; /* protected by dn_struct_rwlock */ struct dmu_buf_impl *dn_bonus; /* bonus buffer dbuf */ -- cgit v1.2.3