Protect cache lock against locking during lock deinitialization
Signed-off-by: Robert Baldyga <robert.baldyga@huawei.com> Signed-off-by: Michal Mielewczyk <michal.mielewczyk@huawei.com>
This commit is contained in:
parent
53ee7c1d3a
commit
7685b70810
@ -2317,14 +2317,14 @@ static void _ocf_mngt_cache_dealloc(void *priv)
|
|||||||
|
|
||||||
static void ocf_mngt_cache_remove(ocf_ctx_t ctx, ocf_cache_t cache)
|
static void ocf_mngt_cache_remove(ocf_ctx_t ctx, ocf_cache_t cache)
|
||||||
{
|
{
|
||||||
|
/* Deinitialize cache lock */
|
||||||
|
ocf_mngt_cache_lock_deinit(cache);
|
||||||
|
|
||||||
/* Mark device uninitialized */
|
/* Mark device uninitialized */
|
||||||
env_refcnt_freeze(&cache->refcnt.cache);
|
env_refcnt_freeze(&cache->refcnt.cache);
|
||||||
env_refcnt_register_zero_cb(&cache->refcnt.cache,
|
env_refcnt_register_zero_cb(&cache->refcnt.cache,
|
||||||
_ocf_mngt_cache_dealloc, cache);
|
_ocf_mngt_cache_dealloc, cache);
|
||||||
|
|
||||||
/* Deinitialize locks */
|
|
||||||
ocf_mngt_cache_lock_deinit(cache);
|
|
||||||
|
|
||||||
env_spinlock_destroy(&cache->io_queues_lock);
|
env_spinlock_destroy(&cache->io_queues_lock);
|
||||||
|
|
||||||
env_mutex_destroy(&cache->flush_mutex);
|
env_mutex_destroy(&cache->flush_mutex);
|
||||||
|
@ -238,9 +238,15 @@ static void _ocf_mngt_cache_lock(ocf_cache_t cache,
|
|||||||
if (ocf_mngt_cache_get(cache))
|
if (ocf_mngt_cache_get(cache))
|
||||||
OCF_CMPL_RET(cache, priv, -OCF_ERR_CACHE_NOT_EXIST);
|
OCF_CMPL_RET(cache, priv, -OCF_ERR_CACHE_NOT_EXIST);
|
||||||
|
|
||||||
|
if (!env_refcnt_inc(&cache->refcnt.lock)) {
|
||||||
|
ocf_mngt_cache_put(cache);
|
||||||
|
OCF_CMPL_RET(cache, priv, -OCF_ERR_CACHE_NOT_EXIST);
|
||||||
|
}
|
||||||
|
|
||||||
waiter = ocf_async_lock_new_waiter(&cache->lock,
|
waiter = ocf_async_lock_new_waiter(&cache->lock,
|
||||||
_ocf_mngt_cache_lock_complete);
|
_ocf_mngt_cache_lock_complete);
|
||||||
if (!waiter) {
|
if (!waiter) {
|
||||||
|
env_refcnt_dec(&cache->refcnt.lock);
|
||||||
ocf_mngt_cache_put(cache);
|
ocf_mngt_cache_put(cache);
|
||||||
OCF_CMPL_RET(cache, priv, -OCF_ERR_NO_MEM);
|
OCF_CMPL_RET(cache, priv, -OCF_ERR_NO_MEM);
|
||||||
}
|
}
|
||||||
@ -252,20 +258,26 @@ static void _ocf_mngt_cache_lock(ocf_cache_t cache,
|
|||||||
context->priv = priv;
|
context->priv = priv;
|
||||||
|
|
||||||
lock_fn(waiter);
|
lock_fn(waiter);
|
||||||
|
env_refcnt_dec(&cache->refcnt.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _ocf_mngt_cache_trylock(ocf_cache_t cache,
|
static int _ocf_mngt_cache_trylock(ocf_cache_t cache,
|
||||||
ocf_trylock_fn_t trylock_fn, ocf_unlock_fn_t unlock_fn)
|
ocf_trylock_fn_t trylock_fn, ocf_unlock_fn_t unlock_fn)
|
||||||
{
|
{
|
||||||
int result;
|
int result = 0;
|
||||||
|
|
||||||
if (ocf_mngt_cache_get(cache))
|
if (ocf_mngt_cache_get(cache))
|
||||||
return -OCF_ERR_CACHE_NOT_EXIST;
|
return -OCF_ERR_CACHE_NOT_EXIST;
|
||||||
|
|
||||||
|
if (!env_refcnt_inc(&cache->refcnt.lock)) {
|
||||||
|
ocf_mngt_cache_put(cache);
|
||||||
|
return -OCF_ERR_CACHE_NOT_EXIST;
|
||||||
|
}
|
||||||
|
|
||||||
result = trylock_fn(&cache->lock);
|
result = trylock_fn(&cache->lock);
|
||||||
if (result) {
|
if (result) {
|
||||||
ocf_mngt_cache_put(cache);
|
ocf_mngt_cache_put(cache);
|
||||||
return result;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env_bit_test(ocf_cache_state_stopping, &cache->cache_state)) {
|
if (env_bit_test(ocf_cache_state_stopping, &cache->cache_state)) {
|
||||||
@ -274,6 +286,8 @@ static int _ocf_mngt_cache_trylock(ocf_cache_t cache,
|
|||||||
result = -OCF_ERR_CACHE_NOT_EXIST;
|
result = -OCF_ERR_CACHE_NOT_EXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
env_refcnt_dec(&cache->refcnt.lock);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,13 +300,38 @@ static void _ocf_mngt_cache_unlock(ocf_cache_t cache,
|
|||||||
|
|
||||||
int ocf_mngt_cache_lock_init(ocf_cache_t cache)
|
int ocf_mngt_cache_lock_init(ocf_cache_t cache)
|
||||||
{
|
{
|
||||||
return ocf_async_lock_init(&cache->lock,
|
int result;
|
||||||
|
|
||||||
|
result = env_refcnt_init(&cache->refcnt.lock, "lock", sizeof("lock"));
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = ocf_async_lock_init(&cache->lock,
|
||||||
sizeof(struct ocf_mngt_cache_lock_context));
|
sizeof(struct ocf_mngt_cache_lock_context));
|
||||||
|
if (result)
|
||||||
|
env_refcnt_deinit(&cache->refcnt.lock);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _ocf_mngt_cache_lock_deinit(void *priv)
|
||||||
|
{
|
||||||
|
ocf_cache_t cache = priv;
|
||||||
|
|
||||||
|
ocf_async_lock_deinit(&cache->lock);
|
||||||
|
env_refcnt_dec(&cache->refcnt.cache);
|
||||||
|
env_refcnt_deinit(&cache->refcnt.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ocf_mngt_cache_lock_deinit(ocf_cache_t cache)
|
void ocf_mngt_cache_lock_deinit(ocf_cache_t cache)
|
||||||
{
|
{
|
||||||
ocf_async_lock_deinit(&cache->lock);
|
bool cache_get;
|
||||||
|
|
||||||
|
cache_get = env_refcnt_inc(&cache->refcnt.cache);
|
||||||
|
ENV_BUG_ON(!cache_get);
|
||||||
|
env_refcnt_freeze(&cache->refcnt.lock);
|
||||||
|
env_refcnt_register_zero_cb(&cache->refcnt.lock,
|
||||||
|
_ocf_mngt_cache_lock_deinit, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ocf_mngt_cache_lock(ocf_cache_t cache,
|
void ocf_mngt_cache_lock(ocf_cache_t cache,
|
||||||
|
@ -86,6 +86,9 @@ struct ocf_cache {
|
|||||||
struct env_refcnt metadata;
|
struct env_refcnt metadata;
|
||||||
/* # of requests in d2c mode */
|
/* # of requests in d2c mode */
|
||||||
struct env_refcnt d2c;
|
struct env_refcnt d2c;
|
||||||
|
/* # of unsettled cache lock operations (lock not acquired,
|
||||||
|
* waiter not added yet) */
|
||||||
|
struct env_refcnt lock;
|
||||||
} refcnt;
|
} refcnt;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user