7f4c2a
From f8c28163309870048415cf58668c06a6ba2d700d Mon Sep 17 00:00:00 2001
7f4c2a
From: Avra Sengupta <asengupt@redhat.com>
7f4c2a
Date: Thu, 14 May 2015 15:00:59 +0530
7f4c2a
Subject: [PATCH 09/18] glusterd/shared_storage: Provide a volume set option to
7f4c2a
 create and mount the shared storage
7f4c2a
7f4c2a
     Backport of http://review.gluster.org/#/c/10793/
7f4c2a
7f4c2a
Introducing a global volume set option(cluster.enable-shared-storage)
7f4c2a
which helps create and set-up the shared storage meta volume.
7f4c2a
7f4c2a
gluster volume set all cluster.enable-shared-storage enable
7f4c2a
7f4c2a
On enabling this option, the system analyzes the number of peers
7f4c2a
in the cluster, which are currently connected, and chooses three
7f4c2a
such peers(including the node the command is issued from). From these
7f4c2a
peers a volume(gluster_shared_storage) is created. Depending on the
7f4c2a
number of peers available the volume is either a replica 3
7f4c2a
volume(if there are 3 connected peers),  or a replica 2 volume(if there
7f4c2a
are 2 connected peers). "/var/run/gluster/ss_brick" serves as the
7f4c2a
brick path on each node for the shared storage volume. We also mount
7f4c2a
the shared storage at "/var/run/gluster/shared_storage" on all the nodes
7f4c2a
in the cluster as part of enabling this option. If there is only one node
7f4c2a
in the cluster,  or only one node is up then the command will fail
7f4c2a
7f4c2a
Once the volume is created, and mounted the maintainance of the
7f4c2a
volume like adding-bricks, removing bricks etc., is expected to
7f4c2a
be the onus of the user.
7f4c2a
7f4c2a
On disabling the option, we provide the user a warning, and on
7f4c2a
affirmation from the user we stop the shared storage volume, and unmount
7f4c2a
it from all the nodes in the cluster.
7f4c2a
7f4c2a
gluster volume set all cluster.enable-shared-storage disable
7f4c2a
7f4c2a
Change-Id: Idd92d67b93f444244f99ede9f634ef18d2945dbc
7f4c2a
BUG: 1223201
7f4c2a
Signed-off-by: Avra Sengupta <asengupt@redhat.com>
7f4c2a
Reviewed-on: https://code.engineering.redhat.com/gerrit/50103
7f4c2a
Reviewed-by: Rajesh Joseph <rjoseph@redhat.com>
7f4c2a
Tested-by: Rajesh Joseph <rjoseph@redhat.com>
7f4c2a
---
7f4c2a
 cli/src/cli-cmd-parser.c                           |  56 ++++--
7f4c2a
 cli/src/cli-cmd-volume.c                           |  51 +++++-
7f4c2a
 cli/src/cli-cmd.h                                  |   2 +
7f4c2a
 cli/src/cli.h                                      |   4 +-
7f4c2a
 extras/hook-scripts/set/post/Makefile.am           |   2 +-
7f4c2a
 .../set/post/S32gluster_enable_shared_storage.sh   | 124 +++++++++++++
7f4c2a
 glusterfs.spec.in                                  |   4 +
7f4c2a
 libglusterfs/src/globals.h                         |   2 +
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-hooks.c         |  40 ++++-
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-op-sm.c         | 196 ++++++++++++++++++++-
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-op-sm.h         |   4 +
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-rpc-ops.c       |   9 +
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-sm.c            |  12 ++
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-snapshot.c      |   6 +-
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-utils.c         |  31 ++++
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-utils.h         |   2 +
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-volume-set.c    |   6 +
7f4c2a
 xlators/mgmt/glusterd/src/glusterd.c               | 107 +++++++----
7f4c2a
 xlators/mgmt/glusterd/src/glusterd.h               |   3 +
7f4c2a
 19 files changed, 588 insertions(+), 73 deletions(-)
7f4c2a
 create mode 100755 extras/hook-scripts/set/post/S32gluster_enable_shared_storage.sh
7f4c2a
7f4c2a
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
7f4c2a
index 2390822..caa3191 100644
7f4c2a
--- a/cli/src/cli-cmd-parser.c
7f4c2a
+++ b/cli/src/cli-cmd-parser.c
7f4c2a
@@ -1406,17 +1406,19 @@ out:
7f4c2a
 }
7f4c2a
 
7f4c2a
 int32_t
