diff options
author | Keith M Wesolowski <wesolows@foobazco.org> | 2014-08-20 20:04:47 +0000 |
---|---|---|
committer | Keith M Wesolowski <wesolows@foobazco.org> | 2014-08-20 20:04:47 +0000 |
commit | 5f00496ef2e39b976b062f196ff01a99fd4864a4 (patch) | |
tree | 20be9cbc8f4b7ed3e616ce23552728083801e846 /usr/src/uts/common/fs | |
parent | af59b1a40df03681c1c8129aea7b1f5f52f2bcea (diff) | |
parent | 86bb58aec7165f8a0303564575c65e5a2ad58bf1 (diff) | |
download | illumos-joyent-release-20140821.tar.gz |
[illumos-gate merge]20140821release-20140821
commit 86bb58aec7165f8a0303564575c65e5a2ad58bf1
5095 panic when adding a duplicate dbuf to dn_dbufs
commit 60a61f7adabc73a7a0cb70d200ac2a6735f4a6e8
5092 env files don't need to define LOCKNAME by default
5091 illumos.sh env file's LOCKNAME definition is busted
commit 5e3f545c431ec4bce3e1b52f3f81bc9befe501f2
4989 removal of ntfsprogs and parted
commit ba3594ba9b5dd4c846c472a8d657edcb7c8109ac
5066 remove support for non-ANSI compilation
5068 Remove SCCSID() macro from <macros.h>
commit d8ccf998f9c944b8cf27ed840c376f9b79ebce5c
5087 8-bit inline atomic {add,or,and} use wrong reg constraints on x86
Manifests:
usr/src/pkg/manifests/SUNWntfsprogs.mf (torch library)
usr/src/pkg/manifests/SUNWparted.mf (torch headers)
usr/src/pkg/manifests/system-file-system-ntfsprogs.mf
usr/src/pkg/manifests/system-storage-parted.mf
Diffstat (limited to 'usr/src/uts/common/fs')
-rw-r--r-- | usr/src/uts/common/fs/zfs/dbuf.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/dnode.c | 34 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/dbuf.h | 8 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/dnode.h | 13 |
4 files changed, 36 insertions, 23 deletions
diff --git a/usr/src/uts/common/fs/zfs/dbuf.c b/usr/src/uts/common/fs/zfs/dbuf.c index 3b4afd6a09..0e97ad4bac 100644 --- a/usr/src/uts/common/fs/zfs/dbuf.c +++ b/usr/src/uts/common/fs/zfs/dbuf.c @@ -70,8 +70,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); } @@ -830,7 +828,7 @@ dbuf_free_range(dnode_t *dn, uint64_t start_blkid, uint64_t end_blkid, 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) { diff --git a/usr/src/uts/common/fs/zfs/dnode.c b/usr/src/uts/common/fs/zfs/dnode.c index f5f5c40163..6f47b440e1 100644 --- a/usr/src/uts/common/fs/zfs/dnode.c +++ b/usr/src/uts/common/fs/zfs/dnode.c @@ -67,33 +67,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 */ diff --git a/usr/src/uts/common/fs/zfs/sys/dbuf.h b/usr/src/uts/common/fs/zfs/sys/dbuf.h index 643d9685b6..8ca8753e5e 100644 --- a/usr/src/uts/common/fs/zfs/sys/dbuf.h +++ b/usr/src/uts/common/fs/zfs/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/usr/src/uts/common/fs/zfs/sys/dnode.h b/usr/src/uts/common/fs/zfs/sys/dnode.h index 6e4a845a36..8a4f3f6185 100644 --- a/usr/src/uts/common/fs/zfs/sys/dnode.h +++ b/usr/src/uts/common/fs/zfs/sys/dnode.h @@ -211,7 +211,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 */ |