mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-18 10:21:01 +03:00
5d43cc9a59
The ZFS range locking code in zfs_rlock.c/h depends on ZPL-specific data structures, specifically znode_t. However, it's also used by the ZVOL code, which uses a "dummy" znode_t to pass to the range locking code. We should clean this up so that the range locking code is generic and can be used equally by ZPL and ZVOL, and also can be used by future consumers that may need to run in userland (libzpool) as well as the kernel. Porting notes: * Added missing sys/avl.h include to sys/zfs_rlock.h. * Removed 'dbuf is within the locked range' ASSERTs from dmu_sync(). This was needed because ztest does not yet use a locked_range_t. * Removed "Approved by:" tag requirement from OpenZFS commit check to prevent needless warnings when integrating changes which has not been merged to illumos. * Reverted free_list range lock changes which were originally needed to defer the cv_destroy() which was called immediately after cv_broadcast(). Withd2733258
this should be safe but if not we may need to reintroduce this logic. * Reverts: The following two commits were reverted and squashed in to this change in order to make it easier to apply OpenZFS 9689. -d88895a0
, which removed the dummy znode from zvol_state -e3a07cd0
, which updated ztest to use range locks * Preserved optimized rangelock comparison function. Preserved the rangelock free list. The cv_destroy() function will block waiting for all processes in cv_wait() to be scheduled and drop their reference. This is done to ensure it's safe to free the condition variable. However, blocking while holding the rl->rl_lock mutex can result in a deadlock on Linux. A free list is introduced to defer the cv_destroy() and kmem_free() until after the mutex is released. Authored by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed by: Serapheim Dimitropoulos <serapheim.dimitro@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Brad Lewis <brad.lewis@delphix.com> Ported-by: Brian Behlendorf <behlendorf1@llnl.gov> OpenZFS-issue: https://illumos.org/issues/9689 OpenZFS-commit: https://github.com/openzfs/openzfs/pull/680 External-issue: DLPX-58662 Closes #7980
82 lines
2.3 KiB
C
82 lines
2.3 KiB
C
/*
|
|
* CDDL HEADER START
|
|
*
|
|
* The contents of this file are subject to the terms of the
|
|
* Common Development and Distribution License (the "License").
|
|
* You may not use this file except in compliance with the License.
|
|
*
|
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
* or http://www.opensolaris.org/os/licensing.
|
|
* See the License for the specific language governing permissions
|
|
* and limitations under the License.
|
|
*
|
|
* When distributing Covered Code, include this CDDL HEADER in each
|
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
* If applicable, add the following below this CDDL HEADER, with the
|
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
*
|
|
* CDDL HEADER END
|
|
*/
|
|
/*
|
|
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
|
* Use is subject to license terms.
|
|
*/
|
|
/*
|
|
* Copyright (c) 2018 by Delphix. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _SYS_FS_ZFS_RLOCK_H
|
|
#define _SYS_FS_ZFS_RLOCK_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <sys/avl.h>
|
|
|
|
typedef enum {
|
|
RL_READER,
|
|
RL_WRITER,
|
|
RL_APPEND
|
|
} rangelock_type_t;
|
|
|
|
struct locked_range;
|
|
|
|
typedef void (rangelock_cb_t)(struct locked_range *, void *);
|
|
|
|
typedef struct rangelock {
|
|
avl_tree_t rl_tree; /* contains locked_range_t */
|
|
kmutex_t rl_lock;
|
|
rangelock_cb_t *rl_cb;
|
|
void *rl_arg;
|
|
} rangelock_t;
|
|
|
|
typedef struct locked_range {
|
|
rangelock_t *lr_rangelock; /* rangelock that this lock applies to */
|
|
avl_node_t lr_node; /* avl node link */
|
|
uint64_t lr_offset; /* file range offset */
|
|
uint64_t lr_length; /* file range length */
|
|
uint_t lr_count; /* range reference count in tree */
|
|
rangelock_type_t lr_type; /* range type */
|
|
kcondvar_t lr_write_cv; /* cv for waiting writers */
|
|
kcondvar_t lr_read_cv; /* cv for waiting readers */
|
|
uint8_t lr_proxy; /* acting for original range */
|
|
uint8_t lr_write_wanted; /* writer wants to lock this range */
|
|
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 *);
|
|
|
|
locked_range_t *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);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _SYS_FS_ZFS_RLOCK_H */
|