From d7e049160a9dea988ded5816491c2234d40ab6b3 Mon Sep 17 00:00:00 2001 From: Ravishankar N Date: Thu, 7 Nov 2019 15:18:30 +0530 Subject: afr: make heal info lockless Changes in locks xlator: Added support for per-domain inodelk count requests. Caller needs to set GLUSTERFS_MULTIPLE_DOM_LK_CNT_REQUESTS key in the dict and then set each key with name 'GLUSTERFS_INODELK_DOM_PREFIX:'. In the response dict, the xlator will send the per domain count as values for each of these keys. Changes in AFR: Replaced afr_selfheal_locked_inspect() with afr_lockless_inspect(). Logic has been added to make the latter behave same as the former, thus not breaking the current heal info output behaviour. fixes: bz#1774011 Change-Id: Ie9e83c162aa77f44a39c2ba7115de558120ada4d Signed-off-by: Ravishankar N --- xlators/features/locks/src/common.h | 4 ++ xlators/features/locks/src/locks.h | 8 +++ xlators/features/locks/src/posix.c | 117 +++++++++++++++++++++++++++++++----- 3 files changed, 115 insertions(+), 14 deletions(-) (limited to 'xlators/features/locks') diff --git a/xlators/features/locks/src/common.h b/xlators/features/locks/src/common.h index 4006062606e..0916c299e84 100644 --- a/xlators/features/locks/src/common.h +++ b/xlators/features/locks/src/common.h @@ -44,6 +44,10 @@ fd_unref(__local->fd); \ if (__local->inode) \ inode_unref(__local->inode); \ + if (__local->xdata) { \ + dict_unref(__local->xdata); \ + __local->xdata = NULL; \ + } \ mem_put(__local); \ } \ } while (0) diff --git a/xlators/features/locks/src/locks.h b/xlators/features/locks/src/locks.h index 0ab2aa6cbae..3305350afb1 100644 --- a/xlators/features/locks/src/locks.h +++ b/xlators/features/locks/src/locks.h @@ -240,6 +240,7 @@ typedef struct { gf_boolean_t inodelk_count_req; gf_boolean_t posixlk_count_req; gf_boolean_t parent_entrylk_req; + gf_boolean_t multiple_dom_lk_requests; int update_mlock_enforced_flag; } pl_local_t; @@ -261,6 +262,13 @@ typedef struct _locks_ctx { struct list_head metalk_list; } pl_ctx_t; +typedef struct _multi_dom_lk_data { + xlator_t *this; + inode_t *inode; + dict_t *xdata_rsp; + gf_boolean_t keep_max; +} multi_dom_lk_data; + typedef enum { DECREMENT, INCREMENT } pl_count_op_t; pl_ctx_t * diff --git a/xlators/features/locks/src/posix.c b/xlators/features/locks/src/posix.c index d2f5db5116b..8bbcef6385a 100644 --- a/xlators/features/locks/src/posix.c +++ b/xlators/features/locks/src/posix.c @@ -151,13 +151,20 @@ fetch_pathinfo(xlator_t *, inode_t *, int32_t *, char **); gf_boolean_t pl_has_xdata_requests(dict_t *xdata) { - static char *reqs[] = {GLUSTERFS_ENTRYLK_COUNT, GLUSTERFS_INODELK_COUNT, - GLUSTERFS_INODELK_DOM_COUNT, GLUSTERFS_POSIXLK_COUNT, - GLUSTERFS_PARENT_ENTRYLK, NULL}; - static int reqs_size[] = { - SLEN(GLUSTERFS_ENTRYLK_COUNT), SLEN(GLUSTERFS_INODELK_COUNT), - SLEN(GLUSTERFS_INODELK_DOM_COUNT), SLEN(GLUSTERFS_POSIXLK_COUNT), - SLEN(GLUSTERFS_PARENT_ENTRYLK), 0}; + static char *reqs[] = {GLUSTERFS_ENTRYLK_COUNT, + GLUSTERFS_INODELK_COUNT, + GLUSTERFS_INODELK_DOM_COUNT, + GLUSTERFS_POSIXLK_COUNT, + GLUSTERFS_PARENT_ENTRYLK, + GLUSTERFS_MULTIPLE_DOM_LK_CNT_REQUESTS, + NULL}; + static int reqs_size[] = {SLEN(GLUSTERFS_ENTRYLK_COUNT), + SLEN(GLUSTERFS_INODELK_COUNT), + SLEN(GLUSTERFS_INODELK_DOM_COUNT), + SLEN(GLUSTERFS_POSIXLK_COUNT), + SLEN(GLUSTERFS_PARENT_ENTRYLK), + SLEN(GLUSTERFS_MULTIPLE_DOM_LK_CNT_REQUESTS), + 0}; int i = 0; if (!xdata) @@ -170,12 +177,22 @@ pl_has_xdata_requests(dict_t *xdata) return _gf_false; } +static int +dict_delete_domain_key(dict_t *dict, char *key, data_t *value, void *data) +{ + dict_del(dict, key); + return 0; +} + void pl_get_xdata_requests(pl_local_t *local, dict_t *xdata) { if (!local || !xdata) return; + GF_ASSERT(local->xdata == NULL); + local->xdata = dict_copy_with_ref(xdata, NULL); + if (dict_get_sizen(xdata, GLUSTERFS_ENTRYLK_COUNT)) { local->entrylk_count_req = 1; dict_del_sizen(xdata, GLUSTERFS_ENTRYLK_COUNT); @@ -184,6 +201,12 @@ pl_get_xdata_requests(pl_local_t *local, dict_t *xdata) local->inodelk_count_req = 1; dict_del_sizen(xdata, GLUSTERFS_INODELK_COUNT); } + if (dict_get_sizen(xdata, GLUSTERFS_MULTIPLE_DOM_LK_CNT_REQUESTS)) { + local->multiple_dom_lk_requests = 1; + dict_del_sizen(xdata, GLUSTERFS_MULTIPLE_DOM_LK_CNT_REQUESTS); + dict_foreach_fnmatch(xdata, GLUSTERFS_INODELK_DOM_PREFIX "*", + dict_delete_domain_key, NULL); + } local->inodelk_dom_count_req = dict_get_sizen(xdata, GLUSTERFS_INODELK_DOM_COUNT); @@ -211,7 +234,7 @@ pl_needs_xdata_response(pl_local_t *local) if (local->parent_entrylk_req || local->entrylk_count_req || local->inodelk_dom_count_req || local->inodelk_count_req || - local->posixlk_count_req) + local->posixlk_count_req || local->multiple_dom_lk_requests) return _gf_true; return _gf_false; @@ -410,6 +433,75 @@ pl_posixlk_xattr_fill(xlator_t *this, inode_t *inode, dict_t *dict, } } +void +pl_inodelk_xattr_fill_each(xlator_t *this, inode_t *inode, dict_t *dict, + char *domname, gf_boolean_t keep_max, char *key) +{ + int32_t count = 0; + int32_t maxcount = -1; + int ret = -1; + + if (keep_max) { + ret = dict_get_int32(dict, key, &maxcount); + if (ret < 0) + gf_msg_debug(this->name, 0, " Failed to fetch the value for key %s", + GLUSTERFS_INODELK_COUNT); + } + count = get_inodelk_count(this, inode, domname); + if (maxcount >= count) + return; + + ret = dict_set_int32(dict, key, count); + if (ret < 0) { + gf_msg_debug(this->name, 0, + "Failed to set count for " + "key %s", + key); + } + + return; +} + +static int +pl_inodelk_xattr_fill_multiple(dict_t *this, char *key, data_t *value, + void *data) +{ + multi_dom_lk_data *d = data; + char *tmp_key = NULL; + char *save_ptr = NULL; + + tmp_key = gf_strdup(key); + strtok_r(tmp_key, ":", &save_ptr); + if (!*save_ptr) { + gf_msg(THIS->name, GF_LOG_ERROR, 0, EINVAL, + "Could not tokenize domain string from key %s", key); + return -1; + } + + pl_inodelk_xattr_fill_each(d->this, d->inode, d->xdata_rsp, save_ptr, + d->keep_max, key); + if (tmp_key) + GF_FREE(tmp_key); + + return 0; +} + +void +pl_fill_multiple_dom_lk_requests(xlator_t *this, pl_local_t *local, + inode_t *inode, dict_t *dict, + gf_boolean_t keep_max) +{ + multi_dom_lk_data data; + + data.this = this; + data.inode = inode; + data.xdata_rsp = dict; + data.keep_max = keep_max; + + dict_foreach_fnmatch(local->xdata, GLUSTERFS_INODELK_DOM_PREFIX "*", + pl_inodelk_xattr_fill_multiple, &data); +} + void pl_set_xdata_response(xlator_t *this, pl_local_t *local, inode_t *parent, inode_t *inode, char *name, dict_t *xdata, @@ -437,6 +529,9 @@ pl_set_xdata_response(xlator_t *this, pl_local_t *local, inode_t *parent, if (local->posixlk_count_req) pl_posixlk_xattr_fill(this, inode, xdata, max_lock); + + if (local->multiple_dom_lk_requests) + pl_fill_multiple_dom_lk_requests(this, local, inode, xdata, max_lock); } /* Checks whether the region where fop is acting upon conflicts @@ -775,9 +870,6 @@ pl_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, { pl_local_t *local = frame->local; - if (local->xdata) - dict_unref(local->xdata); - pl_track_io_fop_count(local, this, DECREMENT); if (local->op == GF_FOP_TRUNCATE) @@ -935,9 +1027,6 @@ unwind: "ret: %d, error: %s", op_ret, strerror(op_errno)); - if (local->xdata) - dict_unref(local->xdata); - switch (local->op) { case GF_FOP_TRUNCATE: PL_STACK_UNWIND(truncate, xdata, frame, op_ret, op_errno, buf, -- cgit