FreeBSD ZFS
The Zettabyte File System
|
#include <sys/dmu.h>
#include <sys/spa.h>
#include <sys/txg.h>
#include <sys/zio.h>
#include <sys/arc.h>
#include <sys/zfs_context.h>
#include <sys/refcount.h>
#include <sys/zrlock.h>
Go to the source code of this file.
Data Structures | |
struct | dbuf_dirty_record |
The structure of dirty records (DR) mirror the dbufs they belong to. More... | |
union | dbuf_dirty_record::dirty_types |
struct | dbuf_dirty_record::dirty_types::dirty_indirect |
struct | dbuf_dirty_record::dirty_types::dirty_leaf |
struct | dmu_buf_impl |
struct | dbuf_hash_table |
Defines | |
#define | IN_DMU_SYNC 2 |
#define | DBUF_MUTEXES 256 |
#define | DBUF_HASH_MUTEX(h, idx) (&(h)->hash_mutexes[(idx) & (DBUF_MUTEXES-1)]) |
#define | DB_DNODE(_db) ((_db)->db_dnode_handle->dnh_dnode) |
#define | DB_DNODE_LOCK(_db) ((_db)->db_dnode_handle->dnh_zrlock) |
#define | DB_DNODE_ENTER(_db) (zrl_add(&DB_DNODE_LOCK(_db))) |
#define | DB_DNODE_EXIT(_db) (zrl_remove(&DB_DNODE_LOCK(_db))) |
#define | DB_DNODE_HELD(_db) (!zrl_is_zero(&DB_DNODE_LOCK(_db))) |
#define | DB_GET_SPA(_spa_p, _db) |
#define | DB_GET_OBJSET(_os_p, _db) |
#define | DBUF_IS_METADATA(_db) (dbuf_is_metadata(_db)) |
#define | DBUF_GET_BUFC_TYPE(_db) (DBUF_IS_METADATA(_db) ? ARC_BUFC_METADATA : ARC_BUFC_DATA) |
#define | DBUF_IS_CACHEABLE(_db) |
#define | DBUF_IS_L2CACHEABLE(_db) |
#define | dprintf_dbuf(db, fmt,...) |
#define | dprintf_dbuf_bp(db, bp, fmt,...) |
#define | DBUF_VERIFY(db) |
Define flags for dbuf_read | |
#define | DB_RF_MUST_SUCCEED (1 << 0) |
#define | DB_RF_CANFAIL (1 << 1) |
#define | DB_RF_HAVESTRUCT (1 << 2) |
#define | DB_RF_NOPREFETCH (1 << 3) |
#define | DB_RF_NEVERWAIT (1 << 4) |
#define | DB_RF_CACHED (1 << 5) |
Typedefs | |
typedef enum dbuf_states | dbuf_states_t |
The simplified state transition diagram for dbufs looks like: | |
typedef enum override_states | override_states_t |
typedef struct dbuf_dirty_record | dbuf_dirty_record_t |
The structure of dirty records (DR) mirror the dbufs they belong to. | |
typedef struct dmu_buf_impl | dmu_buf_impl_t |
typedef struct dbuf_hash_table | dbuf_hash_table_t |
Enumerations | |
enum | dbuf_states { DB_UNCACHED, DB_FILL, DB_NOFILL, DB_READ, DB_CACHED, DB_EVICTING } |
The simplified state transition diagram for dbufs looks like: More... | |
enum | override_states { DR_NOT_OVERRIDDEN, DR_IN_DMU_SYNC, DR_OVERRIDDEN } |
Functions | |
uint64_t | dbuf_whichblock (struct dnode *di, uint64_t offset) |
dmu_buf_impl_t * | dbuf_create_tlib (struct dnode *dn, char *data) |
void | dbuf_create_bonus (struct dnode *dn) |
int | dbuf_spill_set_blksz (dmu_buf_t *db, uint64_t blksz, dmu_tx_t *tx) |
void | dbuf_spill_hold (struct dnode *dn, dmu_buf_impl_t **dbp, void *tag) |
void | dbuf_rm_spill (struct dnode *dn, dmu_tx_t *tx) |
dmu_buf_impl_t * | dbuf_hold (struct dnode *dn, uint64_t blkid, void *tag) |
dmu_buf_impl_t * | dbuf_hold_level (struct dnode *dn, int level, uint64_t blkid, void *tag) |
int | dbuf_hold_impl (struct dnode *dn, uint8_t level, uint64_t blkid, int create, void *tag, dmu_buf_impl_t **dbp) |
Returns with db_holds incremented, and db_mtx not held. | |
void | dbuf_prefetch (struct dnode *dn, uint64_t blkid) |
void | dbuf_add_ref (dmu_buf_impl_t *db, void *tag) |
uint64_t | dbuf_refcount (dmu_buf_impl_t *db) |
void | dbuf_rele (dmu_buf_impl_t *db, void *tag) |
void | dbuf_rele_and_unlock (dmu_buf_impl_t *db, void *tag) |
dbuf_rele() for an already-locked dbuf. | |
dmu_buf_impl_t * | dbuf_find (struct dnode *dn, uint8_t level, uint64_t blkid) |
int | dbuf_read (dmu_buf_impl_t *db, zio_t *zio, uint32_t flags) |
void | dbuf_will_dirty (dmu_buf_impl_t *db, dmu_tx_t *tx) |
void | dbuf_fill_done (dmu_buf_impl_t *db, dmu_tx_t *tx) |
void | dmu_buf_will_not_fill (dmu_buf_t *db, dmu_tx_t *tx) |
void | dmu_buf_will_fill (dmu_buf_t *db, dmu_tx_t *tx) |
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) |
Directly assign a provided arc buf to a given dbuf if it's not referenced by anybody except our caller. | |
dbuf_dirty_record_t * | dbuf_dirty (dmu_buf_impl_t *db, dmu_tx_t *tx) |
Mark a dbuf as dirty. | |
arc_buf_t * | dbuf_loan_arcbuf (dmu_buf_impl_t *db) |
Loan out an arc_buf for read. | |
void | dbuf_clear (dmu_buf_impl_t *db) |
"Clear" the contents of this dbuf. | |
void | dbuf_evict (dmu_buf_impl_t *db) |
void | dbuf_setdirty (dmu_buf_impl_t *db, dmu_tx_t *tx) |
void | dbuf_unoverride (dbuf_dirty_record_t *dr) |
Signal that the dirty record is about to be re-dirtied after sync. | |
void | dbuf_sync_list (list_t *list, dmu_tx_t *tx) |
void | dbuf_release_bp (dmu_buf_impl_t *db) |
void | dbuf_free_range (struct dnode *dn, uint64_t start, uint64_t end, struct dmu_tx *) |
Evict (if its unreferenced) or clear (if its referenced) any level-0 data blocks in the free range, so that any future readers will find empty blocks. | |
void | dbuf_new_size (dmu_buf_impl_t *db, int size, dmu_tx_t *tx) |
void | dbuf_init (void) |
void | dbuf_fini (void) |
boolean_t | dbuf_is_metadata (dmu_buf_impl_t *db) |
#define DB_DNODE_EXIT | ( | _db | ) | (zrl_remove(&DB_DNODE_LOCK(_db))) |
#define DB_DNODE_HELD | ( | _db | ) | (!zrl_is_zero(&DB_DNODE_LOCK(_db))) |
#define DB_DNODE_LOCK | ( | _db | ) | ((_db)->db_dnode_handle->dnh_zrlock) |
#define DB_GET_OBJSET | ( | _os_p, | |
_db | |||
) |
{ \ dnode_t *__dn; \ DB_DNODE_ENTER(_db); \ __dn = DB_DNODE(_db); \ *(_os_p) = __dn->dn_objset; \ DB_DNODE_EXIT(_db); \ }
#define DB_GET_SPA | ( | _spa_p, | |
_db | |||
) |
{ \ dnode_t *__dn; \ DB_DNODE_ENTER(_db); \ __dn = DB_DNODE(_db); \ *(_spa_p) = __dn->dn_objset->os_spa; \ DB_DNODE_EXIT(_db); \ }
#define DBUF_GET_BUFC_TYPE | ( | _db | ) | (DBUF_IS_METADATA(_db) ? ARC_BUFC_METADATA : ARC_BUFC_DATA) |
#define DBUF_HASH_MUTEX | ( | h, | |
idx | |||
) | (&(h)->hash_mutexes[(idx) & (DBUF_MUTEXES-1)]) |
#define DBUF_IS_CACHEABLE | ( | _db | ) |
((_db)->db_objset->os_primary_cache == ZFS_CACHE_ALL || \ (DBUF_IS_METADATA(_db) && \ ((_db)->db_objset->os_primary_cache == ZFS_CACHE_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)))
typedef struct dbuf_dirty_record dbuf_dirty_record_t |
The structure of dirty records (DR) mirror the dbufs they belong to.
That is, a dnode, its indirect blocks, and its data (leaf) blocks all have their own DRs. Each can only have one for each in-flight TXG. Each can have a parent DR, which is associated with its parent dbuf. Indirects can have child DRs, each associated with its child dbufs. Finally, the leaf DRs contain the ARC buffer containing the data to be written.
typedef struct dbuf_hash_table dbuf_hash_table_t |
typedef enum dbuf_states dbuf_states_t |
The simplified state transition diagram for dbufs looks like:
+----> READ ----+ | | | V (alloc)-->UNCACHED CACHED-->EVICTING-->(free) | ^ ^ | | | +----> FILL ----+ | | | | | +--------> NOFILL -------+
typedef struct dmu_buf_impl dmu_buf_impl_t |
typedef enum override_states override_states_t |
enum dbuf_states |
The simplified state transition diagram for dbufs looks like:
+----> READ ----+ | | | V (alloc)-->UNCACHED CACHED-->EVICTING-->(free) | ^ ^ | | | +----> FILL ----+ | | | | | +--------> NOFILL -------+
enum override_states |
void dbuf_add_ref | ( | dmu_buf_impl_t * | db, |
void * | tag | ||
) |
void dbuf_assign_arcbuf | ( | dmu_buf_impl_t * | db, |
arc_buf_t * | buf, | ||
dmu_tx_t * | tx | ||
) |
void dbuf_clear | ( | dmu_buf_impl_t * | db | ) |
"Clear" the contents of this dbuf.
This will mark the dbuf EVICTING and clear *most* of its references. Unfortunately, when we are not holding the dn_dbufs_mtx, we can't clear the entry in the dn_dbufs list. We have to wait until dbuf_destroy() in this case.
For callers from the DMU we will usually see:
For the arc callback, we will usually see:
Sometimes, though, we will get a mix of these two:
dbuf_clear()->arc_buf_evict()
dbuf_do_evict()->dbuf_destroy()
dmu_buf_impl_t* dbuf_create_tlib | ( | struct dnode * | dn, |
char * | data | ||
) |
dbuf_dirty_record_t* dbuf_dirty | ( | dmu_buf_impl_t * | db, |
dmu_tx_t * | tx | ||
) |
void dbuf_evict | ( | dmu_buf_impl_t * | db | ) |
void dbuf_fill_done | ( | dmu_buf_impl_t * | db, |
dmu_tx_t * | tx | ||
) |
dmu_buf_impl_t* dbuf_find | ( | struct dnode * | dn, |
uint8_t | level, | ||
uint64_t | blkid | ||
) |
Evict (if its unreferenced) or clear (if its referenced) any level-0 data blocks in the free range, so that any future readers will find empty blocks.
Also, if we happen accross any level-1 dbufs in the range that have not already been marked dirty, mark them dirty so they stay in memory.
dmu_buf_impl_t* dbuf_hold | ( | struct dnode * | dn, |
uint64_t | blkid, | ||
void * | tag | ||
) |
int dbuf_hold_impl | ( | dnode_t * | dn, |
uint8_t | level, | ||
uint64_t | blkid, | ||
int | fail_sparse, | ||
void * | tag, | ||
dmu_buf_impl_t ** | dbp | ||
) |
dmu_buf_impl_t* dbuf_hold_level | ( | struct dnode * | dn, |
int | level, | ||
uint64_t | blkid, | ||
void * | tag | ||
) |
boolean_t dbuf_is_metadata | ( | dmu_buf_impl_t * | db | ) |
arc_buf_t* dbuf_loan_arcbuf | ( | dmu_buf_impl_t * | db | ) |
void dbuf_new_size | ( | dmu_buf_impl_t * | db, |
int | size, | ||
dmu_tx_t * | tx | ||
) |
int dbuf_read | ( | dmu_buf_impl_t * | db, |
zio_t * | zio, | ||
uint32_t | flags | ||
) |
uint64_t dbuf_refcount | ( | dmu_buf_impl_t * | db | ) |
void dbuf_rele | ( | dmu_buf_impl_t * | db, |
void * | tag | ||
) |
void dbuf_rele_and_unlock | ( | dmu_buf_impl_t * | db, |
void * | tag | ||
) |
dbuf_rele() for an already-locked dbuf.
This is necessary to allow db_dirtycnt and db_holds to be updated atomically.
void dbuf_release_bp | ( | dmu_buf_impl_t * | db | ) |
void dbuf_setdirty | ( | dmu_buf_impl_t * | db, |
dmu_tx_t * | tx | ||
) |
void dbuf_spill_hold | ( | struct dnode * | dn, |
dmu_buf_impl_t ** | dbp, | ||
void * | tag | ||
) |
void dbuf_unoverride | ( | dbuf_dirty_record_t * | dr | ) |
Signal that the dirty record is about to be re-dirtied after sync.
This function is used to notify, if necessary, that a dbuf is about to be dirtied again after having an immediate write via dmu_sync().
uint64_t dbuf_whichblock | ( | struct dnode * | di, |
uint64_t | offset | ||
) |
void dbuf_will_dirty | ( | dmu_buf_impl_t * | db, |
dmu_tx_t * | tx | ||
) |