uint8_t lr_read_wanted; /* reader wants to lock this range */
} locked_range_t;
-void rangelock_init(rangelock_t *, rangelock_cb_t *, void *);
-void rangelock_fini(rangelock_t *);
+void zfs_rangelock_init(rangelock_t *, rangelock_cb_t *, void *);
+void zfs_rangelock_fini(rangelock_t *);
-locked_range_t *rangelock_enter(rangelock_t *,
+locked_range_t *zfs_rangelock_enter(rangelock_t *,
uint64_t, uint64_t, rangelock_type_t);
-void rangelock_exit(locked_range_t *);
-void rangelock_reduce(locked_range_t *, uint64_t, uint64_t);
+void zfs_rangelock_exit(locked_range_t *);
+void zfs_rangelock_reduce(locked_range_t *, uint64_t, uint64_t);
#ifdef __cplusplus
}
/*
* Lock the range against changes.
*/
- locked_range_t *lr = rangelock_enter(&zp->z_rangelock,
+ locked_range_t *lr = zfs_rangelock_enter(&zp->z_rangelock,
uio->uio_loffset, uio->uio_resid, RL_READER);
/*
dataset_kstats_update_read_kstats(&zfsvfs->z_kstat, nread);
task_io_account_read(nread);
out:
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
ZFS_EXIT(zfsvfs);
return (error);
* Obtain an appending range lock to guarantee file append
* semantics. We reset the write offset once we have the lock.
*/
- lr = rangelock_enter(&zp->z_rangelock, 0, n, RL_APPEND);
+ lr = zfs_rangelock_enter(&zp->z_rangelock, 0, n, RL_APPEND);
woff = lr->lr_offset;
if (lr->lr_length == UINT64_MAX) {
/*
* this write, then this range lock will lock the entire file
* so that we can re-write the block safely.
*/
- lr = rangelock_enter(&zp->z_rangelock, woff, n, RL_WRITER);
+ lr = zfs_rangelock_enter(&zp->z_rangelock, woff, n, RL_WRITER);
}
if (woff >= limit) {
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
ZFS_EXIT(zfsvfs);
return (SET_ERROR(EFBIG));
}
new_blksz = MIN(end_size, max_blksz);
}
zfs_grow_blocksize(zp, new_blksz, tx);
- rangelock_reduce(lr, woff, n);
+ zfs_rangelock_reduce(lr, woff, n);
}
/*
}
zfs_inode_update(zp);
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
/*
* If we're in replay mode, or we made no progress, return error.
if (zgd->zgd_db)
dmu_buf_rele(zgd->zgd_db, zgd);
- rangelock_exit(zgd->zgd_lr);
+ zfs_rangelock_exit(zgd->zgd_lr);
/*
* Release the vnode asynchronously as we currently have the
* we don't have to write the data twice.
*/
if (buf != NULL) { /* immediate write */
- zgd->zgd_lr = rangelock_enter(&zp->z_rangelock,
+ zgd->zgd_lr = zfs_rangelock_enter(&zp->z_rangelock,
offset, size, RL_READER);
/* test for truncation needs to be done while range locked */
if (offset >= zp->z_size) {
size = zp->z_blksz;
blkoff = ISP2(size) ? P2PHASE(offset, size) : offset;
offset -= blkoff;
- zgd->zgd_lr = rangelock_enter(&zp->z_rangelock,
+ zgd->zgd_lr = zfs_rangelock_enter(&zp->z_rangelock,
offset, size, RL_READER);
if (zp->z_blksz == size)
break;
offset += blkoff;
- rangelock_exit(zgd->zgd_lr);
+ zfs_rangelock_exit(zgd->zgd_lr);
}
/* test for truncation needs to be done while range locked */
if (lr->lr_offset >= zp->z_size)
redirty_page_for_writepage(wbc, pp);
unlock_page(pp);
- locked_range_t *lr = rangelock_enter(&zp->z_rangelock,
+ locked_range_t *lr = zfs_rangelock_enter(&zp->z_rangelock,
pgoff, pglen, RL_WRITER);
lock_page(pp);
/* Page mapping changed or it was no longer dirty, we're done */
if (unlikely((mapping != pp->mapping) || !PageDirty(pp))) {
unlock_page(pp);
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
ZFS_EXIT(zfsvfs);
return (0);
}
/* Another process started write block if required */
if (PageWriteback(pp)) {
unlock_page(pp);
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
if (wbc->sync_mode != WB_SYNC_NONE) {
if (PageWriteback(pp))
/* Clear the dirty flag the required locks are held */
if (!clear_page_dirty_for_io(pp)) {
unlock_page(pp);
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
ZFS_EXIT(zfsvfs);
return (0);
}
__set_page_dirty_nobuffers(pp);
ClearPageError(pp);
end_page_writeback(pp);
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
ZFS_EXIT(zfsvfs);
return (err);
}
zfs_putpage_commit_cb, pp);
dmu_tx_commit(tx);
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
if (wbc->sync_mode != WB_SYNC_NONE) {
/*
mutex_init(&zp->z_acl_lock, NULL, MUTEX_DEFAULT, NULL);
rw_init(&zp->z_xattr_lock, NULL, RW_DEFAULT, NULL);
- rangelock_init(&zp->z_rangelock, zfs_rangelock_cb, zp);
+ zfs_rangelock_init(&zp->z_rangelock, zfs_rangelock_cb, zp);
zp->z_dirlocks = NULL;
zp->z_acl_cached = NULL;
rw_destroy(&zp->z_name_lock);
mutex_destroy(&zp->z_acl_lock);
rw_destroy(&zp->z_xattr_lock);
- rangelock_fini(&zp->z_rangelock);
+ zfs_rangelock_fini(&zp->z_rangelock);
ASSERT(zp->z_dirlocks == NULL);
ASSERT(zp->z_acl_cached == NULL);
/*
* We will change zp_size, lock the whole file.
*/
- lr = rangelock_enter(&zp->z_rangelock, 0, UINT64_MAX, RL_WRITER);
+ lr = zfs_rangelock_enter(&zp->z_rangelock, 0, UINT64_MAX, RL_WRITER);
/*
* Nothing to do if file already at desired length.
*/
if (end <= zp->z_size) {
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
return (0);
}
tx = dmu_tx_create(zfsvfs->z_os);
error = dmu_tx_assign(tx, TXG_WAIT);
if (error) {
dmu_tx_abort(tx);
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
return (error);
}
VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(ZTOZSB(zp)),
&zp->z_size, sizeof (zp->z_size), tx));
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
dmu_tx_commit(tx);
/*
* Lock the range being freed.
*/
- lr = rangelock_enter(&zp->z_rangelock, off, len, RL_WRITER);
+ lr = zfs_rangelock_enter(&zp->z_rangelock, off, len, RL_WRITER);
/*
* Nothing to do if file already at desired length.
*/
if (off >= zp->z_size) {
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
return (0);
}
page_len);
}
}
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
return (error);
}
/*
* We will change zp_size, lock the whole file.
*/
- lr = rangelock_enter(&zp->z_rangelock, 0, UINT64_MAX, RL_WRITER);
+ lr = zfs_rangelock_enter(&zp->z_rangelock, 0, UINT64_MAX, RL_WRITER);
/*
* Nothing to do if file already at desired length.
*/
if (end >= zp->z_size) {
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
return (0);
}
error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, end,
DMU_OBJECT_END);
if (error) {
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
return (error);
}
tx = dmu_tx_create(zfsvfs->z_os);
error = dmu_tx_assign(tx, TXG_WAIT);
if (error) {
dmu_tx_abort(tx);
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
return (error);
}
VERIFY(sa_bulk_update(zp->z_sa_hdl, bulk, count, tx) == 0);
dmu_tx_commit(tx);
- rangelock_exit(lr);
+ zfs_rangelock_exit(lr);
return (0);
}
if (error)
break;
}
- rangelock_exit(zvr->lr);
+ zfs_rangelock_exit(zvr->lr);
int64_t nwritten = start_resid - uio.uio_resid;
dataset_kstats_update_write_kstats(&zv->zv_zso->zvo_kstat, nwritten);
ZVOL_OBJ, start, size);
}
unlock:
- rangelock_exit(zvr->lr);
+ zfs_rangelock_exit(zvr->lr);
if (error == 0 && sync)
zil_commit(zv->zv_zilog, ZVOL_OBJ);
break;
}
}
- rangelock_exit(zvr->lr);
+ zfs_rangelock_exit(zvr->lr);
int64_t nread = start_resid - uio.uio_resid;
dataset_kstats_update_read_kstats(&zv->zv_zso->zvo_kstat, nread);
* are asynchronous, we take it here synchronously to make
* sure overlapped I/Os are properly ordered.
*/
- zvr->lr = rangelock_enter(&zv->zv_rangelock, offset, size,
+ zvr->lr = zfs_rangelock_enter(&zv->zv_rangelock, offset, size,
RL_WRITER);
/*
* Sync writes and discards execute zil_commit() which may need
rw_enter(&zv->zv_suspend_lock, RW_READER);
- zvr->lr = rangelock_enter(&zv->zv_rangelock, offset, size,
+ zvr->lr = zfs_rangelock_enter(&zv->zv_rangelock, offset, size,
RL_READER);
if (zvol_request_sync || taskq_dispatch(zvol_taskq,
zvol_read, zvr, TQ_SLEEP) == TASKQID_INVALID)
zv->zv_open_count = 0;
strlcpy(zv->zv_name, name, MAXNAMELEN);
- rangelock_init(&zv->zv_rangelock, NULL, NULL);
+ zfs_rangelock_init(&zv->zv_rangelock, NULL, NULL);
rw_init(&zv->zv_suspend_lock, NULL, RW_DEFAULT, NULL);
zv->zv_zso->zvo_disk->major = zvol_major;
ASSERT(zv->zv_zso->zvo_disk->private_data == NULL);
rw_destroy(&zv->zv_suspend_lock);
- rangelock_fini(&zv->zv_rangelock);
+ zfs_rangelock_fini(&zv->zv_rangelock);
del_gendisk(zv->zv_zso->zvo_disk);
blk_cleanup_queue(zv->zv_zso->zvo_queue);
* Locks are ordered on the start offset of the range.
*/
static int
-rangelock_compare(const void *arg1, const void *arg2)
+zfs_rangelock_compare(const void *arg1, const void *arg2)
{
const locked_range_t *rl1 = (const locked_range_t *)arg1;
const locked_range_t *rl2 = (const locked_range_t *)arg2;
* and may increase the range that's locked for RL_WRITER.
*/
void
-rangelock_init(rangelock_t *rl, rangelock_cb_t *cb, void *arg)
+zfs_rangelock_init(rangelock_t *rl, rangelock_cb_t *cb, void *arg)
{
mutex_init(&rl->rl_lock, NULL, MUTEX_DEFAULT, NULL);
- avl_create(&rl->rl_tree, rangelock_compare,
+ avl_create(&rl->rl_tree, zfs_rangelock_compare,
sizeof (locked_range_t), offsetof(locked_range_t, lr_node));
rl->rl_cb = cb;
rl->rl_arg = arg;
}
void
-rangelock_fini(rangelock_t *rl)
+zfs_rangelock_fini(rangelock_t *rl)
{
mutex_destroy(&rl->rl_lock);
avl_destroy(&rl->rl_tree);
* Check if a write lock can be grabbed, or wait and recheck until available.
*/
static void
-rangelock_enter_writer(rangelock_t *rl, locked_range_t *new)
+zfs_rangelock_enter_writer(rangelock_t *rl, locked_range_t *new)
{
avl_tree_t *tree = &rl->rl_tree;
locked_range_t *lr;
* a proxy and return the proxy.
*/
static locked_range_t *
-rangelock_proxify(avl_tree_t *tree, locked_range_t *lr)
+zfs_rangelock_proxify(avl_tree_t *tree, locked_range_t *lr)
{
locked_range_t *proxy;
* returning the *front* proxy.
*/
static locked_range_t *
-rangelock_split(avl_tree_t *tree, locked_range_t *lr, uint64_t off)
+zfs_rangelock_split(avl_tree_t *tree, locked_range_t *lr, uint64_t off)
{
ASSERT3U(lr->lr_length, >, 1);
ASSERT3U(off, >, lr->lr_offset);
rear->lr_write_wanted = B_FALSE;
rear->lr_read_wanted = B_FALSE;
- locked_range_t *front = rangelock_proxify(tree, lr);
+ locked_range_t *front = zfs_rangelock_proxify(tree, lr);
front->lr_length = off - lr->lr_offset;
avl_insert_here(tree, rear, front, AVL_AFTER);
* Create and add a new proxy range lock for the supplied range.
*/
static void
-rangelock_new_proxy(avl_tree_t *tree, uint64_t off, uint64_t len)
+zfs_rangelock_new_proxy(avl_tree_t *tree, uint64_t off, uint64_t len)
{
ASSERT(len != 0);
locked_range_t *lr = kmem_alloc(sizeof (locked_range_t), KM_SLEEP);
}
static void
-rangelock_add_reader(avl_tree_t *tree, locked_range_t *new,
+zfs_rangelock_add_reader(avl_tree_t *tree, locked_range_t *new,
locked_range_t *prev, avl_index_t where)
{
locked_range_t *next;
* convert to proxy if needed then
* split this entry and bump ref count
*/
- prev = rangelock_split(tree, prev, off);
+ prev = zfs_rangelock_split(tree, prev, off);
prev = AVL_NEXT(tree, prev); /* move to rear range */
}
}
if (off < next->lr_offset) {
/* Add a proxy for initial range before the overlap */
- rangelock_new_proxy(tree, off, next->lr_offset - off);
+ zfs_rangelock_new_proxy(tree, off, next->lr_offset - off);
}
new->lr_count = 0; /* will use proxies in tree */
/* there's a gap */
ASSERT3U(next->lr_offset, >,
prev->lr_offset + prev->lr_length);
- rangelock_new_proxy(tree,
+ zfs_rangelock_new_proxy(tree,
prev->lr_offset + prev->lr_length,
next->lr_offset -
(prev->lr_offset + prev->lr_length));
}
if (off + len == next->lr_offset + next->lr_length) {
/* exact overlap with end */
- next = rangelock_proxify(tree, next);
+ next = zfs_rangelock_proxify(tree, next);
next->lr_count++;
return;
}
if (off + len < next->lr_offset + next->lr_length) {
/* new range ends in the middle of this block */
- next = rangelock_split(tree, next, off + len);
+ next = zfs_rangelock_split(tree, next, off + len);
next->lr_count++;
return;
}
ASSERT3U(off + len, >, next->lr_offset + next->lr_length);
- next = rangelock_proxify(tree, next);
+ next = zfs_rangelock_proxify(tree, next);
next->lr_count++;
}
/* Add the remaining end range. */
- rangelock_new_proxy(tree, prev->lr_offset + prev->lr_length,
+ zfs_rangelock_new_proxy(tree, prev->lr_offset + prev->lr_length,
(off + len) - (prev->lr_offset + prev->lr_length));
}
* Check if a reader lock can be grabbed, or wait and recheck until available.
*/
static void
-rangelock_enter_reader(rangelock_t *rl, locked_range_t *new)
+zfs_rangelock_enter_reader(rangelock_t *rl, locked_range_t *new)
{
avl_tree_t *tree = &rl->rl_tree;
locked_range_t *prev, *next;
* Add the read lock, which may involve splitting existing
* locks and bumping ref counts (r_count).
*/
- rangelock_add_reader(tree, new, prev, where);
+ zfs_rangelock_add_reader(tree, new, prev, where);
}
/*
* entire file is locked as RL_WRITER).
*/
locked_range_t *
-rangelock_enter(rangelock_t *rl, uint64_t off, uint64_t len,
+zfs_rangelock_enter(rangelock_t *rl, uint64_t off, uint64_t len,
rangelock_type_t type)
{
ASSERT(type == RL_READER || type == RL_WRITER || type == RL_APPEND);
if (avl_numnodes(&rl->rl_tree) == 0)
avl_add(&rl->rl_tree, new);
else
- rangelock_enter_reader(rl, new);
- } else
- rangelock_enter_writer(rl, new); /* RL_WRITER or RL_APPEND */
+ zfs_rangelock_enter_reader(rl, new);
+ } else {
+ /* RL_WRITER or RL_APPEND */
+ zfs_rangelock_enter_writer(rl, new);
+ }
mutex_exit(&rl->rl_lock);
return (new);
}
* Safely free the locked_range_t.
*/
static void
-rangelock_free(locked_range_t *lr)
+zfs_rangelock_free(locked_range_t *lr)
{
if (lr->lr_write_wanted)
cv_destroy(&lr->lr_write_cv);
* Unlock a reader lock
*/
static void
-rangelock_exit_reader(rangelock_t *rl, locked_range_t *remove,
+zfs_rangelock_exit_reader(rangelock_t *rl, locked_range_t *remove,
list_t *free_list)
{
avl_tree_t *tree = &rl->rl_tree;
* Unlock range and destroy range lock structure.
*/
void
-rangelock_exit(locked_range_t *lr)
+zfs_rangelock_exit(locked_range_t *lr)
{
rangelock_t *rl = lr->lr_rangelock;
list_t free_list;
* lock may be shared, let rangelock_exit_reader()
* release the lock and free the locked_range_t.
*/
- rangelock_exit_reader(rl, lr, &free_list);
+ zfs_rangelock_exit_reader(rl, lr, &free_list);
}
mutex_exit(&rl->rl_lock);
while ((free_lr = list_remove_head(&free_list)) != NULL)
- rangelock_free(free_lr);
+ zfs_rangelock_free(free_lr);
list_destroy(&free_list);
}
* entry in the tree.
*/
void
-rangelock_reduce(locked_range_t *lr, uint64_t off, uint64_t len)
+zfs_rangelock_reduce(locked_range_t *lr, uint64_t off, uint64_t len)
{
rangelock_t *rl = lr->lr_rangelock;
}
#if defined(_KERNEL)
-EXPORT_SYMBOL(rangelock_init);
-EXPORT_SYMBOL(rangelock_fini);
-EXPORT_SYMBOL(rangelock_enter);
-EXPORT_SYMBOL(rangelock_exit);
-EXPORT_SYMBOL(rangelock_reduce);
+EXPORT_SYMBOL(zfs_rangelock_init);
+EXPORT_SYMBOL(zfs_rangelock_fini);
+EXPORT_SYMBOL(zfs_rangelock_enter);
+EXPORT_SYMBOL(zfs_rangelock_exit);
+EXPORT_SYMBOL(zfs_rangelock_reduce);
#endif
if (zgd->zgd_db)
dmu_buf_rele(zgd->zgd_db, zgd);
- rangelock_exit(zgd->zgd_lr);
+ zfs_rangelock_exit(zgd->zgd_lr);
kmem_free(zgd, sizeof (zgd_t));
}
* we don't have to write the data twice.
*/
if (buf != NULL) { /* immediate write */
- zgd->zgd_lr = rangelock_enter(&zv->zv_rangelock, offset, size,
- RL_READER);
+ zgd->zgd_lr = zfs_rangelock_enter(&zv->zv_rangelock, offset,
+ size, RL_READER);
error = dmu_read_by_dnode(zv->zv_dn, offset, size, buf,
DMU_READ_NO_PREFETCH);
} else { /* indirect write */
*/
size = zv->zv_volblocksize;
offset = P2ALIGN_TYPED(offset, size, uint64_t);
- zgd->zgd_lr = rangelock_enter(&zv->zv_rangelock, offset, size,
- RL_READER);
+ zgd->zgd_lr = zfs_rangelock_enter(&zv->zv_rangelock, offset,
+ size, RL_READER);
error = dmu_buf_hold_by_dnode(zv->zv_dn, offset, zgd, &db,
DMU_READ_NO_PREFETCH);
if (error == 0) {