--- old/usr/src/uts/common/fs/zfs/sys/dbuf.h	Mon Aug  5 17:26:57 2019
+++ new/usr/src/uts/common/fs/zfs/sys/dbuf.h	Mon Aug  5 17:26:57 2019
@@ -23,6 +23,7 @@
  * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
  * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  */
 
 #ifndef	_SYS_DBUF_H
@@ -55,6 +56,8 @@
 #define	DB_RF_NEVERWAIT		(1 << 4)
 #define	DB_RF_CACHED		(1 << 5)
 
+#define	DBUF_EVICT_ALL		-1
+
 /*
  * The simplified state transition diagram for dbufs looks like:
  *
@@ -83,6 +86,13 @@
 	DB_EVICTING
 } dbuf_states_t;
 
+typedef enum dbuf_cached_state {
+	DB_NO_CACHE = -1,
+	DB_DBUF_CACHE,
+	DB_DBUF_METADATA_CACHE,
+	DB_CACHE_MAX
+} dbuf_cached_state_t;
+
 struct dnode;
 struct dmu_tx;
 
@@ -125,6 +135,9 @@
 	/* A copy of the bp that points to us */
 	blkptr_t dr_bp_copy;
 
+	/* use special class of dirty entry */
+	boolean_t dr_usesc;
+
 	union dirty_types {
 		struct dirty_indirect {
 
@@ -229,11 +242,12 @@
 	 */
 	avl_node_t db_link;
 
-	/*
-	 * Link in dbuf_cache.
-	 */
+	/* Link in dbuf_cache or dbuf_metadata_cache */
 	multilist_node_t db_cache_link;
 
+	/* Tells us which dbuf cache this dbuf is in, if any */
+	dbuf_cached_state_t db_caching_status;
+
 	/* Data which is unique to data (leaf) blocks: */
 
 	/* User callback information. */
@@ -262,12 +276,20 @@
 } dmu_buf_impl_t;
 
 /* Note: the dbuf hash table is exposed only for the mdb module */
-#define	DBUF_MUTEXES 256
-#define	DBUF_HASH_MUTEX(h, idx) (&(h)->hash_mutexes[(idx) & (DBUF_MUTEXES-1)])
+#define	DBUF_MUTEXES	256
+#define	DBUF_LOCK_PAD	64
+typedef struct {
+	kmutex_t mtx;
+#ifdef _KERNEL
+	unsigned char pad[(DBUF_LOCK_PAD - sizeof (kmutex_t))];
+#endif
+} dbuf_mutex_t;
+#define	DBUF_HASH_MUTEX(h, idx)	\
+	(&((h)->hash_mutexes[(idx) & (DBUF_MUTEXES-1)].mtx))
 typedef struct dbuf_hash_table {
 	uint64_t hash_table_mask;
 	dmu_buf_impl_t **hash_table;
-	kmutex_t hash_mutexes[DBUF_MUTEXES];
+	dbuf_mutex_t hash_mutexes[DBUF_MUTEXES];
 } dbuf_hash_table_t;
 
 uint64_t dbuf_whichblock(struct dnode *di, int64_t level, uint64_t offset);
@@ -306,6 +328,8 @@
 void dmu_buf_fill_done(dmu_buf_t *db, dmu_tx_t *tx);
 void dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx);
 dbuf_dirty_record_t *dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx);
+dbuf_dirty_record_t *dbuf_dirty_sc(dmu_buf_impl_t *db, dmu_tx_t *tx,
+    boolean_t usesc);
 arc_buf_t *dbuf_loan_arcbuf(dmu_buf_impl_t *db);
 void dmu_buf_write_embedded(dmu_buf_t *dbuf, void *data,
     bp_embedded_type_t etype, enum zio_compress comp,
@@ -318,8 +342,6 @@
 void dbuf_sync_list(list_t *list, int level, dmu_tx_t *tx);
 void dbuf_release_bp(dmu_buf_impl_t *db);
 
-boolean_t dbuf_can_remap(const dmu_buf_impl_t *buf);
-
 void dbuf_free_range(struct dnode *dn, uint64_t start, uint64_t end,
     struct dmu_tx *);
 
@@ -335,9 +357,13 @@
 void dbuf_fini(void);
 
 boolean_t dbuf_is_metadata(dmu_buf_impl_t *db);
+boolean_t dbuf_is_ddt(dmu_buf_impl_t *db);
+boolean_t dbuf_ddt_is_l2cacheable(dmu_buf_impl_t *db);
+boolean_t dbuf_meta_is_l2cacheable(dmu_buf_impl_t *db);
 
 #define	DBUF_GET_BUFC_TYPE(_db)	\
-	(dbuf_is_metadata(_db) ? ARC_BUFC_METADATA : ARC_BUFC_DATA)
+	(dbuf_is_ddt(_db) ? ARC_BUFC_DDT :\
+	(dbuf_is_metadata(_db) ? ARC_BUFC_METADATA : ARC_BUFC_DATA))
 
 #define	DBUF_IS_CACHEABLE(_db)						\
 	((_db)->db_objset->os_primary_cache == ZFS_CACHE_ALL ||		\
@@ -344,10 +370,22 @@
 	(dbuf_is_metadata(_db) &&					\
 	((_db)->db_objset->os_primary_cache == ZFS_CACHE_METADATA)))
 
+/*
+ * Checks whether we need to cache dbuf in l2arc.
+ * Metadata is l2cacheable if it is not placed on special device
+ * or it is placed on special device in "dual" mode. We need to check
+ * for ddt in ZFS_CACHE_ALL and ZFS_CACHE_METADATA because it is in MOS.
+ * ZFS_CACHE_DATA mode actually means to cache both data and cacheable
+ * metadata.
+ */
 #define	DBUF_IS_L2CACHEABLE(_db)					\
-	((_db)->db_objset->os_secondary_cache == ZFS_CACHE_ALL ||	\
-	(dbuf_is_metadata(_db) &&					\
-	((_db)->db_objset->os_secondary_cache == ZFS_CACHE_METADATA)))
+	(((_db)->db_objset->os_secondary_cache == ZFS_CACHE_ALL &&	\
+	(dbuf_ddt_is_l2cacheable(_db) == B_TRUE)) ||			\
+	((_db)->db_objset->os_secondary_cache == ZFS_CACHE_METADATA &&  \
+	(dbuf_is_metadata(_db)) &&					\
+	(dbuf_ddt_is_l2cacheable(_db) == B_TRUE)) ||			\
+	((dbuf_meta_is_l2cacheable(_db) == B_TRUE) &&			\
+	((_db)->db_objset->os_secondary_cache == ZFS_CACHE_DATA)))
 
 #define	DNODE_LEVEL_IS_L2CACHEABLE(_dn, _level)				\
 	((_dn)->dn_objset->os_secondary_cache == ZFS_CACHE_ALL ||	\
