summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/cluster/afr/src/afr-inode-read.c254
1 files changed, 112 insertions, 142 deletions
diff --git a/xlators/cluster/afr/src/afr-inode-read.c b/xlators/cluster/afr/src/afr-inode-read.c
index c5521704de..13db3581ec 100644
--- a/xlators/cluster/afr/src/afr-inode-read.c
+++ b/xlators/cluster/afr/src/afr-inode-read.c
@@ -15,6 +15,8 @@
#include <stdlib.h>
#include <signal.h>
+#include <urcu/uatomic.h>
+
#include <glusterfs/glusterfs.h>
#include "afr.h"
#include <glusterfs/dict.h>
@@ -866,188 +868,121 @@ afr_getxattr_quota_size_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
-int32_t
-afr_getxattr_lockinfo_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, dict_t *dict,
- dict_t *xdata)
+static int32_t
+afr_update_local_dicts(call_frame_t *frame, dict_t *dict, dict_t *xdata)
{
- int call_cnt = 0, len = 0;
- char *lockinfo_buf = NULL;
- dict_t *lockinfo = NULL, *newdict = NULL;
- afr_local_t *local = NULL;
+ afr_local_t *local;
+ dict_t *local_dict;
+ dict_t *local_xdata;
+ int32_t ret;
- LOCK(&frame->lock);
- {
- local = frame->local;
+ local = frame->local;
+ local_dict = NULL;
+ local_xdata = NULL;
- call_cnt = --local->call_count;
+ ret = -ENOMEM;
- if ((op_ret < 0) || (!dict && !xdata)) {
- goto unlock;
- }
-
- if (xdata) {
- if (!local->xdata_rsp) {
- local->xdata_rsp = dict_new();
- if (!local->xdata_rsp) {
- local->op_ret = -1;
- local->op_errno = ENOMEM;
- goto unlock;
- }
- }
+ if ((dict != NULL) && (local->dict == NULL)) {
+ local_dict = dict_new();
+ if (local_dict == NULL) {
+ goto done;
}
+ }
- if (!dict) {
- goto unlock;
+ if ((xdata != NULL) && (local->xdata_rsp == NULL)) {
+ local_xdata = dict_new();
+ if (local_xdata == NULL) {
+ goto done;
}
+ }
- op_ret = dict_get_ptr_and_len(dict, GF_XATTR_LOCKINFO_KEY,
- (void **)&lockinfo_buf, &len);
+ if ((local_dict != NULL) || (local_xdata != NULL)) {
+ /* TODO: Maybe it would be better to preallocate both dicts before
+ * sending the requests. This way we don't need to use a LOCK()
+ * here. */
+ LOCK(&frame->lock);
- if (!lockinfo_buf) {
- goto unlock;
+ if ((local_dict != NULL) && (local->dict == NULL)) {
+ local->dict = local_dict;
+ local_dict = NULL;
}
- if (!local->dict) {
- local->dict = dict_new();
- if (!local->dict) {
- local->op_ret = -1;
- local->op_errno = ENOMEM;
- goto unlock;
- }
+ if ((local_xdata != NULL) && (local->xdata_rsp == NULL)) {
+ local->xdata_rsp = local_xdata;
+ local_xdata = NULL;
}
- }
-unlock:
- UNLOCK(&frame->lock);
- if (lockinfo_buf != NULL) {
- lockinfo = dict_new();
- if (lockinfo == NULL) {
- local->op_ret = -1;
- local->op_errno = ENOMEM;
- } else {
- op_ret = dict_unserialize(lockinfo_buf, len, &lockinfo);
-
- if (lockinfo && local->dict) {
- dict_copy(lockinfo, local->dict);
- }
- }
- }
-
- if (xdata && local->xdata_rsp) {
- dict_copy(xdata, local->xdata_rsp);
+ UNLOCK(&frame->lock);
}
- if (!call_cnt) {
- newdict = dict_new();
- if (!newdict) {
- local->op_ret = -1;
- local->op_errno = ENOMEM;
- goto unwind;
+ if (dict != NULL) {
+ if (dict_copy(dict, local->dict) < 0) {
+ goto done;
}
+ }
- op_ret = dict_allocate_and_serialize(
- local->dict, (char **)&lockinfo_buf, (unsigned int *)&len);
- if (op_ret != 0) {
- local->op_ret = -1;
- goto unwind;
+ if (xdata != NULL) {
+ if (dict_copy(xdata, local->xdata_rsp) < 0) {
+ goto done;
}
+ }
- op_ret = dict_set_dynptr(newdict, GF_XATTR_LOCKINFO_KEY,
- (void *)lockinfo_buf, len);
- if (op_ret < 0) {
- local->op_ret = -1;
- local->op_errno = -op_ret;
- goto unwind;
- }
+ ret = 0;
- unwind:
- AFR_STACK_UNWIND(getxattr, frame, op_ret, op_errno, newdict,
- local->xdata_rsp);
+done:
+ if (local_dict != NULL) {
+ dict_unref(local_dict);
}
- dict_unref(lockinfo);
+ if (local_xdata != NULL) {
+ dict_unref(local_xdata);
+ }
- return 0;
+ return ret;
}
-int32_t
-afr_fgetxattr_lockinfo_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, dict_t *dict,
- dict_t *xdata)
+static void
+afr_getxattr_lockinfo_cbk_common(call_frame_t *frame, int32_t op_ret,
+ int32_t op_errno, dict_t *dict, dict_t *xdata,
+ bool is_fgetxattr)
{
- int call_cnt = 0, len = 0;
+ int len = 0;
char *lockinfo_buf = NULL;
dict_t *lockinfo = NULL, *newdict = NULL;
afr_local_t *local = NULL;
- LOCK(&frame->lock);
- {
- local = frame->local;
-
- call_cnt = --local->call_count;
-
- if ((op_ret < 0) || (!dict && !xdata)) {
- goto unlock;
- }
-
- if (xdata) {
- if (!local->xdata_rsp) {
- local->xdata_rsp = dict_new();
- if (!local->xdata_rsp) {
- local->op_ret = -1;
- local->op_errno = ENOMEM;
- goto unlock;
- }
- }
- }
-
- if (!dict) {
- goto unlock;
- }
+ local = frame->local;
+ if ((op_ret >= 0) && (dict != NULL)) {
op_ret = dict_get_ptr_and_len(dict, GF_XATTR_LOCKINFO_KEY,
(void **)&lockinfo_buf, &len);
-
- if (!lockinfo_buf) {
- goto unlock;
- }
-
- if (!local->dict) {
- local->dict = dict_new();
- if (!local->dict) {
- local->op_ret = -1;
- local->op_errno = ENOMEM;
- goto unlock;
+ if (lockinfo_buf != NULL) {
+ lockinfo = dict_new();
+ if (lockinfo == NULL) {
+ op_ret = -1;
+ } else {
+ op_ret = dict_unserialize(lockinfo_buf, len, &lockinfo);
}
}
}
-unlock:
- UNLOCK(&frame->lock);
- if (lockinfo_buf != NULL) {
- lockinfo = dict_new();
- if (lockinfo == NULL) {
- local->op_ret = -1;
- local->op_errno = ENOMEM;
- } else {
- op_ret = dict_unserialize(lockinfo_buf, len, &lockinfo);
-
- if (lockinfo && local->dict) {
- dict_copy(lockinfo, local->dict);
- }
+ if ((op_ret >= 0) && ((lockinfo != NULL) || (xdata != NULL))) {
+ op_ret = afr_update_local_dicts(frame, lockinfo, xdata);
+ if (lockinfo != NULL) {
+ dict_unref(lockinfo);
}
}
- if (xdata && local->xdata_rsp) {
- dict_copy(xdata, local->xdata_rsp);
+ if (op_ret < 0) {
+ local->op_ret = -1;
+ local->op_errno = ENOMEM;
}
- if (!call_cnt) {
+ if (uatomic_sub_return(&local->call_count, 1) == 0) {
newdict = dict_new();
if (!newdict) {
local->op_ret = -1;
- local->op_errno = ENOMEM;
+ local->op_errno = op_errno = ENOMEM;
goto unwind;
}
@@ -1055,23 +990,58 @@ unlock:
local->dict, (char **)&lockinfo_buf, (unsigned int *)&len);
if (op_ret != 0) {
local->op_ret = -1;
+ local->op_errno = op_errno = ENOMEM;
goto unwind;
}
op_ret = dict_set_dynptr(newdict, GF_XATTR_LOCKINFO_KEY,
(void *)lockinfo_buf, len);
if (op_ret < 0) {
- local->op_ret = -1;
- local->op_errno = -op_ret;
+ GF_FREE(lockinfo_buf);
+ local->op_ret = op_ret = -1;
+ local->op_errno = op_errno = -op_ret;
goto unwind;
}
unwind:
- AFR_STACK_UNWIND(fgetxattr, frame, op_ret, op_errno, newdict,
- local->xdata_rsp);
+ /* TODO: These unwinds use op_ret and op_errno instead of local->op_ret
+ * and local->op_errno. This doesn't seem right because any
+ * failure during processing of each answer could be silently
+ * ignored. This is kept this was the old behavior and because
+ * local->op_ret is initialized as -1 and local->op_errno is
+ * initialized as EUCLEAN, which makes these values useless. */
+ if (is_fgetxattr) {
+ AFR_STACK_UNWIND(fgetxattr, frame, op_ret, op_errno, newdict,
+ local->xdata_rsp);
+ } else {
+ AFR_STACK_UNWIND(getxattr, frame, op_ret, op_errno, newdict,
+ local->xdata_rsp);
+ }
+
+ if (newdict != NULL) {
+ dict_unref(newdict);
+ }
}
+}
+
+static int32_t
+afr_getxattr_lockinfo_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *dict,
+ dict_t *xdata)
+{
+ afr_getxattr_lockinfo_cbk_common(frame, op_ret, op_errno, dict, xdata,
+ false);
- dict_unref(lockinfo);
+ return 0;
+}
+
+static int32_t
+afr_fgetxattr_lockinfo_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *dict,
+ dict_t *xdata)
+{
+ afr_getxattr_lockinfo_cbk_common(frame, op_ret, op_errno, dict, xdata,
+ true);
return 0;
}