FreeBSD ZFS
The Zettabyte File System
|
#include <sys/zfs_context.h>
#include <sys/dmu.h>
#include <sys/dmu_impl.h>
#include <sys/dbuf.h>
#include <sys/dmu_objset.h>
#include <sys/dsl_dataset.h>
#include <sys/dsl_dir.h>
#include <sys/dmu_tx.h>
#include <sys/spa.h>
#include <sys/zio.h>
#include <sys/dmu_zfetch.h>
#include <sys/sa.h>
#include <sys/sa_impl.h>
Go to the source code of this file.
Defines | |
#define | DBUF_HASH(os, obj, level, blkid) dbuf_hash(os, obj, level, blkid); |
#define | DBUF_EQUAL(dbuf, os, obj, level, blkid) |
Functions | |
static void | dbuf_destroy (dmu_buf_impl_t *db) |
static int | dbuf_undirty (dmu_buf_impl_t *db, dmu_tx_t *tx) |
Undirty a buffer, clearing dirty records. | |
static void | dbuf_write (dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx) |
Commit a dirty buffer to disk. | |
static int | dbuf_cons (void *vdb, void *unused, int kmflag) |
static void | dbuf_dest (void *vdb, void *unused) |
static uint64_t | dbuf_hash (void *os, uint64_t obj, uint8_t lvl, uint64_t blkid) |
dmu_buf_impl_t * | dbuf_find (dnode_t *dn, uint8_t level, uint64_t blkid) |
static dmu_buf_impl_t * | dbuf_hash_insert (dmu_buf_impl_t *db) |
Insert an entry into the hash table. | |
static void | dbuf_hash_remove (dmu_buf_impl_t *db) |
Remove an entry from the hash table. | |
static void | dbuf_evict_user (dmu_buf_impl_t *db) |
boolean_t | dbuf_is_metadata (dmu_buf_impl_t *db) |
void | dbuf_evict (dmu_buf_impl_t *db) |
void | dbuf_init (void) |
void | dbuf_fini (void) |
static void | dbuf_update_data (dmu_buf_impl_t *db) |
static void | dbuf_set_data (dmu_buf_impl_t *db, arc_buf_t *buf) |
Set the dbuf's buffer to the ARC buffer, including any associated state, such as db_data. | |
arc_buf_t * | dbuf_loan_arcbuf (dmu_buf_impl_t *db) |
Loan out an arc_buf for read. | |
uint64_t | dbuf_whichblock (dnode_t *dn, uint64_t offset) |
static void | dbuf_read_done (zio_t *zio, arc_buf_t *buf, void *vdb) |
static void | dbuf_read_impl (dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags) |
int | dbuf_read (dmu_buf_impl_t *db, zio_t *zio, uint32_t flags) |
static void | dbuf_noread (dmu_buf_impl_t *db) |
static void | dbuf_fix_old_data (dmu_buf_impl_t *db, uint64_t txg) |
This is our just-in-time copy function. | |
void | dbuf_unoverride (dbuf_dirty_record_t *dr) |
Signal that the dirty record is about to be re-dirtied after sync. | |
void | dbuf_free_range (dnode_t *dn, uint64_t start, uint64_t end, dmu_tx_t *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. | |
static int | dbuf_block_freeable (dmu_buf_impl_t *db) |
void | dbuf_new_size (dmu_buf_impl_t *db, int size, dmu_tx_t *tx) |
void | dbuf_release_bp (dmu_buf_impl_t *db) |
dbuf_dirty_record_t * | dbuf_dirty (dmu_buf_impl_t *db, dmu_tx_t *tx) |
Mark a dbuf as dirty. | |
void | dbuf_will_dirty (dmu_buf_impl_t *db, dmu_tx_t *tx) |
void | dmu_buf_will_not_fill (dmu_buf_t *db_fake, dmu_tx_t *tx) |
void | dmu_buf_will_fill (dmu_buf_t *db_fake, dmu_tx_t *tx) |
void | dbuf_fill_done (dmu_buf_impl_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. | |
void | dbuf_clear (dmu_buf_impl_t *db) |
"Clear" the contents of this dbuf. | |
static int | dbuf_findbp (dnode_t *dn, int level, uint64_t blkid, int fail_sparse, dmu_buf_impl_t **parentp, blkptr_t **bpp) |
static dmu_buf_impl_t * | dbuf_create (dnode_t *dn, uint8_t level, uint64_t blkid, dmu_buf_impl_t *parent, blkptr_t *blkptr) |
static int | dbuf_do_evict (void *private) |
void | dbuf_prefetch (dnode_t *dn, uint64_t blkid) |
int | dbuf_hold_impl (dnode_t *dn, uint8_t level, uint64_t blkid, int fail_sparse, void *tag, dmu_buf_impl_t **dbp) |
Returns with db_holds incremented, and db_mtx not held. | |
dmu_buf_impl_t * | dbuf_hold (dnode_t *dn, uint64_t blkid, void *tag) |
dmu_buf_impl_t * | dbuf_hold_level (dnode_t *dn, int level, uint64_t blkid, void *tag) |
void | dbuf_create_bonus (dnode_t *dn) |
int | dbuf_spill_set_blksz (dmu_buf_t *db_fake, uint64_t blksz, dmu_tx_t *tx) |
void | dbuf_rm_spill (dnode_t *dn, dmu_tx_t *tx) |
void | dbuf_add_ref (dmu_buf_impl_t *db, void *tag) |
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. | |
uint64_t | dbuf_refcount (dmu_buf_impl_t *db) |
void * | dmu_buf_set_user (dmu_buf_t *db_fake, void *user_ptr, void *user_data_ptr_ptr, dmu_buf_evict_func_t *evict_func) |
void * | dmu_buf_set_user_ie (dmu_buf_t *db_fake, void *user_ptr, void *user_data_ptr_ptr, dmu_buf_evict_func_t *evict_func) |
The same as set_user, but request immediate eviction when hold count goes to zero. | |
void * | dmu_buf_update_user (dmu_buf_t *db_fake, void *old_user_ptr, void *user_ptr, void *user_data_ptr_ptr, dmu_buf_evict_func_t *evict_func) |
void * | dmu_buf_get_user (dmu_buf_t *db_fake) |
boolean_t | dmu_buf_freeable (dmu_buf_t *dbuf) |
Tells if the given dbuf is freeable. | |
static void | dbuf_check_blkptr (dnode_t *dn, dmu_buf_impl_t *db) |
static void | dbuf_sync_indirect (dbuf_dirty_record_t *dr, dmu_tx_t *tx) |
static void | dbuf_sync_leaf (dbuf_dirty_record_t *dr, dmu_tx_t *tx) |
void | dbuf_sync_list (list_t *list, dmu_tx_t *tx) |
static void | dbuf_write_ready (zio_t *zio, arc_buf_t *buf, void *vdb) |
static void | dbuf_write_done (zio_t *zio, arc_buf_t *buf, void *vdb) |
static void | dbuf_write_nofill_ready (zio_t *zio) |
static void | dbuf_write_nofill_done (zio_t *zio) |
static void | dbuf_write_override_ready (zio_t *zio) |
static void | dbuf_write_override_done (zio_t *zio) |
Variables | |
static kmem_cache_t * | dbuf_cache |
Global data structures and functions for the dbuf cache. | |
static dbuf_hash_table_t | dbuf_hash_table |
dbuf hash table routines | |
static uint64_t | dbuf_hash_count |
static arc_evict_func_t | dbuf_do_evict |
#define DBUF_EQUAL | ( | dbuf, | |
os, | |||
obj, | |||
level, | |||
blkid | |||
) |
#define DBUF_HASH | ( | os, | |
obj, | |||
level, | |||
blkid | |||
) | dbuf_hash(os, obj, level, blkid); |
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 | ||
) |
static int dbuf_block_freeable | ( | dmu_buf_impl_t * | db | ) | [static] |
static void dbuf_check_blkptr | ( | dnode_t * | dn, |
dmu_buf_impl_t * | db | ||
) | [static] |
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()
static int dbuf_cons | ( | void * | vdb, |
void * | unused, | ||
int | kmflag | ||
) | [static] |
static dmu_buf_impl_t* dbuf_create | ( | dnode_t * | dn, |
uint8_t | level, | ||
uint64_t | blkid, | ||
dmu_buf_impl_t * | parent, | ||
blkptr_t * | blkptr | ||
) | [static] |
static void dbuf_destroy | ( | dmu_buf_impl_t * | db | ) | [static] |
dbuf_dirty_record_t* dbuf_dirty | ( | dmu_buf_impl_t * | db, |
dmu_tx_t * | tx | ||
) |
void dbuf_evict | ( | dmu_buf_impl_t * | db | ) |
static void dbuf_evict_user | ( | dmu_buf_impl_t * | db | ) | [static] |
void dbuf_fill_done | ( | dmu_buf_impl_t * | db, |
dmu_tx_t * | tx | ||
) |
dmu_buf_impl_t* dbuf_find | ( | dnode_t * | dn, |
uint8_t | level, | ||
uint64_t | blkid | ||
) |
static int dbuf_findbp | ( | dnode_t * | dn, |
int | level, | ||
uint64_t | blkid, | ||
int | fail_sparse, | ||
dmu_buf_impl_t ** | parentp, | ||
blkptr_t ** | bpp | ||
) | [static] |
static void dbuf_fix_old_data | ( | dmu_buf_impl_t * | db, |
uint64_t | txg | ||
) | [static] |
This is our just-in-time copy function.
It makes a copy of buffers that have been modified in a previous transaction group, before we modify them in the current active group.
This function is used in two places: when we are dirtying a buffer for the first time in a txg, and when we are freeing a range in a dnode that includes this buffer.
Note that when we are called from dbuf_free_range() we do not put a hold on the buffer, we just traverse the active dbuf list for the dnode.
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.
static uint64_t dbuf_hash | ( | void * | os, |
uint64_t | obj, | ||
uint8_t | lvl, | ||
uint64_t | blkid | ||
) | [static] |
static dmu_buf_impl_t* dbuf_hash_insert | ( | dmu_buf_impl_t * | db | ) | [static] |
static void dbuf_hash_remove | ( | dmu_buf_impl_t * | db | ) | [static] |
dmu_buf_impl_t* dbuf_hold | ( | dnode_t * | 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 | ( | dnode_t * | 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 | ||
) |
static void dbuf_noread | ( | dmu_buf_impl_t * | db | ) | [static] |
int dbuf_read | ( | dmu_buf_impl_t * | db, |
zio_t * | zio, | ||
uint32_t | flags | ||
) |
static void dbuf_read_impl | ( | dmu_buf_impl_t * | db, |
zio_t * | zio, | ||
uint32_t * | flags | ||
) | [static] |
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 | ) |
static void dbuf_set_data | ( | dmu_buf_impl_t * | db, |
arc_buf_t * | buf | ||
) | [static] |
static void dbuf_sync_indirect | ( | dbuf_dirty_record_t * | dr, |
dmu_tx_t * | tx | ||
) | [static] |
static void dbuf_sync_leaf | ( | dbuf_dirty_record_t * | dr, |
dmu_tx_t * | tx | ||
) | [static] |
static int dbuf_undirty | ( | dmu_buf_impl_t * | db, |
dmu_tx_t * | tx | ||
) | [static] |
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().
static void dbuf_update_data | ( | dmu_buf_impl_t * | db | ) | [static] |
void dbuf_will_dirty | ( | dmu_buf_impl_t * | db, |
dmu_tx_t * | tx | ||
) |
static void dbuf_write | ( | dbuf_dirty_record_t * | dr, |
arc_buf_t * | data, | ||
dmu_tx_t * | tx | ||
) | [static] |
static void dbuf_write_override_done | ( | zio_t * | zio | ) | [static] |
static void dbuf_write_override_ready | ( | zio_t * | zio | ) | [static] |
boolean_t dmu_buf_freeable | ( | dmu_buf_t * | dbuf | ) |
void* dmu_buf_get_user | ( | dmu_buf_t * | db | ) |
void* dmu_buf_set_user | ( | dmu_buf_t * | db, |
void * | user_ptr, | ||
void * | user_data_ptr_ptr, | ||
dmu_buf_evict_func_t * | evict_func | ||
) |
user_ptr | For use by the user and can be obtained via dmu_buf_get_user() |
user_data_ptr_ptr | Should be NULL, or a pointer to a pointer which will be set to db->db_data when the caller is allowed to access it. Note that db->db_data can change when dmu_buf_read, dmu_buf_tryupgrade, dmu_buf_will_dirty, or dmu_buf_will_fill are called. *user_data_ptr_ptr will be set to the new value when it changes. |
evict_func | If not NULL, evict_func will be called when this buffer is being excised from the cache, so that the data structure pointed to by user_data_ptr_ptr can be cleaned up. |
dmu_evict_user() will call the evict_func for all buffers in a objset with a given pageout func.
void* dmu_buf_set_user_ie | ( | dmu_buf_t * | db_fake, |
void * | user_ptr, | ||
void * | user_data_ptr_ptr, | ||
dmu_buf_evict_func_t * | evict_func | ||
) |
void* dmu_buf_update_user | ( | dmu_buf_t * | db_fake, |
void * | old_user_ptr, | ||
void * | user_ptr, | ||
void * | user_data_ptr_ptr, | ||
dmu_buf_evict_func_t * | evict_func | ||
) |
kmem_cache_t* dbuf_cache [static] |
arc_evict_func_t dbuf_do_evict [static] |
uint64_t dbuf_hash_count [static] |
dbuf_hash_table_t dbuf_hash_table [static] |