Add cache locking functions in trylock variant
- Add cache trylock and read trylock functions. - Introduce new error code -OCF_ERR_NO_LOCK. - Change trylock functions in env to return this code in case of lock contention. [ENV CHANGES REQUIRED] Following functions should return 0 on success or -OCF_ERR_NO_LOCK in case of lock contention: - env_mutex_trylock() - env_rwsem_up_read_trylock() - env_rwsem_up_write_trylock() Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
This commit is contained in:
parent
71d30e948d
commit
9b9b965b55
23
env/posix/ocf_env.h
vendored
23
env/posix/ocf_env.h
vendored
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include "ocf_env_list.h"
|
#include "ocf_env_list.h"
|
||||||
#include "ocf_env_headers.h"
|
#include "ocf_env_headers.h"
|
||||||
|
#include "ocf/ocf_err.h"
|
||||||
|
|
||||||
/* linux sector 512-bytes */
|
/* linux sector 512-bytes */
|
||||||
#define ENV_SECTOR_SHIFT 9
|
#define ENV_SECTOR_SHIFT 9
|
||||||
@ -146,9 +147,7 @@ static inline int env_mutex_lock_interruptible(env_mutex *mutex)
|
|||||||
|
|
||||||
static inline int env_mutex_trylock(env_mutex *mutex)
|
static inline int env_mutex_trylock(env_mutex *mutex)
|
||||||
{
|
{
|
||||||
if (pthread_mutex_trylock(&mutex->m) == 0)
|
return pthread_mutex_trylock(&mutex->m) ? -OCF_ERR_NO_LOCK : 0;
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void env_mutex_unlock(env_mutex *mutex)
|
static inline void env_mutex_unlock(env_mutex *mutex)
|
||||||
@ -158,7 +157,7 @@ static inline void env_mutex_unlock(env_mutex *mutex)
|
|||||||
|
|
||||||
static inline int env_mutex_is_locked(env_mutex *mutex)
|
static inline int env_mutex_is_locked(env_mutex *mutex)
|
||||||
{
|
{
|
||||||
if (env_mutex_trylock(mutex)) {
|
if (env_mutex_trylock(mutex) == 0) {
|
||||||
env_mutex_unlock(mutex);
|
env_mutex_unlock(mutex);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -223,12 +222,7 @@ static inline void env_rwsem_down_read(env_rwsem *s)
|
|||||||
|
|
||||||
static inline int env_rwsem_down_read_trylock(env_rwsem *s)
|
static inline int env_rwsem_down_read_trylock(env_rwsem *s)
|
||||||
{
|
{
|
||||||
int result = pthread_rwlock_tryrdlock(&s->lock);
|
return pthread_rwlock_tryrdlock(&s->lock) ? -OCF_ERR_NO_LOCK : 0;
|
||||||
|
|
||||||
if (result == 0)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void env_rwsem_up_write(env_rwsem *s)
|
static inline void env_rwsem_up_write(env_rwsem *s)
|
||||||
@ -243,17 +237,12 @@ static inline void env_rwsem_down_write(env_rwsem *s)
|
|||||||
|
|
||||||
static inline int env_rwsem_down_write_trylock(env_rwsem *s)
|
static inline int env_rwsem_down_write_trylock(env_rwsem *s)
|
||||||
{
|
{
|
||||||
int result = pthread_rwlock_trywrlock(&s->lock);
|
return pthread_rwlock_trywrlock(&s->lock) ? -OCF_ERR_NO_LOCK : 0;
|
||||||
|
|
||||||
if (result == 0)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int env_rwsem_is_locked(env_rwsem *s)
|
static inline int env_rwsem_is_locked(env_rwsem *s)
|
||||||
{
|
{
|
||||||
if (env_rwsem_down_read_trylock(s)) {
|
if (env_rwsem_down_read_trylock(s) == 0) {
|
||||||
env_rwsem_up_read(s);
|
env_rwsem_up_read(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -18,21 +18,24 @@ typedef enum {
|
|||||||
/** Invalid input parameter value */
|
/** Invalid input parameter value */
|
||||||
OCF_ERR_INVAL = 1000000,
|
OCF_ERR_INVAL = 1000000,
|
||||||
|
|
||||||
/** Invalid volume type */
|
|
||||||
OCF_ERR_INVAL_VOLUME_TYPE,
|
|
||||||
|
|
||||||
/** Operation interrupted */
|
/** Operation interrupted */
|
||||||
OCF_ERR_INTR,
|
OCF_ERR_INTR,
|
||||||
|
|
||||||
|
/** Out of memory */
|
||||||
|
OCF_ERR_NO_MEM,
|
||||||
|
|
||||||
|
/** Lock not acquired */
|
||||||
|
OCF_ERR_NO_LOCK,
|
||||||
|
|
||||||
|
/** Invalid volume type */
|
||||||
|
OCF_ERR_INVAL_VOLUME_TYPE,
|
||||||
|
|
||||||
/** Unknown error occurred */
|
/** Unknown error occurred */
|
||||||
OCF_ERR_UNKNOWN,
|
OCF_ERR_UNKNOWN,
|
||||||
|
|
||||||
/*!< To many caches */
|
/*!< To many caches */
|
||||||
OCF_ERR_TOO_MANY_CACHES,
|
OCF_ERR_TOO_MANY_CACHES,
|
||||||
|
|
||||||
/** Out of memory */
|
|
||||||
OCF_ERR_NO_MEM,
|
|
||||||
|
|
||||||
/** Not enough RAM to start cache */
|
/** Not enough RAM to start cache */
|
||||||
OCF_ERR_NO_FREE_RAM,
|
OCF_ERR_NO_FREE_RAM,
|
||||||
|
|
||||||
|
@ -124,6 +124,34 @@ int ocf_mngt_cache_lock(ocf_cache_t cache);
|
|||||||
*/
|
*/
|
||||||
int ocf_mngt_cache_read_lock(ocf_cache_t cache);
|
int ocf_mngt_cache_read_lock(ocf_cache_t cache);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Lock cache for management oparations (write lock, exclusive)
|
||||||
|
*
|
||||||
|
* @param[in] cache Handle to cache
|
||||||
|
*
|
||||||
|
* @retval 0 Cache successfully locked
|
||||||
|
* @retval -OCF_ERR_CACHE_NOT_EXIST Can not lock cache - cache is already
|
||||||
|
* stopping
|
||||||
|
* @retval -OCF_ERR_CACHE_IN_USE Can not lock cache - cache is in use
|
||||||
|
* @retval -OCF_ERR_NO_LOCK Lock not acquired
|
||||||
|
*/
|
||||||
|
int ocf_mngt_cache_trylock(ocf_cache_t cache);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Lock cache for read - assures cache config does not change while
|
||||||
|
* lock is being held, while allowing other users to acquire
|
||||||
|
* read lock in parallel.
|
||||||
|
*
|
||||||
|
* @param[in] cache Handle to cache
|
||||||
|
*
|
||||||
|
* @retval 0 Cache successfully locked
|
||||||
|
* @retval -OCF_ERR_CACHE_NOT_EXIST Can not lock cache - cache is already
|
||||||
|
* stopping
|
||||||
|
* @retval -OCF_ERR_CACHE_IN_USE Can not lock cache - cache is in use
|
||||||
|
* @retval -OCF_ERR_NO_LOCK Lock not acquired
|
||||||
|
*/
|
||||||
|
int ocf_mngt_cache_read_trylock(ocf_cache_t cache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Write-unlock cache
|
* @brief Write-unlock cache
|
||||||
*
|
*
|
||||||
|
@ -133,7 +133,7 @@ void ocf_cleaner_run(ocf_cleaner_t cleaner, ocf_queue_t queue)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Sleep in case there is management operation in progress. */
|
/* Sleep in case there is management operation in progress. */
|
||||||
if (env_rwsem_down_write_trylock(&cache->lock) == 0) {
|
if (env_rwsem_down_write_trylock(&cache->lock)) {
|
||||||
cleaner->end(cleaner, SLEEP_TIME_MS);
|
cleaner->end(cleaner, SLEEP_TIME_MS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ static inline void ocf_metadata_unlock(struct ocf_cache *cache, int rw)
|
|||||||
|
|
||||||
static inline int ocf_metadata_try_lock(struct ocf_cache *cache, int rw)
|
static inline int ocf_metadata_try_lock(struct ocf_cache *cache, int rw)
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result = 0;
|
||||||
|
|
||||||
if (rw == OCF_METADATA_WR) {
|
if (rw == OCF_METADATA_WR) {
|
||||||
result = env_rwsem_down_write_trylock(
|
result = env_rwsem_down_write_trylock(
|
||||||
@ -60,7 +60,7 @@ static inline int ocf_metadata_try_lock(struct ocf_cache *cache, int rw)
|
|||||||
ENV_BUG();
|
ENV_BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result)
|
if (result)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -232,21 +232,27 @@ bool ocf_mngt_is_cache_locked(ocf_cache_t cache)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _ocf_mngt_cache_unlock(ocf_cache_t cache,
|
||||||
|
void (*unlock_fn)(env_rwsem *s))
|
||||||
|
{
|
||||||
|
unlock_fn(&cache->lock);
|
||||||
|
ocf_mngt_cache_put(cache);
|
||||||
|
}
|
||||||
|
|
||||||
void ocf_mngt_cache_unlock(ocf_cache_t cache)
|
void ocf_mngt_cache_unlock(ocf_cache_t cache)
|
||||||
{
|
{
|
||||||
OCF_CHECK_NULL(cache);
|
OCF_CHECK_NULL(cache);
|
||||||
env_rwsem_up_write(&cache->lock);
|
_ocf_mngt_cache_unlock(cache, env_rwsem_up_write);
|
||||||
ocf_mngt_cache_put(cache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ocf_mngt_cache_read_unlock(ocf_cache_t cache)
|
void ocf_mngt_cache_read_unlock(ocf_cache_t cache)
|
||||||
{
|
{
|
||||||
OCF_CHECK_NULL(cache);
|
OCF_CHECK_NULL(cache);
|
||||||
env_rwsem_up_read(&cache->lock);
|
_ocf_mngt_cache_unlock(cache, env_rwsem_up_read);
|
||||||
ocf_mngt_cache_put(cache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _ocf_mngt_cache_lock(ocf_cache_t cache, bool read)
|
static int _ocf_mngt_cache_lock(ocf_cache_t cache, int (*lock_fn)(env_rwsem *s),
|
||||||
|
void (*unlock_fn)(env_rwsem *s))
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -254,10 +260,7 @@ int _ocf_mngt_cache_lock(ocf_cache_t cache, bool read)
|
|||||||
env_atomic_inc(&cache->ref_count);
|
env_atomic_inc(&cache->ref_count);
|
||||||
|
|
||||||
env_atomic_inc(&cache->lock_waiter);
|
env_atomic_inc(&cache->lock_waiter);
|
||||||
if (read)
|
ret = lock_fn(&cache->lock);
|
||||||
ret = env_rwsem_down_read_interruptible(&cache->lock);
|
|
||||||
else
|
|
||||||
ret = env_rwsem_down_write_interruptible(&cache->lock);
|
|
||||||
env_atomic_dec(&cache->lock_waiter);
|
env_atomic_dec(&cache->lock_waiter);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -283,10 +286,7 @@ int _ocf_mngt_cache_lock(ocf_cache_t cache, bool read)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
if (read)
|
_ocf_mngt_cache_unlock(cache, unlock_fn);
|
||||||
ocf_mngt_cache_read_unlock(cache);
|
|
||||||
else
|
|
||||||
ocf_mngt_cache_unlock(cache);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -294,13 +294,29 @@ unlock:
|
|||||||
int ocf_mngt_cache_lock(ocf_cache_t cache)
|
int ocf_mngt_cache_lock(ocf_cache_t cache)
|
||||||
{
|
{
|
||||||
OCF_CHECK_NULL(cache);
|
OCF_CHECK_NULL(cache);
|
||||||
return _ocf_mngt_cache_lock(cache, false);
|
return _ocf_mngt_cache_lock(cache, env_rwsem_down_write_interruptible,
|
||||||
|
env_rwsem_up_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocf_mngt_cache_read_lock(ocf_cache_t cache)
|
int ocf_mngt_cache_read_lock(ocf_cache_t cache)
|
||||||
{
|
{
|
||||||
OCF_CHECK_NULL(cache);
|
OCF_CHECK_NULL(cache);
|
||||||
return _ocf_mngt_cache_lock(cache, true);
|
return _ocf_mngt_cache_lock(cache, env_rwsem_down_read_interruptible,
|
||||||
|
env_rwsem_up_read);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ocf_mngt_cache_trylock(ocf_cache_t cache)
|
||||||
|
{
|
||||||
|
OCF_CHECK_NULL(cache);
|
||||||
|
return _ocf_mngt_cache_lock(cache, env_rwsem_down_write_trylock,
|
||||||
|
env_rwsem_up_write);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ocf_mngt_cache_read_trylock(ocf_cache_t cache)
|
||||||
|
{
|
||||||
|
OCF_CHECK_NULL(cache);
|
||||||
|
return _ocf_mngt_cache_lock(cache, env_rwsem_down_read_trylock,
|
||||||
|
env_rwsem_up_read);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if cache is either fully initialized or during recovery */
|
/* if cache is either fully initialized or during recovery */
|
||||||
|
@ -247,7 +247,7 @@ static void ocf_cleaner_run_test01(void **state)
|
|||||||
will_return(__wrap_ocf_mngt_is_cache_locked, 0);
|
will_return(__wrap_ocf_mngt_is_cache_locked, 0);
|
||||||
|
|
||||||
expect_function_call(__wrap_env_rwsem_down_write_trylock);
|
expect_function_call(__wrap_env_rwsem_down_write_trylock);
|
||||||
will_return(__wrap_env_rwsem_down_write_trylock, 1);
|
will_return(__wrap_env_rwsem_down_write_trylock, 0);
|
||||||
|
|
||||||
expect_function_call(__wrap__ocf_cleaner_run_check_dirty_inactive);
|
expect_function_call(__wrap__ocf_cleaner_run_check_dirty_inactive);
|
||||||
will_return(__wrap__ocf_cleaner_run_check_dirty_inactive, 0);
|
will_return(__wrap__ocf_cleaner_run_check_dirty_inactive, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user