diff options
| author | Mike Snitzer <snitzer@redhat.com> | 2016-04-12 12:14:46 -0400 |
|---|---|---|
| committer | Mike Snitzer <snitzer@redhat.com> | 2016-04-12 13:15:23 -0400 |
| commit | a64204672859248c89c8df796421442fb41e59ec (patch) | |
| tree | 98a093bb1cb707dbd1e2559ff2d539790f4bd740 | |
| parent | 00938f34e5674a0327fd7726c777308a08496d69 (diff) | |
| download | linux-dm-a64204672859248c89c8df796421442fb41e59ec.tar.gz | |
dm cache metadata: fix READ_LOCK macros and cleanup WRITE_LOCK macros
The READ_LOCK macro was incorrectly returning -EINVAL if
dm_bm_is_read_only() was true -- it will always be true once the cache
metadata transitions to read-only by dm_cache_metadata_set_read_only().
Wrap READ_LOCK and WRITE_LOCK multi-statement macros in do {} while(0).
Also, all accesses of the 'cmd' argument passed to these related macros
are now encapsulated in parenthesis.
A follow-up patch can be developed to eliminate the use of macros in
favor of pure C code. Avoiding that now given that this needs to apply
to stable@.
Reported-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Fixes: d14fcf3dd79 ("dm cache: make sure every metadata function checks fail_io")
Cc: stable@vger.kernel.org
| -rw-r--r-- | drivers/md/dm-cache-metadata.c | 56 |
1 files changed, 33 insertions, 23 deletions
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c index 27f2ef300f8bb..0f8b0aed9deba 100644 --- a/drivers/md/dm-cache-metadata.c +++ b/drivers/md/dm-cache-metadata.c @@ -867,39 +867,49 @@ static int blocks_are_unmapped_or_clean(struct dm_cache_metadata *cmd, return 0; } -#define WRITE_LOCK(cmd) \ - down_write(&cmd->root_lock); \ - if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \ - up_write(&cmd->root_lock); \ - return -EINVAL; \ +static bool cmd_write_lock(struct dm_cache_metadata *cmd) +{ + down_write(&cmd->root_lock); + if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { + up_write(&cmd->root_lock); + return false; } + return true; +} + +#define WRITE_LOCK(cmd) \ + do { \ + if (!cmd_write_lock((cmd))) \ + return -EINVAL; \ + } while(0) #define WRITE_LOCK_VOID(cmd) \ - down_write(&cmd->root_lock); \ - if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \ - up_write(&cmd->root_lock); \ - return; \ - } + (void) cmd_write_lock((cmd)) #define WRITE_UNLOCK(cmd) \ - up_write(&cmd->root_lock) + up_write(&(cmd)->root_lock) -#define READ_LOCK(cmd) \ - down_read(&cmd->root_lock); \ - if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \ - up_read(&cmd->root_lock); \ - return -EINVAL; \ +static bool cmd_read_lock(struct dm_cache_metadata *cmd) +{ + down_write(&cmd->root_lock); + if (cmd->fail_io) { + up_write(&cmd->root_lock); + return false; } + return true; +} -#define READ_LOCK_VOID(cmd) \ - down_read(&cmd->root_lock); \ - if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \ - up_read(&cmd->root_lock); \ - return; \ - } +#define READ_LOCK(cmd) \ + do { \ + if (!cmd_read_lock((cmd))) \ + return -EINVAL; \ + } while(0) + +#define READ_LOCK_VOID(cmd) \ + (void) cmd_read_lock((cmd)) #define READ_UNLOCK(cmd) \ - up_read(&cmd->root_lock) + up_read(&(cmd)->root_lock) int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size) { |
