Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/openzfs/module/zfs/dmu.c
Show First 20 Lines • Show All 818 Lines • ▼ Show 20 Lines | |||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
if (dmu_objset_type(os) == DMU_OST_ZFS) | if (dmu_objset_type(os) == DMU_OST_ZFS) | ||||
return (zfs_get_vfs_flag_unmounted(os)); | return (zfs_get_vfs_flag_unmounted(os)); | ||||
#endif | #endif | ||||
return (B_FALSE); | return (B_FALSE); | ||||
} | } | ||||
static int | static int | ||||
dmu_free_long_range_impl(objset_t *os, dnode_t *dn, uint64_t offset, | dmu_free_long_range_impl(objset_t *os, dnode_t *dn, uint64_t * const offset, | ||||
uint64_t length) | uint64_t * const length) | ||||
{ | { | ||||
uint64_t object_size; | uint64_t object_size; | ||||
int err; | int err; | ||||
uint64_t dirty_frees_threshold; | uint64_t dirty_frees_threshold; | ||||
dsl_pool_t *dp = dmu_objset_pool(os); | dsl_pool_t *dp = dmu_objset_pool(os); | ||||
if (dn == NULL) | if (dn == NULL) | ||||
return (SET_ERROR(EINVAL)); | return (SET_ERROR(EINVAL)); | ||||
object_size = (dn->dn_maxblkid + 1) * dn->dn_datablksz; | object_size = (dn->dn_maxblkid + 1) * dn->dn_datablksz; | ||||
if (offset >= object_size) | if (*offset >= object_size) | ||||
return (0); | return (0); | ||||
if (zfs_per_txg_dirty_frees_percent <= 100) | if (zfs_per_txg_dirty_frees_percent <= 100) | ||||
dirty_frees_threshold = | dirty_frees_threshold = | ||||
zfs_per_txg_dirty_frees_percent * zfs_dirty_data_max / 100; | zfs_per_txg_dirty_frees_percent * zfs_dirty_data_max / 100; | ||||
else | else | ||||
dirty_frees_threshold = zfs_dirty_data_max / 20; | dirty_frees_threshold = zfs_dirty_data_max / 20; | ||||
if (length == DMU_OBJECT_END || offset + length > object_size) | if (*length == DMU_OBJECT_END || *offset + *length > object_size) | ||||
length = object_size - offset; | *length = object_size - *offset; | ||||
while (length != 0) { | while (*length != 0) { | ||||
uint64_t chunk_end, chunk_begin, chunk_len; | uint64_t chunk_end, chunk_begin, chunk_len; | ||||
uint64_t l1blks; | uint64_t l1blks; | ||||
dmu_tx_t *tx; | dmu_tx_t *tx; | ||||
if (dmu_objset_zfs_unmounting(dn->dn_objset)) | if (dmu_objset_zfs_unmounting(dn->dn_objset)) | ||||
return (SET_ERROR(EINTR)); | return (SET_ERROR(EINTR)); | ||||
chunk_end = chunk_begin = offset + length; | chunk_end = chunk_begin = *offset + *length; | ||||
/* move chunk_begin backwards to the beginning of this chunk */ | /* move chunk_begin backwards to the beginning of this chunk */ | ||||
err = get_next_chunk(dn, &chunk_begin, offset, &l1blks); | err = get_next_chunk(dn, &chunk_begin, *offset, &l1blks); | ||||
if (err) | if (err) | ||||
return (err); | return (err); | ||||
ASSERT3U(chunk_begin, >=, offset); | ASSERT3U(chunk_begin, >=, *offset); | ||||
ASSERT3U(chunk_begin, <=, chunk_end); | ASSERT3U(chunk_begin, <=, chunk_end); | ||||
chunk_len = chunk_end - chunk_begin; | chunk_len = chunk_end - chunk_begin; | ||||
tx = dmu_tx_create(os); | tx = dmu_tx_create(os); | ||||
dmu_tx_hold_free(tx, dn->dn_object, chunk_begin, chunk_len); | dmu_tx_hold_free(tx, dn->dn_object, chunk_begin, chunk_len); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | while (*length != 0) { | ||||
mutex_exit(&dp->dp_lock); | mutex_exit(&dp->dp_lock); | ||||
DTRACE_PROBE3(free__long__range, | DTRACE_PROBE3(free__long__range, | ||||
uint64_t, long_free_dirty, uint64_t, chunk_len, | uint64_t, long_free_dirty, uint64_t, chunk_len, | ||||
uint64_t, txg); | uint64_t, txg); | ||||
dnode_free_range(dn, chunk_begin, chunk_len, tx); | dnode_free_range(dn, chunk_begin, chunk_len, tx); | ||||
dmu_tx_commit(tx); | dmu_tx_commit(tx); | ||||
length -= chunk_len; | *length -= chunk_len; | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
dmu_free_long_range(objset_t *os, uint64_t object, | dmu_free_long_range_ofs(objset_t *os, uint64_t object, | ||||
uint64_t offset, uint64_t length) | uint64_t *offset, uint64_t *length) | ||||
{ | { | ||||
dnode_t *dn; | dnode_t *dn; | ||||
uint64_t off, len; | |||||
int err; | int err; | ||||
err = dnode_hold(os, object, FTAG, &dn); | err = dnode_hold(os, object, FTAG, &dn); | ||||
if (err != 0) | if (err != 0) | ||||
return (err); | return (err); | ||||
err = dmu_free_long_range_impl(os, dn, offset, length); | off = *offset; | ||||
len = *length; | |||||
err = dmu_free_long_range_impl(os, dn, &off, &len); | |||||
/* | /* | ||||
* It is important to zero out the maxblkid when freeing the entire | * It is important to zero out the maxblkid when freeing the entire | ||||
* file, so that (a) subsequent calls to dmu_free_long_range_impl() | * file, so that (a) subsequent calls to dmu_free_long_range_impl() | ||||
* will take the fast path, and (b) dnode_reallocate() can verify | * will take the fast path, and (b) dnode_reallocate() can verify | ||||
* that the entire file has been freed. | * that the entire file has been freed. | ||||
*/ | */ | ||||
if (err == 0 && offset == 0 && length == DMU_OBJECT_END) | if (err == 0 && *offset == 0 && *length == DMU_OBJECT_END) | ||||
dn->dn_maxblkid = 0; | dn->dn_maxblkid = 0; | ||||
dnode_rele(dn, FTAG); | dnode_rele(dn, FTAG); | ||||
*offset = off; | |||||
*length = len; | |||||
return (err); | return (err); | ||||
} | |||||
int | |||||
dmu_free_long_range(objset_t *os, uint64_t object, | |||||
uint64_t offset, uint64_t length) | |||||
{ | |||||
return (dmu_free_long_range_ofs(os, object, &offset, &length)); | |||||
} | } | ||||
int | int | ||||
dmu_free_long_object(objset_t *os, uint64_t object) | dmu_free_long_object(objset_t *os, uint64_t object) | ||||
{ | { | ||||
dmu_tx_t *tx; | dmu_tx_t *tx; | ||||
int err; | int err; | ||||
▲ Show 20 Lines • Show All 1,399 Lines • Show Last 20 Lines |