summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--module/zfs/dmu_zfetch.c67
-rw-r--r--module/zfs/dnode.c52
-rw-r--r--module/zfs/include/sys/dmu_zfetch.h3
-rw-r--r--module/zfs/include/sys/dnode.h3
4 files changed, 93 insertions, 32 deletions
diff --git a/module/zfs/dmu_zfetch.c b/module/zfs/dmu_zfetch.c
index 4d79fe98e..5ba366c44 100644
--- a/module/zfs/dmu_zfetch.c
+++ b/module/zfs/dmu_zfetch.c
@@ -203,14 +203,37 @@ dmu_zfetch_dofetch(zfetch_t *zf, zstream_t *zs)
void
dmu_zfetch_init(zfetch_t *zf, dnode_t *dno)
{
- if (zf == NULL) {
- return;
- }
-
zf->zf_dnode = dno;
zf->zf_stream_cnt = 0;
zf->zf_alloc_fail = 0;
+}
+/*
+ * Clean-up state associated with a zfetch structure. This frees allocated
+ * structure members, empties the zf_stream tree, and generally makes things
+ * nice. This doesn't free the zfetch_t itself, that's left to the caller.
+ */
+void
+dmu_zfetch_rele(zfetch_t *zf)
+{
+ zstream_t *zs;
+ zstream_t *zs_next;
+
+ for (zs = list_head(&zf->zf_stream); zs; zs = zs_next) {
+ zs_next = list_next(&zf->zf_stream, zs);
+
+ list_remove(&zf->zf_stream, zs);
+ mutex_destroy(&zs->zst_lock);
+ kmem_free(zs, sizeof (zstream_t));
+ }
+}
+
+/*
+ * Construct a zfetch structure.
+ */
+void
+dmu_zfetch_cons(zfetch_t *zf)
+{
list_create(&zf->zf_stream, sizeof (zstream_t),
offsetof(zstream_t, zst_node));
@@ -218,6 +241,16 @@ dmu_zfetch_init(zfetch_t *zf, dnode_t *dno)
}
/*
+ * Destruct a zfetch structure.
+ */
+void
+dmu_zfetch_dest(zfetch_t *zf)
+{
+ list_destroy(&zf->zf_stream);
+ rw_destroy(&zf->zf_rwlock);
+}
+
+/*
* This function computes the actual size, in blocks, that can be prefetched,
* and fetches it.
*/
@@ -442,32 +475,6 @@ out:
}
/*
- * Clean-up state associated with a zfetch structure. This frees allocated
- * structure members, empties the zf_stream tree, and generally makes things
- * nice. This doesn't free the zfetch_t itself, that's left to the caller.
- */
-void
-dmu_zfetch_rele(zfetch_t *zf)
-{
- zstream_t *zs;
- zstream_t *zs_next;
-
- ASSERT(!RW_LOCK_HELD(&zf->zf_rwlock));
-
- for (zs = list_head(&zf->zf_stream); zs; zs = zs_next) {
- zs_next = list_next(&zf->zf_stream, zs);
-
- list_remove(&zf->zf_stream, zs);
- mutex_destroy(&zs->zst_lock);
- kmem_free(zs, sizeof (zstream_t));
- }
- list_destroy(&zf->zf_stream);
- rw_destroy(&zf->zf_rwlock);
-
- zf->zf_dnode = NULL;
-}
-
-/*
* Given a zfetch and zstream structure, insert the zstream structure into the
* AVL tree contained within the zfetch structure. Peform the appropriate
* book-keeping. It is possible that another thread has inserted a stream which
diff --git a/module/zfs/dnode.c b/module/zfs/dnode.c
index b00a8c4a7..384a5bea9 100644
--- a/module/zfs/dnode.c
+++ b/module/zfs/dnode.c
@@ -72,6 +72,7 @@ dnode_cons(void *arg, void *unused, int kmflag)
list_create(&dn->dn_dbufs, sizeof (dmu_buf_impl_t),
offsetof(dmu_buf_impl_t, db_link));
+ dmu_zfetch_cons(&dn->dn_zfetch);
return (0);
}
@@ -96,6 +97,7 @@ dnode_dest(void *arg, void *unused)
}
list_destroy(&dn->dn_dbufs);
+ dmu_zfetch_dest(&dn->dn_zfetch);
}
void
@@ -165,6 +167,27 @@ dnode_verify(dnode_t *dn)
if (drop_struct_lock)
rw_exit(&dn->dn_struct_rwlock);
}
+
+void
+dnode_verify_clean(dnode_t *dn)
+{
+ int i;
+
+ ASSERT(!RW_LOCK_HELD(&dn->dn_struct_rwlock));
+ ASSERT(!MUTEX_HELD(&dn->dn_mtx));
+ ASSERT(!MUTEX_HELD(&dn->dn_dbufs_mtx));
+ ASSERT(refcount_is_zero(&dn->dn_holds));
+ ASSERT(refcount_is_zero(&dn->dn_tx_holds));
+
+ for (i = 0; i < TXG_SIZE; i++) {
+ ASSERT(NULL == list_head(&dn->dn_dirty_records[i]));
+ ASSERT(0 == avl_numnodes(&dn->dn_ranges[i]));
+ }
+
+ ASSERT(NULL == list_head(&dn->dn_dbufs));
+ ASSERT(NULL == list_head(&dn->dn_zfetch.zf_stream));
+ ASSERT(!RW_LOCK_HELD(&dn->dn_zfetch.zf_rwlock));
+}
#endif
void
@@ -276,14 +299,32 @@ dnode_create(objset_impl_t *os, dnode_phys_t *dnp, dmu_buf_impl_t *db,
uint64_t object)
{
dnode_t *dn = kmem_cache_alloc(dnode_cache, KM_SLEEP);
+ int i;
+ DNODE_VERIFY_CLEAN(dn);
dn->dn_objset = os;
dn->dn_object = object;
dn->dn_dbuf = db;
dn->dn_phys = dnp;
- if (dnp->dn_datablkszsec)
+ list_link_init(&dn->dn_link);
+ for (i = 0; i < TXG_SIZE; i++) {
+ list_link_init(&dn->dn_dirty_link[i]);
+ dn->dn_next_nblkptr[i] = 0;
+ dn->dn_next_nlevels[i] = 0;
+ dn->dn_next_indblkshift[i] = 0;
+ dn->dn_next_bonuslen[i] = 0;
+ dn->dn_next_blksz[i] = 0;
+ }
+
+ if (dnp->dn_datablkszsec) {
dnode_setdblksz(dn, dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
+ } else {
+ dn->dn_datablksz = 0;
+ dn->dn_datablkszsec = 0;
+ dn->dn_datablkshift = 0;
+ }
+
dn->dn_indblkshift = dnp->dn_indblkshift;
dn->dn_nlevels = dnp->dn_nlevels;
dn->dn_type = dnp->dn_type;
@@ -293,7 +334,13 @@ dnode_create(objset_impl_t *os, dnode_phys_t *dnp, dmu_buf_impl_t *db,
dn->dn_bonustype = dnp->dn_bonustype;
dn->dn_bonuslen = dnp->dn_bonuslen;
dn->dn_maxblkid = dnp->dn_maxblkid;
-
+ dn->dn_allocated_txg = 0;
+ dn->dn_free_txg = 0;
+ dn->dn_assigned_txg = 0;
+ dn->dn_dirtyctx = DN_UNDIRTIED;
+ dn->dn_dirtyctx_firstset = NULL;
+ dn->dn_bonus = NULL;
+ dn->dn_zio = NULL;
dmu_zfetch_init(&dn->dn_zfetch, dn);
ASSERT(dn->dn_phys->dn_type < DMU_OT_NUMTYPES);
@@ -335,6 +382,7 @@ dnode_destroy(dnode_t *dn)
dbuf_evict(dn->dn_bonus);
dn->dn_bonus = NULL;
}
+ DNODE_VERIFY_CLEAN(dn);
kmem_cache_free(dnode_cache, dn);
arc_space_return(sizeof (dnode_t), ARC_SPACE_OTHER);
}
diff --git a/module/zfs/include/sys/dmu_zfetch.h b/module/zfs/include/sys/dmu_zfetch.h
index c94bced93..97b673852 100644
--- a/module/zfs/include/sys/dmu_zfetch.h
+++ b/module/zfs/include/sys/dmu_zfetch.h
@@ -65,6 +65,9 @@ typedef struct zfetch {
void dmu_zfetch_init(zfetch_t *, struct dnode *);
void dmu_zfetch_rele(zfetch_t *);
+void dmu_zfetch_cons(zfetch_t *);
+void dmu_zfetch_dest(zfetch_t *);
+
void dmu_zfetch(zfetch_t *, uint64_t, uint64_t, int);
diff --git a/module/zfs/include/sys/dnode.h b/module/zfs/include/sys/dnode.h
index be9e56908..f802a480f 100644
--- a/module/zfs/include/sys/dnode.h
+++ b/module/zfs/include/sys/dnode.h
@@ -222,6 +222,7 @@ void dnode_free(dnode_t *dn, dmu_tx_t *tx);
void dnode_byteswap(dnode_phys_t *dnp);
void dnode_buf_byteswap(void *buf, size_t size);
void dnode_verify(dnode_t *dn);
+void dnode_verify_clean(dnode_t *dn);
int dnode_set_blksz(dnode_t *dn, uint64_t size, int ibs, dmu_tx_t *tx);
uint64_t dnode_current_max_length(dnode_t *dn);
void dnode_free_range(dnode_t *dn, uint64_t off, uint64_t len, dmu_tx_t *tx);
@@ -259,12 +260,14 @@ void dnode_evict_dbufs(dnode_t *dn);
_NOTE(CONSTCOND) } while (0)
#define DNODE_VERIFY(dn) dnode_verify(dn)
+#define DNODE_VERIFY_CLEAN(dn) dnode_verify_clean(dn)
#define FREE_VERIFY(db, start, end, tx) free_verify(db, start, end, tx)
#else
#define dprintf_dnode(db, fmt, ...)
#define DNODE_VERIFY(dn)
+#define DNODE_VERIFY_CLEAN(dn)
#define FREE_VERIFY(db, start, end, tx)
#endif