From 21ab4eb9afa5ab596d11382126a3f8dfce0fddb3 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 10 2018 05:48:43 +0000 Subject: import glusterfs-3.8.4-53.el7 --- diff --git a/SOURCES/0304-features-shard-Pass-the-correct-iatt-for-cache-inval.patch b/SOURCES/0304-features-shard-Pass-the-correct-iatt-for-cache-inval.patch deleted file mode 100644 index 113a59e..0000000 --- a/SOURCES/0304-features-shard-Pass-the-correct-iatt-for-cache-inval.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 795a095a6740a66744f10f864c99095205c97c1a Mon Sep 17 00:00:00 2001 -From: Krutika Dhananjay -Date: Tue, 28 Mar 2017 19:26:41 +0530 -Subject: [PATCH 304/316] features/shard: Pass the correct iatt for cache - invalidation - - Backport of: https://review.gluster.org/16961 - -This fixes a performance issue with shard which was causing -the translator to trigger unusually high number of lookups -for cache invalidation even when there was no modification to -the file. - -In shard_common_stat_cbk(), it is local->prebuf that contains the -aggregated size and block count as opposed to buf which only holds the -attributes for the physical copy of base shard. Passing buf for -inode_ctx invalidation would always set refresh to true since the file -size in inode ctx contains the aggregated size and would never be same -as @buf->ia_size. This was leading to every write/read being preceded -by a lookup on the base shard even when the file underwent no -modification. - -Change-Id: I97b52224823d57f86eb92cc36a726049bdb5cb23 -BUG: 1439731 -Signed-off-by: Krutika Dhananjay -Reviewed-on: https://code.engineering.redhat.com/gerrit/102819 -Reviewed-by: Atin Mukherjee ---- - xlators/features/shard/src/shard.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c -index 39d648b..9504f12 100644 ---- a/xlators/features/shard/src/shard.c -+++ b/xlators/features/shard/src/shard.c -@@ -1269,7 +1269,7 @@ shard_common_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - else - inode = local->fd->inode; - -- shard_inode_ctx_invalidate (inode, this, buf); -+ shard_inode_ctx_invalidate (inode, this, &local->prebuf); - - unwind: - local->handler (frame, this); --- -1.8.3.1 - diff --git a/SOURCES/0305-Snapshot-xml-xml-output-for-snapshot-clone.patch b/SOURCES/0305-Snapshot-xml-xml-output-for-snapshot-clone.patch new file mode 100644 index 0000000..1b3023e --- /dev/null +++ b/SOURCES/0305-Snapshot-xml-xml-output-for-snapshot-clone.patch @@ -0,0 +1,153 @@ +From 0ccff60cdb2a049d9c54745e0935a67e7eda73e1 Mon Sep 17 00:00:00 2001 +From: Mohammed Rafi KC +Date: Tue, 31 Mar 2015 10:54:10 +0530 +Subject: [PATCH 305/361] Snapshot/xml:xml output for snapshot clone + +Snapshot clone is used to create a regular volume from snapshot. +Currently snapshot clone is not supporting xml outout. + +This change introduce a xml output for snapshot clone command + +mainline: +> BUG: 1207604 +> Reviewed-on: http://review.gluster.org/10065 +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Avra Sengupta +> Reviewed-by: Rajesh Joseph +> Tested-by: Avra Sengupta +(cherry picked from commit 2c51208197e1043c84c04d3b37a325b84831f56b) + +BUG: 1167252 +Change-Id: I417b480d36f9d84ee088004999b041c9619edd50 +Signed-off-by: Mohammed Rafi KC +Reviewed-on: https://code.engineering.redhat.com/gerrit/101281 +Tested-by: Milind Changire +Reviewed-by: Atin Mukherjee +--- + cli/src/cli-xml-output.c | 79 ++++++++++++++++++++++++--- + xlators/mgmt/glusterd/src/glusterd-snapshot.c | 2 +- + 2 files changed, 73 insertions(+), 8 deletions(-) + +diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c +index f249e40..063e171 100644 +--- a/cli/src/cli-xml-output.c ++++ b/cli/src/cli-xml-output.c +@@ -4578,6 +4578,65 @@ out: + return ret; + } + ++/* This function will generate snapshot clone output in xml format. ++ * ++ * @param writer xmlTextWriterPtr ++ * @param doc xmlDocPtr ++ * @param dict dict containing create output ++ * ++ * @return 0 on success and -1 on failure ++ */ ++static int ++cli_xml_snapshot_clone (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) ++{ ++ int ret = -1; ++ char *str_value = NULL; ++ ++ GF_VALIDATE_OR_GOTO ("cli", writer, out); ++ GF_VALIDATE_OR_GOTO ("cli", doc, out); ++ GF_VALIDATE_OR_GOTO ("cli", dict, out); ++ ++ /* */ ++ ret = xmlTextWriterStartElement (writer, (xmlChar *)"CloneCreate"); ++ XML_RET_CHECK_AND_GOTO (ret, out); ++ ++ /* */ ++ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volume"); ++ XML_RET_CHECK_AND_GOTO (ret, out); ++ ++ ret = dict_get_str (dict, "clonename", &str_value); ++ if (ret) { ++ gf_log ("cli", GF_LOG_ERROR, "Failed to get clone name"); ++ goto out; ++ } ++ ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", ++ "%s", str_value); ++ XML_RET_CHECK_AND_GOTO (ret, out); ++ ++ ++ ret = dict_get_str (dict, "snapuuid", &str_value); ++ if (ret) { ++ gf_log ("cli", GF_LOG_ERROR, "Failed to get clone uuid"); ++ goto out; ++ } ++ ++ ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", ++ "%s", str_value); ++ XML_RET_CHECK_AND_GOTO (ret, out); ++ ++ /* */ ++ ret = xmlTextWriterEndElement (writer); ++ XML_RET_CHECK_AND_GOTO (ret, out); ++ ++ /* */ ++ ret = xmlTextWriterEndElement (writer); ++ XML_RET_CHECK_AND_GOTO (ret, out); ++ ++ ret = 0; ++out: ++ return ret; ++} ++ + + /* This function will generate snapshot restore output in xml format. + * +@@ -5162,14 +5221,12 @@ cli_xml_snapshot_volume_status (xmlTextWriterPtr writer, xmlDocPtr doc, + + ret = dict_get_str (dict, key, &buffer); + if (ret) { +- gf_log ("cli", GF_LOG_ERROR, ++ gf_log ("cli", GF_LOG_INFO, + "Unable to get Brick Running"); +- ret = xmlTextWriterWriteFormatElement (writer, +- (xmlChar *) "brick_running", "N/A"); +- } else +- ret = xmlTextWriterWriteFormatElement (writer, +- (xmlChar *) "brick_running", "%s", buffer); +- ++ strcpy (buffer, "N/A"); ++ } ++ ret = xmlTextWriterWriteFormatElement (writer, ++ (xmlChar *) "BrickRunning", "%s", buffer); + XML_RET_CHECK_AND_GOTO (ret, out); + + snprintf (key, sizeof (key), "%s.brick%d.pid", keyprefix, i); +@@ -6023,6 +6080,14 @@ cli_xml_output_snapshot (int cmd_type, dict_t *dict, int op_ret, + goto out; + } + break; ++ case GF_SNAP_OPTION_TYPE_CLONE: ++ ret = cli_xml_snapshot_clone (writer, doc, dict); ++ if (ret) { ++ gf_log ("cli", GF_LOG_ERROR, "Failed to create " ++ "xml output for snapshot clone command"); ++ goto out; ++ } ++ break; + case GF_SNAP_OPTION_TYPE_RESTORE: + ret = cli_xml_snapshot_restore (writer, doc, dict); + if (ret) { +diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c +index 47835a8..425fa07 100644 +--- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c ++++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c +@@ -6864,7 +6864,7 @@ glusterd_snapshot_clone_commit (dict_t *dict, char **op_errstr, + + cds_list_del_init (&snap_vol->vol_list); + ret = dict_set_dynstr_with_alloc (rsp_dict, "snapuuid", +- uuid_utoa (snap->snap_id)); ++ uuid_utoa (snap_vol->volume_id)); + if (ret) { + gf_msg (this->name, GF_LOG_ERROR, 0, + GD_MSG_DICT_SET_FAILED, "Failed to set snap " +-- +1.8.3.1 + diff --git a/SOURCES/0305-rpc-bump-up-conn-cleanup_gen-in-rpc_clnt_reconnect_c.patch b/SOURCES/0305-rpc-bump-up-conn-cleanup_gen-in-rpc_clnt_reconnect_c.patch deleted file mode 100644 index e25f9e8..0000000 --- a/SOURCES/0305-rpc-bump-up-conn-cleanup_gen-in-rpc_clnt_reconnect_c.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 37edb3fb56e2612e218b9f29424b4b6a79d18a94 Mon Sep 17 00:00:00 2001 -From: Atin Mukherjee -Date: Sat, 18 Mar 2017 16:29:10 +0530 -Subject: [PATCH 305/316] rpc: bump up conn->cleanup_gen in - rpc_clnt_reconnect_cleanup - -Commit 086436a introduced generation number (cleanup_gen) to ensure that -rpc layer doesn't end up cleaning up the connection object if -application layer has already destroyed it. Bumping up cleanup_gen was -done only in rpc_clnt_connection_cleanup (). However the same is needed -in rpc_clnt_reconnect_cleanup () too as with out it if the object gets destroyed -through the reconnect event in the application layer, rpc layer will -still end up in trying to delete the object resulting into double free -and crash. - -Peer probing an invalid host/IP was the basic test to catch this issue. - ->Reviewed-on: https://review.gluster.org/16914 ->Smoke: Gluster Build System ->NetBSD-regression: NetBSD Build System ->Reviewed-by: Milind Changire ->CentOS-regression: Gluster Build System ->Reviewed-by: Jeff Darcy - -Change-Id: Id5332f3239cb324cead34eb51cf73d426733bd46 -BUG: 1440162 -Signed-off-by: Atin Mukherjee -Reviewed-on: https://code.engineering.redhat.com/gerrit/102946 ---- - rpc/rpc-lib/src/rpc-clnt.c | 4 +++- - .../glusterd/bug-1433578-invalid-peer-glusterd-crash.t | 14 ++++++++++++++ - 2 files changed, 17 insertions(+), 1 deletion(-) - create mode 100644 tests/bugs/glusterd/bug-1433578-invalid-peer-glusterd-crash.t - -diff --git a/rpc/rpc-lib/src/rpc-clnt.c b/rpc/rpc-lib/src/rpc-clnt.c -index 7bd4495..02045e1 100644 ---- a/rpc/rpc-lib/src/rpc-clnt.c -+++ b/rpc/rpc-lib/src/rpc-clnt.c -@@ -495,8 +495,10 @@ rpc_clnt_reconnect_cleanup (rpc_clnt_connection_t *conn) - - if (conn->reconnect) { - ret = gf_timer_call_cancel (clnt->ctx, conn->reconnect); -- if (!ret) -+ if (!ret) { - reconnect_unref = _gf_true; -+ conn->cleanup_gen++; -+ } - conn->reconnect = NULL; - } - -diff --git a/tests/bugs/glusterd/bug-1433578-invalid-peer-glusterd-crash.t b/tests/bugs/glusterd/bug-1433578-invalid-peer-glusterd-crash.t -new file mode 100644 -index 0000000..1aea8bc ---- /dev/null -+++ b/tests/bugs/glusterd/bug-1433578-invalid-peer-glusterd-crash.t -@@ -0,0 +1,14 @@ -+#!/bin/bash -+ -+. $(dirname $0)/../../include.rc -+ -+cleanup; -+ -+## Start glusterd -+TEST glusterd; -+TEST pidof glusterd; -+ -+TEST ! $CLI peer probe invalid-peer -+ -+TEST pidof glusterd; -+cleanup; --- -1.8.3.1 - diff --git a/SOURCES/0306-dht-replica.split-brain-status-attribute-value-is-no.patch b/SOURCES/0306-dht-replica.split-brain-status-attribute-value-is-no.patch new file mode 100644 index 0000000..b38457b --- /dev/null +++ b/SOURCES/0306-dht-replica.split-brain-status-attribute-value-is-no.patch @@ -0,0 +1,422 @@ +From 4546cfb8bd7e9b42c01803a543fa52471574265d Mon Sep 17 00:00:00 2001 +From: Mohit Agrawal +Date: Fri, 19 Aug 2016 10:33:50 +0530 +Subject: [PATCH 306/361] dht: "replica.split-brain-status" attribute value is + not correct + +Problem: In a distributed-replicate volume attribute + "replica.split-brain-status" value does not display split-brain + condition though directory is in split-brain. + If directory is in split brain on mutiple replica-pairs + it does not show full list of replica pairs. + +Solution: Update the dht_aggregate code to aggregate the xattr + value in this specific condition. + +Fix: 1) function getChoices returns the choices from split-brain + status string. + 2) function add_opt adding the choices to local buffer to + store in dictionary + 3) For the key "replica.split-brain-status" function dht_aggregate + call dht_aggregate_split_brain_xattr to prepare the list. + +Test: To verify the patch followed below steps + 1) Create a distributed replica volume and create mount point + 2) Stop heal daemon + 3) Touch file and directories on mount point + mkdir test{1..5};touch tmp{1..5} + 4) Down brick process on one of the replica set + pkill -9 glusterfsd + 5) Change permission of dir on mount point + chmod 755 test{1..5} + 6) Restart brick process on node with force option + 7) kill brick process on other node in same replica set + 8) Change permission of dir again on mount point + chmod 766 test{1..5} + 9) Reexecute same step from 4-9 on other replica set also + 10) After check heal status on server it will show dir's are + in split brain on all replica sets + 11) After check the replica.split-brain-status attr on mount + point it will show wrong status of split brain. + 12) After apply the patch the attribute shows correct value. + +mainline: +> BUG: 1368312 +> Reviewed-on: http://review.gluster.org/15201 +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Raghavendra G +(cherry picked from commit 975932767d8131e8c331ea3eb527bd8b7240976d) + +BUG: 1260779 +Change-Id: Icdfd72005a4aa82337c342762775a3d1761bbe4a +Signed-off-by: Mohit Agrawal +Reviewed-on: https://code.engineering.redhat.com/gerrit/101282 +Tested-by: Milind Changire +Reviewed-by: Atin Mukherjee +--- + tests/bugs/bug-1368312.t | 84 ++++++++++++++ + xlators/cluster/dht/src/dht-common.c | 212 +++++++++++++++++++++++++++++++++-- + xlators/cluster/dht/src/dht-common.h | 9 ++ + 3 files changed, 293 insertions(+), 12 deletions(-) + create mode 100644 tests/bugs/bug-1368312.t + +diff --git a/tests/bugs/bug-1368312.t b/tests/bugs/bug-1368312.t +new file mode 100644 +index 0000000..135048f +--- /dev/null ++++ b/tests/bugs/bug-1368312.t +@@ -0,0 +1,84 @@ ++#!/bin/bash ++. $(dirname $0)/../include.rc ++. $(dirname $0)/../volume.rc ++cleanup; ++ ++function compare_get_split_brain_status { ++ local path=$1 ++ local choice=$2 ++ echo `getfattr -n replica.split-brain-status $path` | cut -f2 -d"=" | sed -e 's/^"//' -e 's/"$//' | grep $choice ++ if [ $? -ne 0 ] ++ then ++ echo 1 ++ else ++ echo 0 ++ fi ++ ++} ++ ++TEST glusterd ++TEST pidof glusterd ++TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1,2,3,4,5} ++TEST $CLI volume start $V0 ++ ++#Disable self-heal-daemon ++TEST $CLI volume set $V0 cluster.self-heal-daemon off ++ ++TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; ++ ++TEST mkdir $M0/tmp1 ++ ++#Create metadata split-brain ++TEST kill_brick $V0 $H0 $B0/${V0}0 ++TEST chmod 666 $M0/tmp1 ++TEST $CLI volume start $V0 force ++TEST kill_brick $V0 $H0 $B0/${V0}1 ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 ++ ++TEST chmod 757 $M0/tmp1 ++ ++TEST $CLI volume start $V0 force ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 ++ ++EXPECT 2 get_pending_heal_count $V0 ++ ++ ++TEST kill_brick $V0 $H0 $B0/${V0}2 ++TEST chmod 755 $M0/tmp1 ++TEST $CLI volume start $V0 force ++TEST kill_brick $V0 $H0 $B0/${V0}3 ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2 ++ ++TEST chmod 766 $M0/tmp1 ++ ++TEST $CLI volume start $V0 force ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2 ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 3 ++ ++EXPECT 4 get_pending_heal_count $V0 ++ ++TEST kill_brick $V0 $H0 $B0/${V0}4 ++TEST chmod 765 $M0/tmp1 ++TEST $CLI volume start $V0 force ++TEST kill_brick $V0 $H0 $B0/${V0}5 ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 4 ++ ++TEST chmod 756 $M0/tmp1 ++ ++TEST $CLI volume start $V0 force ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 4 ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 5 ++ ++EXPECT 6 get_pending_heal_count $V0 ++ ++cd $M0 ++EXPECT 0 compare_get_split_brain_status ./tmp1 patchy-client-0 ++EXPECT 0 compare_get_split_brain_status ./tmp1 patchy-client-1 ++EXPECT 0 compare_get_split_brain_status ./tmp1 patchy-client-2 ++EXPECT 0 compare_get_split_brain_status ./tmp1 patchy-client-3 ++EXPECT 0 compare_get_split_brain_status ./tmp1 patchy-client-4 ++EXPECT 0 compare_get_split_brain_status ./tmp1 patchy-client-5 ++ ++cd - ++cleanup +diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c +index 62657a0..4907931 100644 +--- a/xlators/cluster/dht/src/dht-common.c ++++ b/xlators/cluster/dht/src/dht-common.c +@@ -127,6 +127,190 @@ out: + } + + ++int add_opt(char **optsp, const char *opt) ++{ ++ char *newopts = NULL; ++ unsigned oldsize = 0; ++ unsigned newsize = 0; ++ ++ if (*optsp == NULL) ++ newopts = gf_strdup (opt); ++ else { ++ oldsize = strlen (*optsp); ++ newsize = oldsize + 1 + strlen (opt) + 1; ++ newopts = GF_REALLOC (*optsp, newsize); ++ if (newopts) ++ sprintf (newopts + oldsize, ",%s", opt); ++ } ++ if (newopts == NULL) { ++ gf_msg ("dht", GF_LOG_WARNING, 0, ++ DHT_MSG_NO_MEMORY, ++ "Error to add choices in buffer in add_opt"); ++ return -1; ++ } ++ *optsp = newopts; ++ return 0; ++} ++ ++/* Return Choice list from Split brain status */ ++char * ++getChoices (const char *value) ++{ ++ int i = 0; ++ char *ptr = NULL; ++ char *tok = NULL; ++ char *result = NULL; ++ char *newval = NULL; ++ ++ ptr = strstr (value, "Choices:"); ++ if (!ptr) { ++ result = ptr; ++ goto out; ++ } ++ ++ newval = gf_strdup (ptr); ++ if (!newval) { ++ result = newval; ++ goto out; ++ } ++ ++ tok = strtok (newval, ":"); ++ if (!tok) { ++ result = tok; ++ goto out; ++ } ++ ++ while (tok) { ++ i++; ++ if (i == 2) ++ break; ++ tok = strtok (NULL, ":"); ++ } ++ ++ result = gf_strdup (tok); ++ ++out: ++ if (newval) ++ GF_FREE (newval); ++ ++ return result; ++} ++ ++/* This function prepare a list of choices for key ++ (replica.split-brain-status) in case of metadata split brain ++ only on the basis of key-value passed to this function. ++ After prepare the list of choices it update the same key in dict ++ with this value to reflect the same in ++ replica.split-brain-status attr for file. ++ ++*/ ++ ++int ++dht_aggregate_split_brain_xattr (dict_t *dst, char *key, data_t *value) ++{ ++ ++ int ret = 0; ++ char *oldvalue = NULL; ++ char *old_choice = NULL; ++ char *new_choice = NULL; ++ char *full_choice = NULL; ++ char *status = NULL; ++ ++ if (value == NULL) { ++ gf_msg ("dht", GF_LOG_WARNING, 0, ++ DHT_MSG_DATA_NULL, ++ "GF_AFR_SBRAIN_STATUS value is NULL"); ++ ret = -1; ++ goto out; ++ } ++ ++ ret = dict_get_str (dst, key, &oldvalue); ++ if (ret) ++ goto out; ++ ++ if (oldvalue && (strstr (oldvalue, "not"))) { ++ gf_msg_debug ("dht", 0, ++ "Need to update split-brain status in dict"); ++ ret = -1; ++ goto out; ++ } ++ if (oldvalue && (strstr (oldvalue, "metadata-split-brain:yes")) ++ && (strstr (oldvalue, "data-split-brain:no"))) { ++ if (strstr (value->data, "not")) { ++ gf_msg_debug ("dht", 0, ++ "No need to update split-brain status"); ++ ret = 0; ++ goto out; ++ } ++ if (strstr (value->data, "yes") && ++ (strncmp (oldvalue, value->data, strlen(oldvalue)))) { ++ old_choice = getChoices (oldvalue); ++ if (!old_choice) { ++ gf_msg ("dht", GF_LOG_WARNING, 0, ++ DHT_MSG_NO_MEMORY, ++ "Error to get choices"); ++ ret = -1; ++ goto out; ++ } ++ ++ ret = add_opt (&full_choice, old_choice); ++ if (ret) { ++ gf_msg ("dht", GF_LOG_WARNING, 0, ++ DHT_MSG_NO_MEMORY, ++ "Error to add choices"); ++ ret = -1; ++ goto out; ++ } ++ ++ new_choice = getChoices (value->data); ++ if (!new_choice) { ++ gf_msg ("dht", GF_LOG_WARNING, 0, ++ DHT_MSG_NO_MEMORY, ++ "Error to get choices"); ++ ret = -1; ++ goto out; ++ } ++ ++ ret = add_opt (&full_choice, new_choice); ++ if (ret) { ++ gf_msg ("dht", GF_LOG_WARNING, 0, ++ DHT_MSG_NO_MEMORY, ++ "Error to add choices "); ++ ret = -1; ++ goto out; ++ } ++ ret = gf_asprintf (&status, ++ "data-split-brain:%s " ++ "metadata-split-brain:%s Choices:%s", ++ "no", "yes", full_choice); ++ ++ if (-1 == ret) { ++ gf_msg ("dht", GF_LOG_WARNING, 0, ++ DHT_MSG_NO_MEMORY, ++ "Error to prepare status "); ++ goto out; ++ } ++ ret = dict_set_dynstr (dst, key, status); ++ if (ret) { ++ gf_msg ("dht", GF_LOG_WARNING, 0, ++ DHT_MSG_DICT_SET_FAILED, ++ "Failed to set full choice"); ++ } ++ } ++ } ++ ++out: ++ if (old_choice) ++ GF_FREE (old_choice); ++ if (new_choice) ++ GF_FREE (new_choice); ++ if (full_choice) ++ GF_FREE (full_choice); ++ ++ return ret; ++} ++ ++ + + int + dht_aggregate (dict_t *this, char *key, data_t *value, void *data) +@@ -137,18 +321,22 @@ dht_aggregate (dict_t *this, char *key, data_t *value, void *data) + + dst = data; + +- if (strcmp (key, QUOTA_SIZE_KEY) == 0) { ++ /* compare split brain xattr only */ ++ if (strcmp (key, GF_AFR_SBRAIN_STATUS) == 0) { ++ ret = dht_aggregate_split_brain_xattr(dst, key, value); ++ if (!ret) ++ goto out; ++ } else if (strcmp (key, QUOTA_SIZE_KEY) == 0) { + ret = dht_aggregate_quota_xattr (dst, key, value); + if (ret) { + gf_msg ("dht", GF_LOG_WARNING, 0, + DHT_MSG_AGGREGATE_QUOTA_XATTR_FAILED, + "Failed to aggregate quota xattr"); +- goto out; + } ++ goto out; + } else if (fnmatch (GF_XATTR_STIME_PATTERN, key, FNM_NOESCAPE) == 0) { + ret = gf_get_min_stime (THIS, dst, key, value); +- if (ret < 0) +- goto out; ++ goto out; + } else { + /* compare user xattrs only */ + if (!strncmp (key, "user.", strlen ("user."))) { +@@ -161,16 +349,16 @@ dht_aggregate (dict_t *this, char *key, data_t *value, void *data) + key); + } + } +- ret = dict_set (dst, key, value); +- if (ret) { +- gf_msg ("dht", GF_LOG_WARNING, 0, +- DHT_MSG_DICT_SET_FAILED, +- "Failed to set dictionary value: key = %s", +- key); +- } + } + +- ret = 0; ++ ret = dict_set (dst, key, value); ++ if (ret) { ++ gf_msg ("dht", GF_LOG_WARNING, 0, ++ DHT_MSG_DICT_SET_FAILED, ++ "Failed to set dictionary value: key = %s", ++ key); ++ } ++ + out: + return ret; + } +diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h +index e87bd90..21e000a 100644 +--- a/xlators/cluster/dht/src/dht-common.h ++++ b/xlators/cluster/dht/src/dht-common.h +@@ -1236,4 +1236,13 @@ dht_get_lock_subvolume (xlator_t *this, struct gf_flock *lock, + int + dht_lk_inode_unref (call_frame_t *frame, int32_t op_ret); + ++int ++add_opt(char **optsp, const char *opt); ++ ++char * ++getChoices (const char *value); ++ ++int ++dht_aggregate_split_brain_xattr (dict_t *dst, char *key, data_t *value); ++ + #endif/* _DHT_H */ +-- +1.8.3.1 + diff --git a/SOURCES/0306-glusterd-Fix-snapshot-failure-in-non-root-geo-rep-se.patch b/SOURCES/0306-glusterd-Fix-snapshot-failure-in-non-root-geo-rep-se.patch deleted file mode 100644 index 7c3bf26..0000000 --- a/SOURCES/0306-glusterd-Fix-snapshot-failure-in-non-root-geo-rep-se.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 8606249c1888c092c1d8eac022116f0b4358a07d Mon Sep 17 00:00:00 2001 -From: Kotresh HR -Date: Mon, 17 Apr 2017 08:39:30 -0400 -Subject: [PATCH 306/316] glusterd: Fix snapshot failure in non-root geo-rep - setup - -Geo-replication session directory name has the form -'__'. But in non-root -geo-replication setup, while preparing geo-replication -session directory name, glusterd is including 'user@' -resulting in "__". -Hence snapshot is failing to copy geo-rep specific -session files. Fixing the same. - -> BUG: 1442760 -> Signed-off-by: Kotresh HR -> Reviewed-on: https://review.gluster.org/17067 -> Smoke: Gluster Build System -> NetBSD-regression: NetBSD Build System -> Reviewed-by: Amar Tumballi -> CentOS-regression: Gluster Build System -> Reviewed-by: Aravinda VK - -Change-Id: Id214d3186e40997d2827a0bb60d3676ca2552df7 -BUG: 1445593 -Signed-off-by: Kotresh HR -Reviewed-on: https://code.engineering.redhat.com/gerrit/105176 -Reviewed-by: Atin Mukherjee ---- - xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c -index 26b2f73..c4cfc84 100644 ---- a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c -+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c -@@ -3500,6 +3500,7 @@ glusterd_get_geo_rep_session (char *slave_key, char *origin_volname, - char *slave) - { - int32_t ret = -1; -+ int32_t len = 0; - char *token = NULL; - char *tok = NULL; - char *temp = NULL; -@@ -3568,8 +3569,10 @@ glusterd_get_geo_rep_session (char *slave_key, char *origin_volname, - * 'root@' */ - ip_temp = gf_strdup (ip); - tok = strtok_r (ip_temp, "@", &save_ptr); -- if (tok && !strcmp (tok, "root")) -- ip_i = ip + 5; -+ len = strlen(tok); -+ tok = strtok_r (NULL, "@", &save_ptr); -+ if (tok != NULL) -+ ip_i = ip + len + 1; - - ret = snprintf (session, PATH_MAX, "%s_%s_%s", - origin_volname, ip_i, slave_temp); --- -1.8.3.1 - diff --git a/SOURCES/0307-geo-rep-Do-not-restart-workers-when-log-rsync-perfor.patch b/SOURCES/0307-geo-rep-Do-not-restart-workers-when-log-rsync-perfor.patch new file mode 100644 index 0000000..ebce128 --- /dev/null +++ b/SOURCES/0307-geo-rep-Do-not-restart-workers-when-log-rsync-perfor.patch @@ -0,0 +1,73 @@ +From 39b659e8cabc3a2f2bdd8fe41222f2425e8d067d Mon Sep 17 00:00:00 2001 +From: Aravinda VK +Date: Thu, 10 Nov 2016 12:35:30 +0530 +Subject: [PATCH 307/361] geo-rep: Do not restart workers when + log-rsync-performance config change + +Geo-rep restarts workers when any of the configurations changed. We +don't need to restart workers if tunables like log-rsync-performance +is modified. + +With this patch, Geo-rep workers will get new "log-rsync-performance" +config automatically without restart. + +mainline: +> BUG: 1393678 +> Reviewed-on: http://review.gluster.org/15816 +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Kotresh HR +(cherry picked from commit 423ac928402fa215fb4eda5f135fb725f6a2bf98) + +BUG: 1425690 +Change-Id: I40ec253892ea7e70c727fa5d3c540a11e891897b +Signed-off-by: Aravinda VK +Reviewed-on: https://code.engineering.redhat.com/gerrit/101287 +Tested-by: Milind Changire +Reviewed-by: Atin Mukherjee +--- + geo-replication/syncdaemon/resource.py | 6 ++++-- + xlators/mgmt/glusterd/src/glusterd-geo-rep.c | 2 ++ + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py +index b887d37..be663e4 100644 +--- a/geo-replication/syncdaemon/resource.py ++++ b/geo-replication/syncdaemon/resource.py +@@ -1001,7 +1001,8 @@ class SlaveRemote(object): + (boolify(gconf.sync_acls) and ['--acls'] or []) + \ + ['.'] + list(args) + +- if gconf.log_rsync_performance: ++ if boolify(gconf.configinterface.get_realtime( ++ "log_rsync_performance")): + # use stdout=PIPE only when log_rsync_performance enabled + # Else rsync will write to stdout and nobody is their + # to consume. If PIPE is full rsync hangs. +@@ -1020,7 +1021,8 @@ class SlaveRemote(object): + for errline in stderr.strip().split("\n")[:-1]: + logging.error("SYNC Error(Rsync): %s" % errline) + +- if gconf.log_rsync_performance: ++ if boolify(gconf.configinterface.get_realtime( ++ "log_rsync_performance")): + rsync_msg = [] + for line in stdout.split("\n"): + if line.startswith("Number of files:") or \ +diff --git a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c +index a67dea1..9a702b7 100644 +--- a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c ++++ b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c +@@ -81,6 +81,8 @@ static char *gsync_reserved_opts[] = { + + static char *gsync_no_restart_opts[] = { + "checkpoint", ++ "log_rsync_performance", ++ "log-rsync-performance", + NULL + }; + +-- +1.8.3.1 + diff --git a/SOURCES/0307-nfs-make-subdir-mounting-work-for-Solaris-10-clients.patch b/SOURCES/0307-nfs-make-subdir-mounting-work-for-Solaris-10-clients.patch deleted file mode 100644 index d517b99..0000000 --- a/SOURCES/0307-nfs-make-subdir-mounting-work-for-Solaris-10-clients.patch +++ /dev/null @@ -1,225 +0,0 @@ -From f25b41d227c2e58ebff356e73c7a5123dc032fb8 Mon Sep 17 00:00:00 2001 -From: Bipin Kunal -Date: Mon, 27 Feb 2017 15:23:04 +0530 -Subject: [PATCH 307/316] nfs: make subdir mounting work for Solaris 10 clients - -This fixes the segfault caused by solaris client in Gluster/NFS. -Volname was not being parsed properly, Instead of volume -name complete path was being used in nfs_mntpath_to_xlator(). -Fixed it by striping volume name from complete path in nfs_mntpath_to_xlator(). - -Modified function name nfs3_funge_solaris_zerolen_fh() to -nfs3_funge_webnfs_zerolen_fh() as zero-filled filehandle is specific to WebNFS. -RFC : https://tools.ietf.org/html/rfc2055 -Solaris uses WebNFS, the zero-filled FH is defined in the WebNFS spec. - -Logic was even added in fuction nfs3_funge_webnfs_zerolen_fh() to send -subdir path in function glfs_resolve_at() instead of complete path for -subdir mount. - ->Reviewed-on: https://review.gluster.org/16770 ->Reviewed-by: Niels de Vos ->Smoke: Gluster Build System ->NetBSD-regression: NetBSD Build System ->CentOS-regression: Gluster Build System - -Change-Id: I19aae3547b8910e7ed4974ee5385424cab3e834a -Signed-off-by: Bipin Kunal -Reviewed-on: https://code.engineering.redhat.com/gerrit/105188 -Reviewed-by: Niels de Vos -Tested-by: Atin Mukherjee ---- - api/src/glfs-resolve.c | 6 ++- - xlators/nfs/server/src/nfs-common.c | 18 +++++-- - xlators/nfs/server/src/nfs3.c | 96 +++++++++++++++++++++++++++---------- - 3 files changed, 89 insertions(+), 31 deletions(-) - -diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c -index f8b437b..d495cd2 100644 ---- a/api/src/glfs-resolve.c -+++ b/api/src/glfs-resolve.c -@@ -385,6 +385,9 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at, - int ret = -1; - struct iatt ciatt = {0, }; - -+ DECLARE_OLD_THIS; -+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs); -+ - path = gf_strdup (origpath); - if (!path) { - errno = ENOMEM; -@@ -510,9 +513,10 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at, - } - out: - GF_FREE (path); -+ __GLFS_EXIT_FS; - - /* do NOT loc_wipe here as only last component might be missing */ -- -+invalid_fs: - return ret; - } - -diff --git a/xlators/nfs/server/src/nfs-common.c b/xlators/nfs/server/src/nfs-common.c -index af37f6b..5269188 100644 ---- a/xlators/nfs/server/src/nfs-common.c -+++ b/xlators/nfs/server/src/nfs-common.c -@@ -73,10 +73,11 @@ nfs_xlator_to_xlid (xlator_list_t *cl, xlator_t *xl) - xlator_t * - nfs_mntpath_to_xlator (xlator_list_t *cl, char *path) - { -- char *volname = NULL; -- char *volptr = NULL; -- size_t pathlen; -+ char *volname = NULL; -+ char *volptr = NULL; -+ size_t pathlen = -1; - xlator_t *targetxl = NULL; -+ int i = 0; - - if ((!cl) || (!path)) - return NULL; -@@ -89,10 +90,17 @@ nfs_mntpath_to_xlator (xlator_list_t *cl, char *path) - else - volptr = &volname[0]; - -- if (pathlen && volname[pathlen - 1] == '/') -- volname[pathlen - 1] = '\0'; -+ for (i = 0; i < pathlen; i++) { -+ if (volname[i] == '/') { -+ volname[i] = '\0'; -+ break; -+ } -+ } - - while (cl) { -+ gf_msg_trace (GF_NFS, 0, "Volptr: %s and cl->xlator->name: %s", -+ volptr, cl->xlator->name); -+ - if (strcmp (volptr, cl->xlator->name) == 0) { - targetxl = cl->xlator; - break; -diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c -index 64287c5..8b1d62b 100644 ---- a/xlators/nfs/server/src/nfs3.c -+++ b/xlators/nfs/server/src/nfs3.c -@@ -28,6 +28,7 @@ - #include "xdr-rpc.h" - #include "xdr-generic.h" - #include "nfs-messages.h" -+#include "glfs-internal.h" - - #include - #include -@@ -348,28 +349,68 @@ out: - } - - --#define nfs3_funge_solaris_zerolen_fh(nfs3st, fhd, enam, nfsst, erl) \ -- do { \ -- xlator_t *fungexl = NULL; \ -- uuid_t zero = {0, }; \ -- fungexl =nfs_mntpath_to_xlator ((nfs3st)->exportslist,enam);\ -- if (!fungexl) { \ -- (nfsst) = NFS3ERR_NOENT; \ -- goto erl; \ -- } \ -- \ -- gf_uuid_copy ((fhd)->gfid, zero); \ -- (fhd)->gfid[15] = 1; \ -- (enam) = NULL; \ -- if ((gf_nfs_dvm_off (nfs_state (nfs3st->nfsx)))) \ -- (fhd)->exportid[15] = nfs_xlator_to_xlid ((nfs3st)->exportslist, fungexl); \ -- else { \ -- if(__nfs3_get_volume_id ((nfs3st), fungexl, (fhd)->exportid) < 0) { \ -- (nfsst) = NFS3ERR_STALE; \ -- goto erl; \ -- } \ -- } \ -- } while (0) \ -+static enum nfsstat3 -+nfs3_funge_webnfs_zerolen_fh (struct nfs3_state *nfs3st, struct nfs3_fh *fhd, -+ char *name) -+{ -+ xlator_t *fungexl = NULL; -+ glfs_t *fs = NULL; -+ loc_t loc = { 0, }; -+ enum nfsstat3 nfsstat = NFS3ERR_SERVERFAULT; -+ int ret = -1; -+ size_t namelen = -1; -+ -+ fungexl = nfs_mntpath_to_xlator (nfs3st->exportslist, name); -+ if (!fungexl) { -+ nfsstat = NFS3ERR_NOENT; -+ goto out; -+ } -+ -+ /* glfs_resolve_at copied from UDP MNT support */ -+ fs = glfs_new_from_ctx (fungexl->ctx); -+ if (!fs) { -+ nfsstat = NFS3ERR_NOENT; -+ goto out; -+ } -+ -+ /* strip volname/ from 'name' */ -+ namelen = strlen(name); -+ while (namelen != 0) { -+ name++; -+ if (name[0] == '/') { -+ break; -+ } -+ namelen--; -+ } -+ gf_msg_debug (GF_NFS, 0, "NAME :%s ", name); -+ -+ ret = glfs_resolve_at (fs, fungexl, NULL, name, &loc, NULL, 1, 0); -+ if (ret != 0) { -+ nfsstat = NFS3ERR_NOENT; -+ goto out; -+ } -+ -+ /* resolved subdir, copy gfid for the fh */ -+ gf_uuid_copy (fhd->gfid, loc.gfid); -+ loc_wipe (&loc); -+ -+ if (gf_nfs_dvm_off (nfs_state (nfs3st->nfsx))) -+ fhd->exportid[15] = nfs_xlator_to_xlid (nfs3st->exportslist, -+ fungexl); -+ else { -+ if (__nfs3_get_volume_id (nfs3st, fungexl, fhd->exportid) < 0) { -+ nfsstat = NFS3ERR_STALE; -+ goto out; -+ } -+ } -+ -+ nfsstat = NFS3_OK; -+out: -+ if (fs) -+ glfs_free_from_ctx (fs); -+ -+ return nfsstat; -+} - - - #define nfs3_volume_started_check(nf3stt, vlm, rtval, erlbl) \ -@@ -1495,9 +1536,14 @@ nfs3_lookup (rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name) - nfs3_log_fh_entry_call (rpcsvc_request_xid (req), "LOOKUP", fh, - name); - nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret); -- if (nfs3_solaris_zerolen_fh (fh, fhlen)) -- nfs3_funge_solaris_zerolen_fh (nfs3, fh, name, stat, nfs3err); -- else -+ if (nfs3_solaris_zerolen_fh (fh, fhlen)) { -+ stat = nfs3_funge_webnfs_zerolen_fh (nfs3, fh, name); -+ if (stat != NFS3_OK) -+ goto nfs3err; -+ -+ /* this fh means we're doing a mount, name is no more useful */ -+ name = NULL; -+ } else - nfs3_validate_gluster_fh (fh, stat, nfs3err); - nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret); - nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err); --- -1.8.3.1 - diff --git a/SOURCES/0308-features-shard-Fix-vm-corruption-upon-fix-layout.patch b/SOURCES/0308-features-shard-Fix-vm-corruption-upon-fix-layout.patch deleted file mode 100644 index c20cdf6..0000000 --- a/SOURCES/0308-features-shard-Fix-vm-corruption-upon-fix-layout.patch +++ /dev/null @@ -1,300 +0,0 @@ -From 4a6bdc7f785b8a030142d8036a13ae2f78984934 Mon Sep 17 00:00:00 2001 -From: Krutika Dhananjay -Date: Thu, 6 Apr 2017 18:10:41 +0530 -Subject: [PATCH 308/316] features/shard: Fix vm corruption upon fix-layout - - Backport of: https://review.gluster.org/17010 - -shard's writev implementation, as part of identifying -presence of participant shards that aren't in memory, -first sends an MKNOD on these shards, and upon EEXIST error, -looks up the shards before proceeding with the writes. - -The VM corruption was caused when the following happened: -1. DHT had n subvolumes initially. -2. Upon add-brick + fix-layout, the layout of .shard changed - although the existing shards under it were yet to be migrated - to their new hashed subvolumes. -3. During this time, there were writes on the VM falling in regions - of the file whose corresponding shards were already existing under - .shard. -4. Sharding xl sent MKNOD on these shards, now creating them in their - new hashed subvolumes although there already exist shard blocks for - this region with valid data. -5. All subsequent writes were wound on these newly created copies. - -The net outcome is that both copies of the shard didn't have the correct -data. This caused the affected VMs to be unbootable. - -FIX: -For want of better alternatives in DHT, the fix changes shard fops to do -a LOOKUP before the MKNOD and upon EEXIST error, perform another lookup. - -Change-Id: I4086e7a9c27c9325b3830f4274be87847283a9f2 -BUG: 1439753 -RCA'd-by: Raghavendra Gowdappa -Reported-by: Mahdi Adnan -Signed-off-by: Krutika Dhananjay -Reviewed-on: https://code.engineering.redhat.com/gerrit/105195 -Reviewed-by: Atin Mukherjee ---- - xlators/features/shard/src/shard.c | 154 +++++++++++++++++++++++-------------- - xlators/features/shard/src/shard.h | 1 + - 2 files changed, 96 insertions(+), 59 deletions(-) - -diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c -index 9504f12..eabed90 100644 ---- a/xlators/features/shard/src/shard.c -+++ b/xlators/features/shard/src/shard.c -@@ -1693,11 +1693,30 @@ shard_common_lookup_shards_cbk (call_frame_t *frame, void *cookie, - - if (op_ret < 0) { - /* Ignore absence of shards in the backend in truncate fop. */ -- if (((local->fop == GF_FOP_TRUNCATE) || -- (local->fop == GF_FOP_FTRUNCATE) || -- (local->fop == GF_FOP_RENAME) || -- (local->fop == GF_FOP_UNLINK)) && (op_errno == ENOENT)) -- goto done; -+ switch (local->fop) { -+ case GF_FOP_TRUNCATE: -+ case GF_FOP_FTRUNCATE: -+ case GF_FOP_RENAME: -+ case GF_FOP_UNLINK: -+ if (op_errno == ENOENT) -+ goto done; -+ break; -+ case GF_FOP_WRITE: -+ case GF_FOP_READ: -+ case GF_FOP_ZEROFILL: -+ case GF_FOP_DISCARD: -+ case GF_FOP_FALLOCATE: -+ if ((!local->first_lookup_done) && -+ (op_errno == ENOENT)) { -+ local->create_count++; -+ goto done; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ /* else */ - gf_msg (this->name, GF_LOG_ERROR, op_errno, - SHARD_MSG_LOOKUP_SHARD_FAILED, "Lookup on shard %d " - "failed. Base file gfid = %s", shard_block_num, -@@ -1714,6 +1733,8 @@ shard_common_lookup_shards_cbk (call_frame_t *frame, void *cookie, - done: - call_count = shard_call_count_return (frame); - if (call_count == 0) { -+ if (!local->first_lookup_done) -+ local->first_lookup_done = _gf_true; - if (local->op_ret < 0) - goto unwind; - else -@@ -3197,47 +3218,6 @@ next: - } - - int --shard_post_lookup_shards_readv_handler (call_frame_t *frame, xlator_t *this) --{ -- shard_local_t *local = NULL; -- -- local = frame->local; -- -- if (local->op_ret < 0) { -- SHARD_STACK_UNWIND (readv, frame, local->op_ret, -- local->op_errno, NULL, 0, NULL, NULL, NULL); -- return 0; -- } -- -- shard_readv_do (frame, this); -- -- return 0; --} -- --int --shard_post_mknod_readv_handler (call_frame_t *frame, xlator_t *this) --{ -- shard_local_t *local = NULL; -- -- local = frame->local; -- -- if (local->op_ret < 0) { -- SHARD_STACK_UNWIND (readv, frame, local->op_ret, -- local->op_errno, NULL, 0, NULL, NULL, NULL); -- return 0; -- } -- -- if (!local->eexist_count) { -- shard_readv_do (frame, this); -- } else { -- local->call_count = local->eexist_count; -- shard_common_lookup_shards (frame, this, local->loc.inode, -- shard_post_lookup_shards_readv_handler); -- } -- return 0; --} -- --int - shard_common_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, inode_t *inode, - struct iatt *buf, struct iatt *preparent, -@@ -3267,6 +3247,7 @@ done: - call_count = shard_call_count_return (frame); - if (call_count == 0) { - SHARD_UNSET_ROOT_FS_ID (frame, local); -+ local->create_count = 0; - local->post_mknod_handler (frame, this); - } - -@@ -3397,6 +3378,55 @@ err: - } - - int -+shard_post_mknod_readv_handler (call_frame_t *frame, xlator_t *this); -+ -+int -+shard_post_lookup_shards_readv_handler (call_frame_t *frame, xlator_t *this) -+{ -+ shard_local_t *local = NULL; -+ -+ local = frame->local; -+ -+ if (local->op_ret < 0) { -+ SHARD_STACK_UNWIND (readv, frame, local->op_ret, -+ local->op_errno, NULL, 0, NULL, NULL, NULL); -+ return 0; -+ } -+ -+ if (local->create_count) { -+ shard_common_resume_mknod (frame, this, -+ shard_post_mknod_readv_handler); -+ } else { -+ shard_readv_do (frame, this); -+ } -+ -+ return 0; -+} -+ -+int -+shard_post_mknod_readv_handler (call_frame_t *frame, xlator_t *this) -+{ -+ shard_local_t *local = NULL; -+ -+ local = frame->local; -+ -+ if (local->op_ret < 0) { -+ SHARD_STACK_UNWIND (readv, frame, local->op_ret, -+ local->op_errno, NULL, 0, NULL, NULL, NULL); -+ return 0; -+ } -+ -+ if (!local->eexist_count) { -+ shard_readv_do (frame, this); -+ } else { -+ local->call_count = local->eexist_count; -+ shard_common_lookup_shards (frame, this, local->loc.inode, -+ shard_post_lookup_shards_readv_handler); -+ } -+ return 0; -+} -+ -+int - shard_post_resolve_readv_handler (call_frame_t *frame, xlator_t *this) - { - shard_local_t *local = NULL; -@@ -3422,9 +3452,9 @@ shard_post_resolve_readv_handler (call_frame_t *frame, xlator_t *this) - } - - if (local->call_count) { -- local->create_count = local->call_count; -- shard_common_resume_mknod (frame, this, -- shard_post_mknod_readv_handler); -+ shard_common_lookup_shards (frame, this, -+ local->resolver_base_inode, -+ shard_post_lookup_shards_readv_handler); - } else { - shard_readv_do (frame, this); - } -@@ -3575,14 +3605,11 @@ shard_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, - - shard_lookup_base_file (frame, this, &local->loc, - shard_post_lookup_readv_handler); -- - return 0; -- - err: - SHARD_STACK_UNWIND (readv, frame, -1, ENOMEM, NULL, 0, NULL, NULL, - NULL); - return 0; -- - } - - int -@@ -3875,6 +3902,10 @@ next: - } - - int -+shard_common_inode_write_post_mknod_handler (call_frame_t *frame, -+ xlator_t *this); -+ -+int - shard_common_inode_write_post_lookup_shards_handler (call_frame_t *frame, - xlator_t *this) - { -@@ -3889,7 +3920,12 @@ shard_common_inode_write_post_lookup_shards_handler (call_frame_t *frame, - return 0; - } - -- shard_common_inode_write_do (frame, this); -+ if (local->create_count) { -+ shard_common_resume_mknod (frame, this, -+ shard_common_inode_write_post_mknod_handler); -+ } else { -+ shard_common_inode_write_do (frame, this); -+ } - - return 0; - } -@@ -3937,11 +3973,13 @@ shard_common_inode_write_post_lookup_handler (call_frame_t *frame, - - local->postbuf = local->prebuf; - -- if (local->create_count) -- shard_common_resume_mknod (frame, this, -- shard_common_inode_write_post_mknod_handler); -- else -+ if (local->call_count) { -+ shard_common_lookup_shards (frame, this, -+ local->resolver_base_inode, -+ shard_common_inode_write_post_lookup_shards_handler); -+ } else { - shard_common_inode_write_do (frame, this); -+ } - - return 0; - } -@@ -3961,8 +3999,6 @@ shard_common_inode_write_post_resolve_handler (call_frame_t *frame, - return 0; - } - -- local->create_count = local->call_count; -- - shard_lookup_base_file (frame, this, &local->loc, - shard_common_inode_write_post_lookup_handler); - return 0; -diff --git a/xlators/features/shard/src/shard.h b/xlators/features/shard/src/shard.h -index 09232a4..7319598 100644 ---- a/xlators/features/shard/src/shard.h -+++ b/xlators/features/shard/src/shard.h -@@ -255,6 +255,7 @@ typedef struct shard_local { - shard_lock_t *shard_lock; - } lock; - inode_t *resolver_base_inode; -+ gf_boolean_t first_lookup_done; - } shard_local_t; - - typedef struct shard_inode_ctx { --- -1.8.3.1 - diff --git a/SOURCES/0308-geo-rep-Fix-log-rsync-performance-config-issue.patch b/SOURCES/0308-geo-rep-Fix-log-rsync-performance-config-issue.patch new file mode 100644 index 0000000..6fc2f9c --- /dev/null +++ b/SOURCES/0308-geo-rep-Fix-log-rsync-performance-config-issue.patch @@ -0,0 +1,110 @@ +From a7d463c44d1daa0be48a5ad063ec63b5a8e8002e Mon Sep 17 00:00:00 2001 +From: Aravinda VK +Date: Mon, 12 Dec 2016 13:06:15 +0530 +Subject: [PATCH 308/361] geo-rep: Fix log-rsync-performance config issue + +If log-rsync-performance config is not set, gconf.get_realtime +will return None, Added default value as False if config file +doesn't have this option set. + +mainline: +> BUG: 1393678 +> Reviewed-on: http://review.gluster.org/16102 +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Kotresh HR +> Tested-by: Kotresh HR +(cherry picked from commit 508e052a95e2f36173a274250f38dd92c8add868) + +BUG: 1425690 +Change-Id: I89016ab480a16179db59913d635d8553beb7e14f +Signed-off-by: Aravinda VK +Reviewed-on: https://code.engineering.redhat.com/gerrit/101288 +Tested-by: Milind Changire +Reviewed-by: Atin Mukherjee +--- + geo-replication/syncdaemon/configinterface.py | 17 +++++++++-------- + geo-replication/syncdaemon/resource.py | 9 +++++---- + 2 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/geo-replication/syncdaemon/configinterface.py b/geo-replication/syncdaemon/configinterface.py +index adcefb8..b5935df 100644 +--- a/geo-replication/syncdaemon/configinterface.py ++++ b/geo-replication/syncdaemon/configinterface.py +@@ -235,7 +235,7 @@ class GConffile(object): + self.config.readfp(fp) + self._normconfig() + +- def get_realtime(self, opt): ++ def get_realtime(self, opt, default_value=None): + try: + sres = os.stat(self.path) + except (OSError, IOError): +@@ -249,7 +249,7 @@ class GConffile(object): + sres[ST_INO] != self.ino or self.mtime != sres[ST_MTIME]: + self._load() + +- return self.get(opt, printValue=False) ++ return self.get(opt, printValue=False, default_value=default_value) + + def section(self, rx=False): + """get the section name of the section representing .peers +@@ -348,7 +348,7 @@ class GConffile(object): + if self.config.has_section(self.section()): + update_from_sect(self.section(), MultiDict(dct, *self.auxdicts)) + +- def get(self, opt=None, printValue=True): ++ def get(self, opt=None, printValue=True, default_value=None): + """print the matching key/value pairs from .config, + or if @opt given, the value for @opt (according to the + logic described in .update_to) +@@ -357,12 +357,13 @@ class GConffile(object): + self.update_to(d, allow_unresolved=True) + if opt: + opt = norm(opt) +- v = d.get(opt) +- if v: +- if printValue: ++ v = d.get(opt, default_value) ++ ++ if printValue: ++ if v is not None: + print(v) +- else: +- return v ++ else: ++ return v + else: + for k, v in d.iteritems(): + if k == '__name__': +diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py +index be663e4..9c7a70a 100644 +--- a/geo-replication/syncdaemon/resource.py ++++ b/geo-replication/syncdaemon/resource.py +@@ -1001,8 +1001,10 @@ class SlaveRemote(object): + (boolify(gconf.sync_acls) and ['--acls'] or []) + \ + ['.'] + list(args) + +- if boolify(gconf.configinterface.get_realtime( +- "log_rsync_performance")): ++ log_rsync_performance = boolify(gconf.configinterface.get_realtime( ++ "log_rsync_performance", default_value=False)) ++ ++ if log_rsync_performance: + # use stdout=PIPE only when log_rsync_performance enabled + # Else rsync will write to stdout and nobody is their + # to consume. If PIPE is full rsync hangs. +@@ -1021,8 +1023,7 @@ class SlaveRemote(object): + for errline in stderr.strip().split("\n")[:-1]: + logging.error("SYNC Error(Rsync): %s" % errline) + +- if boolify(gconf.configinterface.get_realtime( +- "log_rsync_performance")): ++ if log_rsync_performance: + rsync_msg = [] + for line in stdout.split("\n"): + if line.startswith("Number of files:") or \ +-- +1.8.3.1 + diff --git a/SOURCES/0309-features-shard-Initialize-local-fop-in-readv.patch b/SOURCES/0309-features-shard-Initialize-local-fop-in-readv.patch deleted file mode 100644 index 23412b2..0000000 --- a/SOURCES/0309-features-shard-Initialize-local-fop-in-readv.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 6494b76754e9da36338a6b30a9c66ba08285a401 Mon Sep 17 00:00:00 2001 -From: Krutika Dhananjay -Date: Mon, 10 Apr 2017 11:04:31 +0530 -Subject: [PATCH 309/316] features/shard: Initialize local->fop in readv - - Backport of: https://review.gluster.org/17014 - -Change-Id: I9ea64df96e3b05a1d92522a03cf2a1045f1ded3d -BUG: 1439753 -Signed-off-by: Krutika Dhananjay -Reviewed-on: https://code.engineering.redhat.com/gerrit/105196 -Reviewed-by: Atin Mukherjee ---- - xlators/features/shard/src/shard.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c -index eabed90..4dd581d 100644 ---- a/xlators/features/shard/src/shard.c -+++ b/xlators/features/shard/src/shard.c -@@ -3596,6 +3596,7 @@ shard_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, - local->offset = offset; - local->req_size = size; - local->flags = flags; -+ local->fop = GF_FOP_READ; - local->xattr_req = (xdata) ? dict_ref (xdata) : dict_new (); - if (!local->xattr_req) - goto err; --- -1.8.3.1 - diff --git a/SOURCES/0309-glusterd-Add-info-on-op-version-for-clients-in-vol-s.patch b/SOURCES/0309-glusterd-Add-info-on-op-version-for-clients-in-vol-s.patch new file mode 100644 index 0000000..a6e44d2 --- /dev/null +++ b/SOURCES/0309-glusterd-Add-info-on-op-version-for-clients-in-vol-s.patch @@ -0,0 +1,218 @@ +From dcc96757fbafa555a548271c7efd52ca796f9552 Mon Sep 17 00:00:00 2001 +From: Samikshan Bairagya +Date: Wed, 28 Dec 2016 20:33:54 +0530 +Subject: [PATCH 309/361] glusterd: Add info on op-version for clients in vol + status output + +Currently the `gluster volume status clients` command +gives us the following information on clients: +1. Brick name +2. Client count for each brick +3. hostname:port for each client +4. Bytes read and written for each client + +There is no information regarding op-version for each client. This +patch adds that to the output. + +mainline: +> BUG: 1409078 +> Reviewed-on: http://review.gluster.org/16303 +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Atin Mukherjee +(cherry picked from commit fc39ed4d69f7e7f7ca9b3fd100f8be307ae53fe2) + +BUG: 1351185 +Change-Id: Ib2ece93ab00c234162bb92b7c67a7d86f3350a8d +Signed-off-by: Samikshan Bairagya +Reviewed-on: https://code.engineering.redhat.com/gerrit/101289 +Tested-by: Milind Changire +Reviewed-by: Atin Mukherjee +--- + cli/src/cli-rpc-ops.c | 19 +++++++++++++------ + cli/src/cli-xml-output.c | 12 ++++++++++++ + xlators/protocol/client/src/client-handshake.c | 6 ++++++ + xlators/protocol/server/src/server-handshake.c | 18 ++++++++++++++++++ + xlators/protocol/server/src/server-messages.h | 11 ++++++++++- + xlators/protocol/server/src/server.c | 8 ++++++++ + 6 files changed, 67 insertions(+), 7 deletions(-) + +diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c +index bea5437..5a0cfdf 100644 +--- a/cli/src/cli-rpc-ops.c ++++ b/cli/src/cli-rpc-ops.c +@@ -7253,6 +7253,7 @@ cli_print_volume_status_clients (dict_t *dict, gf_boolean_t notbrick) + char *clientname = NULL; + uint64_t bytesread = 0; + uint64_t byteswrite = 0; ++ uint32_t opversion = 0; + char key[1024] = {0,}; + int i = 0; + int j = 0; +@@ -7318,10 +7319,10 @@ cli_print_volume_status_clients (dict_t *dict, gf_boolean_t notbrick) + if (client_count == 0) + continue; + +- cli_out ("%-48s %15s %15s", "Hostname", "BytesRead", +- "BytesWritten"); +- cli_out ("%-48s %15s %15s", "--------", "---------", +- "------------"); ++ cli_out ("%-48s %15s %15s %15s", "Hostname", "BytesRead", ++ "BytesWritten", "OpVersion"); ++ cli_out ("%-48s %15s %15s %15s", "--------", "---------", ++ "------------", "---------"); + for (j =0; j < client_count; j++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), +@@ -7338,8 +7339,14 @@ cli_print_volume_status_clients (dict_t *dict, gf_boolean_t notbrick) + "brick%d.client%d.byteswrite", i, j); + ret = dict_get_uint64 (dict, key, &byteswrite); + +- cli_out ("%-48s %15"PRIu64" %15"PRIu64, +- clientname, bytesread, byteswrite); ++ memset (key, 0, sizeof (key)); ++ snprintf (key, sizeof (key), ++ "brick%d.client%d.opversion", i, j); ++ ret = dict_get_uint32 (dict, key, &opversion); ++ ++ cli_out ("%-48s %15"PRIu64" %15"PRIu64" %15"PRIu32, ++ clientname, bytesread, byteswrite, ++ opversion); + } + } + out: +diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c +index 063e171..d0d8179 100644 +--- a/cli/src/cli-xml-output.c ++++ b/cli/src/cli-xml-output.c +@@ -743,6 +743,7 @@ cli_xml_output_vol_status_clients (xmlTextWriterPtr writer, dict_t *dict, + char *hostname = NULL; + uint64_t bytes_read = 0; + uint64_t bytes_write = 0; ++ uint32_t opversion = 0; + char key[1024] = {0,}; + int i = 0; + +@@ -797,6 +798,17 @@ cli_xml_output_vol_status_clients (xmlTextWriterPtr writer, dict_t *dict, + "%"PRIu64, bytes_write); + XML_RET_CHECK_AND_GOTO (ret, out); + ++ memset (key, 0, sizeof (key)); ++ snprintf (key, sizeof (key), "brick%d.client%d.opversion", ++ brick_index, i); ++ ret = dict_get_uint32 (dict, key, &opversion); ++ if (ret) ++ goto out; ++ ret = xmlTextWriterWriteFormatElement (writer, ++ (xmlChar *)"opVersion", ++ "%"PRIu32, opversion); ++ XML_RET_CHECK_AND_GOTO (ret, out); ++ + /* */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); +diff --git a/xlators/protocol/client/src/client-handshake.c b/xlators/protocol/client/src/client-handshake.c +index 7866697..f51c43f 100644 +--- a/xlators/protocol/client/src/client-handshake.c ++++ b/xlators/protocol/client/src/client-handshake.c +@@ -1379,6 +1379,12 @@ client_setvolume (xlator_t *this, struct rpc_clnt *rpc) + "msg", client_get_lk_ver (conf)); + } + ++ ret = dict_set_int32 (options, "opversion", GD_OP_VERSION_MAX); ++ if (ret < 0) { ++ gf_msg (this->name, GF_LOG_ERROR, 0, PC_MSG_DICT_SET_FAILED, ++ "Failed to set client opversion in handshake message"); ++ } ++ + ret = dict_serialized_length (options); + if (ret < 0) { + gf_msg (this->name, GF_LOG_ERROR, 0, PC_MSG_DICT_ERROR, +diff --git a/xlators/protocol/server/src/server-handshake.c b/xlators/protocol/server/src/server-handshake.c +index 1230cdf..a33efb8 100644 +--- a/xlators/protocol/server/src/server-handshake.c ++++ b/xlators/protocol/server/src/server-handshake.c +@@ -431,6 +431,8 @@ server_setvolume (rpcsvc_request_t *req) + uint32_t lk_version = 0; + char *buf = NULL; + gf_boolean_t cancelled = _gf_false; ++ uint32_t opversion = 0; ++ rpc_transport_t *xprt = NULL; + + params = dict_new (); + reply = dict_new (); +@@ -669,6 +671,22 @@ server_setvolume (rpcsvc_request_t *req) + gf_msg_debug (this->name, 0, "failed to set " + "peer-info"); + } ++ ++ ret = dict_get_uint32 (params, "opversion", &opversion); ++ if (ret) ++ gf_msg (this->name, GF_LOG_INFO, 0, ++ PS_MSG_CLIENT_OPVERSION_GET_FAILED, ++ "Failed to get client opversion"); ++ ++ /* Assign op-version value to the client */ ++ pthread_mutex_lock (&conf->mutex); ++ list_for_each_entry (xprt, &conf->xprt_list, list) { ++ if (strcmp (peerinfo->identifier, xprt->peerinfo.identifier)) ++ continue; ++ xprt->peerinfo.max_op_version = opversion; ++ } ++ pthread_mutex_unlock (&conf->mutex); ++ + if (conf->auth_modules == NULL) { + gf_msg (this->name, GF_LOG_ERROR, 0, PS_MSG_AUTH_INIT_FAILED, + "Authentication module not initialized"); +diff --git a/xlators/protocol/server/src/server-messages.h b/xlators/protocol/server/src/server-messages.h +index 5593e68..b8245af 100644 +--- a/xlators/protocol/server/src/server-messages.h ++++ b/xlators/protocol/server/src/server-messages.h +@@ -40,7 +40,7 @@ + */ + + #define GLFS_PS_BASE GLFS_MSGID_COMP_PS +-#define GLFS_NUM_MESSAGES 90 ++#define GLFS_NUM_MESSAGES 91 + #define GLFS_MSGID_END (GLFS_PS_BASE + GLFS_NUM_MESSAGES + 1) + /* Messages with message IDs */ + #define glfs_msg_start_x GLFS_PS_BASE, "Invalid: Start of messages" +@@ -848,6 +848,15 @@ + */ + + #define PS_MSG_COMPOUND_INFO (GLFS_PS_BASE + 90) ++ ++/*! ++ * @messageid ++ * @diagnosis ++ * @recommendedaction ++ * ++ */ ++ ++#define PS_MSG_CLIENT_OPVERSION_GET_FAILED (GLFS_PS_BASE + 91) + /*------------*/ + #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages" + +diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c +index 0bbfd09..db4338e 100644 +--- a/xlators/protocol/server/src/server.c ++++ b/xlators/protocol/server/src/server.c +@@ -276,6 +276,14 @@ server_priv_to_dict (xlator_t *this, dict_t *dict) + if (ret) + goto unlock; + ++ memset (key, 0, sizeof (key)); ++ snprintf (key, sizeof (key), "client%d.opversion", ++ count); ++ ret = dict_set_uint32 (dict, key, ++ peerinfo->max_op_version); ++ if (ret) ++ goto unlock; ++ + count++; + } + } +-- +1.8.3.1 + diff --git a/SOURCES/0310-cli-geo-rep-Fix-geo-rep-status-detail.patch b/SOURCES/0310-cli-geo-rep-Fix-geo-rep-status-detail.patch new file mode 100644 index 0000000..b7de928 --- /dev/null +++ b/SOURCES/0310-cli-geo-rep-Fix-geo-rep-status-detail.patch @@ -0,0 +1,95 @@ +From 2cae6c74f4ff8a26d81d12322e4c005f0fd25c20 Mon Sep 17 00:00:00 2001 +From: SonaArora +Date: Fri, 6 Jan 2017 14:21:56 +0530 +Subject: [PATCH 310/361] cli/geo-rep: Fix geo-rep status detail + +Earlier this command works when master and slave volume args are +given. Now it works even when no volume args are given (i.e. 'gluster +volume geo-replication status detail) and also when master volume is given +(i.e.'gluster volume geo-replication status detail'). + +mainline: +> BUG: 1410071 +> Reviewed-on: http://review.gluster.org/16347 +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Kotresh HR +> Tested-by: Kotresh HR +(cherry picked from commit fc5f52889edb83d3f4692fe51d2c1f942851a345) + +BUG: 843838 +Change-Id: I1a39241a4a5d70c20b2326599b3cccd8f1f6dc78 +Signed-off-by: SonaArora +Reviewed-on: https://code.engineering.redhat.com/gerrit/101290 +Tested-by: Milind Changire +Reviewed-by: Atin Mukherjee +--- + cli/src/cli-cmd-parser.c | 40 ++++++++++++++++++---------------------- + 1 file changed, 18 insertions(+), 22 deletions(-) + +diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c +index 4b97623..2e61c3a 100644 +--- a/cli/src/cli-cmd-parser.c ++++ b/cli/src/cli-cmd-parser.c +@@ -2852,23 +2852,22 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) + cmdi = slavei + 1; + if (slavei == 3) + masteri = 2; +- } else if (i <= 3) { +- if (!strcmp ((char *)words[wordcount-1], "detail")) { +- /* For status detail it is mandatory to provide +- * both master and slave */ +- ret = -1; +- goto out; ++ } else if (i <= 4) { ++ if (strtail ("detail", (char *)words[wordcount-1])) { ++ cmdi = wordcount - 2; ++ if (i == 4) ++ masteri = 2; ++ } else { ++ /* no $s, can only be status cmd ++ * (with either a single $m before it or nothing) ++ * -- these conditions imply that i <= 3 after ++ * the iteration and that i is the successor of ++ * the (0 or 1 length) sequence of $m-s. ++ */ ++ cmdi = i; ++ if (i == 3) ++ masteri = 2; + } +- +- /* no $s, can only be status cmd +- * (with either a single $m before it or nothing) +- * -- these conditions imply that i <= 3 after +- * the iteration and that i is the successor of +- * the (0 or 1 length) sequence of $m-s. +- */ +- cmdi = i; +- if (i == 3) +- masteri = 2; + } else + goto out; + +@@ -2933,15 +2932,12 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) + if (ret) + goto out; + +- if (!strcmp ((char *)words[wordcount-1], "detail")) { +- if (strcmp ((char *)words[wordcount-2], "status")) { +- ret = -1; +- goto out; +- } +- if (!slavei || !masteri) { ++ if (strtail ("detail", (char *)words[wordcount-1])) { ++ if (!strtail ("status", (char *)words[wordcount-2])) { + ret = -1; + goto out; + } ++ + ret = dict_set_uint32 (dict, "status-detail", _gf_true); + if (ret) + goto out; +-- +1.8.3.1 + diff --git a/SOURCES/0310-glusterd-geo-rep-Fix-snapshot-create-in-geo-rep-setu.patch b/SOURCES/0310-glusterd-geo-rep-Fix-snapshot-create-in-geo-rep-setu.patch deleted file mode 100644 index 96ef54d..0000000 --- a/SOURCES/0310-glusterd-geo-rep-Fix-snapshot-create-in-geo-rep-setu.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 9a8cc33d72e024e77567e4e32659792a7acf8c40 Mon Sep 17 00:00:00 2001 -From: Kotresh HR -Date: Thu, 20 Apr 2017 07:18:52 -0400 -Subject: [PATCH 310/316] glusterd/geo-rep: Fix snapshot create in geo-rep - setup - -glusterd persists geo-rep sessions in glusterd -info file which is represented by dictionary -'volinfo->gsync_slaves' in memory. Glusterd also -maintains in memory active geo-rep sessions in -dictionary 'volinfo->gsync_active_slaves' whose key -is "::". - -When glusterd is restarted while the geo-rep sessions -are active, it builds the 'volinfo->gsync_active_slaves' -from persisted glusterd info file. Since slave volume -uuid is added to "voinfo->gsync_slaves" with the commit -"http://review.gluster.org/13111", it builds it with key -":::" which is -wrong. So during snapshot pre-validation which checks -whether geo-rep is active or not, it always says it is -ACTIVE, as geo-rep stop would not deleted this key. -Fixed the same in this patch. - -> BUG: 1443977 -> Signed-off-by: Kotresh HR -> Reviewed-on: https://review.gluster.org/17093 -> Smoke: Gluster Build System -> NetBSD-regression: NetBSD Build System -> CentOS-regression: Gluster Build System -> Reviewed-by: Atin Mukherjee - -Change-Id: I185178910b4b8a62e66aba406d88d12fabc5c122 -BUG: 1445591 -Signed-off-by: Kotresh HR -Reviewed-on: https://code.engineering.redhat.com/gerrit/105181 -Reviewed-by: Atin Mukherjee ---- - xlators/mgmt/glusterd/src/glusterd-utils.c | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c -index d849690..49044b8 100644 ---- a/xlators/mgmt/glusterd/src/glusterd-utils.c -+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c -@@ -4994,7 +4994,7 @@ _local_gsyncd_start (dict_t *this, char *key, data_t *value, void *data) - glusterd_conf_t *priv = NULL; - gf_boolean_t is_template_in_use = _gf_false; - gf_boolean_t is_paused = _gf_false; -- char *key1 = NULL; -+ char key1[1024] = {0,}; - xlator_t *this1 = NULL; - - this1 = THIS; -@@ -5089,9 +5089,8 @@ _local_gsyncd_start (dict_t *this, char *key, data_t *value, void *data) - goto out; - } - -- /* Move the pointer two characters ahead to surpass '//' */ -- if ((key1 = strchr (slave, '/'))) -- key1 = key1 + 2; -+ /* Form key1 which is "::" */ -+ snprintf (key1, sizeof (key1), "%s::%s", slave_url, slave_vol); - - /* Looks for the last status, to find if the session was running - * when the node went down. If the session was just created or --- -1.8.3.1 - diff --git a/SOURCES/0311-cluster-dht-rm-rf-fails-if-dir-has-stale-linkto-file.patch b/SOURCES/0311-cluster-dht-rm-rf-fails-if-dir-has-stale-linkto-file.patch deleted file mode 100644 index 33f5471..0000000 --- a/SOURCES/0311-cluster-dht-rm-rf-fails-if-dir-has-stale-linkto-file.patch +++ /dev/null @@ -1,447 +0,0 @@ -From 586b35b717e884b138de6d2a8715cb7082f0e9ca Mon Sep 17 00:00:00 2001 -From: N Balachandran -Date: Tue, 2 May 2017 13:21:57 +0530 -Subject: [PATCH 311/316] cluster/dht: rm -rf fails if dir has stale linkto - files - -rm -rf fails with ENOENT if dir contains a lot of -stale linkto files. This is because a single -readdirp is sent as part of the rmdir which would return -and delete only as many linkto files on the bricks as would fit -in one readdirp buffer. Running rm -rf multiple times -will eventually delete all the files. The fix sends readdirp -on each subvol until no more entries are returned. - -> BUG: 1444540 -> Signed-off-by: N Balachandran -> Reviewed-on: https://review.gluster.org/17102 -> NetBSD-regression: NetBSD Build System -> Smoke: Gluster Build System -> CentOS-regression: Gluster Build System -> Reviewed-by: Raghavendra G - -Change-Id: I74dfbe90a169421f1fad037152771a9b6faf1b04 -BUG: 1447186 -Signed-off-by: N Balachandran -Reviewed-on: https://code.engineering.redhat.com/gerrit/104865 -Reviewed-by: Raghavendra Gowdappa ---- - xlators/cluster/dht/src/dht-common.c | 223 +++++++++++++++++++++++++++++------ - 1 file changed, 188 insertions(+), 35 deletions(-) - -diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c -index 62657a0..5d9ab12 100644 ---- a/xlators/cluster/dht/src/dht-common.c -+++ b/xlators/cluster/dht/src/dht-common.c -@@ -41,6 +41,9 @@ dht_setxattr2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, - int ret); - - -+int -+dht_rmdir_readdirp_do (call_frame_t *readdirp_frame, xlator_t *this); -+ - /* Sets the blocks and size values to fixed values. This is to be called - * only for dirs. The caller is responsible for checking the type - */ -@@ -7968,8 +7971,8 @@ dht_rmdir_linkfile_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this - dht_local_t *local = NULL; - call_frame_t *prev = NULL; - xlator_t *src = NULL; -- call_frame_t *main_frame = NULL; -- dht_local_t *main_local = NULL; -+ call_frame_t *readdirp_frame = NULL; -+ dht_local_t *readdirp_local = NULL; - int this_call_cnt = 0; - char gfid[GF_UUID_BUF_SIZE] ={0}; - -@@ -7978,8 +7981,8 @@ dht_rmdir_linkfile_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this - prev = cookie; - src = prev->this; - -- main_frame = local->main_frame; -- main_local = main_frame->local; -+ readdirp_frame = local->main_frame; -+ readdirp_local = readdirp_frame->local; - - gf_uuid_unparse(local->loc.gfid, gfid); - -@@ -7988,16 +7991,18 @@ dht_rmdir_linkfile_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this - "Unlinked linkfile %s on %s, gfid = %s", - local->loc.path, src->name, gfid); - } else { -- main_local->op_ret = -1; -- main_local->op_errno = op_errno; -+ if (op_errno != ENOENT) { -+ readdirp_local->op_ret = -1; -+ readdirp_local->op_errno = op_errno; -+ } - gf_msg_debug (this->name, op_errno, - "Unlink of %s on %s failed. (gfid = %s)", - local->loc.path, src->name, gfid); - } - -- this_call_cnt = dht_frame_return (main_frame); -+ this_call_cnt = dht_frame_return (readdirp_frame); - if (is_last_call (this_call_cnt)) -- dht_rmdir_do (main_frame, this); -+ dht_rmdir_readdirp_do (readdirp_frame, this); - - DHT_STACK_DESTROY (frame); - return 0; -@@ -8012,8 +8017,8 @@ dht_rmdir_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - dht_local_t *local = NULL; - call_frame_t *prev = NULL; - xlator_t *src = NULL; -- call_frame_t *main_frame = NULL; -- dht_local_t *main_local = NULL; -+ call_frame_t *readdirp_frame = NULL; -+ dht_local_t *readdirp_local = NULL; - int this_call_cnt = 0; - dht_conf_t *conf = this->private; - char gfid[GF_UUID_BUF_SIZE] = {0}; -@@ -8022,15 +8027,23 @@ dht_rmdir_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - prev = cookie; - src = prev->this; - -- main_frame = local->main_frame; -- main_local = main_frame->local; -+gf_log ("dht", GF_LOG_INFO, "dht_rmdir_lookup_cbk %s", local->loc.path); -+ -+ readdirp_frame = local->main_frame; -+ readdirp_local = readdirp_frame->local; -+ -+ if (op_ret != 0) { - -- if (op_ret != 0) -+ gf_msg (this->name, GF_LOG_WARNING, op_errno, -+ DHT_MSG_NOT_LINK_FILE_ERROR, -+ "lookup failed for %s on %s (type=0%o)", -+ local->loc.path, src->name, stbuf->ia_type); - goto err; -+ } - - if (!check_is_linkfile (inode, stbuf, xattr, conf->link_xattr_name)) { -- main_local->op_ret = -1; -- main_local->op_errno = ENOTEMPTY; -+ readdirp_local->op_ret = -1; -+ readdirp_local->op_errno = ENOTEMPTY; - - gf_uuid_unparse(local->loc.gfid, gfid); - -@@ -8046,9 +8059,9 @@ dht_rmdir_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - return 0; - err: - -- this_call_cnt = dht_frame_return (main_frame); -+ this_call_cnt = dht_frame_return (readdirp_frame); - if (is_last_call (this_call_cnt)) -- dht_rmdir_do (main_frame, this); -+ dht_rmdir_readdirp_do (readdirp_frame, this); - - DHT_STACK_DESTROY (frame); - return 0; -@@ -8063,8 +8076,8 @@ dht_rmdir_cached_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - { - dht_local_t *local = NULL; - xlator_t *src = NULL; -- call_frame_t *main_frame = NULL; -- dht_local_t *main_local = NULL; -+ call_frame_t *readdirp_frame = NULL; -+ dht_local_t *readdirp_local = NULL; - int this_call_cnt = 0; - dht_conf_t *conf = this->private; - dict_t *xattrs = NULL; -@@ -8073,12 +8086,17 @@ dht_rmdir_cached_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - local = frame->local; - src = local->hashed_subvol; - -- main_frame = local->main_frame; -- main_local = main_frame->local; -+ /* main_frame here is the readdirp_frame */ -+ -+ readdirp_frame = local->main_frame; -+ readdirp_local = readdirp_frame->local; -+ -+ gf_msg_debug (this->name, 0, "returning for %s ", -+ local->loc.path); - - if (op_ret == 0) { -- main_local->op_ret = -1; -- main_local->op_errno = ENOTEMPTY; -+ readdirp_local->op_ret = -1; -+ readdirp_local->op_errno = ENOTEMPTY; - - gf_msg (this->name, GF_LOG_WARNING, 0, - DHT_MSG_SUBVOL_ERROR, -@@ -8086,8 +8104,13 @@ dht_rmdir_cached_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - local->loc.path, src->name); - goto err; - } else if (op_errno != ENOENT) { -- main_local->op_ret = -1; -- main_local->op_errno = op_errno; -+ readdirp_local->op_ret = -1; -+ readdirp_local->op_errno = op_errno; -+ -+ gf_msg (this->name, GF_LOG_WARNING, op_errno, -+ DHT_MSG_SUBVOL_ERROR, -+ "%s not found on cached subvol %s", -+ local->loc.path, src->name); - goto err; - } - -@@ -8117,9 +8140,16 @@ dht_rmdir_cached_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - return 0; - err: - -- this_call_cnt = dht_frame_return (main_frame); -+ this_call_cnt = dht_frame_return (readdirp_frame); -+ -+ /* Once all the lookups/unlinks etc have returned, proceed to wind -+ * readdirp on the subvol again until no entries are returned. -+ * This is required if there are more entries than can be returned -+ * in a single readdirp call. -+ */ -+ - if (is_last_call (this_call_cnt)) -- dht_rmdir_do (main_frame, this); -+ dht_rmdir_do (readdirp_frame, this); - - DHT_STACK_DESTROY (frame); - return 0; -@@ -8214,12 +8244,13 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this, - - gf_uuid_unparse(lookup_local->loc.gfid, gfid); - -- gf_msg_trace (this->name, 0, -+ gf_msg_debug (this->name, 0, - "looking up %s on subvolume %s, gfid = %s", - lookup_local->loc.path, src->name, gfid); - - LOCK (&frame->lock); - { -+ /* Increment the call count for the readdir frame */ - local->call_cnt++; - } - UNLOCK (&frame->lock); -@@ -8227,15 +8258,27 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this, - subvol = dht_linkfile_subvol (this, NULL, &trav->d_stat, - trav->dict); - if (!subvol) { -+ - gf_msg (this->name, GF_LOG_INFO, 0, - DHT_MSG_INVALID_LINKFILE, - "Linkfile does not have link subvolume. " - "path = %s, gfid = %s", - lookup_local->loc.path, gfid); -+ -+ gf_msg_debug (this->name, 0, -+ "looking up %s on subvolume %s, gfid = %s", -+ lookup_local->loc.path, src->name, gfid); -+ - STACK_WIND (lookup_frame, dht_rmdir_lookup_cbk, - src, src->fops->lookup, - &lookup_local->loc, xattrs); - } else { -+ gf_msg_debug (this->name, 0, -+ "Looking up linkfile target %s on " -+ " subvolume %s, gfid = %s", -+ lookup_local->loc.path, subvol->name, -+ gfid); -+ - STACK_WIND (lookup_frame, dht_rmdir_cached_lookup_cbk, - subvol, subvol->fops->lookup, - &lookup_local->loc, xattrs); -@@ -8257,6 +8300,46 @@ err: - } - - -+ -+/* -+ * No more entries on this subvol. Proceed to the actual rmdir operation. -+ */ -+ -+void -+dht_rmdir_readdirp_done (call_frame_t *readdirp_frame, xlator_t *this) -+{ -+ -+ call_frame_t *main_frame = NULL; -+ dht_local_t *main_local = NULL; -+ dht_local_t *local = NULL; -+ int this_call_cnt = 0; -+ -+ -+ local = readdirp_frame->local; -+ main_frame = local->main_frame; -+ main_local = main_frame->local; -+ -+ /* At least one readdirp failed. -+ * This is a bit hit or miss - if readdirp failed on more than -+ * one subvol, we don't know which error is returned. -+ */ -+ -+ if (local->op_ret == -1) { -+ main_local->op_ret = local->op_ret; -+ main_local->op_errno = local->op_errno; -+ } -+ -+ this_call_cnt = dht_frame_return (main_frame); -+ -+ if (is_last_call (this_call_cnt)) -+ dht_rmdir_do (main_frame, this); -+ -+ -+ DHT_STACK_DESTROY (readdirp_frame); -+} -+ -+ -+ - int - dht_rmdir_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, gf_dirent_t *entries, -@@ -8268,6 +8351,7 @@ dht_rmdir_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - xlator_t *src = NULL; - int ret = 0; - -+ - local = frame->local; - prev = cookie; - src = prev->this; -@@ -8283,7 +8367,7 @@ dht_rmdir_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - local->loc.path, op_ret); - local->op_ret = -1; - local->op_errno = ENOTEMPTY; -- break; -+ goto done; - default: - /* @ret number of linkfiles are getting unlinked */ - gf_msg_trace (this->name, 0, -@@ -8292,15 +8376,49 @@ dht_rmdir_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - local->loc.path, ret); - break; - } -+ - } - -- this_call_cnt = dht_frame_return (frame); -+ if (ret) { -+ return 0; -+ } -+done: -+ /* readdirp failed or no linkto files were found on this subvol */ - -- if (is_last_call (this_call_cnt)) { -- dht_rmdir_do (frame, this); -+ dht_rmdir_readdirp_done (frame, this); -+ return 0; -+} -+ -+/* Keep sending readdirp on the subvol until it returns no more entries -+ * It is possible that not all entries will fit in a single readdirp in which -+ * case the rmdir will keep failing with ENOTEMPTY -+ */ -+ -+int -+dht_rmdir_readdirp_do (call_frame_t *readdirp_frame, xlator_t *this) -+{ -+ dht_local_t *local = NULL; -+ -+ local = readdirp_frame->local; -+ -+ if (local->op_ret == -1) { -+ /* there is no point doing another readdirp on this -+ * subvol . */ -+ dht_rmdir_readdirp_done (readdirp_frame, this); -+ return 0; - } - -+ gf_msg_debug ("this->name", 0, "Calling dht_rmdir_readdirp_do for %p", -+ readdirp_frame); -+ -+ STACK_WIND (readdirp_frame, dht_rmdir_readdirp_cbk, -+ local->hashed_subvol, -+ local->hashed_subvol->fops->readdirp, -+ local->fd, 4096, 0, local->xattr); -+ -+ - return 0; -+ - } - - -@@ -8311,11 +8429,13 @@ dht_rmdir_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - dht_local_t *local = NULL; - int this_call_cnt = -1; - call_frame_t *prev = NULL; -- dict_t *dict = NULL; - int ret = 0; - dht_conf_t *conf = this->private; -+ dict_t *dict = NULL; - int i = 0; - char gfid[GF_UUID_BUF_SIZE] = {0}; -+ dht_local_t *readdirp_local = NULL; -+ call_frame_t *readdirp_frame = NULL; - - local = frame->local; - prev = cookie; -@@ -8343,6 +8463,7 @@ dht_rmdir_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - goto err; - - fd_bind (fd); -+ - dict = dict_new (); - if (!dict) { - local->op_ret = -1; -@@ -8358,16 +8479,48 @@ dht_rmdir_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - local->loc.path, conf->link_xattr_name); - - local->call_cnt = conf->subvolume_cnt; -+ -+ /* Create a separate frame per subvol as we might need -+ * to resend readdirp multiple times to get all the -+ * entries. -+ */ -+ - for (i = 0; i < conf->subvolume_cnt; i++) { -- STACK_WIND (frame, dht_rmdir_readdirp_cbk, -+ readdirp_frame = copy_frame (frame); -+ -+ if (!readdirp_frame) { -+ local->call_cnt--; -+ continue; -+ } -+ -+ readdirp_local = dht_local_init (readdirp_frame, &local->loc, -+ local->fd, 0); -+ -+ if (!readdirp_local) { -+ DHT_STACK_DESTROY (readdirp_frame); -+ local->call_cnt--; -+ continue; -+ } -+ readdirp_local->main_frame = frame; -+ readdirp_local->op_ret = 0; -+ readdirp_local->xattr = dict_ref (dict); -+ /* overload this field to save the subvol info */ -+ readdirp_local->hashed_subvol = conf->subvolumes[i]; -+ -+ STACK_WIND (readdirp_frame, dht_rmdir_readdirp_cbk, - conf->subvolumes[i], - conf->subvolumes[i]->fops->readdirp, -- local->fd, 4096, 0, dict); -+ readdirp_local->fd, 4096, 0, -+ readdirp_local->xattr); - } - - if (dict) - dict_unref (dict); - -+ /* Could not wind readdirp to any subvol */ -+ if (!local->call_cnt) -+ goto err; -+ - return 0; - - err: --- -1.8.3.1 - diff --git a/SOURCES/0311-geo-rep-Handle-directory-sync-failure-as-hard-error.patch b/SOURCES/0311-geo-rep-Handle-directory-sync-failure-as-hard-error.patch new file mode 100644 index 0000000..c7c0244 --- /dev/null +++ b/SOURCES/0311-geo-rep-Handle-directory-sync-failure-as-hard-error.patch @@ -0,0 +1,88 @@ +From 0c39ae4bb678c256ea20387b88507565cc38872d Mon Sep 17 00:00:00 2001 +From: Kotresh HR +Date: Tue, 10 Jan 2017 00:30:42 -0500 +Subject: [PATCH 311/361] geo-rep: Handle directory sync failure as hard error + +If directory creation is failed, return immediately before +further processing. Allowing it to further process will +fail the entire directory tree syncing to slave. Hence +master will log and raise exception if it's directory +failure. Earlier, master used to log the failure and +proceed. + +mainline: +> BUG: 1411607 +> Reviewed-on: http://review.gluster.org/16364 +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Aravinda VK +(cherry picked from commit d1f84c77faeaa915cc57e0c13925cfe8bbe90ad6) + +BUG: 1425695 +Change-Id: Iba2a8b5d3d0092e7a9c8a3c2cdf9e6e29c73ddf0 +Signed-off-by: Kotresh HR +Reviewed-on: https://code.engineering.redhat.com/gerrit/101291 +Tested-by: Milind Changire +Reviewed-by: Atin Mukherjee +--- + geo-replication/syncdaemon/resource.py | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py +index 9c7a70a..be97b16 100644 +--- a/geo-replication/syncdaemon/resource.py ++++ b/geo-replication/syncdaemon/resource.py +@@ -628,16 +628,19 @@ class Server(object): + # We do this for failing fops on Slave + # Master should be logging this + if cmd_ret is None: +- return ++ return False + + if cmd_ret == EEXIST: + disk_gfid = cls.gfid_mnt(e['entry']) +- if isinstance(disk_gfid, basestring): +- if e['gfid'] != disk_gfid: +- failures.append((e, cmd_ret, disk_gfid)) ++ if isinstance(disk_gfid, basestring) and e['gfid'] != disk_gfid: ++ failures.append((e, cmd_ret, disk_gfid)) ++ else: ++ return False + else: + failures.append((e, cmd_ret)) + ++ return True ++ + failures = [] + + def matching_disk_gfid(gfid, entry): +@@ -807,7 +810,15 @@ class Server(object): + [pg, 'glusterfs.gfid.newfile', blob], + [EEXIST, ENOENT], + [ESTALE, EINVAL]) +- collect_failure(e, cmd_ret) ++ failed = collect_failure(e, cmd_ret) ++ ++ # If directory creation is failed, return immediately before ++ # further processing. Allowing it to further process will ++ # cause the entire directory tree to fail syncing to slave. ++ # Hence master will log and raise exception if it's ++ # directory failure. ++ if failed and op == 'MKDIR': ++ return failures + + # If UID/GID is different than zero that means we are trying + # create Entry with different UID/GID. Create Entry with +@@ -816,7 +827,7 @@ class Server(object): + path = os.path.join(pfx, gfid) + cmd_ret = errno_wrap(os.chown, [path, uid, gid], [ENOENT], + [ESTALE, EINVAL]) +- collect_failure(e, cmd_ret) ++ collect_failure(e, cmd_ret) + + return failures + +-- +1.8.3.1 + diff --git a/SOURCES/0312-cluster-dht-Remove-redundant-logs-in-dht-rmdir.patch b/SOURCES/0312-cluster-dht-Remove-redundant-logs-in-dht-rmdir.patch deleted file mode 100644 index 8fb6da3..0000000 --- a/SOURCES/0312-cluster-dht-Remove-redundant-logs-in-dht-rmdir.patch +++ /dev/null @@ -1,88 +0,0 @@ -From afd354c13de6b0aac750f353db3fdbc5b53cc470 Mon Sep 17 00:00:00 2001 -From: N Balachandran -Date: Fri, 5 May 2017 15:35:11 +0530 -Subject: [PATCH 312/316] cluster/dht Remove redundant logs in dht rmdir - -Removing redundant logs were introduced in -https://review.gluster.org/#/c/17065/ - -Upstream patch: - -> BUG: 1446227 -> Signed-off-by: N Balachandran -> Reviewed-on: https://review.gluster.org/17130 -> Reviewed-by: Shyamsundar Ranganathan - -Change-Id: I0d6055488b51a13c91d2121e87f653cdb94888b0 -BUG: 1447186 -Signed-off-by: N Balachandran -Reviewed-on: https://code.engineering.redhat.com/gerrit/105361 -Reviewed-by: Milind Changire -Reviewed-by: Mohit Agrawal ---- - xlators/cluster/dht/src/dht-common.c | 14 ++++++-------- - 1 file changed, 6 insertions(+), 8 deletions(-) - -diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c -index 5d9ab12..d54405b 100644 ---- a/xlators/cluster/dht/src/dht-common.c -+++ b/xlators/cluster/dht/src/dht-common.c -@@ -8027,7 +8027,8 @@ dht_rmdir_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - prev = cookie; - src = prev->this; - --gf_log ("dht", GF_LOG_INFO, "dht_rmdir_lookup_cbk %s", local->loc.path); -+ gf_msg_debug (this->name, 0, "dht_rmdir_lookup_cbk %s", -+ local->loc.path); - - readdirp_frame = local->main_frame; - readdirp_local = readdirp_frame->local; -@@ -8035,7 +8036,7 @@ gf_log ("dht", GF_LOG_INFO, "dht_rmdir_lookup_cbk %s", local->loc.path); - if (op_ret != 0) { - - gf_msg (this->name, GF_LOG_WARNING, op_errno, -- DHT_MSG_NOT_LINK_FILE_ERROR, -+ DHT_MSG_FILE_LOOKUP_FAILED, - "lookup failed for %s on %s (type=0%o)", - local->loc.path, src->name, stbuf->ia_type); - goto err; -@@ -8045,7 +8046,7 @@ gf_log ("dht", GF_LOG_INFO, "dht_rmdir_lookup_cbk %s", local->loc.path); - readdirp_local->op_ret = -1; - readdirp_local->op_errno = ENOTEMPTY; - -- gf_uuid_unparse(local->loc.gfid, gfid); -+ gf_uuid_unparse(local->loc.gfid, gfid); - - gf_msg (this->name, GF_LOG_WARNING, 0, - DHT_MSG_NOT_LINK_FILE_ERROR, -@@ -8244,7 +8245,7 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this, - - gf_uuid_unparse(lookup_local->loc.gfid, gfid); - -- gf_msg_debug (this->name, 0, -+ gf_msg_trace (this->name, 0, - "looking up %s on subvolume %s, gfid = %s", - lookup_local->loc.path, src->name, gfid); - -@@ -8266,7 +8267,7 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this, - lookup_local->loc.path, gfid); - - gf_msg_debug (this->name, 0, -- "looking up %s on subvolume %s, gfid = %s", -+ "looking up %s on subvol %s, gfid = %s", - lookup_local->loc.path, src->name, gfid); - - STACK_WIND (lookup_frame, dht_rmdir_lookup_cbk, -@@ -8408,9 +8409,6 @@ dht_rmdir_readdirp_do (call_frame_t *readdirp_frame, xlator_t *this) - return 0; - } - -- gf_msg_debug ("this->name", 0, "Calling dht_rmdir_readdirp_do for %p", -- readdirp_frame); -- - STACK_WIND (readdirp_frame, dht_rmdir_readdirp_cbk, - local->hashed_subvol, - local->hashed_subvol->fops->readdirp, --- -1.8.3.1 - diff --git a/SOURCES/0312-geo-rep-Separate-slave-mount-logs-for-each-connectio.patch b/SOURCES/0312-geo-rep-Separate-slave-mount-logs-for-each-connectio.patch new file mode 100644 index 0000000..e7ebf33 --- /dev/null +++ b/SOURCES/0312-geo-rep-Separate-slave-mount-logs-for-each-connectio.patch @@ -0,0 +1,166 @@ +From f34a1a12427043c9409df0861a3b95e6350e1107 Mon Sep 17 00:00:00 2001 +From: Kotresh HR +Date: Tue, 10 Jan 2017 15:39:55 -0500 +Subject: [PATCH 312/361] geo-rep: Separate slave mount logs for each + connection + +Geo-rep worker mounts the slave volume on the slave +node. If multiple worker connects to same slave node, +all workers share the same mount log file. This +is very difficult to debug as logs are cluttered from +different mounts. Hence creating separate mount log +file for each connection from worker. Each connection +from worker is identified uniquely using 'mastervol uuid', +'master host', 'master brickpath', 'salve vol'. The log +file name will be combination of the above. + +mainline: +> BUG: 1412689 +> Reviewed-on: http://review.gluster.org/16384 +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Aravinda VK +(cherry picked from commit 67d1410d2cc8539a026ce6e62f9783c836b2f407) + +BUG: 1414750 +Change-Id: I67871dc8e8ea5864e2ad55e2a82063be0138bf0c +Signed-off-by: Kotresh HR +Reviewed-on: https://code.engineering.redhat.com/gerrit/101292 +Tested-by: Milind Changire +Reviewed-by: Atin Mukherjee +--- + geo-replication/syncdaemon/configinterface.py | 12 ++++++++++++ + geo-replication/syncdaemon/gsyncd.py | 4 +++- + geo-replication/syncdaemon/resource.py | 6 ++++++ + xlators/mgmt/glusterd/src/glusterd-geo-rep.c | 6 +++--- + xlators/mgmt/glusterd/src/glusterd.c | 6 +++--- + 5 files changed, 27 insertions(+), 7 deletions(-) + +diff --git a/geo-replication/syncdaemon/configinterface.py b/geo-replication/syncdaemon/configinterface.py +index b5935df..50e7aed 100644 +--- a/geo-replication/syncdaemon/configinterface.py ++++ b/geo-replication/syncdaemon/configinterface.py +@@ -78,6 +78,18 @@ CONFIGS = ( + "${slavevol}/${eSlave}.status", + GLUSTERD_WORKDIR + "/geo-replication/${mastervol}_${remotehost}_" + "${slavevol}/monitor.status"), ++ ("peersrx .", ++ "log_file", ++ "${iprefix}/log/glusterfs/geo-replication-slaves/${session_owner}:${eSlave}.log", ++ "${iprefix}/log/glusterfs/geo-replication-slaves/${session_owner}:${local_node}${local_id}.${slavevol}.log"), ++ ("peersrx .", ++ "log_file_mbr", ++ "${iprefix}/log/glusterfs/geo-replication-slaves/mbr/${session_owner}:${eSlave}.log", ++ "${iprefix}/log/glusterfs/geo-replication-slaves/mbr/${session_owner}:${local_node}${local_id}.${slavevol}.log"), ++ ("peersrx .", ++ "gluster_log_file", ++ "${iprefix}/log/glusterfs/geo-replication-slaves/${session_owner}:${eSlave}.gluster.log", ++ "${iprefix}/log/glusterfs/geo-replication-slaves/${session_owner}:${local_node}${local_id}.${slavevol}.gluster.log") + ) + + +diff --git a/geo-replication/syncdaemon/gsyncd.py b/geo-replication/syncdaemon/gsyncd.py +index 76d9939..eccc5ea 100644 +--- a/geo-replication/syncdaemon/gsyncd.py ++++ b/geo-replication/syncdaemon/gsyncd.py +@@ -413,7 +413,8 @@ def main_i(): + if (o.callback in (store_abs, 'store_true', None) and + o.get_opt_string() not in ('--version', '--help'))] + remote_tunables = ['listen', 'go_daemon', 'timeout', +- 'session_owner', 'config_file', 'use_rsync_xattrs'] ++ 'session_owner', 'config_file', 'use_rsync_xattrs', ++ 'local_id', 'local_node'] + rq_remote_tunables = {'listen': True} + + # precedence for sources of values: 1) commandline, 2) cfg file, 3) +@@ -541,6 +542,7 @@ def main_i(): + namedict[name + 'vol'] = x.volume + if name == 'remote': + namedict['remotehost'] = x.remotehost ++ + if not 'config_file' in rconf: + rconf['config_file'] = TMPL_CONFIG_FILE + +diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py +index be97b16..9ac5c2d 100644 +--- a/geo-replication/syncdaemon/resource.py ++++ b/geo-replication/syncdaemon/resource.py +@@ -970,6 +970,12 @@ class SlaveRemote(object): + so = getattr(gconf, 'session_owner', None) + if so: + extra_opts += ['--session-owner', so] ++ li = getattr(gconf, 'local_id', None) ++ if li: ++ extra_opts += ['--local-id', li] ++ ln = getattr(gconf, 'local_node', None) ++ if ln: ++ extra_opts += ['--local-node', ln] + if boolify(gconf.use_rsync_xattrs): + extra_opts.append('--use-rsync-xattrs') + po = Popen(rargs + gconf.remote_gsyncd.split() + extra_opts + +diff --git a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c +index 9a702b7..872f3ff 100644 +--- a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c ++++ b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c +@@ -6123,7 +6123,7 @@ create_conf_file (glusterd_conf_t *conf, char *conf_path) + runinit_gsyncd_setrx (&runner, conf_path); + runner_add_args (&runner, + "log-file", +- DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/${session_owner}:${eSlave}.log", ++ DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/${session_owner}:${local_node}${local_id}.${slavevol}.log", + ".", NULL); + RUN_GSYNCD_CMD; + +@@ -6131,7 +6131,7 @@ create_conf_file (glusterd_conf_t *conf, char *conf_path) + runinit_gsyncd_setrx (&runner, conf_path); + runner_add_args (&runner, + "log-file-mbr", +- DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/mbr/${session_owner}:${eSlave}.log", ++ DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/mbr/${session_owner}:${local_node}${local_id}.${slavevol}.log", + ".", NULL); + RUN_GSYNCD_CMD; + +@@ -6139,7 +6139,7 @@ create_conf_file (glusterd_conf_t *conf, char *conf_path) + runinit_gsyncd_setrx (&runner, conf_path); + runner_add_args (&runner, + "gluster-log-file", +- DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/${session_owner}:${eSlave}.gluster.log", ++ DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/${session_owner}:${local_node}${local_id}.${slavevol}.gluster.log", + ".", NULL); + RUN_GSYNCD_CMD; + +diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c +index 3bcf2d5..6599c53 100644 +--- a/xlators/mgmt/glusterd/src/glusterd.c ++++ b/xlators/mgmt/glusterd/src/glusterd.c +@@ -804,7 +804,7 @@ configure_syncdaemon (glusterd_conf_t *conf) + runinit_gsyncd_setrx (&runner, conf); + runner_add_args (&runner, + "log-file", +- DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/${session_owner}:${eSlave}.log", ++ DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/${session_owner}:${local_node}${local_id}.${slavevol}.log", + ".", NULL); + RUN_GSYNCD_CMD; + +@@ -812,7 +812,7 @@ configure_syncdaemon (glusterd_conf_t *conf) + runinit_gsyncd_setrx (&runner, conf); + runner_add_args (&runner, + "log-file-mbr", +- DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/mbr/${session_owner}:${eSlave}.log", ++ DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/mbr/${session_owner}:${local_node}${local_id}.${slavevol}.log", + ".", NULL); + RUN_GSYNCD_CMD; + +@@ -820,7 +820,7 @@ configure_syncdaemon (glusterd_conf_t *conf) + runinit_gsyncd_setrx (&runner, conf); + runner_add_args (&runner, + "gluster-log-file", +- DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/${session_owner}:${eSlave}.gluster.log", ++ DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/${session_owner}:${local_node}${local_id}.${slavevol}.gluster.log", + ".", NULL); + RUN_GSYNCD_CMD; + +-- +1.8.3.1 + diff --git a/SOURCES/0313-cluster-dht-Pass-the-req-dict-instead-of-NULL-in-dht.patch b/SOURCES/0313-cluster-dht-Pass-the-req-dict-instead-of-NULL-in-dht.patch deleted file mode 100644 index 80c027e..0000000 --- a/SOURCES/0313-cluster-dht-Pass-the-req-dict-instead-of-NULL-in-dht.patch +++ /dev/null @@ -1,529 +0,0 @@ -From 272082ffde8507dc93f802a809265f2622933426 Mon Sep 17 00:00:00 2001 -From: Krutika Dhananjay -Date: Thu, 20 Apr 2017 10:08:02 +0530 -Subject: [PATCH 313/316] cluster/dht: Pass the req dict instead of NULL in - dht_attr2() - - Backport of: https://review.gluster.org/17085 - -This bug was causing VMs to pause during rebalance. When qemu winds -down a STAT, shard fills the trusted.glusterfs.shard.file-size attribute -in the req dict which DHT doesn't wind its STAT fop with upon detecting -the file has undergone migration. As a result shard doesn't find the -value to this key in the unwind path, causing it to fail the STAT -with EINVAL. - -Also, the same bug exists in other fops too, which is also fixed in -this patch. - -Change-Id: I1c19b98c1c002c90a17c5becff1cb70d0fd8017c -BUG: 1439753 -Signed-off-by: Krutika Dhananjay -Reviewed-on: https://code.engineering.redhat.com/gerrit/105197 -Reviewed-by: Nithya Balachandran -Reviewed-by: Atin Mukherjee ---- - xlators/cluster/dht/src/dht-common.c | 61 +++++++++++++------------------ - xlators/cluster/dht/src/dht-inode-read.c | 37 +++++++++++++------ - xlators/cluster/dht/src/dht-inode-write.c | 33 ++++++++++++----- - 3 files changed, 74 insertions(+), 57 deletions(-) - -diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c -index d54405b..93bb2ad 100644 ---- a/xlators/cluster/dht/src/dht-common.c -+++ b/xlators/cluster/dht/src/dht-common.c -@@ -3639,6 +3639,7 @@ dht_fsetxattr (call_frame_t *frame, xlator_t *this, - goto err; - } - -+ local->xattr_req = xdata ? dict_ref (xdata) : dict_new (); - local->call_cnt = call_cnt = layout->cnt; - - if (IA_ISDIR (fd->inode->ia_type)) { -@@ -3646,7 +3647,7 @@ dht_fsetxattr (call_frame_t *frame, xlator_t *this, - STACK_WIND (frame, dht_err_cbk, - layout->list[i].xlator, - layout->list[i].xlator->fops->fsetxattr, -- fd, xattr, flags, NULL); -+ fd, xattr, flags, xdata); - } - - } else { -@@ -3655,10 +3656,8 @@ dht_fsetxattr (call_frame_t *frame, xlator_t *this, - local->rebalance.xattr = dict_ref (xattr); - local->rebalance.flags = flags; - -- xdata = xdata ? dict_ref (xdata) : dict_new (); -- if (xdata) -- ret = dict_set_dynstr_with_alloc (xdata, -- DHT_IATT_IN_XDATA_KEY, "yes"); -+ ret = dict_set_dynstr_with_alloc (local->xattr_req, -+ DHT_IATT_IN_XDATA_KEY, "yes"); - if (ret) { - gf_msg_debug (this->name, 0, - "Failed to set dictionary key %s for fd=%p", -@@ -3666,11 +3665,8 @@ dht_fsetxattr (call_frame_t *frame, xlator_t *this, - } - - STACK_WIND (frame, dht_file_setxattr_cbk, subvol, -- subvol->fops->fsetxattr, fd, xattr, flags, xdata); -- -- if (xdata) -- dict_unref (xdata); -- -+ subvol->fops->fsetxattr, fd, xattr, flags, -+ local->xattr_req); - } - return 0; - -@@ -3766,12 +3762,12 @@ dht_setxattr2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - STACK_WIND (frame, dht_file_setxattr_cbk, subvol, - subvol->fops->setxattr, &local->loc, - local->rebalance.xattr, local->rebalance.flags, -- NULL); -+ local->xattr_req); - } else { - STACK_WIND (frame, dht_file_setxattr_cbk, subvol, - subvol->fops->fsetxattr, local->fd, - local->rebalance.xattr, local->rebalance.flags, -- NULL); -+ local->xattr_req); - } - - return 0; -@@ -4046,6 +4042,7 @@ dht_setxattr (call_frame_t *frame, xlator_t *this, - if (tmp) { - return dht_nuke_dir (frame, this, loc, tmp); - } -+ local->xattr_req = xdata ? dict_ref (xdata) : dict_new (); - - if (IA_ISDIR (loc->inode->ia_type)) { - -@@ -4062,17 +4059,12 @@ dht_setxattr (call_frame_t *frame, xlator_t *this, - local->rebalance.flags = flags; - local->call_cnt = 1; - -- xdata = xdata ? dict_ref (xdata) : dict_new (); -- if (xdata) -- ret = dict_set_dynstr_with_alloc (xdata, -- DHT_IATT_IN_XDATA_KEY, "yes"); -+ ret = dict_set_dynstr_with_alloc (local->xattr_req, -+ DHT_IATT_IN_XDATA_KEY, "yes"); - - STACK_WIND (frame, dht_file_setxattr_cbk, - subvol, subvol->fops->setxattr, -- loc, xattr, flags, xdata); -- -- if (xdata) -- dict_unref (xdata); -+ loc, xattr, flags, local->xattr_req); - } - - return 0; -@@ -4187,11 +4179,11 @@ dht_removexattr2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, - if (local->fop == GF_FOP_REMOVEXATTR) { - STACK_WIND (frame, dht_file_removexattr_cbk, subvol, - subvol->fops->removexattr, &local->loc, -- local->key, NULL); -+ local->key, local->xattr_req); - } else { - STACK_WIND (frame, dht_file_removexattr_cbk, subvol, - subvol->fops->fremovexattr, local->fd, -- local->key, NULL); -+ local->key, local->xattr_req); - } - - return 0; -@@ -4228,8 +4220,6 @@ dht_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - unlock: - UNLOCK (&frame->lock); - -- -- - this_call_cnt = dht_frame_return (frame); - if (is_last_call (this_call_cnt)) { - DHT_STACK_UNWIND (removexattr, frame, local->op_ret, -@@ -4285,6 +4275,7 @@ dht_removexattr (call_frame_t *frame, xlator_t *this, - op_errno = EINVAL; - goto err; - } -+ local->xattr_req = (xdata) ? dict_ref (xdata) : dict_new (); - - local->call_cnt = call_cnt = layout->cnt; - local->key = gf_strdup (key); -@@ -4294,16 +4285,15 @@ dht_removexattr (call_frame_t *frame, xlator_t *this, - STACK_WIND (frame, dht_removexattr_cbk, - layout->list[i].xlator, - layout->list[i].xlator->fops->removexattr, -- loc, key, NULL); -+ loc, key, local->xattr_req); - } - - } else { - - local->call_cnt = 1; -- xdata = xdata ? dict_ref (xdata) : dict_new (); -- if (xdata) -- ret = dict_set_dynstr_with_alloc (xdata, -- DHT_IATT_IN_XDATA_KEY, "yes"); -+ -+ ret = dict_set_dynstr_with_alloc (local->xattr_req, -+ DHT_IATT_IN_XDATA_KEY, "yes"); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, ENOMEM, - DHT_MSG_DICT_SET_FAILED, "Failed to " -@@ -4313,10 +4303,7 @@ dht_removexattr (call_frame_t *frame, xlator_t *this, - - STACK_WIND (frame, dht_file_removexattr_cbk, - subvol, subvol->fops->removexattr, -- loc, key, xdata); -- -- if (xdata) -- dict_unref (xdata); -+ loc, key, local->xattr_req); - } - - return 0; -@@ -6314,7 +6301,7 @@ dht_link2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - local->call_cnt = 2; - - STACK_WIND (frame, dht_link_cbk, subvol, subvol->fops->link, -- &local->loc, &local->loc2, NULL); -+ &local->loc, &local->loc2, local->xattr_req); - - return 0; - err: -@@ -6341,7 +6328,7 @@ dht_link_linkfile_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - srcvol = local->linkfile.srcvol; - - STACK_WIND (frame, dht_link_cbk, srcvol, srcvol->fops->link, -- &local->loc, &local->loc2, xdata); -+ &local->loc, &local->loc2, local->xattr_req); - - return 0; - -@@ -6350,7 +6337,7 @@ err: - dht_set_fixed_dir_stat (preparent); - dht_set_fixed_dir_stat (postparent); - DHT_STACK_UNWIND (link, frame, op_ret, op_errno, inode, stbuf, preparent, -- postparent, NULL); -+ postparent, xdata); - - return 0; - } -@@ -6401,6 +6388,8 @@ dht_link (call_frame_t *frame, xlator_t *this, - op_errno = ENOMEM; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - if (hashed_subvol != cached_subvol) { - gf_uuid_copy (local->gfid, oldloc->inode->gfid); -diff --git a/xlators/cluster/dht/src/dht-inode-read.c b/xlators/cluster/dht/src/dht-inode-read.c -index 8abf0d5..298eca7 100644 ---- a/xlators/cluster/dht/src/dht-inode-read.c -+++ b/xlators/cluster/dht/src/dht-inode-read.c -@@ -76,7 +76,7 @@ dht_open2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - if (we_are_not_migrating (ret)) { - /* This DHT layer is not migrating the file */ - DHT_STACK_UNWIND (open, frame, -1, local->op_errno, -- NULL, NULL); -+ NULL, local->rebalance.xdata); - return 0; - - } -@@ -88,7 +88,7 @@ dht_open2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - - STACK_WIND (frame, dht_open_cbk, subvol, subvol->fops->open, - &local->loc, local->rebalance.flags, local->fd, -- NULL); -+ local->xattr_req); - return 0; - - out: -@@ -122,6 +122,8 @@ dht_open (call_frame_t *frame, xlator_t *this, - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - local->rebalance.flags = flags; - local->call_cnt = 1; -@@ -239,10 +241,10 @@ dht_attr2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - - if (local->fop == GF_FOP_FSTAT) { - STACK_WIND (frame, dht_file_attr_cbk, subvol, -- subvol->fops->fstat, local->fd, NULL); -+ subvol->fops->fstat, local->fd, local->xattr_req); - } else { - STACK_WIND (frame, dht_file_attr_cbk, subvol, -- subvol->fops->stat, &local->loc, NULL); -+ subvol->fops->stat, &local->loc, local->xattr_req); - } - - return 0; -@@ -325,6 +327,8 @@ dht_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - if (IA_ISREG (loc->inode->ia_type)) { - local->call_cnt = 1; -@@ -385,6 +389,8 @@ dht_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - if (IA_ISREG (fd->inode->ia_type)) { - local->call_cnt = 1; -@@ -506,7 +512,7 @@ dht_readv2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - - STACK_WIND (frame, dht_readv_cbk, subvol, subvol->fops->readv, - local->fd, local->rebalance.size, local->rebalance.offset, -- local->rebalance.flags, NULL); -+ local->rebalance.flags, local->xattr_req); - - return 0; - -@@ -541,6 +547,8 @@ dht_readv (call_frame_t *frame, xlator_t *this, - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - local->rebalance.offset = off; - local->rebalance.size = size; -@@ -635,7 +643,7 @@ dht_access2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - local->call_cnt = 2; - - STACK_WIND (frame, dht_access_cbk, subvol, subvol->fops->access, -- &local->loc, local->rebalance.flags, NULL); -+ &local->loc, local->rebalance.flags, local->xattr_req); - - return 0; - -@@ -674,6 +682,8 @@ dht_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask, - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - STACK_WIND (frame, dht_access_cbk, subvol, subvol->fops->access, - loc, mask, xdata); -@@ -708,9 +718,6 @@ dht_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - local->op_ret = op_ret; - local->op_errno = op_errno; - -- if (xdata) -- local->rebalance.xdata = dict_ref (xdata); -- - /* If context is set, then send flush() it to the destination */ - dht_inode_ctx_get_mig_info (this, local->fd->inode, NULL, &subvol); - if (subvol && dht_fd_open_on_dst (this, local->fd, subvol)) { -@@ -751,7 +758,7 @@ dht_flush2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - - STACK_WIND (frame, dht_flush_cbk, - subvol, subvol->fops->flush, local->fd, -- local->rebalance.xdata); -+ local->xattr_req); - - return 0; - -@@ -785,6 +792,8 @@ dht_flush (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - local->call_cnt = 1; - -@@ -907,7 +916,7 @@ dht_fsync2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - local->call_cnt = 2; /* This is the second attempt */ - - STACK_WIND (frame, dht_fsync_cbk, subvol, subvol->fops->fsync, -- local->fd, local->rebalance.flags, NULL); -+ local->fd, local->rebalance.flags, local->xattr_req); - - return 0; - -@@ -934,6 +943,8 @@ dht_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int datasync, - - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - local->call_cnt = 1; - local->rebalance.flags = datasync; -@@ -1024,7 +1035,7 @@ dht_lk2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - - STACK_WIND (frame, dht_lk_cbk, subvol, subvol->fops->lk, local->fd, - local->rebalance.lock_cmd, &local->rebalance.flock, -- local->rebalance.xdata); -+ local->xattr_req); - - return 0; - -@@ -1059,6 +1070,8 @@ dht_lk (call_frame_t *frame, xlator_t *this, - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - local->rebalance.flock = *flock; - local->rebalance.lock_cmd = cmd; -diff --git a/xlators/cluster/dht/src/dht-inode-write.c b/xlators/cluster/dht/src/dht-inode-write.c -index 112685b..364b66c 100644 ---- a/xlators/cluster/dht/src/dht-inode-write.c -+++ b/xlators/cluster/dht/src/dht-inode-write.c -@@ -143,7 +143,7 @@ dht_writev2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - subvol, subvol->fops->writev, - local->fd, local->rebalance.vector, local->rebalance.count, - local->rebalance.offset, local->rebalance.flags, -- local->rebalance.iobref, NULL); -+ local->rebalance.iobref, local->xattr_req); - - return 0; - -@@ -180,7 +180,8 @@ dht_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, - op_errno = EINVAL; - goto err; - } -- -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - local->rebalance.vector = iov_dup (vector, count); - local->rebalance.offset = off; -@@ -323,11 +324,11 @@ dht_truncate2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - if (local->fop == GF_FOP_TRUNCATE) { - STACK_WIND (frame, dht_truncate_cbk, subvol, - subvol->fops->truncate, &local->loc, -- local->rebalance.offset, NULL); -+ local->rebalance.offset, local->xattr_req); - } else { - STACK_WIND (frame, dht_truncate_cbk, subvol, - subvol->fops->ftruncate, local->fd, -- local->rebalance.offset, NULL); -+ local->rebalance.offset, local->xattr_req); - } - - return 0; -@@ -366,6 +367,8 @@ dht_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - STACK_WIND (frame, dht_truncate_cbk, - subvol, subvol->fops->truncate, -@@ -407,6 +410,8 @@ dht_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - STACK_WIND (frame, dht_truncate_cbk, - subvol, subvol->fops->ftruncate, -@@ -533,7 +538,7 @@ dht_fallocate2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - - STACK_WIND(frame, dht_fallocate_cbk, subvol, subvol->fops->fallocate, - local->fd, local->rebalance.flags, local->rebalance.offset, -- local->rebalance.size, NULL); -+ local->rebalance.size, local->xattr_req); - - return 0; - -@@ -572,6 +577,8 @@ dht_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t mode, - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - STACK_WIND (frame, dht_fallocate_cbk, - subvol, subvol->fops->fallocate, -@@ -698,7 +705,7 @@ dht_discard2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - - STACK_WIND(frame, dht_discard_cbk, subvol, subvol->fops->discard, - local->fd, local->rebalance.offset, local->rebalance.size, -- NULL); -+ local->xattr_req); - - return 0; - -@@ -736,6 +743,8 @@ dht_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - STACK_WIND (frame, dht_discard_cbk, subvol, subvol->fops->discard, - fd, offset, len, xdata); -@@ -861,7 +870,7 @@ dht_zerofill2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - - STACK_WIND(frame, dht_zerofill_cbk, subvol, subvol->fops->zerofill, - local->fd, local->rebalance.offset, local->rebalance.size, -- NULL); -+ local->xattr_req); - - return 0; - -@@ -900,6 +909,8 @@ dht_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - STACK_WIND (frame, dht_zerofill_cbk, subvol, subvol->fops->zerofill, - fd, offset, len, xdata); -@@ -1004,12 +1015,12 @@ dht_setattr2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret) - STACK_WIND (frame, dht_file_setattr_cbk, subvol, - subvol->fops->setattr, &local->loc, - &local->rebalance.stbuf, local->rebalance.flags, -- NULL); -+ local->xattr_req); - } else { - STACK_WIND (frame, dht_file_setattr_cbk, subvol, - subvol->fops->fsetattr, local->fd, - &local->rebalance.stbuf, local->rebalance.flags, -- NULL); -+ local->xattr_req); - } - - return 0; -@@ -1102,6 +1113,8 @@ dht_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - if (IA_ISREG (loc->inode->ia_type)) { - /* in the regular file _cbk(), we need to check for -@@ -1173,6 +1186,8 @@ dht_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iatt *stbuf, - op_errno = EINVAL; - goto err; - } -+ if (xdata) -+ local->xattr_req = dict_ref (xdata); - - if (IA_ISREG (fd->inode->ia_type)) { - /* in the regular file _cbk(), we need to check for --- -1.8.3.1 - diff --git a/SOURCES/0313-gfapi-add-API-to-trigger-events-for-debugging-and-tr.patch b/SOURCES/0313-gfapi-add-API-to-trigger-events-for-debugging-and-tr.patch new file mode 100644 index 0000000..de11a68 --- /dev/null +++ b/SOURCES/0313-gfapi-add-API-to-trigger-events-for-debugging-and-tr.patch @@ -0,0 +1,339 @@ +From ddea13cfd96075170266022ed9a806726c7238fa Mon Sep 17 00:00:00 2001 +From: Niels de Vos +Date: Fri, 6 Jan 2017 12:49:32 +0100 +Subject: [PATCH 313/361] gfapi: add API to trigger events for debugging and + troubleshooting + +Introduce glfs_sysrq() as a generic API for triggering debug and +troubleshoot events. This interface will be used by the feature to get +statedumps for applications using libgfapi. + +The current events that can be requested through this API are: + - 'h'elp: log a mesage with all supported events + - 's'tatedump: trigger a statedump for the passed glfs_t + +In future, this API can be used by a CLI to trigger statedumps from +storage servers. At the moment it is limited to take statedumps, but it +is extensible to set the log-level, clear caches, force reconnects and +much more. + +mainline: +> BUG: 1169302 +> Reviewed-on: http://review.gluster.org/16414 +> Original-author: Poornima G +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Prashanth Pai +> Reviewed-by: Kaleb KEITHLEY +(cherry picked from commit dbeaa3a88514ce6cee39bfe0fd0c79f971d2bea8) + +BUG: 1378085 +Change-Id: I18858359a3957870cea5139c79efe1365a15a992 +Signed-off-by: Niels de Vos +Reviewed-on: https://code.engineering.redhat.com/gerrit/101293 +Tested-by: Milind Changire +Reviewed-by: Atin Mukherjee +--- + api/src/gfapi-messages.h | 5 ++-- + api/src/gfapi.aliases | 6 ++++ + api/src/gfapi.map | 15 ++++++++++ + api/src/glfs.c | 64 ++++++++++++++++++++++++++++++++++++++++-- + api/src/glfs.h | 18 ++++++++++++ + tests/basic/gfapi/glfs_sysrq.c | 61 ++++++++++++++++++++++++++++++++++++++++ + tests/basic/gfapi/glfs_sysrq.t | 39 +++++++++++++++++++++++++ + 7 files changed, 203 insertions(+), 5 deletions(-) + create mode 100644 tests/basic/gfapi/glfs_sysrq.c + create mode 100755 tests/basic/gfapi/glfs_sysrq.t + +diff --git a/api/src/gfapi-messages.h b/api/src/gfapi-messages.h +index fd90ff4..6e131b5 100644 +--- a/api/src/gfapi-messages.h ++++ b/api/src/gfapi-messages.h +@@ -40,8 +40,8 @@ + */ + + #define GLFS_GFAPI_BASE GLFS_MSGID_COMP_API +-#define GLFS_NUM_MESSAGES 48 +-#define GLFS_MSGID_END (GLFS_GFAPI_BASE + GLFS_NUM_MESSAGESi + 1) ++#define GLFS_NUM_MESSAGES 49 ++#define GLFS_MSGID_END (GLFS_GFAPI_BASE + GLFS_NUM_MESSAGES + 1) + /* Messages with message IDs */ + #define glfs_msg_start_x GLFS_GFAPI_BASE, "Invalid: Start of messages" + /*------------*/ +@@ -94,6 +94,7 @@ + #define API_MSG_ALLOC_FAILED (GLFS_GFAPI_BASE + 46) + #define API_MSG_CREATE_HANDLE_FAILED (GLFS_GFAPI_BASE + 47) + #define API_MSG_INODE_LINK_FAILED (GLFS_GFAPI_BASE + 48) ++#define API_MSG_STATEDUMP_FAILED (GLFS_GFAPI_BASE + 49) + + /*------------*/ + #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages" +diff --git a/api/src/gfapi.aliases b/api/src/gfapi.aliases +index a3eddda..c69d650 100644 +--- a/api/src/gfapi.aliases ++++ b/api/src/gfapi.aliases +@@ -154,3 +154,9 @@ _pub_glfs_upcall_inode_get_pobject _glfs_upcall_inode_get_pobject$GFAPI_3.7.16 + _pub_glfs_upcall_inode_get_pstat _glfs_upcall_inode_get_pstat$GFAPI_3.7.16 + _pub_glfs_upcall_inode_get_oldpobject _glfs_upcall_inode_get_oldpobject$GFAPI_3.7.16 + _pub_glfs_upcall_inode_get_oldpstat _glfs_upcall_inode_get_oldpstat$GFAPI_3.7.16 ++ ++_pub_glfs_realpath _glfs_realpath$GFAPI_3.7.17 ++ ++_pub_glfs_sysrq _glfs_sysrq$GFAPI_3.10.0 ++ ++_pub_glfs_ipc _glfs_ipc$GFAPI_4.0.0 +diff --git a/api/src/gfapi.map b/api/src/gfapi.map +index 02da0fe..3bf2ffe 100644 +--- a/api/src/gfapi.map ++++ b/api/src/gfapi.map +@@ -187,3 +187,18 @@ GFAPI_3.7.16 { + glfs_upcall_inode_get_oldpobject; + glfs_upcall_inode_get_oldpstat; + } GFAPI_3.7.15; ++ ++GFAPI_3.7.17 { ++ global: ++ glfs_realpath; ++} GFAPI_3.7.16; ++ ++GFAPI_3.10.0 { ++ global: ++ glfs_sysrq; ++} GFAPI_3.7.17; ++ ++GFAPI_4.0.0 { ++ global: ++ glfs_ipc; ++} GFAPI_3.10.0; +diff --git a/api/src/glfs.c b/api/src/glfs.c +index 9f70cce..5474922 100644 +--- a/api/src/glfs.c ++++ b/api/src/glfs.c +@@ -40,12 +40,13 @@ + #include "common-utils.h" + #include "syncop.h" + #include "call-stub.h" +-#include "gfapi-messages.h" ++#include "hashfn.h" ++#include "rpc-clnt.h" ++#include "statedump.h" + ++#include "gfapi-messages.h" + #include "glfs.h" + #include "glfs-internal.h" +-#include "hashfn.h" +-#include "rpc-clnt.h" + + + static gf_boolean_t +@@ -1408,3 +1409,60 @@ pub_glfs_upcall_inode_get_oldpstat (struct glfs_upcall_inode *arg) + return &arg->oldp_buf; + } + GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_oldpstat, 3.7.16); ++ ++ ++/* definitions of the GLFS_SYSRQ_* chars are in glfs.h */ ++static struct glfs_sysrq_help { ++ char sysrq; ++ char *msg; ++} glfs_sysrq_help[] = { ++ { GLFS_SYSRQ_HELP, "(H)elp" }, ++ { GLFS_SYSRQ_STATEDUMP, "(S)tatedump" }, ++ { 0, NULL } ++}; ++ ++int ++pub_glfs_sysrq (struct glfs *fs, char sysrq) ++{ ++ glusterfs_ctx_t *ctx = NULL; ++ int ret = 0; ++ ++ if (!fs || !fs->ctx) { ++ ret = -1; ++ errno = EINVAL; ++ goto out; ++ } ++ ++ ctx = fs->ctx; ++ ++ switch (sysrq) { ++ case GLFS_SYSRQ_HELP: ++ { ++ char msg[1024]; /* help text should not exceed 1024 chars */ ++ struct glfs_sysrq_help *usage; ++ ++ msg[0] = '\0'; ++ for (usage = glfs_sysrq_help; usage->sysrq; usage++) { ++ strncat (msg, usage->msg, 1024); ++ strncat (msg, " ", 1024); ++ } ++ ++ /* not really an 'error', but make sure it gets logged */ ++ gf_log ("glfs", GF_LOG_ERROR, "available events: %s", msg); ++ ++ break; ++ } ++ case GLFS_SYSRQ_STATEDUMP: ++ gf_proc_dump_info (SIGUSR1, ctx); ++ break; ++ default: ++ gf_msg ("glfs", GF_LOG_ERROR, ENOTSUP, API_MSG_INVALID_ENTRY, ++ "'%c' is not a valid sysrq", sysrq); ++ errno = ENOTSUP; ++ ret = -1; ++ } ++out: ++ return ret; ++} ++ ++GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_sysrq, 3.10.0); +diff --git a/api/src/glfs.h b/api/src/glfs.h +index 8b5782e..9780b52 100644 +--- a/api/src/glfs.h ++++ b/api/src/glfs.h +@@ -772,11 +772,29 @@ glfs_fd_t *glfs_dup (glfs_fd_t *fd) __THROW + void glfs_free (void *ptr) __THROW + GFAPI_PUBLIC(glfs_free, 3.7.16); + ++ ++/* ++ * glfs_sysrq: send a system request to the @fs instance ++ * ++ * Different commands for @sysrq are possible, the defines for these are listed ++ * below the function definition. ++ * ++ * This function always returns success if the @sysrq is recognized. The return ++ * value does not way anythin about the result of the @sysrq execution. Not all ++ * @sysrq command will be able to return a success/failure status. ++ */ ++int glfs_sysrq (glfs_t *fs, char sysrq) __THROW ++ GFAPI_PUBLIC(glfs_sysrq, 3.10.0); ++ ++#define GLFS_SYSRQ_HELP 'h' /* log a message with supported sysrq commands */ ++#define GLFS_SYSRQ_STATEDUMP 's' /* create a statedump */ ++ + /* + * No xdata support for now. Nobody needs this call at all yet except for the + * test script, and that doesn't need xdata. Adding dict_t support and a new + * header-file requirement doesn't seem worth it until the need is greater. + */ ++ + int glfs_ipc (glfs_fd_t *fd, int cmd) __THROW + GFAPI_PUBLIC(glfs_ipc, 3.7.0); + +diff --git a/tests/basic/gfapi/glfs_sysrq.c b/tests/basic/gfapi/glfs_sysrq.c +new file mode 100644 +index 0000000..c843c2a +--- /dev/null ++++ b/tests/basic/gfapi/glfs_sysrq.c +@@ -0,0 +1,61 @@ ++/** glfs_sysrq.c ++ * ++ * Simple test application to run all glfs_syqrq() debugging calls. ++ * ++ * Usage: ./glfs_sysrq ++ */ ++#include ++#include ++ ++#include ++ ++int ++main (int argc, char *argv[]) ++{ ++ /* cmdline arguments */ ++ char *host = NULL; ++ char *volume = NULL; ++ char *logfile = NULL; ++ ++ /* other variables */ ++ glfs_t *fs = NULL; ++ int ret = 0; ++ ++ if (argc != 4) { ++ fprintf (stderr, "Usage: %s \n", ++ argv[0]); ++ return -1; ++ } ++ ++ host = argv[1]; ++ volume = argv[2]; ++ logfile = argv[3]; ++ ++ fs = glfs_new (volume); ++ if (!fs) { ++ return -1; ++ } ++ ++ ret = glfs_set_logging (fs, logfile, 7); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ ret = glfs_set_volfile_server (fs, "tcp", host, 24007); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ ret = glfs_init (fs); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ /* checking of the results is easier in the script running this test */ ++ glfs_sysrq (fs, GLFS_SYSRQ_HELP); ++ glfs_sysrq (fs, GLFS_SYSRQ_STATEDUMP); ++ ++ glfs_fini (fs); ++ ++ return 0; ++} +diff --git a/tests/basic/gfapi/glfs_sysrq.t b/tests/basic/gfapi/glfs_sysrq.t +new file mode 100755 +index 0000000..d1a0e9b +--- /dev/null ++++ b/tests/basic/gfapi/glfs_sysrq.t +@@ -0,0 +1,39 @@ ++#!/bin/bash ++# ++# Run glfs_sysrq, a gfapi applications calling all glfs_sysrq() commands. ++# Each command generates a specific log message, or something else that can be ++# tested for existance. ++# ++ ++. $(dirname $0)/../../include.rc ++. $(dirname $0)/../../volume.rc ++ ++cleanup ++ ++TEST glusterd ++TEST pidof glusterd ++TEST $CLI volume create $V0 $H0:$B0/brick1 ++EXPECT 'Created' volinfo_field $V0 'Status' ++ ++TEST $CLI volume start $V0; ++EXPECT 'Started' volinfo_field $V0 'Status' ++ ++logdir=$(gluster --print-logdir) ++ ++# clear all statedumps ++cleanup_statedump ++TEST ! test -e $statedumpdir/*.dump.* ++# vim friendly command */ ++ ++build_tester $(dirname $0)/glfs_sysrq.c -lgfapi ++TEST $(dirname $0)/glfs_sysrq $H0 $V0 $logdir/glfs_sysrq.log ++ ++# check for the help message in the log ++TEST grep -q '"(H)elp"' $logdir/glfs_sysrq.log ++ ++# see if there is a statedump ++TEST test -e $statedumpdir/*.dump.* ++# vim friendly command */ ++ ++cleanup_tester $(dirname $0)/glfs_sysrq ++cleanup +-- +1.8.3.1 + diff --git a/SOURCES/0314-cluster-dht-Pass-the-correct-xdata-in-fremovexattr-f.patch b/SOURCES/0314-cluster-dht-Pass-the-correct-xdata-in-fremovexattr-f.patch deleted file mode 100644 index 8d553f3..0000000 --- a/SOURCES/0314-cluster-dht-Pass-the-correct-xdata-in-fremovexattr-f.patch +++ /dev/null @@ -1,66 +0,0 @@ -From f1712395a255656dc57f1ebb095001d084cbec79 Mon Sep 17 00:00:00 2001 -From: Krutika Dhananjay -Date: Thu, 27 Apr 2017 11:53:24 +0530 -Subject: [PATCH 314/316] cluster/dht: Pass the correct xdata in fremovexattr - fop - - Backport of: https://review.gluster.org/17126 - -Change-Id: Ibcb50dbccaab9b8b965dc92e771a5252942f0578 -BUG: 1439753 -Signed-off-by: Krutika Dhananjay -Reviewed-on: https://code.engineering.redhat.com/gerrit/105198 -Reviewed-by: Nithya Balachandran ---- - xlators/cluster/dht/src/dht-common.c | 15 +++++---------- - 1 file changed, 5 insertions(+), 10 deletions(-) - -diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c -index 93bb2ad..8317cc0 100644 ---- a/xlators/cluster/dht/src/dht-common.c -+++ b/xlators/cluster/dht/src/dht-common.c -@@ -4361,6 +4361,7 @@ dht_fremovexattr (call_frame_t *frame, xlator_t *this, - op_errno = EINVAL; - goto err; - } -+ local->xattr_req = xdata ? dict_ref (xdata) : dict_new (); - - local->call_cnt = call_cnt = layout->cnt; - local->key = gf_strdup (key); -@@ -4370,29 +4371,23 @@ dht_fremovexattr (call_frame_t *frame, xlator_t *this, - STACK_WIND (frame, dht_removexattr_cbk, - layout->list[i].xlator, - layout->list[i].xlator->fops->fremovexattr, -- fd, key, NULL); -+ fd, key, local->xattr_req); - } - - } else { - - local->call_cnt = 1; -- xdata = xdata ? dict_ref (xdata) : dict_new (); -- if (xdata) -- ret = dict_set_dynstr_with_alloc (xdata, -- DHT_IATT_IN_XDATA_KEY, "yes"); -+ ret = dict_set_dynstr_with_alloc (local->xattr_req, -+ DHT_IATT_IN_XDATA_KEY, "yes"); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, ENOMEM, - DHT_MSG_DICT_SET_FAILED, "Failed to " - "set dictionary key %s for fd=%p", - DHT_IATT_IN_XDATA_KEY, fd); - } -- - STACK_WIND (frame, dht_file_removexattr_cbk, - subvol, subvol->fops->fremovexattr, -- fd, key, xdata); -- -- if (xdata) -- dict_unref (xdata); -+ fd, key, local->xattr_req); - } - - return 0; --- -1.8.3.1 - diff --git a/SOURCES/0314-dht-rebalance-Estimate-time-to-complete-rebalance.patch b/SOURCES/0314-dht-rebalance-Estimate-time-to-complete-rebalance.patch new file mode 100644 index 0000000..e5ad70d --- /dev/null +++ b/SOURCES/0314-dht-rebalance-Estimate-time-to-complete-rebalance.patch @@ -0,0 +1,577 @@ +From 68b385605f52503f8c80ebf0aa15fd278b5db6d0 Mon Sep 17 00:00:00 2001 +From: N Balachandran +Date: Tue, 17 Jan 2017 15:43:47 +0530 +Subject: [PATCH 314/361] dht/rebalance Estimate time to complete rebalance + +The estimates will be logged to the rebalance log on running +gluster v rebalance status + +mainline: +> BUG: 1396004 +> Reviewed-on: http://review.gluster.org/15893 +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Raghavendra G +(cherry picked from commit 310405d689760fc1abe3075c4bcf6cf7351e60bc) + +BUG: 1380598 +Change-Id: I9d51b139cd4c8dfde1ff2c2050720ae606c13fc6 +Signed-off-by: N Balachandran +Reviewed-on: https://code.engineering.redhat.com/gerrit/101294 +Tested-by: Milind Changire +Reviewed-by: Atin Mukherjee +--- + cli/src/cli-rpc-ops.c | 28 +++- + xlators/cluster/dht/src/dht-rebalance.c | 102 +++++++++++- + xlators/mgmt/glusterd/src/glusterd-utils.c | 251 ++++++++++++++++++++++++++++- + xlators/mgmt/glusterd/src/glusterd.h | 1 + + 4 files changed, 376 insertions(+), 6 deletions(-) + +diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c +index 5a0cfdf..339d91b 100644 +--- a/cli/src/cli-rpc-ops.c ++++ b/cli/src/cli-rpc-ops.c +@@ -1611,6 +1611,9 @@ gf_cli_print_rebalance_status (dict_t *dict, enum gf_task_types task_type, + int sec = 0; + gf_boolean_t down = _gf_false; + gf_boolean_t fix_layout = _gf_false; ++ uint64_t max_time = 0; ++ uint64_t time_left = 0; ++ + + ret = dict_get_int32 (dict, "count", &count); + if (ret) { +@@ -1663,6 +1666,7 @@ gf_cli_print_rebalance_status (dict_t *dict, enum gf_task_types task_type, + skipped = 0; + status_str = NULL; + elapsed = 0; ++ time_left = 0; + + /* Check if status is NOT_STARTED, and continue early */ + memset (key, 0, 256); +@@ -1740,6 +1744,15 @@ gf_cli_print_rebalance_status (dict_t *dict, enum gf_task_types task_type, + if (ret) + gf_log ("cli", GF_LOG_TRACE, "failed to get run-time"); + ++ memset (key, 0, 256); ++ snprintf (key, 256, "time-left-%d", i); ++ ret = dict_get_uint64 (dict, key, &time_left); ++ if (ret) ++ gf_log ("cli", GF_LOG_TRACE, ++ "failed to get time left"); ++ if (time_left > max_time) ++ max_time = time_left; ++ + /* Check for array bound */ + if (status_rcd >= GF_DEFRAG_STATUS_MAX) + status_rcd = GF_DEFRAG_STATUS_MAX; +@@ -1757,15 +1770,15 @@ gf_cli_print_rebalance_status (dict_t *dict, enum gf_task_types task_type, + if (size_str) { + cli_out ("%40s %16"PRIu64 " %13s" " %13"PRIu64 + " %13" PRIu64" %13"PRIu64 " %20s " +- "%8d:%d:%d", node_name, files, ++ "%8d:%02d:%02d", node_name, files, + size_str, lookup, failures, skipped, + status_str, hrs, min, sec); + } else { + cli_out ("%40s %16"PRIu64 " %13"PRIu64 " %13" + PRIu64 " %13"PRIu64" %13"PRIu64 " %20s" +- " %8d:%d:%d", node_name, files, size, +- lookup, failures, skipped, status_str, +- hrs, min, sec); ++ " %8d:%02d:%02d", node_name, files, ++ size, lookup, failures, skipped, ++ status_str, hrs, min, sec); + } + } + GF_FREE(size_str); +@@ -1775,6 +1788,13 @@ gf_cli_print_rebalance_status (dict_t *dict, enum gf_task_types task_type, + " Please check the nodes that are down using \'gluster" + " peer status\' and start the glusterd on those nodes," + " else tier detach commit might fail!"); ++ if (max_time) { ++ hrs = max_time / 3600; ++ min = ((int) max_time % 3600) / 60; ++ sec = ((int) max_time % 3600) % 60; ++ cli_out ("Estimated time left for rebalance to complete :" ++ " %8d:%02d:%02d", hrs, min, sec); ++ } + out: + return ret; + } +diff --git a/xlators/cluster/dht/src/dht-rebalance.c b/xlators/cluster/dht/src/dht-rebalance.c +index 39a7bb6..76778de 100644 +--- a/xlators/cluster/dht/src/dht-rebalance.c ++++ b/xlators/cluster/dht/src/dht-rebalance.c +@@ -46,6 +46,9 @@ + } \ + } \ + ++uint64_t g_totalfiles = 0; ++ ++ + void + gf_defrag_free_container (struct dht_container *container) + { +@@ -3701,6 +3704,58 @@ gf_tier_wait_fix_lookup (gf_defrag_info_t *defrag) { + /******************Tier background Fix layout functions END********************/ + + ++uint64_t gf_defrag_subvol_file_cnt (xlator_t *this, loc_t *root_loc) ++{ ++ int ret = -1; ++ struct statvfs buf = {0,}; ++ ++ if (!this) ++ return 0; ++ ++ ret = syncop_statfs (this, root_loc, &buf, NULL, NULL); ++ if (ret) { ++ /* Aargh! */ ++ return 0; ++ } ++ return (buf.f_files - buf.f_ffree); ++} ++ ++ ++int gf_defrag_total_file_cnt (xlator_t *this, loc_t *root_loc) ++{ ++ dht_conf_t *conf = NULL; ++ int ret = -1; ++ int i = 0; ++ uint64_t num_files = 0; ++ ++ ++ conf = this->private; ++ if (!conf) { ++ return ret; ++ } ++ ++ for (i = 0 ; i < conf->local_subvols_cnt; i++) { ++ num_files = gf_defrag_subvol_file_cnt (conf->local_subvols[i], ++ root_loc); ++ g_totalfiles += num_files; ++ gf_msg (this->name, GF_LOG_INFO, 0, 0, "local subvol: %s," ++ "cnt = %"PRIu64, conf->local_subvols[i]->name, ++ num_files); ++ } ++ ++ /* FIXFIXFIX: halve the number of files to negate .glusterfs contents ++ We need a better way to figure this out */ ++ ++ g_totalfiles = g_totalfiles/2; ++ if (g_totalfiles > 20000) ++ g_totalfiles += 10000; ++ ++ gf_msg (this->name, GF_LOG_INFO, 0, 0, ++ "Total number of files = %"PRIu64, g_totalfiles); ++ ++ return 0; ++} ++ + + int + gf_defrag_start_crawl (void *data) +@@ -3725,6 +3780,7 @@ gf_defrag_start_crawl (void *data) + pthread_t *tid = NULL; + gf_boolean_t is_tier_detach = _gf_false; + ++ + this = data; + if (!this) + goto exit; +@@ -3854,6 +3910,13 @@ gf_defrag_start_crawl (void *data) + "are %s", conf->local_subvols[i]->name); + } + ++ ret = gf_defrag_total_file_cnt (this, &loc); ++ if (!ret) { ++ gf_msg (this->name, GF_LOG_ERROR, 0, 0, "Failed to get " ++ "the total number of files. Unable to estimate " ++ "time to complete rebalance."); ++ } ++ + /* Initialize global entry queue */ + defrag->queue = GF_CALLOC (1, sizeof (struct dht_container), + gf_dht_mt_container_t); +@@ -4090,8 +4153,11 @@ gf_defrag_status_get (gf_defrag_info_t *defrag, dict_t *dict) + uint64_t skipped = 0; + uint64_t promoted = 0; + uint64_t demoted = 0; +- char *status = ""; ++ char *status = ""; + double elapsed = 0; ++ uint64_t time_left = 0; ++ uint64_t time_to_complete = 0; ++ double rate_lookedup = 0; + struct timeval end = {0,}; + + +@@ -4114,6 +4180,34 @@ gf_defrag_status_get (gf_defrag_info_t *defrag, dict_t *dict) + + elapsed = end.tv_sec - defrag->start_time.tv_sec; + ++/*START */ ++ ++/* rate at which files looked up */ ++ ++ ++ if ((defrag->cmd != GF_DEFRAG_CMD_START_TIER) ++ && (defrag->defrag_status == GF_DEFRAG_STATUS_STARTED) ++ && g_totalfiles) { ++ ++ rate_lookedup = (defrag->num_files_lookedup)/elapsed; ++ if (defrag->num_files_lookedup > g_totalfiles) ++ g_totalfiles = defrag->num_files_lookedup + 10000; ++ time_to_complete = (g_totalfiles)/rate_lookedup; ++ time_left = time_to_complete - elapsed; ++ ++ gf_log (THIS->name, GF_LOG_INFO, ++ "TIME: num_files_lookedup=%"PRIu64",elapsed time = %f," ++ "rate_lookedup=%f", defrag->num_files_lookedup, elapsed, ++ rate_lookedup); ++ gf_log (THIS->name, GF_LOG_INFO, ++ "TIME: Estimated total time to complete = %"PRIu64 ++ " seconds", time_to_complete); ++ ++ gf_log (THIS->name, GF_LOG_INFO, ++ "TIME: Seconds left = %"PRIu64" seconds", time_left); ++ } ++ ++/*END */ + if (!dict) + goto log; + +@@ -4162,6 +4256,12 @@ gf_defrag_status_get (gf_defrag_info_t *defrag, dict_t *dict) + if (ret) + gf_log (THIS->name, GF_LOG_WARNING, + "failed to set skipped file count"); ++ ++ ret = dict_set_uint64 (dict, "time-left", time_left); ++ if (ret) ++ gf_log (THIS->name, GF_LOG_WARNING, ++ "failed to set time-left"); ++ + log: + switch (defrag->defrag_status) { + case GF_DEFRAG_STATUS_NOT_STARTED: +diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c +index d849690..e976ba2 100644 +--- a/xlators/mgmt/glusterd/src/glusterd-utils.c ++++ b/xlators/mgmt/glusterd/src/glusterd-utils.c +@@ -7586,6 +7586,7 @@ glusterd_defrag_volume_status_update (glusterd_volinfo_t *volinfo, + dict_t *rsp_dict) + { + int ret = 0; ++ int ret2 = 0; + uint64_t files = 0; + uint64_t size = 0; + uint64_t lookup = 0; +@@ -7596,6 +7597,7 @@ glusterd_defrag_volume_status_update (glusterd_volinfo_t *volinfo, + double run_time = 0; + uint64_t promoted = 0; + uint64_t demoted = 0; ++ uint64_t time_left = 0; + + this = THIS; + +@@ -7658,6 +7660,11 @@ glusterd_defrag_volume_status_update (glusterd_volinfo_t *volinfo, + volinfo->rebal.skipped_files = skipped; + if (run_time) + volinfo->rebal.rebalance_time = run_time; ++ ret2 = dict_get_uint64 (rsp_dict, "time-left", &time_left); ++ if (ret2) ++ gf_msg_trace (this->name, 0, ++ "failed to get time left"); ++ + if (promoted) + volinfo->tier_info.promoted = promoted; + if (demoted) +@@ -9254,7 +9261,7 @@ glusterd_volume_rebalance_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict) + ret = dict_set_uint64 (ctx_dict, key, value); + if (ret) { + gf_msg_debug (THIS->name, 0, +- "failed to set lookuped file count"); ++ "failed to set looked up file count"); + } + } + +@@ -9310,6 +9317,18 @@ glusterd_volume_rebalance_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict) + } + + memset (key, 0, 256); ++ snprintf (key, 256, "time-left-%d", index); ++ ret = dict_get_uint64 (rsp_dict, key, &value); ++ if (!ret) { ++ memset (key, 0, 256); ++ snprintf (key, 256, "time-left-%d", current_index); ++ ret = dict_set_uint64 (ctx_dict, key, value); ++ if (ret) { ++ gf_msg_debug (THIS->name, 0, ++ "failed to set time-left"); ++ } ++ } ++ memset (key, 0, 256); + snprintf (key, 256, "demoted-%d", index); + ret = dict_get_uint64 (rsp_dict, key, &value); + if (!ret) { +@@ -9341,6 +9360,228 @@ out: + } + + int ++<<<<<<< 07a9e00a5702e76932142e9d9cdc2df601632b7a ++======= ++glusterd_volume_tier_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict) ++{ ++ char key[256] = {0,}; ++ char *node_uuid = NULL; ++ char *node_uuid_str = NULL; ++ char *volname = NULL; ++ dict_t *ctx_dict = NULL; ++ double elapsed_time = 0; ++ glusterd_volinfo_t *volinfo = NULL; ++ int ret = 0; ++ int32_t index = 0; ++ int32_t count = 0; ++ int32_t value32 = 0; ++ uint64_t value = 0; ++ xlator_t *this = NULL; ++ char *task_id_str = NULL; ++ ++ this = THIS; ++ GF_VALIDATE_OR_GOTO (this->name, this, out); ++ GF_VALIDATE_OR_GOTO (this->name, rsp_dict, out); ++ ++ if (aggr) { ++ ctx_dict = aggr; ++ ++ } else { ++ gf_msg (this->name, GF_LOG_ERROR, 0, ++ GD_MSG_OPCTX_GET_FAIL, ++ "Operation Context is not present"); ++ goto out; ++ } ++ ++ if (!ctx_dict) ++ goto out; ++ ++ ret = dict_get_str (ctx_dict, "volname", &volname); ++ if (ret) { ++ gf_msg (this->name, GF_LOG_ERROR, 0, ++ GD_MSG_DICT_GET_FAILED, ++ "Unable to get volume name"); ++ goto out; ++ } ++ ++ ret = glusterd_volinfo_find (volname, &volinfo); ++ ++ if (ret) ++ goto out; ++ ++ ret = dict_get_int32 (rsp_dict, "count", &index); ++ if (ret) ++ gf_msg (this->name, GF_LOG_ERROR, 0, ++ GD_MSG_DICT_GET_FAILED, ++ "failed to get index"); ++ ++ memset (key, 0, 256); ++ snprintf (key, 256, "node-uuid-%d", index); ++ ret = dict_get_str (rsp_dict, key, &node_uuid); ++ if (!ret) { ++ node_uuid_str = gf_strdup (node_uuid); ++ ++ } ++ ret = dict_get_int32 (ctx_dict, "count", &count); ++ count++; ++ ret = dict_set_int32 (ctx_dict, "count", count); ++ if (ret) ++ gf_msg (this->name, GF_LOG_ERROR, 0, ++ GD_MSG_DICT_SET_FAILED, ++ "Failed to set count"); ++ ++ memset (key, 0, 256); ++ snprintf (key, 256, "node-uuid-%d", count); ++ ret = dict_set_dynstr (ctx_dict, key, node_uuid_str); ++ if (ret) { ++ gf_msg_debug (this->name, 0, ++ "failed to set node-uuid"); ++ } ++ ++ snprintf (key, 256, "files-%d", index); ++ ret = dict_get_uint64 (rsp_dict, key, &value); ++ if (!ret) { ++ memset (key, 0, 256); ++ snprintf (key, 256, "files-%d", count); ++ ret = dict_set_uint64 (ctx_dict, key, value); ++ if (ret) { ++ gf_msg_debug (this->name, 0, ++ "failed to set the file count"); ++ } ++ } ++ ++ memset (key, 0, 256); ++ snprintf (key, 256, "size-%d", index); ++ ret = dict_get_uint64 (rsp_dict, key, &value); ++ if (!ret) { ++ memset (key, 0, 256); ++ snprintf (key, 256, "size-%d", count); ++ ret = dict_set_uint64 (ctx_dict, key, value); ++ if (ret) { ++ gf_msg_debug (this->name, 0, ++ "failed to set the size of migration"); ++ } ++ } ++ ++ memset (key, 0, 256); ++ snprintf (key, 256, "lookups-%d", index); ++ ret = dict_get_uint64 (rsp_dict, key, &value); ++ if (!ret) { ++ memset (key, 0, 256); ++ snprintf (key, 256, "lookups-%d", count); ++ ret = dict_set_uint64 (ctx_dict, key, value); ++ if (ret) { ++ gf_msg_debug (this->name, 0, ++ "failed to set looked up file count"); ++ } ++ } ++ ++ memset (key, 0, 256); ++ snprintf (key, 256, "status-%d", index); ++ ret = dict_get_int32 (rsp_dict, key, &value32); ++ if (!ret) { ++ memset (key, 0, 256); ++ snprintf (key, 256, "status-%d", count); ++ ret = dict_set_int32 (ctx_dict, key, value32); ++ if (ret) { ++ gf_msg_debug (this->name, 0, ++ "failed to set status"); ++ } ++ } ++ ++ memset (key, 0, 256); ++ snprintf (key, 256, "failures-%d", index); ++ ret = dict_get_uint64 (rsp_dict, key, &value); ++ if (!ret) { ++ memset (key, 0, 256); ++ snprintf (key, 256, "failures-%d", count); ++ ret = dict_set_uint64 (ctx_dict, key, value); ++ if (ret) { ++ gf_msg_debug (this->name, 0, ++ "failed to set failure count"); ++ } ++ } ++ ++ memset (key, 0, 256); ++ snprintf (key, 256, "skipped-%d", index); ++ ret = dict_get_uint64 (rsp_dict, key, &value); ++ if (!ret) { ++ memset (key, 0, 256); ++ snprintf (key, 256, "skipped-%d", count); ++ ret = dict_set_uint64 (ctx_dict, key, value); ++ if (ret) { ++ gf_msg_debug (this->name, 0, ++ "failed to set skipped count"); ++ } ++ } ++ memset (key, 0, 256); ++ snprintf (key, 256, "run-time-%d", index); ++ ret = dict_get_double (rsp_dict, key, &elapsed_time); ++ if (!ret) { ++ memset (key, 0, 256); ++ snprintf (key, 256, "run-time-%d", count); ++ ret = dict_set_double (ctx_dict, key, elapsed_time); ++ if (ret) { ++ gf_msg_debug (this->name, 0, ++ "failed to set run-time"); ++ } ++ } ++ ++ memset (key, 0, 256); ++ snprintf (key, 256, "demoted-%d", index); ++ ret = dict_get_uint64 (rsp_dict, key, &value); ++ if (!ret) { ++ memset (key, 0, 256); ++ snprintf (key, 256, "demoted-%d", count); ++ ret = dict_set_uint64 (ctx_dict, key, value); ++ if (ret) { ++ gf_msg_debug (this->name, 0, ++ "failed to set demoted count"); ++ } ++ } ++ memset (key, 0, 256); ++ snprintf (key, 256, "promoted-%d", index); ++ ret = dict_get_uint64 (rsp_dict, key, &value); ++ if (!ret) { ++ memset (key, 0, 256); ++ snprintf (key, 256, "promoted-%d", count); ++ ret = dict_set_uint64 (ctx_dict, key, value); ++ if (ret) { ++ gf_msg_debug (this->name, 0, ++ "failed to set promoted count"); ++ } ++ } ++ ++ memset (key, 0, 256); ++ snprintf (key, 256, "time-left-%d", index); ++ ret = dict_get_uint64 (rsp_dict, key, &value); ++ if (!ret) { ++ memset (key, 0, 256); ++ snprintf (key, 256, "time-left-%d", count); ++ ret = dict_set_uint64 (ctx_dict, key, value); ++ if (ret) { ++ gf_msg_debug (THIS->name, 0, ++ "failed to set time-left"); ++ } ++ } ++ ++ ret = dict_get_str (rsp_dict, GF_REMOVE_BRICK_TID_KEY, ++ &task_id_str); ++ if (ret) { ++ gf_msg_debug (this->name, errno, ++ "Missing remove-brick-id"); ++ } else ++ ret = dict_set_str (ctx_dict, GF_REMOVE_BRICK_TID_KEY, ++ task_id_str); ++ ++ ret = 0; ++ ++out: ++ return ret; ++} ++ ++int ++>>>>>>> dht/rebalance Estimate time to complete rebalance + glusterd_sys_exec_output_rsp_dict (dict_t *dst, dict_t *src) + { + char output_name[PATH_MAX] = ""; +@@ -9976,6 +10217,14 @@ glusterd_defrag_volume_node_rsp (dict_t *req_dict, dict_t *rsp_dict, + "failed to set run-time"); + + memset (key, 0 , 256); ++ snprintf (key, 256, "time-left-%d", i); ++ ret = dict_set_uint64 (op_ctx, key, volinfo->rebal.time_left); ++ if (ret) ++ gf_msg (THIS->name, GF_LOG_ERROR, errno, ++ GD_MSG_DICT_SET_FAILED, ++ "failed to set time left"); ++ ++ memset (key, 0 , 256); + snprintf (key, 256, "promoted-%d", i); + ret = dict_set_uint64 (op_ctx, key, volinfo->tier_info.promoted); + if (ret) +diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h +index a21b0a1..c84f019 100644 +--- a/xlators/mgmt/glusterd/src/glusterd.h ++++ b/xlators/mgmt/glusterd/src/glusterd.h +@@ -308,6 +308,7 @@ struct glusterd_rebalance_ { + uint64_t rebalance_failures; + uuid_t rebalance_id; + double rebalance_time; ++ uint64_t time_left; + glusterd_op_t op; + dict_t *dict; /* Dict to store misc information + * like list of bricks being removed */ +-- +1.8.3.1 + diff --git a/SOURCES/0315-cluster-dht-Fix-crash-in-dht-rmdir.patch b/SOURCES/0315-cluster-dht-Fix-crash-in-dht-rmdir.patch deleted file mode 100644 index f8626a5..0000000 --- a/SOURCES/0315-cluster-dht-Fix-crash-in-dht-rmdir.patch +++ /dev/null @@ -1,88 +0,0 @@ -From ad43f68a39cc7b2765531049b93e2286ad69a7b0 Mon Sep 17 00:00:00 2001 -From: N Balachandran -Date: Tue, 16 May 2017 21:14:11 +0530 -Subject: [PATCH 315/316] cluster/dht: Fix crash in dht rmdir - -Using local->call_cnt to check STACK_WINDs can -cause dht_rmdir_do to be called erroneously if -dht_rmdir_readdirp_cbk unwinds before we check if -local->call_cnt is zero in dht_rmdir_opendir_cbk. -This can cause frame corruptions and crashes. - -Thanks to Shyam (srangana@redhat.com) for the -analysis. - -> BUG: 1451083 -> Signed-off-by: N Balachandran -> Reviewed-on: https://review.gluster.org/17305 -> Smoke: Gluster Build System -> NetBSD-regression: NetBSD Build System -> CentOS-regression: Gluster Build System -> Reviewed-by: Shyamsundar Ranganathan - -Change-Id: I64cfc9a7fa5c964dd4a7c599d3cec1cd556cc3bb -BUG: 1451200 -Signed-off-by: N Balachandran -Reviewed-on: https://code.engineering.redhat.com/gerrit/106332 -Reviewed-by: Shyam Ranganathan ---- - xlators/cluster/dht/src/dht-common.c | 15 +++++++++++---- - 1 file changed, 11 insertions(+), 4 deletions(-) - -diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c -index 8317cc0..a97294c 100644 ---- a/xlators/cluster/dht/src/dht-common.c -+++ b/xlators/cluster/dht/src/dht-common.c -@@ -8418,6 +8418,8 @@ dht_rmdir_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - char gfid[GF_UUID_BUF_SIZE] = {0}; - dht_local_t *readdirp_local = NULL; - call_frame_t *readdirp_frame = NULL; -+ int cnt = 0; -+ - - local = frame->local; - prev = cookie; -@@ -8460,7 +8462,7 @@ dht_rmdir_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - "%s: Failed to set dictionary value:key = %s", - local->loc.path, conf->link_xattr_name); - -- local->call_cnt = conf->subvolume_cnt; -+ cnt = local->call_cnt = conf->subvolume_cnt; - - /* Create a separate frame per subvol as we might need - * to resend readdirp multiple times to get all the -@@ -8471,7 +8473,9 @@ dht_rmdir_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - readdirp_frame = copy_frame (frame); - - if (!readdirp_frame) { -- local->call_cnt--; -+ cnt--; -+ /* Reduce the local->call_cnt as well */ -+ dht_frame_return (frame); - continue; - } - -@@ -8480,7 +8484,9 @@ dht_rmdir_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - - if (!readdirp_local) { - DHT_STACK_DESTROY (readdirp_frame); -- local->call_cnt--; -+ cnt--; -+ /* Reduce the local->call_cnt as well */ -+ dht_frame_return (frame); - continue; - } - readdirp_local->main_frame = frame; -@@ -8500,7 +8506,8 @@ dht_rmdir_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - dict_unref (dict); - - /* Could not wind readdirp to any subvol */ -- if (!local->call_cnt) -+ -+ if (!cnt) - goto err; - - return 0; --- -1.8.3.1 - diff --git a/SOURCES/0315-glusterd-add-a-cli-command-to-trigger-a-statedump-on.patch b/SOURCES/0315-glusterd-add-a-cli-command-to-trigger-a-statedump-on.patch new file mode 100644 index 0000000..7bc9fdd --- /dev/null +++ b/SOURCES/0315-glusterd-add-a-cli-command-to-trigger-a-statedump-on.patch @@ -0,0 +1,493 @@ +From 66b1bb65618f8205e8aa7a0229b0f003f82c5c81 Mon Sep 17 00:00:00 2001 +From: Poornima G +Date: Fri, 22 Jan 2016 11:44:21 -0500 +Subject: [PATCH 315/361] glusterd: add a cli command to trigger a statedump on + a client + +With this, we will be able to trigger statedumps on remote Gluster +clients, mainly targetted for applications using libgfapi. + +Design: +SIGUSR signal is the most comman way of taking a statedump in Gluster. +But it cannot be used for libgfapi based processes, as the process +loading the library might have already consumed SIGUSR signal. Hence +going by the command way. + +One has to issue a Gluster command to initiate a statedump on the +libgfapi based client. The command takes hostname and PID as an +argument. All the glusterds in the cluster, check if they are connected +to the specified hostname, and send an RPC request to all the connected +clients from that hostname (via the mgmt connection). + +[ndevos: minor fixes and split patch in smaller pieces] + +mainline: +> BUG: 1169302 +> Reviewed-on: http://review.gluster.org/16357 +> Reviewed-on: https://review.gluster.org/9228 +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Niels de Vos +> Reviewed-by: Kaleb KEITHLEY +> Reviewed-by: Samikshan Bairagya +> Tested-by: Niels de Vos +(cherry picked from commit 1f1f1eee47c4aad678bd52971b96c1debfce4805) + +BUG: 1378085 +Change-Id: Icbe4d2f026b32a2c7d5535e1bfb2cdaaff042e91 +Signed-off-by: Poornima G +Reviewed-on: https://code.engineering.redhat.com/gerrit/101296 +Tested-by: Milind Changire +Reviewed-by: Atin Mukherjee +--- + cli/src/cli-cmd-parser.c | 46 +++++++++++++---- + cli/src/cli-cmd-volume.c | 4 +- + doc/debugging/statedump.md | 13 +++++ + glusterfsd/src/glusterfsd-mgmt.c | 1 + + libglusterfs/src/common-utils.c | 21 ++++++++ + libglusterfs/src/common-utils.h | 2 + + rpc/rpc-lib/src/protocol-common.h | 1 + + rpc/rpc-lib/src/rpc-transport.h | 2 +- + rpc/xdr/src/rpc-common-xdr.x | 3 ++ + tests/bugs/cli/bug-1169302.t | 34 +++++++++++++ + xlators/mgmt/glusterd/src/glusterd-utils.c | 43 ++++++++++++++++ + xlators/mgmt/glusterd/src/glusterd-utils.h | 4 ++ + xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 7 +++ + xlators/mgmt/glusterd/src/glusterd.c | 67 +++++++++++++++++++++++++ + xlators/mgmt/glusterd/src/glusterd.h | 4 ++ + 15 files changed, 239 insertions(+), 13 deletions(-) + create mode 100755 tests/bugs/cli/bug-1169302.t + +diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c +index 2e61c3a..7637944 100644 +--- a/cli/src/cli-cmd-parser.c ++++ b/cli/src/cli-cmd-parser.c +@@ -3530,19 +3530,44 @@ cli_cmd_volume_statedump_options_parse (const char **words, int wordcount, + dict_t *dict = NULL; + int option_cnt = 0; + char *option = NULL; +- char option_str[100] = {0,}; +- +- for (i = 3; i < wordcount; i++, option_cnt++) { +- if (!cli_cmd_validate_dumpoption (words[i], &option)) { ++ char option_str[_POSIX_HOST_NAME_MAX + 100] = {0,}; ++ char *tmp = NULL; ++ char *ip_addr = NULL; ++ char *pid = NULL; ++ ++ if ((wordcount >= 5) && ((strcmp (words[3], "client")) == 0)) { ++ tmp = gf_strdup(words[4]); ++ if (!tmp) { ++ ret = -1; ++ goto out; ++ } ++ ip_addr = strtok(tmp, ":"); ++ pid = strtok(NULL, ":"); ++ if (valid_internet_address (ip_addr, _gf_true) ++ && pid && gf_valid_pid (pid, strlen(pid))) { ++ strncat (option_str, words[3], strlen (words[3])); ++ strncat (option_str, " ", 1); ++ strncat (option_str, ip_addr, strlen (ip_addr)); ++ strncat (option_str, " ", 1); ++ strncat (option_str, pid, strlen (pid)); ++ option_cnt = 3; ++ } else { ++ ret = -1; ++ goto out; ++ } ++ } else { ++ for (i = 3; i < wordcount; i++, option_cnt++) { ++ if (!cli_cmd_validate_dumpoption (words[i], &option)) { ++ ret = -1; ++ goto out; ++ } ++ strncat (option_str, option, strlen (option)); ++ strncat (option_str, " ", 1); ++ } ++ if ((strstr (option_str, "nfs")) && strstr (option_str, "quotad")) { + ret = -1; + goto out; + } +- strncat (option_str, option, strlen (option)); +- strncat (option_str, " ", 1); +- } +- if((strstr (option_str, "nfs")) && strstr (option_str, "quotad")) { +- ret = -1; +- goto out; + } + + dict = dict_new (); +@@ -3559,6 +3584,7 @@ cli_cmd_volume_statedump_options_parse (const char **words, int wordcount, + + *options = dict; + out: ++ GF_FREE (tmp); + if (ret && dict) + dict_destroy (dict); + if (ret) +diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c +index 04fe432..6737ffd 100644 +--- a/cli/src/cli-cmd-volume.c ++++ b/cli/src/cli-cmd-volume.c +@@ -3295,8 +3295,8 @@ struct cli_cmd volume_cmds[] = { + cli_cmd_volume_heal_cbk, + "self-heal commands on volume specified by "}, + +- {"volume statedump [nfs|quotad] [all|mem|iobuf|callpool|priv|fd|" +- "inode|history]...", ++ {"volume statedump [[nfs|quotad] [all|mem|iobuf|callpool|" ++ "priv|fd|inode|history]... | [client ]]", + cli_cmd_volume_statedump_cbk, + "perform statedump on bricks"}, + +diff --git a/doc/debugging/statedump.md b/doc/debugging/statedump.md +index f34a5c3..e4e02a9 100644 +--- a/doc/debugging/statedump.md ++++ b/doc/debugging/statedump.md +@@ -19,6 +19,19 @@ For quotad: `gluster volume statedump quotad` + + For brick-processes files will be created in `statedump-directory` with name of the file as `hyphenated-brick-path..dump.timestamp`. For all other processes it will be `glusterdump..dump.timestamp`. + ++For applications using libgfapi, `SIGUSR1` cannot be used, eg: smbd/libvirtd ++processes could have used the `SIGUSR1` signal already for other purposes. ++To generate statedump for the processes, using libgfapi, below command can be ++executed from one of the nodes in the gluster cluster to which the libgfapi ++application is connected to. ++ ++ gluster volume statedump client : ++ ++The statedumps can be found in the `statedump-directory`, the name of the ++statedumps being `glusterdump..dump.timestamp`. For a process there can be ++multiple such files created depending on the number of times the volume is ++accessed by the process (related to the number of `glfs_init()` calls). ++ + ##How to read statedump + We shall see snippets of each type of statedump. + +diff --git a/glusterfsd/src/glusterfsd-mgmt.c b/glusterfsd/src/glusterfsd-mgmt.c +index a12496e..bf7b4fc 100644 +--- a/glusterfsd/src/glusterfsd-mgmt.c ++++ b/glusterfsd/src/glusterfsd-mgmt.c +@@ -1450,6 +1450,7 @@ rpcclnt_cb_actor_t mgmt_cbk_actors[GF_CBK_MAXVALUE] = { + [GF_CBK_FETCHSPEC] = {"FETCHSPEC", GF_CBK_FETCHSPEC, mgmt_cbk_spec }, + [GF_CBK_EVENT_NOTIFY] = {"EVENTNOTIFY", GF_CBK_EVENT_NOTIFY, + mgmt_cbk_event}, ++ [GF_CBK_STATEDUMP] = {"STATEDUMP", GF_CBK_STATEDUMP, mgmt_cbk_event}, + }; + + +diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c +index d36069f..9d9f1d5 100644 +--- a/libglusterfs/src/common-utils.c ++++ b/libglusterfs/src/common-utils.c +@@ -3670,6 +3670,27 @@ out: + return running; + } + ++/* Check if the pid is > 0 */ ++gf_boolean_t ++gf_valid_pid (const char *pid, int length) ++{ ++ gf_boolean_t ret = _gf_true; ++ pid_t value = 0; ++ char *end_ptr = NULL; ++ ++ if (length <= 0) { ++ ret = _gf_false; ++ goto out; ++ } ++ ++ value = strtol (pid, &end_ptr, 10); ++ if (value <= 0) { ++ ret = _gf_false; ++ } ++out: ++ return ret; ++} ++ + static int + dht_is_linkfile_key (dict_t *this, char *key, data_t *value, void *data) + { +diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h +index 2a6d02c..ccda0d9 100644 +--- a/libglusterfs/src/common-utils.h ++++ b/libglusterfs/src/common-utils.h +@@ -786,6 +786,8 @@ int gf_thread_create_detached (pthread_t *thread, + + gf_boolean_t + gf_is_service_running (char *pidfile, int *pid); ++gf_boolean_t ++gf_valid_pid (const char *pid, int length); + int + gf_skip_header_section (int fd, int header_len); + +diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h +index 0fe7d1f..ea680f9 100644 +--- a/rpc/rpc-lib/src/protocol-common.h ++++ b/rpc/rpc-lib/src/protocol-common.h +@@ -141,6 +141,7 @@ enum gf_cbk_procnum { + GF_CBK_CHILD_UP, + GF_CBK_CHILD_DOWN, + GF_CBK_RECALL_LEASE, ++ GF_CBK_STATEDUMP, + GF_CBK_MAXVALUE, + }; + +diff --git a/rpc/rpc-lib/src/rpc-transport.h b/rpc/rpc-lib/src/rpc-transport.h +index 630729d..dbfa32a 100644 +--- a/rpc/rpc-lib/src/rpc-transport.h ++++ b/rpc/rpc-lib/src/rpc-transport.h +@@ -70,7 +70,7 @@ struct peer_info { + uint32_t max_op_version; + uint32_t min_op_version; + //Volume mounted by client +- char volname[1024]; ++ char volname[NAME_MAX]; + }; + typedef struct peer_info peer_info_t; + +diff --git a/rpc/xdr/src/rpc-common-xdr.x b/rpc/xdr/src/rpc-common-xdr.x +index c2b2570..169b16d 100644 +--- a/rpc/xdr/src/rpc-common-xdr.x ++++ b/rpc/xdr/src/rpc-common-xdr.x +@@ -24,6 +24,9 @@ struct gf_dump_req { + u_quad_t gfs_id; + }; + ++struct gf_statedump { ++ unsigned int pid; ++}; + + struct gf_prog_detail { + string progname<>; +diff --git a/tests/bugs/cli/bug-1169302.t b/tests/bugs/cli/bug-1169302.t +new file mode 100755 +index 0000000..92252aa +--- /dev/null ++++ b/tests/bugs/cli/bug-1169302.t +@@ -0,0 +1,34 @@ ++#!/bin/bash ++ ++. $(dirname $0)/../../include.rc ++. $(dirname $0)/../../volume.rc ++. $(dirname $0)/../../cluster.rc ++ ++function check_peers { ++ $CLI_1 peer status | grep 'Peer in Cluster (Connected)' | wc -l ++} ++cleanup; ++ ++#setup cluster and test volume ++TEST launch_cluster 3; # start 3-node virtual cluster ++TEST $CLI_1 peer probe $H2; # peer probe server 2 from server 1 cli ++TEST $CLI_1 peer probe $H3; # peer probe server 3 from server 1 cli ++ ++EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers; ++ ++TEST $CLI_1 volume create $V0 $H1:$B1/$V0 $H2:$B2/$V0 $H3:$B3/$V0 ++TEST $CLI_1 volume start $V0 ++ ++# there is no gfapi application to take statedumps yet, it will get added in ++# the next patch, this only tests the CLI for correctness ++ ++cleanup_statedump ++ ++TEST ! $CLI_1 volume statedump $V0 client $H2:0 ++TEST ! $CLI_2 volume statedump $V0 client $H2:-1 ++TEST $CLI_3 volume statedump $V0 client $H2:765 ++TEST ! $CLI_1 volume statedump $V0 client $H2: ++TEST ! $CLI_2 volume statedump $V0 client ++ ++cleanup_statedump ++cleanup; +diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c +index e976ba2..9e9d609 100644 +--- a/xlators/mgmt/glusterd/src/glusterd-utils.c ++++ b/xlators/mgmt/glusterd/src/glusterd-utils.c +@@ -7022,6 +7022,49 @@ out: + } + + int ++glusterd_client_statedump (char *volname, char *options, int option_cnt, ++ char **op_errstr) ++{ ++ int ret = 0; ++ char *dup_options = NULL; ++ char *option = NULL; ++ char *tmpptr = NULL; ++ char msg[256] = {0,}; ++ char *target_ip = NULL; ++ char *pid = NULL; ++ ++ dup_options = gf_strdup (options); ++ option = strtok_r (dup_options, " ", &tmpptr); ++ if (strcmp (option, "client")) { ++ snprintf (msg, sizeof (msg), "for gluster client statedump, options " ++ "should be after the key 'client'"); ++ *op_errstr = gf_strdup (msg); ++ ret = -1; ++ goto out; ++ } ++ target_ip = strtok_r (NULL, " ", &tmpptr); ++ if (target_ip == NULL) { ++ snprintf (msg, sizeof (msg), "ip address not specified"); ++ *op_errstr = gf_strdup (msg); ++ ret = -1; ++ goto out; ++ } ++ ++ pid = strtok_r (NULL, " ", &tmpptr); ++ if (pid == NULL) { ++ snprintf (msg, sizeof (msg), "pid not specified"); ++ *op_errstr = gf_strdup (msg); ++ ret = -1; ++ goto out; ++ } ++ ++ ret = glusterd_client_statedump_submit_req (volname, target_ip, pid); ++out: ++ GF_FREE (dup_options); ++ return ret; ++} ++ ++int + glusterd_quotad_statedump (char *options, int option_cnt, char **op_errstr) + { + int ret = -1; +diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h +index 160b2ef..b1493df 100644 +--- a/xlators/mgmt/glusterd/src/glusterd-utils.h ++++ b/xlators/mgmt/glusterd/src/glusterd-utils.h +@@ -348,6 +348,10 @@ int + glusterd_nfs_statedump (char *options, int option_cnt, char **op_errstr); + + int ++glusterd_client_statedump (char *volname, char *options, int option_cnt, ++ char **op_errstr); ++ ++int + glusterd_quotad_statedump (char *options, int option_cnt, char **op_errstr); + + gf_boolean_t +diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c +index d157734..2eb7548 100644 +--- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c ++++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c +@@ -2860,6 +2860,13 @@ glusterd_op_statedump_volume (dict_t *dict, char **op_errstr) + op_errstr); + if (ret) + goto out; ++ ++ } else if (strstr (options, "client")) { ++ ret = glusterd_client_statedump (volname, options, option_cnt, ++ op_errstr); ++ if (ret) ++ goto out; ++ + } else { + cds_list_for_each_entry (brickinfo, &volinfo->bricks, + brick_list) { +diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c +index 6599c53..ae81de6 100644 +--- a/xlators/mgmt/glusterd/src/glusterd.c ++++ b/xlators/mgmt/glusterd/src/glusterd.c +@@ -47,6 +47,7 @@ + #include "glusterd-geo-rep.h" + #include "run.h" + #include "rpc-clnt-ping.h" ++#include "rpc-common-xdr.h" + + #include "syncop.h" + +@@ -232,6 +233,72 @@ out: + } + + int ++glusterd_client_statedump_submit_req (char *volname, char *target_ip, ++ char *pid) ++{ ++ gf_statedump statedump_req = {0, }; ++ glusterd_conf_t *conf = NULL; ++ int ret = 0; ++ char *end_ptr = NULL; ++ rpc_transport_t *trans = NULL; ++ char *ip_addr = NULL; ++ xlator_t *this = NULL; ++ char tmp[UNIX_PATH_MAX] = {0, }; ++ ++ this = THIS; ++ GF_ASSERT (this); ++ conf = this->private; ++ GF_ASSERT (conf); ++ ++ if (target_ip == NULL || pid == NULL) { ++ ret = -1; ++ goto out; ++ } ++ ++ statedump_req.pid = strtol (pid, &end_ptr, 10); ++ ++ gf_msg_debug (this->name, 0, "Performing statedump on volume %s " ++ "client with pid:%d host:%s", volname, statedump_req.pid, ++ target_ip); ++ ++ pthread_mutex_lock (&conf->xprt_lock); ++ { ++ list_for_each_entry (trans, &conf->xprt_list, list) { ++ /* check if this connection matches "all" or the ++ * volname */ ++ if (strncmp (volname, "all", NAME_MAX) && ++ strncmp (trans->peerinfo.volname, volname, ++ NAME_MAX)) { ++ /* no match, try next trans */ ++ continue; ++ } ++ ++ strcpy (tmp, trans->peerinfo.identifier); ++ ip_addr = strtok (tmp, ":"); ++ if (gf_is_same_address (ip_addr, target_ip)) { ++ /* Every gluster client would have ++ * connected to glusterd(volfile server). This ++ * connection is used to send the statedump ++ * request rpc to the application. ++ */ ++ gf_msg_trace (this->name, 0, "Submitting " ++ "statedump rpc request for %s", ++ trans->peerinfo.identifier); ++ rpcsvc_request_submit (conf->rpc, trans, ++ &glusterd_cbk_prog, ++ GF_CBK_STATEDUMP, ++ &statedump_req, this->ctx, ++ (xdrproc_t)xdr_gf_statedump); ++ } ++ } ++ } ++ pthread_mutex_unlock (&conf->xprt_lock); ++out: ++ return ret; ++ ++} ++ ++int + glusterd_fetchspec_notify (xlator_t *this) + { + int ret = -1; +diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h +index c84f019..ab7c03e 100644 +--- a/xlators/mgmt/glusterd/src/glusterd.h ++++ b/xlators/mgmt/glusterd/src/glusterd.h +@@ -963,6 +963,10 @@ glusterd_xfer_cli_deprobe_resp (rpcsvc_request_t *req, int32_t op_ret, + char *hostname, dict_t *dict); + + int ++glusterd_client_statedump_submit_req (char *volname, char *target_ip, ++ char *pid); ++ ++int + glusterd_fetchspec_notify (xlator_t *this); + + int +-- +1.8.3.1 + diff --git a/SOURCES/0316-Revert-nfs-make-subdir-mounting-work-for-Solaris-10-.patch b/SOURCES/0316-Revert-nfs-make-subdir-mounting-work-for-Solaris-10-.patch deleted file mode 100644 index 6a60bbc..0000000 --- a/SOURCES/0316-Revert-nfs-make-subdir-mounting-work-for-Solaris-10-.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 5142508ada067c57df58fbf89074cce099e012b1 Mon Sep 17 00:00:00 2001 -From: Soumya Koduri -Date: Wed, 17 May 2017 14:58:08 +0530 -Subject: [PATCH 316/316] Revert "nfs: make subdir mounting work for Solaris 10 - clients" - -This reverts commit f25b41d227c2e58ebff356e73c7a5123dc032fb8. - -There are others issues uncovered while qualifing this fix for -3.2.0-async release. All the stake holders agreed to revert this -change for now and address them in RHGS 3.3.0 - -BUG: 1451673 -Change-Id: Iae975b0a524eed80be19213ce448543e7073ad28 -Signed-off-by: Soumya Koduri -Reviewed-on: https://code.engineering.redhat.com/gerrit/106413 -Reviewed-by: Niels de Vos -Reviewed-by: Jiffin Thottan -Tested-by: Atin Mukherjee -Reviewed-by: Atin Mukherjee ---- - api/src/glfs-resolve.c | 6 +-- - xlators/nfs/server/src/nfs-common.c | 18 ++----- - xlators/nfs/server/src/nfs3.c | 96 ++++++++++--------------------------- - 3 files changed, 31 insertions(+), 89 deletions(-) - -diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c -index d495cd2..f8b437b 100644 ---- a/api/src/glfs-resolve.c -+++ b/api/src/glfs-resolve.c -@@ -385,9 +385,6 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at, - int ret = -1; - struct iatt ciatt = {0, }; - -- DECLARE_OLD_THIS; -- __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs); -- - path = gf_strdup (origpath); - if (!path) { - errno = ENOMEM; -@@ -513,10 +510,9 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at, - } - out: - GF_FREE (path); -- __GLFS_EXIT_FS; - - /* do NOT loc_wipe here as only last component might be missing */ --invalid_fs: -+ - return ret; - } - -diff --git a/xlators/nfs/server/src/nfs-common.c b/xlators/nfs/server/src/nfs-common.c -index 5269188..af37f6b 100644 ---- a/xlators/nfs/server/src/nfs-common.c -+++ b/xlators/nfs/server/src/nfs-common.c -@@ -73,11 +73,10 @@ nfs_xlator_to_xlid (xlator_list_t *cl, xlator_t *xl) - xlator_t * - nfs_mntpath_to_xlator (xlator_list_t *cl, char *path) - { -- char *volname = NULL; -- char *volptr = NULL; -- size_t pathlen = -1; -+ char *volname = NULL; -+ char *volptr = NULL; -+ size_t pathlen; - xlator_t *targetxl = NULL; -- int i = 0; - - if ((!cl) || (!path)) - return NULL; -@@ -90,17 +89,10 @@ nfs_mntpath_to_xlator (xlator_list_t *cl, char *path) - else - volptr = &volname[0]; - -- for (i = 0; i < pathlen; i++) { -- if (volname[i] == '/') { -- volname[i] = '\0'; -- break; -- } -- } -+ if (pathlen && volname[pathlen - 1] == '/') -+ volname[pathlen - 1] = '\0'; - - while (cl) { -- gf_msg_trace (GF_NFS, 0, "Volptr: %s and cl->xlator->name: %s", -- volptr, cl->xlator->name); -- - if (strcmp (volptr, cl->xlator->name) == 0) { - targetxl = cl->xlator; - break; -diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c -index 8b1d62b..d6c9495 100644 ---- a/xlators/nfs/server/src/nfs3.c -+++ b/xlators/nfs/server/src/nfs3.c -@@ -28,7 +28,6 @@ - #include "xdr-rpc.h" - #include "xdr-generic.h" - #include "nfs-messages.h" --#include "glfs-internal.h" - - #include - #include -@@ -349,68 +348,28 @@ out: - } - - --static enum nfsstat3 --nfs3_funge_webnfs_zerolen_fh (struct nfs3_state *nfs3st, struct nfs3_fh *fhd, -- char *name) --{ -- xlator_t *fungexl = NULL; -- glfs_t *fs = NULL; -- loc_t loc = { 0, }; -- enum nfsstat3 nfsstat = NFS3ERR_SERVERFAULT; -- int ret = -1; -- size_t namelen = -1; -- -- fungexl = nfs_mntpath_to_xlator (nfs3st->exportslist, name); -- if (!fungexl) { -- nfsstat = NFS3ERR_NOENT; -- goto out; -- } -- -- /* glfs_resolve_at copied from UDP MNT support */ -- fs = glfs_new_from_ctx (fungexl->ctx); -- if (!fs) { -- nfsstat = NFS3ERR_NOENT; -- goto out; -- } -- -- /* strip volname/ from 'name' */ -- namelen = strlen(name); -- while (namelen != 0) { -- name++; -- if (name[0] == '/') { -- break; -- } -- namelen--; -- } -- gf_msg_debug (GF_NFS, 0, "NAME :%s ", name); -- -- ret = glfs_resolve_at (fs, fungexl, NULL, name, &loc, NULL, 1, 0); -- if (ret != 0) { -- nfsstat = NFS3ERR_NOENT; -- goto out; -- } -- -- /* resolved subdir, copy gfid for the fh */ -- gf_uuid_copy (fhd->gfid, loc.gfid); -- loc_wipe (&loc); -- -- if (gf_nfs_dvm_off (nfs_state (nfs3st->nfsx))) -- fhd->exportid[15] = nfs_xlator_to_xlid (nfs3st->exportslist, -- fungexl); -- else { -- if (__nfs3_get_volume_id (nfs3st, fungexl, fhd->exportid) < 0) { -- nfsstat = NFS3ERR_STALE; -- goto out; -- } -- } -- -- nfsstat = NFS3_OK; --out: -- if (fs) -- glfs_free_from_ctx (fs); -- -- return nfsstat; --} -+#define nfs3_funge_solaris_zerolen_fh(nfs3st, fhd, enam, nfsst, erl) \ -+ do { \ -+ xlator_t *fungexl = NULL; \ -+ uuid_t zero = {0, }; \ -+ fungexl = nfs_mntpath_to_xlator ((nfs3st)->exportslist, enam);\ -+ if (!fungexl) { \ -+ (nfsst) = NFS3ERR_NOENT; \ -+ goto erl; \ -+ } \ -+ \ -+ gf_uuid_copy ((fhd)->gfid, zero); \ -+ (fhd)->gfid[15] = 1; \ -+ (enam) = NULL; \ -+ if ((gf_nfs_dvm_off (nfs_state (nfs3st->nfsx)))) \ -+ (fhd)->exportid[15] = nfs_xlator_to_xlid ((nfs3st)->exportslist, fungexl); \ -+ else { \ -+ if (__nfs3_get_volume_id ((nfs3st), fungexl, (fhd)->exportid) < 0) { \ -+ (nfsst) = NFS3ERR_STALE; \ -+ goto erl; \ -+ } \ -+ } \ -+ } while (0) \ - - - #define nfs3_volume_started_check(nf3stt, vlm, rtval, erlbl) \ -@@ -1536,14 +1495,9 @@ nfs3_lookup (rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name) - nfs3_log_fh_entry_call (rpcsvc_request_xid (req), "LOOKUP", fh, - name); - nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret); -- if (nfs3_solaris_zerolen_fh (fh, fhlen)) { -- stat = nfs3_funge_webnfs_zerolen_fh (nfs3, fh, name); -- if (stat != NFS3_OK) -- goto nfs3err; -- -- /* this fh means we're doing a mount, name is no more useful */ -- name = NULL; -- } else -+ if (nfs3_solaris_zerolen_fh (fh, fhlen)) -+ nfs3_funge_solaris_zerolen_fh (nfs3, fh, name, stat, nfs3err); -+ else - nfs3_validate_gluster_fh (fh, stat, nfs3err); - nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret); - nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err); --- -1.8.3.1 - diff --git a/SOURCES/0316-gfapi-create-statedump-when-glusterd-requests-it.patch b/SOURCES/0316-gfapi-create-statedump-when-glusterd-requests-it.patch new file mode 100644 index 0000000..f20632c --- /dev/null +++ b/SOURCES/0316-gfapi-create-statedump-when-glusterd-requests-it.patch @@ -0,0 +1,261 @@ +From e7bbd87a4c3892d70cb84a9c5cef33430112d7a4 Mon Sep 17 00:00:00 2001 +From: Niels de Vos +Date: Fri, 6 Jan 2017 12:58:02 +0100 +Subject: [PATCH 316/361] gfapi: create statedump when glusterd requests it + +When GlusterD sends the STATEDUMP procedure to the libgfapi client, the +client checks if it matches the PID that should take the statedump. If +so, it will do a statedump for the glfs_t that is connected to this mgmt +connection. + +See-also: http://review.gluster.org/9228 +[ndevos: separated patch from 9228] + +mainline: +> BUG: 1169302 +> Reviewed-on: https://review.gluster.org/16415 +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Niels de Vos +> Reviewed-by: Kaleb KEITHLEY +> Reviewed-by: Prashanth Pai +> Tested-by: Niels de Vos +(cherry picked from commit c9027e04456d724a3211e4b08084c96059798e1f) + +BUG: 1378085 +Change-Id: I70d6a1f4f19d525377aebc8fa57f51e513b92d84 +Signed-off-by: Poornima G +Reviewed-on: https://code.engineering.redhat.com/gerrit/101297 +Tested-by: Milind Changire +Reviewed-by: Atin Mukherjee +--- + api/src/glfs-mgmt.c | 61 ++++++++++++++++++++++++++++++++++ + tests/bugs/cli/bug-1169302.c | 78 ++++++++++++++++++++++++++++++++++++++++++++ + tests/bugs/cli/bug-1169302.t | 30 +++++++++++++---- + 3 files changed, 162 insertions(+), 7 deletions(-) + create mode 100644 tests/bugs/cli/bug-1169302.c + +diff --git a/api/src/glfs-mgmt.c b/api/src/glfs-mgmt.c +index 8c9872c..9aa92d7 100644 +--- a/api/src/glfs-mgmt.c ++++ b/api/src/glfs-mgmt.c +@@ -29,6 +29,7 @@ + #include "portmap-xdr.h" + #include "xdr-common.h" + #include "xdr-generic.h" ++#include "rpc-common-xdr.h" + + #include "syncop.h" + #include "xlator.h" +@@ -116,11 +117,71 @@ mgmt_cbk_event (struct rpc_clnt *rpc, void *mydata, void *data) + return 0; + } + ++static int ++mgmt_cbk_statedump (struct rpc_clnt *rpc, void *mydata, void *data) ++{ ++ struct glfs *fs = NULL; ++ xlator_t *this = NULL; ++ gf_statedump target_pid = {0, }; ++ struct iovec *iov = NULL; ++ int ret = -1; ++ ++ this = mydata; ++ if (!this) { ++ gf_msg ("glfs", GF_LOG_ERROR, EINVAL, ++ API_MSG_STATEDUMP_FAILED, "NULL mydata"); ++ errno = EINVAL; ++ goto out; ++ } ++ ++ fs = this->private; ++ if (!fs) { ++ gf_msg ("glfs", GF_LOG_ERROR, EINVAL, ++ API_MSG_STATEDUMP_FAILED, "NULL glfs"); ++ errno = EINVAL; ++ goto out; ++ } ++ ++ iov = (struct iovec *)data; ++ if (!iov) { ++ gf_msg ("glfs", GF_LOG_ERROR, EINVAL, ++ API_MSG_STATEDUMP_FAILED, "NULL iovec data"); ++ errno = EINVAL; ++ goto out; ++ } ++ ++ ret = xdr_to_generic (*iov, &target_pid, ++ (xdrproc_t)xdr_gf_statedump); ++ if (ret < 0) { ++ gf_msg ("glfs", GF_LOG_ERROR, EINVAL, ++ API_MSG_STATEDUMP_FAILED, ++ "Failed to decode xdr response for GF_CBK_STATEDUMP"); ++ goto out; ++ } ++ ++ gf_msg_trace ("glfs", 0, "statedump requested for pid: %d", ++ target_pid.pid); ++ ++ if ((uint64_t)getpid() == target_pid.pid) { ++ gf_msg_debug ("glfs", 0, "Taking statedump for pid: %d", ++ target_pid.pid); ++ ++ ret = glfs_sysrq (fs, GLFS_SYSRQ_STATEDUMP); ++ if (ret < 0) { ++ gf_msg ("glfs", GF_LOG_INFO, 0, ++ API_MSG_STATEDUMP_FAILED, ++ "statedump failed"); ++ } ++ } ++out: ++ return ret; ++} + + rpcclnt_cb_actor_t mgmt_cbk_actors[GF_CBK_MAXVALUE] = { + [GF_CBK_FETCHSPEC] = {"FETCHSPEC", GF_CBK_FETCHSPEC, mgmt_cbk_spec }, + [GF_CBK_EVENT_NOTIFY] = {"EVENTNOTIFY", GF_CBK_EVENT_NOTIFY, + mgmt_cbk_event}, ++ [GF_CBK_STATEDUMP] = {"STATEDUMP", GF_CBK_STATEDUMP, mgmt_cbk_statedump}, + }; + + +diff --git a/tests/bugs/cli/bug-1169302.c b/tests/bugs/cli/bug-1169302.c +new file mode 100644 +index 0000000..aa9f950 +--- /dev/null ++++ b/tests/bugs/cli/bug-1169302.c +@@ -0,0 +1,78 @@ ++#include ++#include ++#include ++ ++#include ++#include ++ ++int keep_running = 1; ++ ++void stop_running(int sig) ++{ ++ if (sig == SIGTERM) ++ keep_running = 0; ++} ++ ++int ++main (int argc, char *argv[]) ++{ ++ glfs_t *fs = NULL; ++ int ret = 0; ++ glfs_fd_t *fd = NULL; ++ char *filename = NULL; ++ char *logfile = NULL; ++ char *host = NULL; ++ ++ if (argc != 5) { ++ return -1; ++ } ++ ++ host = argv[2]; ++ logfile = argv[3]; ++ filename = argv[4]; ++ ++ /* setup signal handler for exiting */ ++ signal (SIGTERM, stop_running); ++ ++ fs = glfs_new (argv[1]); ++ if (!fs) { ++ return -1; ++ } ++ ++ ret = glfs_set_volfile_server (fs, "tcp", host, 24007); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ ret = glfs_set_logging (fs, logfile, 7); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ ret = glfs_init (fs); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ fd = glfs_creat (fs, filename, O_RDWR, 0644); ++ if (!fd) { ++ return -1; ++ } ++ ++ /* sleep until SIGTERM has been received */ ++ while (keep_running) { ++ sleep (1); ++ } ++ ++ ret = glfs_close (fd); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ ret = glfs_fini (fs); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ return 0; ++} +diff --git a/tests/bugs/cli/bug-1169302.t b/tests/bugs/cli/bug-1169302.t +index 92252aa..24355e5 100755 +--- a/tests/bugs/cli/bug-1169302.t ++++ b/tests/bugs/cli/bug-1169302.t +@@ -7,7 +7,7 @@ + function check_peers { + $CLI_1 peer status | grep 'Peer in Cluster (Connected)' | wc -l + } +-cleanup; ++cleanup + + #setup cluster and test volume + TEST launch_cluster 3; # start 3-node virtual cluster +@@ -19,16 +19,32 @@ EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers; + TEST $CLI_1 volume create $V0 $H1:$B1/$V0 $H2:$B2/$V0 $H3:$B3/$V0 + TEST $CLI_1 volume start $V0 + +-# there is no gfapi application to take statedumps yet, it will get added in +-# the next patch, this only tests the CLI for correctness +- +-cleanup_statedump +- ++# test CLI parameter acceptance + TEST ! $CLI_1 volume statedump $V0 client $H2:0 + TEST ! $CLI_2 volume statedump $V0 client $H2:-1 + TEST $CLI_3 volume statedump $V0 client $H2:765 + TEST ! $CLI_1 volume statedump $V0 client $H2: + TEST ! $CLI_2 volume statedump $V0 client ++TEST ! $CLI_3 volume statedump $V0 client $H2 $GFAPI_PID ++ ++# build and run a gfapi appliction for triggering a statedump ++logdir=`gluster --print-logdir` ++STATEDUMP_TIMEOUT=60 ++ ++build_tester $(dirname $0)/bug-1169302.c -lgfapi ++$(dirname $0)/bug-1169302 $V0 $H1 $logdir/bug-1169302.log testfile & GFAPI_PID=$! ++ ++cleanup_statedump ++ ++# Take the statedump of the process connected to $H1, it should match the ++# hostname or IP-address with the connection from the bug-1169302 executable. ++# In our CI it seems not possible to use $H0, 'localhost', $(hostname --fqdn) ++# or even "127.0.0.1".... ++TEST $CLI_3 volume statedump $V0 client $H1:$GFAPI_PID ++EXPECT_WITHIN $STATEDUMP_TIMEOUT "Y" path_exists $statedumpdir/glusterdump.$GFAPI_PID* ++ ++kill $GFAPI_PID + + cleanup_statedump +-cleanup; ++cleanup_tester $(dirname $0)/bug-1169302 ++cleanup +-- +1.8.3.1 + diff --git a/SOURCES/0317-glusterd-daemon-restart-logic-should-adhere-server-s.patch b/SOURCES/0317-glusterd-daemon-restart-logic-should-adhere-server-s.patch new file mode 100644 index 0000000..09185e7 --- /dev/null +++ b/SOURCES/0317-glusterd-daemon-restart-logic-should-adhere-server-s.patch @@ -0,0 +1,364 @@ +From df8fdd1d7fab692169a667fcc07c652fcc5e2ad7 Mon Sep 17 00:00:00 2001 +From: Atin Mukherjee +Date: Wed, 5 Oct 2016 14:59:51 +0530 +Subject: [PATCH 317/361] glusterd: daemon restart logic should adhere server + side quorum + +Just like brick processes, other daemon services should also follow the same +logic of quorum checks to see if a particular service needs to come up if +glusterd is restarted or the incoming friend add/update request is received +(in glusterd_restart_bricks () function) + +mainline: +> BUG: 1383893 +> Reviewed-on: https://review.gluster.org/15626 +> Smoke: Gluster Build System +> NetBSD-regression: NetBSD Build System +> CentOS-regression: Gluster Build System +> Reviewed-by: Prashanth Pai +(cherry picked from commit 5a6f509263a810ca21a22bbbd1e6ffcf43b70d18) + +BUG: 1381825 +Change-Id: I54a1fbdaa1571cc45eed627181b81463fead47a3 +Signed-off-by: Atin Mukherjee +Reviewed-on: https://code.engineering.redhat.com/gerrit/101298 +Tested-by: Milind Changire +--- + .../bug-1383893-daemons-to-follow-quorum.t | 57 +++++ + xlators/mgmt/glusterd/src/glusterd-utils.c | 235 +-------------------- + 2 files changed, 64 insertions(+), 228 deletions(-) + create mode 100644 tests/bugs/glusterd/bug-1383893-daemons-to-follow-quorum.t + +diff --git a/tests/bugs/glusterd/bug-1383893-daemons-to-follow-quorum.t b/tests/bugs/glusterd/bug-1383893-daemons-to-follow-quorum.t +new file mode 100644 +index 0000000..105292a +--- /dev/null ++++ b/tests/bugs/glusterd/bug-1383893-daemons-to-follow-quorum.t +@@ -0,0 +1,57 @@ ++#!/bin/bash ++ ++# This test checks for if shd or any other daemons brought down (apart from ++# brick processes) is not brought up automatically when glusterd on the other ++# node is (re)started ++ ++. $(dirname $0)/../../include.rc ++. $(dirname $0)/../../volume.rc ++. $(dirname $0)/../../cluster.rc ++ ++function shd_up_status_1 { ++ $CLI_1 volume status | grep "localhost" | grep "Self-heal Daemon" | awk '{print $7}' ++} ++ ++function shd_up_status_2 { ++ $CLI_2 volume status | grep "localhost" | grep "Self-heal Daemon" | awk '{print $7}' ++} ++ ++function get_shd_pid_2 { ++ $CLI_2 volume status | grep "localhost" | grep "Self-heal Daemon" | awk '{print $8}' ++} ++cleanup; ++ ++TEST launch_cluster 3 ++ ++TEST $CLI_1 peer probe $H2; ++EXPECT_WITHIN $PROBE_TIMEOUT 1 peer_count ++ ++TEST $CLI_1 peer probe $H3; ++EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count ++ ++# Lets create the volume ++TEST $CLI_1 volume create $V0 replica 2 $H1:$B1/${V0}1 $H2:$B2/${V0}2 ++ ++# Start the volume ++TEST $CLI_1 volume start $V0 ++ ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status_1 $V0 $H1 $B1/${V0}1 ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status_1 $V0 $H2 $B2/${V0}2 ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" shd_up_status_1 ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" shd_up_status_2 ++ ++# Bring down shd on 2nd node ++kill -15 $(get_shd_pid_2) ++ ++# Bring down glusterd on 1st node ++TEST kill_glusterd 1 ++ ++#Bring back 1st glusterd ++TEST $glusterd_1 ++ ++# We need to wait till PROCESS_UP_TIMEOUT and then check shd service does not ++# come up on node 2 ++sleep $PROCESS_UP_TIMEOUT ++EXPECT "N" shd_up_status_2 ++ ++cleanup; +diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c +index 9e9d609..91cc12e 100644 +--- a/xlators/mgmt/glusterd/src/glusterd-utils.c ++++ b/xlators/mgmt/glusterd/src/glusterd-utils.c +@@ -4902,10 +4902,6 @@ glusterd_restart_bricks (glusterd_conf_t *conf) + cds_list_for_each_entry (volinfo, &conf->volumes, vol_list) { + if (volinfo->status != GLUSTERD_STATUS_STARTED) + continue; +- if (start_svcs == _gf_false) { +- start_svcs = _gf_true; +- glusterd_svcs_manager (NULL); +- } + gf_msg_debug (this->name, 0, "starting the volume %s", + volinfo->volname); + +@@ -4928,6 +4924,11 @@ glusterd_restart_bricks (glusterd_conf_t *conf) + */ + continue; + } else { ++ if (start_svcs == _gf_false) { ++ start_svcs = _gf_true; ++ glusterd_svcs_manager (NULL); ++ } ++ + cds_list_for_each_entry (brickinfo, &volinfo->bricks, + brick_list) { + glusterd_brick_start (volinfo, brickinfo, +@@ -4940,8 +4941,8 @@ glusterd_restart_bricks (glusterd_conf_t *conf) + cds_list_for_each_entry (volinfo, &snap->volumes, vol_list) { + if (volinfo->status != GLUSTERD_STATUS_STARTED) + continue; +- /* Check the quorum, if quorum is not met, don't start the +- bricks ++ /* Check the quorum, if quorum is not met, don't start ++ * the bricks + */ + ret = check_quorum_for_brick_start (volinfo, + node_quorum); +@@ -9403,228 +9404,6 @@ out: + } + + int +-<<<<<<< 07a9e00a5702e76932142e9d9cdc2df601632b7a +-======= +-glusterd_volume_tier_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict) +-{ +- char key[256] = {0,}; +- char *node_uuid = NULL; +- char *node_uuid_str = NULL; +- char *volname = NULL; +- dict_t *ctx_dict = NULL; +- double elapsed_time = 0; +- glusterd_volinfo_t *volinfo = NULL; +- int ret = 0; +- int32_t index = 0; +- int32_t count = 0; +- int32_t value32 = 0; +- uint64_t value = 0; +- xlator_t *this = NULL; +- char *task_id_str = NULL; +- +- this = THIS; +- GF_VALIDATE_OR_GOTO (this->name, this, out); +- GF_VALIDATE_OR_GOTO (this->name, rsp_dict, out); +- +- if (aggr) { +- ctx_dict = aggr; +- +- } else { +- gf_msg (this->name, GF_LOG_ERROR, 0, +- GD_MSG_OPCTX_GET_FAIL, +- "Operation Context is not present"); +- goto out; +- } +- +- if (!ctx_dict) +- goto out; +- +- ret = dict_get_str (ctx_dict, "volname", &volname); +- if (ret) { +- gf_msg (this->name, GF_LOG_ERROR, 0, +- GD_MSG_DICT_GET_FAILED, +- "Unable to get volume name"); +- goto out; +- } +- +- ret = glusterd_volinfo_find (volname, &volinfo); +- +- if (ret) +- goto out; +- +- ret = dict_get_int32 (rsp_dict, "count", &index); +- if (ret) +- gf_msg (this->name, GF_LOG_ERROR, 0, +- GD_MSG_DICT_GET_FAILED, +- "failed to get index"); +- +- memset (key, 0, 256); +- snprintf (key, 256, "node-uuid-%d", index); +- ret = dict_get_str (rsp_dict, key, &node_uuid); +- if (!ret) { +- node_uuid_str = gf_strdup (node_uuid); +- +- } +- ret = dict_get_int32 (ctx_dict, "count", &count); +- count++; +- ret = dict_set_int32 (ctx_dict, "count", count); +- if (ret) +- gf_msg (this->name, GF_LOG_ERROR, 0, +- GD_MSG_DICT_SET_FAILED, +- "Failed to set count"); +- +- memset (key, 0, 256); +- snprintf (key, 256, "node-uuid-%d", count); +- ret = dict_set_dynstr (ctx_dict, key, node_uuid_str); +- if (ret) { +- gf_msg_debug (this->name, 0, +- "failed to set node-uuid"); +- } +- +- snprintf (key, 256, "files-%d", index); +- ret = dict_get_uint64 (rsp_dict, key, &value); +- if (!ret) { +- memset (key, 0, 256); +- snprintf (key, 256, "files-%d", count); +- ret = dict_set_uint64 (ctx_dict, key, value); +- if (ret) { +- gf_msg_debug (this->name, 0, +- "failed to set the file count"); +- } +- } +- +- memset (key, 0, 256); +- snprintf (key, 256, "size-%d", index); +- ret = dict_get_uint64 (rsp_dict, key, &value); +- if (!ret) { +- memset (key, 0, 256); +- snprintf (key, 256, "size-%d", count); +- ret = dict_set_uint64 (ctx_dict, key, value); +- if (ret) { +- gf_msg_debug (this->name, 0, +- "failed to set the size of migration"); +- } +- } +- +- memset (key, 0, 256); +- snprintf (key, 256, "lookups-%d", index); +- ret = dict_get_uint64 (rsp_dict, key, &value); +- if (!ret) { +- memset (key, 0, 256); +- snprintf (key, 256, "lookups-%d", count); +- ret = dict_set_uint64 (ctx_dict, key, value); +- if (ret) { +- gf_msg_debug (this->name, 0, +- "failed to set looked up file count"); +- } +- } +- +- memset (key, 0, 256); +- snprintf (key, 256, "status-%d", index); +- ret = dict_get_int32 (rsp_dict, key, &value32); +- if (!ret) { +- memset (key, 0, 256); +- snprintf (key, 256, "status-%d", count); +- ret = dict_set_int32 (ctx_dict, key, value32); +- if (ret) { +- gf_msg_debug (this->name, 0, +- "failed to set status"); +- } +- } +- +- memset (key, 0, 256); +- snprintf (key, 256, "failures-%d", index); +- ret = dict_get_uint64 (rsp_dict, key, &value); +- if (!ret) { +- memset (key, 0, 256); +- snprintf (key, 256, "failures-%d", count); +- ret = dict_set_uint64 (ctx_dict, key, value); +- if (ret) { +- gf_msg_debug (this->name, 0, +- "failed to set failure count"); +- } +- } +- +- memset (key, 0, 256); +- snprintf (key, 256, "skipped-%d", index); +- ret = dict_get_uint64 (rsp_dict, key, &value); +- if (!ret) { +- memset (key, 0, 256); +- snprintf (key, 256, "skipped-%d", count); +- ret = dict_set_uint64 (ctx_dict, key, value); +- if (ret) { +- gf_msg_debug (this->name, 0, +- "failed to set skipped count"); +- } +- } +- memset (key, 0, 256); +- snprintf (key, 256, "run-time-%d", index); +- ret = dict_get_double (rsp_dict, key, &elapsed_time); +- if (!ret) { +- memset (key, 0, 256); +- snprintf (key, 256, "run-time-%d", count); +- ret = dict_set_double (ctx_dict, key, elapsed_time); +- if (ret) { +- gf_msg_debug (this->name, 0, +- "failed to set run-time"); +- } +- } +- +- memset (key, 0, 256); +- snprintf (key, 256, "demoted-%d", index); +- ret = dict_get_uint64 (rsp_dict, key, &value); +- if (!ret) { +- memset (key, 0, 256); +- snprintf (key, 256, "demoted-%d", count); +- ret = dict_set_uint64 (ctx_dict, key, value); +- if (ret) { +- gf_msg_debug (this->name, 0, +- "failed to set demoted count"); +- } +- } +- memset (key, 0, 256); +- snprintf (key, 256, "promoted-%d", index); +- ret = dict_get_uint64 (rsp_dict, key, &value); +- if (!ret) { +- memset (key, 0, 256); +- snprintf (key, 256, "promoted-%d", count); +- ret = dict_set_uint64 (ctx_dict, key, value); +- if (ret) { +- gf_msg_debug (this->name, 0, +- "failed to set promoted count"); +- } +- } +- +- memset (key, 0, 256); +- snprintf (key, 256, "time-left-%d", index); +- ret = dict_get_uint64 (rsp_dict, key, &value); +- if (!ret) { +- memset (key, 0, 256); +- snprintf (key, 256, "time-left-%d", count); +- ret = dict_set_uint64 (ctx_dict, key, value); +- if (ret) { +- gf_msg_debug (THIS->name, 0, +- "failed to set time-left"); +- } +- } +- +- ret = dict_get_str (rsp_dict, GF_REMOVE_BRICK_TID_KEY, +- &task_id_str); +- if (ret) { +- gf_msg_debug (this->name, errno, +- "Missing remove-brick-id"); +- } else +- ret = dict_set_str (ctx_dict, GF_REMOVE_BRICK_TID_KEY, +- task_id_str); +- +- ret = 0; +- +-out: +- return ret; +-} +- +-int +->>>>>>> dht/rebalance Estimate time to complete rebalance + glusterd_sys_exec_output_rsp_dict (dict_t *dst, dict_t *src) + { + char output_name[PATH_MAX] = ""; +-- +1.8.3.1 + diff --git a/SOURCES/0317-libglusterfs-extract-some-functionality-to-functions.patch b/SOURCES/0317-libglusterfs-extract-some-functionality-to-functions.patch deleted file mode 100644 index d0428d0..0000000 --- a/SOURCES/0317-libglusterfs-extract-some-functionality-to-functions.patch +++ /dev/null @@ -1,485 +0,0 @@ -From b6a7c1cb473e775f80d74553e83132e10603d584 Mon Sep 17 00:00:00 2001 -From: Amar Tumballi -Date: Mon, 29 May 2017 17:20:55 +0530 -Subject: [PATCH 317/318] libglusterfs: extract some functionality to functions - -- code in run.c to close all file descriptors, - except for specified ones is extracted to - - int close_fds_except (int *fdv, size_t count); - -- tokenizing and editing a string that consists - of comma-separated tokens (as done eg. in - mount_param_to_flag() of contrib/fuse/mount.c - is abstacted into the following API: - - char *token_iter_init (char *str, char sep, token_iter_t *tit); - gf_boolean_t next_token (char **tokenp, token_iter_t *tit); - void drop_token (char *token, token_iter_t *tit); - -Also contains minimum changes from https://review.gluster.org/16313 -which is used for resolving the conflicts. - -Upstream: -> Change-Id: I7cb5bda38f680f08882e2a7ef84f9142ffaa54eb -> Signed-off-by: Csaba Henk -> Reviewed-on: https://review.gluster.org/17229 -> Smoke: Gluster Build System -> NetBSD-regression: NetBSD Build System -> CentOS-regression: Gluster Build System -> Reviewed-by: Amar Tumballi - -BUG: 1456420 -Change-Id: Ia4e500ae40cc3029136bcb4f2f1a0dd81d813e04 -Signed-off-by: Amar Tumballi -Reviewed-on: https://code.engineering.redhat.com/gerrit/107572 -Reviewed-by: Atin Mukherjee ---- - contrib/fuse-lib/mount.c | 102 ++++++++++++++++++-- - libglusterfs/src/common-utils.c | 208 ++++++++++++++++++++++++++++++++++++++++ - libglusterfs/src/common-utils.h | 10 ++ - libglusterfs/src/run.c | 30 +----- - 4 files changed, 317 insertions(+), 33 deletions(-) - -diff --git a/contrib/fuse-lib/mount.c b/contrib/fuse-lib/mount.c -index 1edde86..5e0b4dd 100644 ---- a/contrib/fuse-lib/mount.c -+++ b/contrib/fuse-lib/mount.c -@@ -224,19 +224,107 @@ build_iovec_argf(struct iovec **iov, int *iovlen, const char *name, - } - #endif /* __FreeBSD__ */ - -+ -+#ifdef GF_LINUX_HOST_OS -+typedef unsigned long mount_flag_t; -+#endif -+ -+struct mount_flags { -+ const char *opt; -+ mount_flag_t flag; -+ int on; -+} mount_flags[] = { -+ /* We provide best effort cross platform support for mount flags by -+ * defining the ones which are commonly used in Unix-like OS-es. -+ */ -+ {"ro", MS_RDONLY, 1}, -+ {"nosuid", MS_NOSUID, 1}, -+ {"nodev", MS_NODEV, 1}, -+ {"noatime", MS_NOATIME, 1}, -+ {"noexec", MS_NOEXEC, 1}, -+#ifdef GF_LINUX_HOST_OS -+ {"rw", MS_RDONLY, 0}, -+ {"suid", MS_NOSUID, 0}, -+ {"dev", MS_NODEV, 0}, -+ {"exec", MS_NOEXEC, 0}, -+ {"async", MS_SYNCHRONOUS, 0}, -+ {"sync", MS_SYNCHRONOUS, 1}, -+ {"atime", MS_NOATIME, 0}, -+ {"dirsync", MS_DIRSYNC, 1}, -+#endif -+ {NULL, 0, 0} -+}; -+ -+ -+static int -+mount_param_to_flag (char *mnt_param, mount_flag_t *mntflags, -+ char **mnt_param_new) -+{ -+ gf_boolean_t found = _gf_false; -+ struct mount_flags *flag = NULL; -+ char *param_tok = NULL; -+ token_iter_t tit = {0,}; -+ gf_boolean_t iter_end = _gf_false; -+ -+ /* Allocate a buffer that will hold the mount parameters remaining -+ * after the ones corresponding to mount flags are processed and -+ * removed.The length of the original params are a good upper bound -+ * of the size needed. -+ */ -+ *mnt_param_new = strdup (mnt_param); -+ if (!*mnt_param_new) -+ return -1; -+ -+ for (param_tok = token_iter_init (*mnt_param_new, ',', &tit) ;;) { -+ iter_end = next_token (¶m_tok, &tit); -+ -+ found = _gf_false; -+ for (flag = mount_flags; flag->opt; flag++) { -+ /* Compare the mount flag name to the param -+ * name at hand. -+ */ -+ if (strcmp (flag->opt, param_tok) == 0) { -+ /* If there is a match, adjust mntflags -+ * accordingly and break. -+ */ -+ if (flag->on) { -+ *mntflags |= flag->flag; -+ } else { -+ *mntflags &= ~flag->flag; -+ } -+ found = _gf_true; -+ break; -+ } -+ } -+ /* Exclude flag names from new parameter list. */ -+ if (found) -+ drop_token (param_tok, &tit); -+ -+ if (iter_end) -+ break; -+ } -+ -+ return 0; -+} -+ - static int - fuse_mount_sys (const char *mountpoint, char *fsname, -- unsigned long mountflags, char *mnt_param, int fd) -+ unsigned long dummy, char *mnt_param, int fd) - { - int ret = -1; - unsigned mounted = 0; - char *mnt_param_mnt = NULL; - char *fstype = "fuse.glusterfs"; - char *source = fsname; -- -- ret = asprintf (&mnt_param_mnt, -- "%s,fd=%i,rootmode=%o,user_id=%i,group_id=%i", -- mnt_param, fd, S_IFDIR, getuid (), getgid ()); -+ mount_flag_t mountflags = 0; -+ char *mnt_param_new = NULL; -+ -+ ret = mount_param_to_flag (mnt_param, &mountflags, &mnt_param_new); -+ if (ret == 0) { -+ ret = asprintf (&mnt_param_mnt, -+ "%s,fd=%i,rootmode=%o,user_id=%i,group_id=%i", -+ mnt_param_new, fd, S_IFDIR, getuid (), getgid ()); -+ } - if (ret == -1) { - GFFUSE_LOGERR ("Out of memory"); - -@@ -295,7 +383,7 @@ fuse_mount_sys (const char *mountpoint, char *fsname, - - ret = asprintf (&mnt_param_mtab, "%s%s", - mountflags & MS_RDONLY ? "ro," : "", -- mnt_param); -+ mnt_param_new); - if (ret == -1) - GFFUSE_LOGERR ("Out of memory"); - else { -@@ -320,6 +408,8 @@ out: - umount2 (mountpoint, 2); /* lazy umount */ - } - FREE (mnt_param_mnt); -+ FREE (mnt_param_new); -+ - if (source != fsname) - FREE (source); - -diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c -index d36069f..e305190 100644 ---- a/libglusterfs/src/common-utils.c -+++ b/libglusterfs/src/common-utils.c -@@ -50,6 +50,10 @@ - #include - #include "libglusterfs-messages.h" - -+#ifndef GF_LINUX_HOST_OS -+#include -+#endif -+ - #ifndef AI_ADDRCONFIG - #define AI_ADDRCONFIG 0 - #endif /* AI_ADDRCONFIG */ -@@ -2140,6 +2144,150 @@ get_nth_word (const char *str, int n) - return word; - } - -+/** -+ * token_iter_init -- initialize tokenization -+ * -+ * @str: string to be tokenized -+ * @sep: token separator character -+ * @tit: pointer to iteration state -+ * -+ * @return: token string -+ * -+ * The returned token string and tit are -+ * not to be used directly, but through -+ * next_token(). -+ */ -+char * -+token_iter_init (char *str, char sep, token_iter_t *tit) -+{ -+ tit->end = str + strlen (str); -+ tit->sep = sep; -+ -+ return str; -+} -+ -+/** -+ * next_token -- fetch next token in tokenization -+ * inited by token_iter_init(). -+ * -+ * @tokenp: pointer to token -+ * @tit: pointer to iteration state -+ * -+ * @return: true if iteration ends, else false -+ * -+ * The token pointed by @tokenp can be used -+ * after a call to next_token(). When next_token() -+ * returns true the iteration is to be stopped -+ * and the string with which the tokenization -+ * was inited (see token_iter_init() is restored, -+ * apart from dropped tokens (see drop_token()). -+ */ -+gf_boolean_t -+next_token (char **tokenp, token_iter_t *tit) -+{ -+ char *cursor = NULL; -+ gf_boolean_t is_last = _gf_false; -+ -+ for (cursor = *tokenp; *cursor; cursor++) -+ ; -+ if (cursor < tit->end) { -+ /* -+ * We detect that in between current token and end a zero -+ * marker has already been inserted. This means that the -+ * token has already been returned. We restore the -+ * separator and move ahead. -+ */ -+ *cursor = tit->sep; -+ *tokenp = cursor + 1; -+ } -+ -+ for (cursor = *tokenp; *cursor && *cursor != tit->sep; cursor++) -+ ; -+ /* If the cursor ended up on a zero byte, then it's the last token. */ -+ is_last = !*cursor; -+ /* Zero-terminate the token. */ -+ *cursor = 0; -+ -+ return is_last; -+} -+ -+/* -+ * drop_token -- drop a token during iterated calls of next_token(). -+ * -+ * Sample program that uses these functions to tokenize -+ * a comma-separated first argument while dropping the -+ * rest of the arguments if they occur as token: -+ * -+ * #include -+ * #include -+ * #include -+ * #include "common-utils.h" -+ * -+ * int -+ * main (int argc, char **argv) -+ * { -+ * char *buf; -+ * char *token; -+ * token_iter_t tit; -+ * int i; -+ * gf_boolean_t iter_end; -+ * -+ * if (argc <= 1) -+ * abort(); -+ * -+ * buf = strdup (argv[1]); -+ * if (!buf) -+ * abort(); -+ * -+ * for (token = token_iter_init (buf, ',', &tit) ;;) { -+ * iter_end = next_token (&token, &tit); -+ * printf("found token: '%s'\n", token); -+ * for (i = 2; i < argc; i++) { -+ * if (strcmp (argv[i], token) == 0) { -+ * printf ("%s\n", "dropping token!"); -+ * drop_token (token, &tit); -+ * break; -+ * } -+ * } -+ * if (iter_end) -+ * break; -+ * } -+ * -+ * printf ("finally: '%s'\n", buf); -+ * -+ * return 0; -+ * } -+ */ -+void -+drop_token (char *token, token_iter_t *tit) -+{ -+ char *cursor = NULL; -+ -+ for (cursor = token; *cursor; cursor++) -+ ; -+ if (cursor < tit->end) { -+ /* -+ * We detect a zero inserted by next_token(). -+ * Step the cursor and copy what comes after -+ * to token. -+ */ -+ for (cursor++; cursor < tit->end; *token++ = *cursor++) -+ ; -+ } -+ -+ /* -+ * Zero out the remainder of the buffer. -+ * It would be enough to insert just a single zero, -+ * but we continue 'till the end to have cleaner -+ * memory content. -+ */ -+ for (cursor = token; cursor < tit->end; *cursor++ = 0) -+ ; -+ -+ /* Adjust the end to point to the new terminating zero. */ -+ tit->end = token; -+} -+ - /* Syntax formed according to RFC 1912 (RFC 1123 & 952 are more restrictive) * - ::= *["."] * - ::= <[*[]] */ -@@ -4606,3 +4754,63 @@ is_virtual_xattr (const char *k) - - return ret; - } -+ -+int -+close_fds_except (int *fdv, size_t count) -+{ -+ int i = 0; -+ size_t j = 0; -+ gf_boolean_t should_close = _gf_true; -+#ifdef GF_LINUX_HOST_OS -+ DIR *d = NULL; -+ struct dirent *de = NULL; -+ struct dirent scratch[2] = {{0,},}; -+ char *e = NULL; -+ -+ d = sys_opendir ("/proc/self/fd"); -+ if (!d) -+ return -1; -+ -+ for (;;) { -+ should_close = _gf_true; -+ -+ errno = 0; -+ de = sys_readdir (d); -+ if (!de || errno != 0) -+ break; -+ i = strtoul (de->d_name, &e, 10); -+ if (*e != '\0' || i == dirfd (d)) -+ continue; -+ -+ for (j = 0; j < count; j++) { -+ if (i == fdv[j]) { -+ should_close = _gf_false; -+ break; -+ } -+ } -+ if (should_close) -+ sys_close (i); -+ } -+ sys_closedir (d); -+#else /* !GF_LINUX_HOST_OS */ -+ struct rlimit rl; -+ int ret = -1; -+ -+ ret = getrlimit (RLIMIT_NOFILE, &rl); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < rl.rlim_cur; i++) { -+ should_close = _gf_true; -+ for (j = 0; j < count; j++) { -+ if (i == fdv[j]) { -+ should_close = _gf_false; -+ break; -+ } -+ } -+ if (should_close) -+ sys_close (i); -+ } -+#endif /* !GF_LINUX_HOST_OS */ -+ return 0; -+} -diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h -index 2a6d02c..99142b1 100644 ---- a/libglusterfs/src/common-utils.h -+++ b/libglusterfs/src/common-utils.h -@@ -736,6 +736,14 @@ void skip_word (char **str); - /* returns a new string with nth word of given string. n>=1 */ - char *get_nth_word (const char *str, int n); - -+typedef struct token_iter { -+ char *end; -+ char sep; -+} token_iter_t; -+char *token_iter_init (char *str, char sep, token_iter_t *tit); -+gf_boolean_t next_token (char **tokenp, token_iter_t *tit); -+void drop_token (char *token, token_iter_t *tit); -+ - gf_boolean_t mask_match (const uint32_t a, const uint32_t b, const uint32_t m); - gf_boolean_t gf_is_ip_in_net (const char *network, const char *ip_str); - char valid_host_name (char *address, int length); -@@ -862,4 +870,6 @@ gf_bits_index (uint64_t n); - char * - get_ip_from_addrinfo (struct addrinfo *addr, char **ip); - -+int -+close_fds_except (int *fdv, size_t count); - #endif /* _COMMON_UTILS_H */ -diff --git a/libglusterfs/src/run.c b/libglusterfs/src/run.c -index c625a5b..a7d98af 100644 ---- a/libglusterfs/src/run.c -+++ b/libglusterfs/src/run.c -@@ -23,7 +23,6 @@ - #include - #include - #include --#include - #include "syscall.h" - - #ifdef RUN_STANDALONE -@@ -274,32 +273,9 @@ runner_start (runner_t *runner) - } - - if (ret != -1 ) { --#ifdef GF_LINUX_HOST_OS -- DIR *d = NULL; -- struct dirent *de = NULL; -- char *e = NULL; -- -- d = sys_opendir ("/proc/self/fd"); -- if (d) { -- while ((de = sys_readdir (d))) { -- i = strtoul (de->d_name, &e, 10); -- if (*e == '\0' && i > 2 && -- i != dirfd (d) && i != xpi[1]) -- sys_close (i); -- } -- sys_closedir (d); -- } else -- ret = -1; --#else /* !GF_LINUX_HOST_OS */ -- struct rlimit rl; -- ret = getrlimit (RLIMIT_NOFILE, &rl); -- GF_ASSERT (ret == 0); -- -- for (i = 3; i < rl.rlim_cur; i++) { -- if (i != xpi[1]) -- sys_close (i); -- } --#endif /* !GF_LINUX_HOST_OS */ -+ int fdv[4] = {0, 1, 2, xpi[1]}; -+ -+ ret = close_fds_except(fdv, sizeof (fdv) / sizeof (*fdv)); - } - - if (ret != -1) { --- -1.8.3.1 - diff --git a/SOURCES/0318-fuse-implement-oauto_unmount.patch b/SOURCES/0318-fuse-implement-oauto_unmount.patch deleted file mode 100644 index 6091df6..0000000 --- a/SOURCES/0318-fuse-implement-oauto_unmount.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 137b7b034169022540c69a6ace4c108015910b2d Mon Sep 17 00:00:00 2001 -From: Amar Tumballi -Date: Mon, 29 May 2017 17:26:35 +0530 -Subject: [PATCH 318/318] fuse: implement "-oauto_unmount" - -libfuse has an auto_unmount option which, -if enabled, ensures that the file system -is unmounted at FUSE server termination -by running a separate monitor process -that performs the unmount when that -occurs. (This feature would probably -better be called "robust auto-unmount", -as FUSE servers usually do try to unmount -their file systems upon termination, -it's just this mechanism is not crash -resilient.) - -This change implements that option and -behavior for glusterfs. - -Note that "auto unmount" (robust or not) is -a leaky abstraction, as the kernel cannot -guarantee that at the path where the FUSE -fs is mounted is actually the toplevel mount -at the time of the umount(2) call, for -multiple reasons, among others, see: - - fuse-devel: "fuse: feasible to distinguish between umount and abort?" - http://fuse.996288.n3.nabble.com/fuse-feasible-to-distinguish-between-umount-and-abort-tt14358.html - https://github.com/libfuse/libfuse/issues/122 - -> Change-Id: Ia4432580c9fd2c156d9c73c3a44f4bfd42437599 -> Signed-off-by: Csaba Henk -> Reviewed-on: https://review.gluster.org/17230 -> Tested-by: Amar Tumballi -> CentOS-regression: Gluster Build System -> Smoke: Gluster Build System -> Reviewed-by: Amar Tumballi -> NetBSD-regression: NetBSD Build System - -BUG: 1456420 -Change-Id: I4bae611254bad749b02abaf18d0ed6f447aec7b8 -Signed-off-by: Amar Tumballi -Reviewed-on: https://code.engineering.redhat.com/gerrit/107573 -Reviewed-by: Atin Mukherjee ---- - contrib/fuse-include/fuse-mount.h | 1 + - contrib/fuse-lib/mount.c | 46 +++++++++++++++++++++++++++++ - xlators/mount/fuse/src/fuse-bridge.c | 34 +++++++++++++++++++-- - xlators/mount/fuse/src/fuse-bridge.h | 3 ++ - xlators/mount/fuse/utils/mount.glusterfs.in | 2 +- - 5 files changed, 82 insertions(+), 4 deletions(-) - -diff --git a/contrib/fuse-include/fuse-mount.h b/contrib/fuse-include/fuse-mount.h -index 9358ac8..f2f08e3 100644 ---- a/contrib/fuse-include/fuse-mount.h -+++ b/contrib/fuse-include/fuse-mount.h -@@ -8,6 +8,7 @@ - */ - - void gf_fuse_unmount (const char *mountpoint, int fd); -+int gf_fuse_unmount_daemon (const char *mountpoint, int fd); - int gf_fuse_mount (const char *mountpoint, char *fsname, - unsigned long mountflags, char *mnt_param, - pid_t *mtab_pid, int status_fd); -diff --git a/contrib/fuse-lib/mount.c b/contrib/fuse-lib/mount.c -index 5e0b4dd..876ac90 100644 ---- a/contrib/fuse-lib/mount.c -+++ b/contrib/fuse-lib/mount.c -@@ -75,6 +75,52 @@ gf_fuse_unmount (const char *mountpoint, int fd) - - /* gluster-specific routines */ - -+/* Unmounting in a daemon that lurks 'till main process exits */ -+int -+gf_fuse_unmount_daemon (const char *mountpoint, int fd) -+{ -+ int ret = -1; -+ pid_t pid = -1; -+ -+ if (fd == -1) -+ return -1; -+ -+ int ump[2] = {0,}; -+ -+ ret = pipe(ump); -+ if (ret == -1) { -+ close (fd); -+ return -1; -+ } -+ -+ pid = fork (); -+ switch (pid) { -+ char c = 0; -+ sigset_t sigset; -+ case 0: -+ -+ close_fds_except (ump, 1); -+ -+ setsid(); -+ chdir("/"); -+ sigfillset(&sigset); -+ sigprocmask(SIG_BLOCK, &sigset, NULL); -+ -+ read (ump[0], &c, 1); -+ -+ gf_fuse_unmount (mountpoint, fd); -+ exit (0); -+ case -1: -+ close (fd); -+ fd = -1; -+ ret = -1; -+ close (ump[1]); -+ } -+ close (ump[0]); -+ -+ return ret; -+} -+ - static char * - escape (char *s) - { -diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c -index eead33f..60280ef 100644 ---- a/xlators/mount/fuse/src/fuse-bridge.c -+++ b/xlators/mount/fuse/src/fuse-bridge.c -@@ -5079,7 +5079,7 @@ fuse_thread_proc (void *data) - ZR_MOUNTPOINT_OPT)); - if (mount_point) { - gf_log (this->name, GF_LOG_INFO, -- "unmounting %s", mount_point); -+ "initating unmount of %s", mount_point); - } - - /* Kill the whole process, not just this thread. */ -@@ -5701,6 +5701,24 @@ init (xlator_t *this_xl) - if (!mnt_args) - goto cleanup_exit; - -+ { -+ char *mnt_tok = NULL; -+ token_iter_t tit = {0,}; -+ gf_boolean_t iter_end = _gf_false; -+ -+ for (mnt_tok = token_iter_init (mnt_args, ',', &tit) ;;) { -+ iter_end = next_token (&mnt_tok, &tit); -+ -+ if (strcmp (mnt_tok, "auto_unmount") == 0) { -+ priv->auto_unmount = _gf_true; -+ drop_token (mnt_tok, &tit); -+ } -+ -+ if (iter_end) -+ break; -+ } -+ } -+ - if (pipe(priv->status_pipe) < 0) { - gf_log (this_xl->name, GF_LOG_ERROR, - "could not create pipe to separate mount process"); -@@ -5712,6 +5730,11 @@ init (xlator_t *this_xl) - priv->status_pipe[1]); - if (priv->fd == -1) - goto cleanup_exit; -+ if (priv->auto_unmount) { -+ ret = gf_fuse_unmount_daemon (priv->mount_point, priv->fd); -+ if (ret == -1) -+ goto cleanup_exit; -+ } - - event = eh_new (FUSE_EVENT_HISTORY_SIZE, _gf_false, NULL); - if (!event) { -@@ -5789,10 +5812,15 @@ fini (xlator_t *this_xl) - mount_point = data_to_str (dict_get (this_xl->options, - ZR_MOUNTPOINT_OPT)); - if (mount_point != NULL) { -+ if (!priv->auto_unmount) { -+ gf_log (this_xl->name, GF_LOG_INFO, -+ "Unmounting '%s'.", mount_point); -+ gf_fuse_unmount (mount_point, priv->fd); -+ } -+ - gf_log (this_xl->name, GF_LOG_INFO, -- "Unmounting '%s'.", mount_point); -+ "Closing fuse connection to '%s'.", mount_point); - -- gf_fuse_unmount (mount_point, priv->fd); - sys_close (priv->fuse_dump_fd); - dict_del (this_xl->options, ZR_MOUNTPOINT_OPT); - } -diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h -index 40bd17b..0c70189 100644 ---- a/xlators/mount/fuse/src/fuse-bridge.h -+++ b/xlators/mount/fuse/src/fuse-bridge.h -@@ -134,6 +134,9 @@ struct fuse_private { - - /* Enable or disable capability support */ - gf_boolean_t capability; -+ -+ /* whether to run the unmount daemon */ -+ gf_boolean_t auto_unmount; - }; - typedef struct fuse_private fuse_private_t; - -diff --git a/xlators/mount/fuse/utils/mount.glusterfs.in b/xlators/mount/fuse/utils/mount.glusterfs.in -index 6c4cdfe..2c5e466 100755 ---- a/xlators/mount/fuse/utils/mount.glusterfs.in -+++ b/xlators/mount/fuse/utils/mount.glusterfs.in -@@ -538,7 +538,7 @@ without_options() - "atime"|"noatime"|"diratime"|"nodiratime"|\ - "relatime"|"norelatime"|\ - "strictatime"|"nostrictatime"|"lazyatime"|"nolazyatime"|\ -- "dev"|"nodev"|"exec"|"noexec"|"suid"|"nosuid") -+ "dev"|"nodev"|"exec"|"noexec"|"suid"|"nosuid"|"auto_unmount") - [ -z "$fuse_mountopts" ] || fuse_mountopts="$fuse_mountopts," - fuse_mountopts="${fuse_mountopts}${option}" - ;; --- -1.8.3.1 - diff --git a/SOURCES/0318-glusterd-cli-Get-global-options-through-volume-get-f.patch b/SOURCES/0318-glusterd-cli-Get-global-options-through-volume-get-f.patch new file mode 100644 index 0000000..c392f1e --- /dev/null +++ b/SOURCES/0318-glusterd-cli-Get-global-options-through-volume-get-f.patch @@ -0,0 +1,444 @@ +From 994b4f5337f9bba1b2ca966d52d78983fd4e32f0 Mon Sep 17 00:00:00 2001 +From: Samikshan Bairagya +Date: Fri, 23 Sep 2016 16:35:15 +0530 +Subject: [PATCH 318/361] glusterd, cli: Get global options through volume get + functionality + +Currently it is not possible to retrieve values of global options +by using the 'gluster volume get' functionality if there are no +volumes present. In order to get the global options one has to use +'gluster volume get' with a specific volume name. This usage makes +the illusion as though the option is set only on one volume, which +is incorrect. When setting the global options, 'gluster volume set' +provides a way to set them using the volume name as 'all'. + +Similarly, retrieving the global options should be made possible by +using the volume name 'all' with the 'gluster volume get' +functionality. This patch adds that functionality to 'volume get' + +Usage: + # gluster volume get all