7f4c2a
-cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options,
7f4c2a
-                          char **op_errstr)
7f4c2a
+cli_cmd_volume_set_parse (struct cli_state *state, const char **words,
7f4c2a
+                          int wordcount, dict_t **options, char **op_errstr)
7f4c2a
 {
7f4c2a
-        dict_t                  *dict = NULL;
7f4c2a
-        char                    *volname = NULL;
7f4c2a
-        int                     ret = -1;
7f4c2a
-        int                     count = 0;
7f4c2a
-        char                    *key = NULL;
7f4c2a
-        char                    *value = NULL;
7f4c2a
-        int                     i = 0;
7f4c2a
-        char                    str[50] = {0,};
7f4c2a
+        dict_t                 *dict      = NULL;
7f4c2a
+        char                   *volname   = NULL;
7f4c2a
+        int                     ret       = -1;
7f4c2a
+        int                     count     = 0;
7f4c2a
+        char                   *key       = NULL;
7f4c2a
+        char                   *value     = NULL;
7f4c2a
+        int                     i         = 0;
7f4c2a
+        char                    str[50]   = {0,};
7f4c2a
+        const char             *question  = NULL;
7f4c2a
+        gf_answer_t             answer    = GF_ANSWER_NO;
7f4c2a
 
7f4c2a
         GF_ASSERT (words);
7f4c2a
         GF_ASSERT (options);
7f4c2a
@@ -1438,6 +1440,22 @@ cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options,
7f4c2a
         if (ret)
7f4c2a
                 goto out;
7f4c2a
 
7f4c2a
+        if (!strcmp (volname, "all")) {
7f4c2a
+                ret = dict_set_str (dict, "globalname", "All");
7f4c2a
+                if (ret) {
7f4c2a
+                        gf_log (THIS->name, GF_LOG_ERROR,
7f4c2a
+                                "dict set on global key failed.");
7f4c2a
+                        goto out;
7f4c2a
+                }
7f4c2a
+
7f4c2a
+                ret = dict_set_int32 (dict, "hold_global_locks", _gf_true);
7f4c2a
+                if (ret) {
7f4c2a
+                        gf_log (THIS->name, GF_LOG_ERROR,
7f4c2a
+                                "dict set on global key failed.");
7f4c2a
+                        goto out;
7f4c2a
+                }
7f4c2a
+        }
7f4c2a
+
7f4c2a
         if ((!strcmp (volname, "help") || !strcmp (volname, "help-xml"))
7f4c2a
             && wordcount == 3 ) {
7f4c2a
                 ret = dict_set_str (dict, volname, volname);
7f4c2a
@@ -1507,6 +1525,24 @@ cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options,
7f4c2a
 
7f4c2a
                 if (ret)
7f4c2a
                         goto out;
7f4c2a
+
7f4c2a
+                if ((!strcmp (key, "cluster.enable-shared-storage")) &&
7f4c2a
+                    (!strcmp (value, "disable"))) {
7f4c2a
+                        question = "Disabling cluster.enable-shared-storage "
7f4c2a
+                                   "will delete the shared storage volume"
7f4c2a
+                                   "(gluster_shared_storage), which is used "
7f4c2a
+                                   "by snapshot scheduler, geo-replication "
7f4c2a
+                                   "and NFS-Ganesha. Do you still want to "
7f4c2a
+                                   "continue?";
7f4c2a
+                        answer = cli_cmd_get_confirmation (state, question);
7f4c2a
+                        if (GF_ANSWER_NO == answer) {
7f4c2a
+                                gf_log ("cli", GF_LOG_ERROR, "Operation "
7f4c2a
+                                        "cancelled, exiting");
7f4c2a
+                                *op_errstr = gf_strdup ("Aborted by user.");
7f4c2a
+                                ret = -1;
7f4c2a
+                                goto out;
7f4c2a
+                        }
7f4c2a
+                }
7f4c2a
         }
7f4c2a
 
7f4c2a
         ret = dict_set_int32 (dict, "count", wordcount-3);
7f4c2a
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
7f4c2a
index da6603c..6dd3058 100644
7f4c2a
--- a/cli/src/cli-cmd-volume.c
7f4c2a
+++ b/cli/src/cli-cmd-volume.c
7f4c2a
@@ -286,22 +286,28 @@ cli_cmd_volume_delete_cbk (struct cli_state *state, struct cli_cmd_word *word,
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
 
7f4c2a
-        answer = cli_cmd_get_confirmation (state, question);
7f4c2a
-
7f4c2a
-        if (GF_ANSWER_NO == answer) {
7f4c2a
-                ret = 0;
7f4c2a
-                goto out;
7f4c2a
-        }
7f4c2a
-
7f4c2a
         volname = (char *)words[2];
7f4c2a
 
7f4c2a
         ret = dict_set_str (dict, "volname", volname);
7f4c2a
-
7f4c2a
         if (ret) {
7f4c2a
                 gf_log (THIS->name, GF_LOG_WARNING, "dict set failed");
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
 
7f4c2a
+        if (!strcmp (volname, GLUSTER_SHARED_STORAGE)) {
7f4c2a
+                question = "Deleting the shared storage volume"
7f4c2a
+                           "(gluster_shared_storage), will affect features "
7f4c2a
+                           "like snapshot scheduler, geo-replication "
7f4c2a
+                           "and NFS-Ganesha. Do you still want to "
7f4c2a
+                           "continue?";
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        answer = cli_cmd_get_confirmation (state, question);
7f4c2a
+        if (GF_ANSWER_NO == answer) {
7f4c2a
+                ret = 0;
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
         CLI_LOCAL_INIT (local, words, frame, dict);
7f4c2a
 
7f4c2a
         if (proc->fn) {
7f4c2a
@@ -473,6 +479,14 @@ cli_cmd_volume_stop_cbk (struct cli_state *state, struct cli_cmd_word *word,
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
 
7f4c2a
+        if (!strcmp (volname, GLUSTER_SHARED_STORAGE)) {
7f4c2a
+                question = "Stopping the shared storage volume"
7f4c2a
+                           "(gluster_shared_storage), will affect features "
7f4c2a
+                           "like snapshot scheduler, geo-replication "
7f4c2a
+                           "and NFS-Ganesha. Do you still want to "
7f4c2a
+                           "continue?";
7f4c2a
+        }
7f4c2a
+
7f4c2a
         if (wordcount == 4) {
7f4c2a
                 if (!strcmp("force", words[3])) {
7f4c2a
                         flags |= GF_CLI_FLAG_OP_FORCE;
7f4c2a
@@ -483,6 +497,7 @@ cli_cmd_volume_stop_cbk (struct cli_state *state, struct cli_cmd_word *word,
7f4c2a
                         goto out;
7f4c2a
                 }
7f4c2a
         }
7f4c2a
+
7f4c2a
         ret = dict_set_int32 (dict, "flags", flags);
7f4c2a
         if (ret) {
7f4c2a
                 gf_log (THIS->name, GF_LOG_ERROR,
7f4c2a
@@ -732,7 +747,8 @@ cli_cmd_volume_set_cbk (struct cli_state *state, struct cli_cmd_word *word,
7f4c2a
         if (!frame)
7f4c2a
                 goto out;
7f4c2a
 
7f4c2a
-        ret = cli_cmd_volume_set_parse (words, wordcount, &options, &op_errstr);
7f4c2a
+        ret = cli_cmd_volume_set_parse (state, words, wordcount,
7f4c2a
+                                        &options, &op_errstr);
7f4c2a
         if (ret) {
7f4c2a
                 if (op_errstr) {
7f4c2a
                     cli_err ("%s", op_errstr);
7f4c2a
@@ -1612,6 +1628,7 @@ cli_cmd_volume_remove_brick_cbk (struct cli_state *state,
7f4c2a
         int                     parse_error = 0;
7f4c2a
         int                     need_question = 0;
7f4c2a
         cli_local_t             *local = NULL;
7f4c2a
+        char                    *volname = NULL;
7f4c2a
 
7f4c2a
         const char *question = "Removing brick(s) can result in data loss. "
7f4c2a
                                "Do you want to Continue?";
7f4c2a
@@ -1628,6 +1645,22 @@ cli_cmd_volume_remove_brick_cbk (struct cli_state *state,
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
 
7f4c2a
+        ret = dict_get_str (options, "volname", &volname);
7f4c2a
+        if (ret || !volname) {
7f4c2a
+                gf_log ("cli", GF_LOG_ERROR, "Failed to fetch volname");
7f4c2a
+                ret = -1;
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        if (!strcmp (volname, GLUSTER_SHARED_STORAGE)) {
7f4c2a
+                question = "Removing brick from the shared storage volume"
7f4c2a
+                           "(gluster_shared_storage), will affect features "
7f4c2a
+                           "like snapshot scheduler, geo-replication "
7f4c2a
+                           "and NFS-Ganesha. Do you still want to "
7f4c2a
+                           "continue?";
7f4c2a
+                need_question = _gf_true;
7f4c2a
+        }
7f4c2a
+
7f4c2a
         if (!(state->mode & GLUSTER_MODE_SCRIPT) && need_question) {
7f4c2a
                 /* we need to ask question only in case of 'commit or force' */
7f4c2a
                 answer = cli_cmd_get_confirmation (state, question);
7f4c2a
diff --git a/cli/src/cli-cmd.h b/cli/src/cli-cmd.h
7f4c2a
index 94fa3e9..3a689c4 100644
7f4c2a
--- a/cli/src/cli-cmd.h
7f4c2a
+++ b/cli/src/cli-cmd.h
7f4c2a
@@ -20,6 +20,8 @@
7f4c2a
 #include "cli.h"
7f4c2a
 #include "list.h"
7f4c2a
 
7f4c2a
+#define GLUSTER_SHARED_STORAGE      "gluster_shared_storage"
7f4c2a
+
7f4c2a
 #define CLI_LOCAL_INIT(local, words, frame, dictionary) \
7f4c2a
         do {                                                 \
7f4c2a
                 local = cli_local_get ();                    \
7f4c2a
diff --git a/cli/src/cli.h b/cli/src/cli.h
7f4c2a
index c9283b5..6c0fbce 100644
7f4c2a
--- a/cli/src/cli.h
7f4c2a
+++ b/cli/src/cli.h
7f4c2a
@@ -248,8 +248,8 @@ int32_t
7f4c2a
 cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **opt);
7f4c2a
 
7f4c2a
 int32_t
7f4c2a
-cli_cmd_volume_set_parse (const char **words, int wordcount,
7f4c2a
-                          dict_t **options, char **op_errstr);
7f4c2a
+cli_cmd_volume_set_parse (struct cli_state *state, const char **words,
7f4c2a
+                          int wordcount, dict_t **options, char **op_errstr);
7f4c2a
 int32_t
7f4c2a
 cli_cmd_ganesha_parse (struct cli_state *state, const char **words,
7f4c2a
                        int wordcount, dict_t **options, char **op_errstr);
7f4c2a
diff --git a/extras/hook-scripts/set/post/Makefile.am b/extras/hook-scripts/set/post/Makefile.am
7f4c2a
index 3ec25d9..99dfaa3 100644
7f4c2a
--- a/extras/hook-scripts/set/post/Makefile.am
7f4c2a
+++ b/extras/hook-scripts/set/post/Makefile.am
7f4c2a
@@ -1 +1 @@
7f4c2a
-EXTRA_DIST = S30samba-set.sh S31ganesha-set.sh
7f4c2a
+EXTRA_DIST = S30samba-set.sh S31ganesha-set.sh S32gluster_enable_shared_storage.sh
7f4c2a
diff --git a/extras/hook-scripts/set/post/S32gluster_enable_shared_storage.sh b/extras/hook-scripts/set/post/S32gluster_enable_shared_storage.sh
7f4c2a
new file mode 100755
7f4c2a
index 0000000..28fa0e5
7f4c2a
--- /dev/null
7f4c2a
+++ b/extras/hook-scripts/set/post/S32gluster_enable_shared_storage.sh
7f4c2a
@@ -0,0 +1,124 @@
7f4c2a
+#!/bin/bash
7f4c2a
+
7f4c2a
+key=`echo $3 | cut -d '=' -f 1`
7f4c2a
+val=`echo $3 | cut -d '=' -f 2`
7f4c2a
+if [ "$key" != "cluster.enable-shared-storage" ]; then
7f4c2a
+    exit;
7f4c2a
+fi
7f4c2a
+if [ "$val" != 'enable' ]; then
7f4c2a
+    if [ "$val" != 'disable' ]; then
7f4c2a
+        exit;
7f4c2a
+    fi
7f4c2a
+fi
7f4c2a
+
7f4c2a
+option=$val
7f4c2a
+
7f4c2a
+key_val_pair1=`echo $4 | cut -d ',' -f 1`
7f4c2a
+key_val_pair2=`echo $4 | cut -d ',' -f 2`
7f4c2a
+
7f4c2a
+key=`echo $key_val_pair1 | cut -d '=' -f 1`
7f4c2a
+val=`echo $key_val_pair1 | cut -d '=' -f 2`
7f4c2a
+if [ "$key" != "is_originator" ]; then
7f4c2a
+    exit;
7f4c2a
+fi
7f4c2a
+is_originator=$val;
7f4c2a
+
7f4c2a
+key=`echo $key_val_pair2 | cut -d '=' -f 1`
7f4c2a
+val=`echo $key_val_pair2 | cut -d '=' -f 2`
7f4c2a
+if [ "$key" != "local_node_hostname" ]; then
7f4c2a
+    exit;
7f4c2a
+fi
7f4c2a
+local_node_hostname=$val;
7f4c2a
+
7f4c2a
+# Read gluster peer status to find the peers
7f4c2a
+# which are in 'Peer in Cluster' mode and
7f4c2a
+# are connected.
7f4c2a
+
7f4c2a
+number_of_connected_peers=0
7f4c2a
+while read -r line
7f4c2a
+do
7f4c2a
+    # Already got two connected peers. Including the current node
7f4c2a
+    # we have 3 peers which is enough to create a shared storage
7f4c2a
+    # with replica 3
7f4c2a
+    if [ "$number_of_connected_peers" == "2" ]; then
7f4c2a
+        break;
7f4c2a
+    fi
7f4c2a
+
7f4c2a
+    key=`echo $line | cut -d ':' -f 1`
7f4c2a
+    if [ "$key" == "Hostname" ]; then
7f4c2a
+        hostname=`echo $line | cut -d ':' -f 2 | xargs`
7f4c2a
+    fi
7f4c2a
+
7f4c2a
+    if [ "$key" == "State" ]; then
7f4c2a
+        peer_state=`echo $line | cut -d ':' -f 2 | cut -d '(' -f 1 | xargs`
7f4c2a
+        conn_state=`echo $line | cut -d '(' -f 2 | cut -d ')' -f 1 | xargs`
7f4c2a
+
7f4c2a
+        if [ "$peer_state" == "Peer in Cluster" ]; then
7f4c2a
+            if [ "$conn_state" == "Connected" ]; then
7f4c2a
+                ((number_of_connected_peers++))
7f4c2a
+                connected_peer[$number_of_connected_peers]=$hostname
7f4c2a
+            fi
7f4c2a
+        fi
7f4c2a
+    fi
7f4c2a
+
7f4c2a
+done < <(gluster peer status)
7f4c2a
+
7f4c2a
+# Include current node in connected peer list
7f4c2a
+((number_of_connected_peers++))
7f4c2a
+connected_peer[$number_of_connected_peers]=$local_node_hostname
7f4c2a
+
7f4c2a
+# forming the create vol command
7f4c2a
+create_cmd="gluster --mode=script --wignore volume create \
7f4c2a
+            gluster_shared_storage replica $number_of_connected_peers"
7f4c2a
+
7f4c2a
+# Adding the brick names in the command
7f4c2a
+for i in "${connected_peer[@]}"
7f4c2a
+do
7f4c2a
+    create_cmd=$create_cmd" "$i:/var/run/gluster/ss_brick
7f4c2a
+done
7f4c2a
+
7f4c2a
+if [ "$option" == "disable" ]; then
7f4c2a
+    # Unmount the volume on all the nodes
7f4c2a
+    umount /var/run/gluster/shared_storage
7f4c2a
+fi
7f4c2a
+
7f4c2a
+if [ "$is_originator" == 1 ]; then
7f4c2a
+    if [ "$option" == "enable" ]; then
7f4c2a
+        # Create and start the volume
7f4c2a
+        $create_cmd
7f4c2a
+        gluster --mode=script --wignore volume start gluster_shared_storage
7f4c2a
+    fi
7f4c2a
+
7f4c2a
+    if [ "$option" == "disable" ]; then
7f4c2a
+        # Stop and delete the volume
7f4c2a
+        gluster --mode=script --wignore volume stop gluster_shared_storage
7f4c2a
+        gluster --mode=script --wignore volume delete gluster_shared_storage
7f4c2a
+    fi
7f4c2a
+fi
7f4c2a
+
7f4c2a
+function check_volume_status()
7f4c2a
+{
7f4c2a
+    status=`gluster volume info gluster_shared_storage  | grep Status | cut -d ':' -f 2 | xargs`
7f4c2a
+    echo $status
7f4c2a
+}
7f4c2a
+
7f4c2a
+mount_cmd="mount -t glusterfs "$local_node_hostname":/gluster_shared_storage \
7f4c2a
+           /var/run/gluster/shared_storage"
7f4c2a
+
7f4c2a
+if [ "$option" == "enable" ]; then
7f4c2a
+    retry=0;
7f4c2a
+    # Wait for volume to start before mounting
7f4c2a
+    status=$(check_volume_status)
7f4c2a
+    while [ "$status" != "Started" ]; do
7f4c2a
+        sleep 5;
7f4c2a
+        ((retry++))
7f4c2a
+        if [ "$retry" == 3 ]; then
7f4c2a
+            break;
7f4c2a
+        fi
7f4c2a
+        status = check_volume_status;
7f4c2a
+    done
7f4c2a
+    # Mount the volume on all the nodes
7f4c2a
+    umount /var/run/gluster/shared_storage
7f4c2a
+    mkdir -p /var/run/gluster/shared_storage
7f4c2a
+    $mount_cmd
7f4c2a
+fi
7f4c2a
diff --git a/glusterfs.spec.in b/glusterfs.spec.in
7f4c2a
index 0ec8201..a5a884f 100644
7f4c2a
--- a/glusterfs.spec.in
7f4c2a
+++ b/glusterfs.spec.in
7f4c2a
@@ -1115,6 +1115,7 @@ fi
7f4c2a
 %config %{_sharedstatedir}/glusterd/hooks/1/add-brick/pre/S28Quota-enable-root-xattr-heal.sh
7f4c2a
 %config %{_sharedstatedir}/glusterd/hooks/1/set/post/S30samba-set.sh
7f4c2a
 %config %{_sharedstatedir}/glusterd/hooks/1/set/post/S31ganesha-set.sh
7f4c2a
+%config %{_sharedstatedir}/glusterd/hooks/1/set/post/S32gluster_enable_shared_storage.sh
7f4c2a
 %config %{_sharedstatedir}/glusterd/hooks/1/start/post/S29CTDBsetup.sh
7f4c2a
 %config %{_sharedstatedir}/glusterd/hooks/1/start/post/S30samba-start.sh
7f4c2a
 %config %{_sharedstatedir}/glusterd/hooks/1/stop/pre/S30samba-stop.sh
7f4c2a
@@ -1208,6 +1209,9 @@ fi
7f4c2a
 * Sat May 31 2015 Aravinda VK <avishwan@redhat.com>
7f4c2a
 - Added stop-all-gluster-processes.sh in glusterfs-server section (#1225331)
7f4c2a
 
7f4c2a
+* Tue May 19 2015 Avra Sengupta <asengupt@redhat.com>
7f4c2a
+- Added S32gluster_enable_shared_storage.sh as volume set hook script (#1222013)
7f4c2a
+
7f4c2a
 * Fri May 29 2015 Anand Nekkunti <anekkunt@redhat.com>
7f4c2a
 - glusterd.socket file cleanup during post run upgrade (#1222869)
7f4c2a
 
7f4c2a
diff --git a/libglusterfs/src/globals.h b/libglusterfs/src/globals.h
7f4c2a
index b9eaf8a..ed1bb7c 100644
7f4c2a
--- a/libglusterfs/src/globals.h
7f4c2a
+++ b/libglusterfs/src/globals.h
7f4c2a
@@ -43,6 +43,8 @@
7f4c2a
 
7f4c2a
 #define GD_OP_VERSION_3_7_0    30700 /* Op-version for GlusterFS 3.7.0 */
7f4c2a
 
7f4c2a
+#define GD_OP_VERSION_3_7_1    30701 /* Op-version for GlusterFS 3.7.1 */
7f4c2a
+
7f4c2a
 #define GD_OP_VER_PERSISTENT_AFR_XATTRS GD_OP_VERSION_3_6_0
7f4c2a
 
7f4c2a
 #include "xlator.h"
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-hooks.c b/xlators/mgmt/glusterd/src/glusterd-hooks.c
7f4c2a
index 569f274..3e3f189 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-hooks.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-hooks.c
7f4c2a
@@ -162,6 +162,34 @@ glusterd_hooks_add_hooks_version (runner_t* runner)
7f4c2a
         runner_argprintf (runner, "--version=%d", GLUSTERD_HOOK_VER);
7f4c2a
 }
7f4c2a
 
7f4c2a
+static void
7f4c2a
+glusterd_hooks_add_custom_args (dict_t *dict, runner_t *runner)
7f4c2a
+{
7f4c2a
+        char      *hooks_args     = NULL;
7f4c2a
+        int32_t    ret            = -1;
7f4c2a
+        xlator_t  *this           = NULL;
7f4c2a
+
7f4c2a
+        this = THIS;
7f4c2a
+        GF_VALIDATE_OR_GOTO ("glusterd", this, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, dict, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, runner, out);
7f4c2a
+
7f4c2a
+        ret = dict_get_str (dict, "hooks_args", &hooks_args);
7f4c2a
+        if (ret)
7f4c2a
+                gf_log (this->name, GF_LOG_DEBUG,
7f4c2a
+                        "No Hooks Arguments.");
7f4c2a
+        else
7f4c2a
+                gf_log (this->name, GF_LOG_DEBUG,
7f4c2a
+                        "Hooks Args = %s", hooks_args);
7f4c2a
+
7f4c2a
+        if (hooks_args)
7f4c2a
+                runner_argprintf (runner, "%s", hooks_args);
7f4c2a
+
7f4c2a
+out:
7f4c2a
+        return;
7f4c2a
+}
7f4c2a
+
7f4c2a
+
7f4c2a
 int
7f4c2a
 glusterd_hooks_set_volume_args (dict_t *dict, runner_t *runner)
7f4c2a
 {
7f4c2a
@@ -196,6 +224,8 @@ glusterd_hooks_set_volume_args (dict_t *dict, runner_t *runner)
7f4c2a
                 runner_argprintf (runner, "%s=%s", key, value);
7f4c2a
         }
7f4c2a
 
7f4c2a
+        glusterd_hooks_add_custom_args (dict, runner);
7f4c2a
+
7f4c2a
         ret = 0;
7f4c2a
 out:
7f4c2a
         return ret;
7f4c2a
@@ -263,15 +293,7 @@ glusterd_hooks_add_op_args (runner_t *runner, glusterd_op_t op,
7f4c2a
                         break;
7f4c2a
 
7f4c2a
                 case GD_OP_GSYNC_CREATE:
7f4c2a
-                        ret = dict_get_str (op_ctx, "hooks_args", &hooks_args);
7f4c2a
-                        if (ret)
7f4c2a
-                                gf_log ("", GF_LOG_DEBUG,
7f4c2a
-                                        "No Hooks Arguments.");
7f4c2a
-                        else
7f4c2a
-                                gf_log ("", GF_LOG_DEBUG,
7f4c2a
-                                        "Hooks Args = %s", hooks_args);
7f4c2a
-                        if (hooks_args)
7f4c2a
-                                runner_argprintf (runner, "%s", hooks_args);
7f4c2a
+                        glusterd_hooks_add_custom_args (op_ctx, runner);
7f4c2a
                         break;
7f4c2a
 
7f4c2a
                 case GD_OP_ADD_BRICK:
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
7f4c2a
index 326968e..9b9684e 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
7f4c2a
@@ -55,11 +55,36 @@
7f4c2a
 #include <signal.h>
7f4c2a
 #include <sys/wait.h>
7f4c2a
 
7f4c2a
+extern char ss_brick_path[PATH_MAX];
7f4c2a
+extern char local_node_hostname[PATH_MAX];
7f4c2a
+static int
7f4c2a
+glusterd_set_shared_storage (dict_t *dict, char *key, char *value,
7f4c2a
+                             char **op_errstr);
7f4c2a
+
7f4c2a
+/* Valid options for all volumes to be listed in the *
7f4c2a
+ * valid_all_vol_opts table. To add newer options to *
7f4c2a
+ * all volumes, we can just add more entries to this *
7f4c2a
+ * table                                             *
7f4c2a
+ */
7f4c2a
+glusterd_all_vol_opts   valid_all_vol_opts[] = {
7f4c2a
+        { GLUSTERD_QUORUM_RATIO_KEY },
7f4c2a
+        { GLUSTERD_SHARED_STORAGE_KEY },
7f4c2a
+        { NULL },
7f4c2a
+};
7f4c2a
+
7f4c2a
 #define ALL_VOLUME_OPTION_CHECK(volname, key, ret, op_errstr, label)           \
7f4c2a
         do {                                                                   \
7f4c2a
-                gf_boolean_t    _all = !strcmp ("all", volname);               \
7f4c2a
-                gf_boolean_t    _ratio = !strcmp (key,                         \
7f4c2a
-                                                  GLUSTERD_QUORUM_RATIO_KEY);  \
7f4c2a
+                gf_boolean_t    _all   = !strcmp ("all", volname);             \
7f4c2a
+                gf_boolean_t    _ratio = _gf_false;                            \
7f4c2a
+                int32_t         i      = 0;                                    \
7f4c2a
+                                                                               \
7f4c2a
+                for (i = 0; valid_all_vol_opts[i].option; i++) {               \
7f4c2a
+                        if (!strcmp (key, valid_all_vol_opts[i].option)) {     \
7f4c2a
+                                _ratio = _gf_true;                             \
7f4c2a
+                                break;                                         \
7f4c2a
+                        }                                                      \
7f4c2a
+                }                                                              \
7f4c2a
+                                                                               \
7f4c2a
                 if (_all && !_ratio) {                                         \
7f4c2a
                         ret = -1;                                              \
7f4c2a
                         *op_errstr = gf_strdup ("Not a valid option for all "  \
7f4c2a
@@ -682,6 +707,71 @@ out:
7f4c2a
 }
7f4c2a
 
7f4c2a
 static int
7f4c2a
+glusterd_validate_shared_storage (char *key, char *value, char *errstr)
7f4c2a
+{
7f4c2a
+        int32_t       ret      = -1;
7f4c2a
+        int32_t       exists   = -1;
7f4c2a
+        int32_t       count    = -1;
7f4c2a
+        xlator_t     *this     = NULL;
7f4c2a
+
7f4c2a
+        this = THIS;
7f4c2a
+        GF_VALIDATE_OR_GOTO ("glusterd", this, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, key, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, value, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, errstr, out);
7f4c2a
+
7f4c2a
+        ret = 0;
7f4c2a
+
7f4c2a
+        if (strcmp (key, GLUSTERD_SHARED_STORAGE_KEY)) {
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        if ((strcmp (value, "enable")) &&
7f4c2a
+            (strcmp (value, "disable"))) {
7f4c2a
+                snprintf (errstr, PATH_MAX,
7f4c2a
+                          "Invalid option(%s). Valid options "
7f4c2a
+                          "are 'enable' and 'disable'", value);
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR, "%s", errstr);
7f4c2a
+                ret = -1;
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        if (strcmp (value, "enable")) {
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        exists = glusterd_check_volume_exists (GLUSTER_SHARED_STORAGE);
7f4c2a
+        if (exists) {
7f4c2a
+                snprintf (errstr, PATH_MAX,
7f4c2a
+                          "Shared storage volume("GLUSTER_SHARED_STORAGE
7f4c2a
+                          ") already exists.");
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR, "%s", errstr);
7f4c2a
+                ret = -1;
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        ret = glusterd_count_connected_peers (&count);
7f4c2a
+        if (ret) {
7f4c2a
+                snprintf (errstr, PATH_MAX,
7f4c2a
+                          "Failed to calculate number of connected peers.");
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR, "%s", errstr);
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        if (count <= 1) {
7f4c2a
+                snprintf (errstr, PATH_MAX,
7f4c2a
+                          "More than one node should "
7f4c2a
+                          "be up/present in the cluster to enable this option");
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR, "%s", errstr);
7f4c2a
+                ret = -1;
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+out:
7f4c2a
+        return ret;
7f4c2a
+}
7f4c2a
+
7f4c2a
+static int
7f4c2a
 glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr)
7f4c2a
 {
7f4c2a
         int                             ret                     = -1;
7f4c2a
@@ -696,7 +786,7 @@ glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr)
7f4c2a
         int                             trash_path_len          = 0;
7f4c2a
         int                             count                   = 0;
7f4c2a
         int                             dict_count              = 0;
7f4c2a
-        char                            errstr[2048]            = {0, };
7f4c2a
+        char                            errstr[PATH_MAX]        = {0, };
7f4c2a
         glusterd_volinfo_t              *volinfo                = NULL;
7f4c2a
         glusterd_brickinfo_t            *brickinfo              = NULL;
7f4c2a
         dict_t                          *val_dict               = NULL;
7f4c2a
@@ -1000,6 +1090,14 @@ glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr)
7f4c2a
                         }
7f4c2a
                 }
7f4c2a
 
7f4c2a
+                ret = glusterd_validate_shared_storage (key, value, errstr);
7f4c2a
+                if (ret) {
7f4c2a
+                        gf_log (this->name, GF_LOG_ERROR,
7f4c2a
+                                "Failed to validate shared "
7f4c2a
+                                "storage volume options");
7f4c2a
+                        goto out;
7f4c2a
+                }
7f4c2a
+
7f4c2a
                 if (!strcmp(key, "features.trash-dir") && trash_enabled) {
7f4c2a
                         if (strchr (value, '/')) {
7f4c2a
                                 snprintf (errstr, sizeof (errstr),
7f4c2a
@@ -1918,7 +2016,8 @@ out:
7f4c2a
 }
7f4c2a
 
7f4c2a
 static int
7f4c2a
-glusterd_op_set_all_volume_options (xlator_t *this, dict_t *dict)
7f4c2a
+glusterd_op_set_all_volume_options (xlator_t *this, dict_t *dict,
7f4c2a
+                                    char **op_errstr)
7f4c2a
 {
7f4c2a
         char            *key            = NULL;
7f4c2a
         char            *key_fixed      = NULL;
7f4c2a
@@ -1942,6 +2041,7 @@ glusterd_op_set_all_volume_options (xlator_t *this, dict_t *dict)
7f4c2a
                         "invalid key,value pair in 'volume set'");
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
+
7f4c2a
         ret = glusterd_check_option_exists (key, &key_fixed);
7f4c2a
         if (ret <= 0) {
7f4c2a
                 gf_log (this->name, GF_LOG_ERROR, "Invalid key %s", key);
7f4c2a
@@ -1952,6 +2052,13 @@ glusterd_op_set_all_volume_options (xlator_t *this, dict_t *dict)
7f4c2a
         if (key_fixed)
7f4c2a
                 key = key_fixed;
7f4c2a
 
7f4c2a
+        ret = glusterd_set_shared_storage (dict, key, value, op_errstr);
7f4c2a
+        if (ret) {
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR,
7f4c2a
+                        "Failed to set shared storage option");
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
         /* If the key is cluster.op-version, set conf->op_version to the value
7f4c2a
          * if needed and save it.
7f4c2a
          */
7f4c2a
@@ -2030,6 +2137,82 @@ out:
7f4c2a
 }
7f4c2a
 
7f4c2a
 static int
7f4c2a
+glusterd_set_shared_storage (dict_t *dict, char *key, char *value,
7f4c2a
+                             char **op_errstr)
7f4c2a
+{
7f4c2a
+        int32_t       ret                  = -1;
7f4c2a
+        int32_t       exists               = -1;
7f4c2a
+        int32_t       count                = -1;
7f4c2a
+        char          hooks_args[PATH_MAX] = {0, };
7f4c2a
+        char          errstr[PATH_MAX]     = {0, };
7f4c2a
+        xlator_t     *this                 = NULL;
7f4c2a
+
7f4c2a
+        this = THIS;
7f4c2a
+        GF_VALIDATE_OR_GOTO ("glusterd", this, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, dict, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, key, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, value, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, op_errstr, out);
7f4c2a
+
7f4c2a
+        ret = 0;
7f4c2a
+
7f4c2a
+        if (strcmp (key, GLUSTERD_SHARED_STORAGE_KEY)) {
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        /* Re-create the brick path so as to be *
7f4c2a
+         * able to re-use it                    *
7f4c2a
+         */
7f4c2a
+        ret = recursive_rmdir (ss_brick_path);
7f4c2a
+        if (ret) {
7f4c2a
+                snprintf (errstr, PATH_MAX,
7f4c2a
+                          "Failed to remove shared "
7f4c2a
+                          "storage brick(%s). "
7f4c2a
+                          "Reason: %s", ss_brick_path,
7f4c2a
+                          strerror (errno));
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR, "%s", errstr);
7f4c2a
+                ret = -1;
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        ret = mkdir_p (ss_brick_path, 0777, _gf_true);
7f4c2a
+        if (-1 == ret) {
7f4c2a
+                snprintf (errstr, PATH_MAX,
7f4c2a
+                          "Failed to create shared "
7f4c2a
+                          "storage brick(%s). "
7f4c2a
+                          "Reason: %s", ss_brick_path,
7f4c2a
+                          strerror (errno));
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR, "%s", errstr);
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        if (is_origin_glusterd (dict)) {
7f4c2a
+                snprintf(hooks_args, sizeof(hooks_args),
7f4c2a
+                         "is_originator=1,local_node_hostname=%s",
7f4c2a
+                         local_node_hostname);
7f4c2a
+        } else {
7f4c2a
+                snprintf(hooks_args, sizeof(hooks_args),
7f4c2a
+                         "is_originator=0,local_node_hostname=%s",
7f4c2a
+                         local_node_hostname);
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        ret = dict_set_dynstr_with_alloc (dict, "hooks_args", hooks_args);
7f4c2a
+        if (ret) {
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR, "Failed to set"
7f4c2a
+                        " hooks_args in dict.");
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+out:
7f4c2a
+        if (ret && strlen(errstr)) {
7f4c2a
+                *op_errstr = gf_strdup (errstr);
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        return ret;
7f4c2a
+}
7f4c2a
+
7f4c2a
+
7f4c2a
+static int
7f4c2a
 glusterd_op_set_volume (dict_t *dict, char **errstr)
7f4c2a
 {
7f4c2a
         int                                      ret = 0;
7f4c2a
@@ -2083,7 +2266,8 @@ glusterd_op_set_volume (dict_t *dict, char **errstr)
7f4c2a
         }
7f4c2a
 
7f4c2a
         if (strcasecmp (volname, "all") == 0) {
7f4c2a
-                ret = glusterd_op_set_all_volume_options (this, dict);
7f4c2a
+                ret = glusterd_op_set_all_volume_options (this, dict,
7f4c2a
+                                                          &op_errstr);
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
 
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.h b/xlators/mgmt/glusterd/src/glusterd-op-sm.h
7f4c2a
index 6a1baa4..368bb04 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-op-sm.h
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.h
7f4c2a
@@ -168,6 +168,10 @@ typedef enum cli_cmd_type_ {
7f4c2a
         ALL_HEAL_XL,
7f4c2a
  } cli_cmd_type;
7f4c2a
 
7f4c2a
+typedef struct glusterd_all_volume_options {
7f4c2a
+        char          *option;
7f4c2a
+} glusterd_all_vol_opts;
7f4c2a
+
7f4c2a
 int
7f4c2a
 glusterd_op_sm_new_event (glusterd_op_sm_event_type_t event_type,
7f4c2a
                           glusterd_op_sm_event_t **new_event);
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
7f4c2a
index 415d04f..dcd257c 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
7f4c2a
@@ -1472,6 +1472,15 @@ glusterd_rpc_friend_add (call_frame_t *frame, xlator_t *this,
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
 
7f4c2a
+        ret = dict_set_dynstr_with_alloc (peer_data,
7f4c2a
+                                          "hostname_in_cluster",
7f4c2a
+                                          peerinfo->hostname);
7f4c2a
+        if (ret) {
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR,
7f4c2a
+                        "Unable to add hostname of the peer");
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
         if (priv->op_version >= GD_OP_VERSION_3_6_0) {
7f4c2a
                 ret = glusterd_add_missed_snaps_to_export_dict (peer_data);
7f4c2a
                 if (ret) {
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.c b/xlators/mgmt/glusterd/src/glusterd-sm.c
7f4c2a
index f8228b0..0d8654a 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-sm.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-sm.c
7f4c2a
@@ -38,6 +38,8 @@
7f4c2a
 #include "glusterd-snapshot-utils.h"
7f4c2a
 #include "glusterd-server-quorum.h"
7f4c2a
 
7f4c2a
+char local_node_hostname[PATH_MAX] = {0, };
7f4c2a
+
7f4c2a
 static struct cds_list_head gd_friend_sm_queue;
7f4c2a
 
7f4c2a
 static  char *glusterd_friend_sm_state_names[] = {
7f4c2a
@@ -733,6 +735,7 @@ glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx)
7f4c2a
         int32_t                         op_ret = -1;
7f4c2a
         int32_t                         op_errno = 0;
7f4c2a
         xlator_t                       *this       = NULL;
7f4c2a
+        char                           *hostname   = NULL;
7f4c2a
 
7f4c2a
         this = THIS;
7f4c2a
         GF_ASSERT (this);
7f4c2a
@@ -837,6 +840,15 @@ glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx)
7f4c2a
 
7f4c2a
         new_event->ctx = new_ev_ctx;
7f4c2a
 
7f4c2a
+        ret = dict_get_str (ev_ctx->vols, "hostname_in_cluster",
7f4c2a
+                            &hostname);
7f4c2a
+        if (ret || !hostname) {
7f4c2a
+                gf_log (this->name, GF_LOG_DEBUG,
7f4c2a
+                        "Unable to fetch local hostname from peer");
7f4c2a
+        } else
7f4c2a
+                strncpy (local_node_hostname, hostname,
7f4c2a
+                         sizeof(local_node_hostname));
7f4c2a
+
7f4c2a
         glusterd_friend_sm_inject_event (new_event);
7f4c2a
         new_event = NULL;
7f4c2a
 
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
7f4c2a
index fec7494..e5a7cac 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
7f4c2a
@@ -66,7 +66,7 @@
7f4c2a
 
7f4c2a
 #include "lvm-defaults.h"
7f4c2a
 
7f4c2a
-char snap_mount_folder[PATH_MAX];
7f4c2a
+char snap_mount_dir[PATH_MAX];
7f4c2a
 struct snap_create_args_ {
7f4c2a
         xlator_t             *this;
7f4c2a
         dict_t               *dict;
7f4c2a
@@ -4558,7 +4558,7 @@ glusterd_snap_brick_create (glusterd_volinfo_t *snap_volinfo,
7f4c2a
         GF_ASSERT (brickinfo);
7f4c2a
 
7f4c2a
         snprintf (snap_brick_mount_path, sizeof (snap_brick_mount_path),
7f4c2a
-                  "%s/%s/brick%d",  snap_mount_folder, snap_volinfo->volname,
7f4c2a
+                  "%s/%s/brick%d",  snap_mount_dir, snap_volinfo->volname,
7f4c2a
                   brick_count + 1);
7f4c2a
 
7f4c2a
         ret = mkdir_p (snap_brick_mount_path, 0777, _gf_true);
7f4c2a
@@ -4748,7 +4748,7 @@ glusterd_add_brick_to_snap_volume (dict_t *dict, dict_t *rsp_dict,
7f4c2a
          * <snap-uuid>/<original-brick#>/snap-brick-dir *
7f4c2a
          */
7f4c2a
         snprintf (snap_brick_path, sizeof(snap_brick_path),
7f4c2a
-                  "%s/%s/brick%d%s", snap_mount_folder,
7f4c2a
+                  "%s/%s/brick%d%s", snap_mount_dir,
7f4c2a
                   snap_vol->volname, brick_count+1,
7f4c2a
                   snap_brick_dir);
7f4c2a
 
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
7f4c2a
index 86b22f8..0721110 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
7f4c2a
@@ -9763,3 +9763,34 @@ glusterd_disallow_op_for_tier (glusterd_volinfo_t *volinfo, glusterd_op_t op,
7f4c2a
 out:
7f4c2a
         return ret;
7f4c2a
 }
7f4c2a
+
7f4c2a
+int32_t
7f4c2a
+glusterd_count_connected_peers (int32_t *count)
7f4c2a
+{
7f4c2a
+        glusterd_peerinfo_t  *peerinfo  = NULL;
7f4c2a
+        glusterd_conf_t      *conf      = NULL;
7f4c2a
+        int32_t               ret       = -1;
7f4c2a
+        xlator_t             *this      = NULL;
7f4c2a
+
7f4c2a
+        this = THIS;
7f4c2a
+        GF_VALIDATE_OR_GOTO ("glusterd", this, out);
7f4c2a
+        conf = this->private;
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, conf, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, count, out);
7f4c2a
+
7f4c2a
+        *count = 1;
7f4c2a
+
7f4c2a
+        rcu_read_lock ();
7f4c2a
+        cds_list_for_each_entry_rcu (peerinfo, &conf->peers, uuid_list) {
7f4c2a
+                /* Find peer who is connected and is a friend */
7f4c2a
+                if ((peerinfo->connected) &&
7f4c2a
+                     (peerinfo->state.state == GD_FRIEND_STATE_BEFRIENDED)) {
7f4c2a
+                        (*count)++;
7f4c2a
+                }
7f4c2a
+        }
7f4c2a
+        rcu_read_unlock ();
7f4c2a
+
7f4c2a
+        ret = 0;
7f4c2a
+out:
7f4c2a
+        return ret;
7f4c2a
+}
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h
7f4c2a
index 246d3ed..d617f60 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
7f4c2a
@@ -663,5 +663,7 @@ glusterd_defrag_rpc_put (glusterd_defrag_info_t *defrag);
7f4c2a
 int
7f4c2a
 glusterd_disallow_op_for_tier (glusterd_volinfo_t *volinfo, glusterd_op_t op,
7f4c2a
                                int cmd);
7f4c2a
+int32_t
7f4c2a
+glusterd_count_connected_peers (int32_t *count);
7f4c2a
 
7f4c2a
 #endif
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
7f4c2a
index 02d59ed..b8ca6be 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
7f4c2a
@@ -1740,6 +1740,12 @@ struct volopt_map_entry glusterd_volopt_map[] = {
7f4c2a
           .voltype     = "features/trash",
7f4c2a
           .op_version  = GD_OP_VERSION_3_7_0,
7f4c2a
         },
7f4c2a
+        { .key         = GLUSTERD_SHARED_STORAGE_KEY,
7f4c2a
+          .voltype     = "mgmt/glusterd",
7f4c2a
+          .value       = "disable",
7f4c2a
+          .type        = GLOBAL_DOC,
7f4c2a
+          .op_version  = GD_OP_VERSION_3_7_1,
7f4c2a
+        },
7f4c2a
 
7f4c2a
 #if USE_GFDB /* no GFDB means tiering is disabled */
7f4c2a
         /* tier translator - global tunables */
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c
7f4c2a
index 3735c62..54a5fbd 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd.c
7f4c2a
@@ -66,7 +66,8 @@ extern struct rpcsvc_program gd_svc_cli_trusted_progs;
7f4c2a
 extern struct rpc_clnt_program gd_brick_prog;
7f4c2a
 extern struct rpcsvc_program glusterd_mgmt_hndsk_prog;
7f4c2a
 
7f4c2a
-extern char snap_mount_folder[PATH_MAX];
7f4c2a
+extern char snap_mount_dir[PATH_MAX];
7f4c2a
+char ss_brick_path[PATH_MAX];
7f4c2a
 
7f4c2a
 rpcsvc_cbk_program_t glusterd_cbk_prog = {
7f4c2a
         .progname  = "Gluster Callback",
7f4c2a
@@ -1119,18 +1120,18 @@ glusterd_stop_uds_listener (xlator_t *this)
7f4c2a
 }
7f4c2a
 
7f4c2a
 static int
7f4c2a
-glusterd_init_snap_folder (xlator_t *this)
7f4c2a
+glusterd_find_correct_var_run_dir (xlator_t *this, char *var_run_dir)
7f4c2a
 {
7f4c2a
         int             ret = -1;
7f4c2a
         struct stat     buf = {0,};
7f4c2a
 
7f4c2a
-        GF_ASSERT (this);
7f4c2a
+        GF_VALIDATE_OR_GOTO ("glusterd", this, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, var_run_dir, out);
7f4c2a
 
7f4c2a
-        /* Snapshot volumes are mounted under /var/run/gluster/snaps folder.
7f4c2a
-         * But /var/run is normally a symbolic link to /run folder, which
7f4c2a
+        /* /var/run is normally a symbolic link to /run dir, which
7f4c2a
          * creates problems as the entry point in the mtab for the mount point
7f4c2a
          * and glusterd maintained entry point will be different. Therefore
7f4c2a
-         * identify the correct run folder and use it for snap volume mounting.
7f4c2a
+         * identify the correct run dir and use it
7f4c2a
          */
7f4c2a
         ret = lstat (GLUSTERD_VAR_RUN_DIR, &buf;;
7f4c2a
         if (ret != 0) {
7f4c2a
@@ -1140,20 +1141,38 @@ glusterd_init_snap_folder (xlator_t *this)
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
 
7f4c2a
-        /* If /var/run is symlink then use /run folder */
7f4c2a
+        /* If /var/run is symlink then use /run dir */
7f4c2a
         if (S_ISLNK (buf.st_mode)) {
7f4c2a
-                strcpy (snap_mount_folder, GLUSTERD_RUN_DIR);
7f4c2a
+                strcpy (var_run_dir, GLUSTERD_RUN_DIR);
7f4c2a
         } else {
7f4c2a
-                strcpy (snap_mount_folder, GLUSTERD_VAR_RUN_DIR);
7f4c2a
+                strcpy (var_run_dir, GLUSTERD_VAR_RUN_DIR);
7f4c2a
         }
7f4c2a
 
7f4c2a
-        strcat (snap_mount_folder, GLUSTERD_DEFAULT_SNAPS_BRICK_DIR);
7f4c2a
+        ret = 0;
7f4c2a
+out:
7f4c2a
+        return ret;
7f4c2a
+}
7f4c2a
+
7f4c2a
+static int
7f4c2a
+glusterd_init_var_run_dirs (xlator_t *this, char *var_run_dir,
7f4c2a
+                            char *dir_to_be_created)
7f4c2a
+{
7f4c2a
+        int             ret                = -1;
7f4c2a
+        struct stat     buf                = {0,};
7f4c2a
+        char            abs_path[PATH_MAX] = {0, };
7f4c2a
+
7f4c2a
+        GF_VALIDATE_OR_GOTO ("glusterd", this, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, var_run_dir, out);
7f4c2a
+        GF_VALIDATE_OR_GOTO (this->name, dir_to_be_created, out);
7f4c2a
+
7f4c2a
+        snprintf (abs_path, sizeof(abs_path), "%s%s",
7f4c2a
+                  var_run_dir, dir_to_be_created);
7f4c2a
 
7f4c2a
-        ret = stat (snap_mount_folder, &buf;;
7f4c2a
+        ret = stat (abs_path, &buf;;
7f4c2a
         if ((ret != 0) && (ENOENT != errno)) {
7f4c2a
                 gf_log (this->name, GF_LOG_ERROR,
7f4c2a
                         "stat fails on %s, exiting. (errno = %d)",
7f4c2a
-                        snap_mount_folder, errno);
7f4c2a
+                        abs_path, errno);
7f4c2a
                 ret = -1;
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
@@ -1161,19 +1180,19 @@ glusterd_init_snap_folder (xlator_t *this)
7f4c2a
         if ((!ret) && (!S_ISDIR(buf.st_mode))) {
7f4c2a
                 gf_log (this->name, GF_LOG_CRITICAL,
7f4c2a
                         "Provided snap path %s is not a directory,"
7f4c2a
-                        "exiting", snap_mount_folder);
7f4c2a
+                        "exiting", abs_path);
7f4c2a
                 ret = -1;
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
 
7f4c2a
         if ((-1 == ret) && (ENOENT == errno)) {
7f4c2a
-                /* Create missing folders */
7f4c2a
-                ret = mkdir_p (snap_mount_folder, 0777, _gf_true);
7f4c2a
+                /* Create missing dirs */
7f4c2a
+                ret = mkdir_p (abs_path, 0777, _gf_true);
7f4c2a
 
7f4c2a
                 if (-1 == ret) {
7f4c2a
                         gf_log (this->name, GF_LOG_CRITICAL,
7f4c2a
                                 "Unable to create directory %s"
7f4c2a
-                                " ,errno = %d", snap_mount_folder, errno);
7f4c2a
+                                " ,errno = %d", abs_path, errno);
7f4c2a
                         goto out;
7f4c2a
                 }
7f4c2a
         }
7f4c2a
@@ -1250,21 +1269,22 @@ out:
7f4c2a
 int
7f4c2a
 init (xlator_t *this)
7f4c2a
 {
7f4c2a
-        int32_t            ret               = -1;
7f4c2a
-        rpcsvc_t          *rpc               = NULL;
7f4c2a
-        rpcsvc_t          *uds_rpc           = NULL;
7f4c2a
-        glusterd_conf_t   *conf              = NULL;
7f4c2a
-        data_t            *dir_data          = NULL;
7f4c2a
-        struct stat        buf               = {0,};
7f4c2a
-        char               storedir [PATH_MAX] = {0,};
7f4c2a
-        char               workdir [PATH_MAX] = {0,};
7f4c2a
-        char               cmd_log_filename [PATH_MAX] = {0,};
7f4c2a
-        int                first_time        = 0;
7f4c2a
-        char              *mountbroker_root  = NULL;
7f4c2a
-        int                i                 = 0;
7f4c2a
-        int                total_transport   = 0;
7f4c2a
-        char              *valgrind_str      = NULL;
7f4c2a
-        char              *transport_type    = NULL;
7f4c2a
+        int32_t            ret                        = -1;
7f4c2a
+        rpcsvc_t          *rpc                        = NULL;
7f4c2a
+        rpcsvc_t          *uds_rpc                    = NULL;
7f4c2a
+        glusterd_conf_t   *conf                       = NULL;
7f4c2a
+        data_t            *dir_data                   = NULL;
7f4c2a
+        struct stat        buf                        = {0,};
7f4c2a
+        char               storedir[PATH_MAX]         = {0,};
7f4c2a
+        char               workdir[PATH_MAX]          = {0,};
7f4c2a
+        char               cmd_log_filename[PATH_MAX] = {0,};
7f4c2a
+        int                first_time                 = 0;
7f4c2a
+        char              *mountbroker_root           = NULL;
7f4c2a
+        int                i                          = 0;
7f4c2a
+        int                total_transport            = 0;
7f4c2a
+        char              *valgrind_str               = NULL;
7f4c2a
+        char              *transport_type             = NULL;
7f4c2a
+        char               var_run_dir[PATH_MAX]      = {0,};
7f4c2a
 
7f4c2a
 #ifndef GF_DARWIN_HOST_OS
7f4c2a
         {
7f4c2a
@@ -1326,14 +1346,35 @@ init (xlator_t *this)
7f4c2a
         gf_log (this->name, GF_LOG_INFO, "Using %s as working directory",
7f4c2a
                 workdir);
7f4c2a
 
7f4c2a
-        ret = glusterd_init_snap_folder (this);
7f4c2a
+        ret = glusterd_find_correct_var_run_dir (this, var_run_dir);
7f4c2a
+        if (ret) {
7f4c2a
+                gf_log (this->name, GF_LOG_CRITICAL, "Unable to find "
7f4c2a
+                        "the correct var run dir");
7f4c2a
+                exit (1);
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        ret = glusterd_init_var_run_dirs (this, var_run_dir,
7f4c2a
+                                      GLUSTERD_DEFAULT_SNAPS_BRICK_DIR);
7f4c2a
+        if (ret) {
7f4c2a
+                gf_log (this->name, GF_LOG_CRITICAL, "Unable to create "
7f4c2a
+                        "snap backend dir");
7f4c2a
+                exit (1);
7f4c2a
+        }
7f4c2a
 
7f4c2a
+        snprintf (snap_mount_dir, sizeof(snap_mount_dir), "%s%s",
7f4c2a
+                  var_run_dir, GLUSTERD_DEFAULT_SNAPS_BRICK_DIR);
7f4c2a
+
7f4c2a
+        ret = glusterd_init_var_run_dirs (this, var_run_dir,
7f4c2a
+                                      GLUSTER_SHARED_STORAGE_BRICK_DIR);
7f4c2a
         if (ret) {
7f4c2a
                 gf_log (this->name, GF_LOG_CRITICAL, "Unable to create "
7f4c2a
-                        "snap backend folder");
7f4c2a
+                        "shared storage brick");
7f4c2a
                 exit (1);
7f4c2a
         }
7f4c2a
 
7f4c2a
+        snprintf (ss_brick_path, sizeof(ss_brick_path), "%s%s",
7f4c2a
+                  var_run_dir, GLUSTER_SHARED_STORAGE_BRICK_DIR);
7f4c2a
+
7f4c2a
         snprintf (cmd_log_filename, PATH_MAX, "%s/cmd_history.log",
7f4c2a
                   DEFAULT_LOG_FILE_DIRECTORY);
7f4c2a
         ret = gf_cmd_log_init (cmd_log_filename);
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h
7f4c2a
index ab62952..5b5edfd 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd.h
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd.h
7f4c2a
@@ -52,6 +52,8 @@
7f4c2a
 #define GEO_CONF_MAX_OPT_VALS           6
7f4c2a
 #define GLUSTERD_CREATE_HOOK_SCRIPT     "/hooks/1/gsync-create/post/" \
7f4c2a
                                         "S56glusterd-geo-rep-create-post.sh"
7f4c2a
+#define GLUSTER_SHARED_STORAGE          "gluster_shared_storage"
7f4c2a
+#define GLUSTERD_SHARED_STORAGE_KEY     "cluster.enable-shared-storage"
7f4c2a
 
7f4c2a
 #define GANESHA_HA_CONF  CONFDIR "/ganesha-ha.conf"
7f4c2a
 #define GLUSTERD_SNAPS_MAX_HARD_LIMIT 256
7f4c2a
@@ -512,6 +514,7 @@ typedef enum {
7f4c2a
 #define GLUSTERD_VOL_SNAP_DIR_PREFIX "snaps"
7f4c2a
 
7f4c2a
 #define GLUSTERD_DEFAULT_SNAPS_BRICK_DIR        "/gluster/snaps"
7f4c2a
+#define GLUSTER_SHARED_STORAGE_BRICK_DIR        "/gluster/ss_brick"
7f4c2a
 #define GLUSTERD_VAR_RUN_DIR                    "/var/run"
7f4c2a
 #define GLUSTERD_RUN_DIR                        "/run"
7f4c2a
 
7f4c2a
-- 
7f4c2a
1.9.3
7f4c2a