diff options
author | Amar Tumballi <amar@gluster.com> | 2010-08-09 05:38:46 +0000 |
---|---|---|
committer | Anand V. Avati <avati@dev.gluster.com> | 2010-08-11 22:24:32 -0700 |
commit | 0b501ac95edc0ef5945228eb47e6482cfc4efa41 (patch) | |
tree | 58fa16eb100868a65e754f704b2a19817250ca91 /xlators/mgmt | |
parent | 6ff316dca7c9eebab14e71b6ad0908c2e45a5ee2 (diff) |
'gluster volume rebalance' related fixes
Signed-off-by: Amar Tumballi <amar@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 1307 (gluster volume defrag <VOLNAME> status)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1307
Diffstat (limited to 'xlators/mgmt')
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 309 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-mem-types.h | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 37 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd3_1-mops.c | 2 |
4 files changed, 313 insertions, 36 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index a8b334c3dd9..ce4c661826e 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -594,7 +594,203 @@ out: return ret; } +int +glusterd_check_and_rebalance (glusterd_volinfo_t *volinfo, char *dir) +{ + int ret = -1; + int dst_fd = -1; + int src_fd = -1; + DIR *fd = NULL; + glusterd_defrag_info_t *defrag = NULL; + struct dirent *entry = NULL; + struct stat stbuf = {0,}; + struct stat new_stbuf = {0,}; + char full_path[1024] = {0,}; + char tmp_filename[1024] = {0,}; + char value[128] = {0,}; + + defrag = volinfo->defrag; + if (!defrag) + goto out; + + fd = opendir (dir); + if (!fd) + goto out; + + do { + entry = readdir (fd); + if (!entry) + break; + + if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, "..")) + continue; + + snprintf (full_path, 1024, "%s/%s", dir, entry->d_name); + + ret = stat (full_path, &stbuf); + if (ret == -1) + continue; + + if (S_ISDIR (stbuf.st_mode)) { + //getfattr -n trusted.distribute.fix.layout "$path" ; + getxattr (full_path, "trusted.distribute.fix.layout", + &value, 128); + + ret = glusterd_check_and_rebalance (volinfo, full_path); + } + if (S_ISREG (stbuf.st_mode) && ((stbuf.st_mode & 01000) == 01000)) { + /* TODO: run the defrag */ + snprintf (tmp_filename, 1024, "%s/.%s.gfs%zu", dir, + entry->d_name, stbuf.st_size); + + dst_fd = creat (tmp_filename, (stbuf.st_mode & ~01000)); + if (dst_fd == -1) + continue; + + src_fd = open (full_path, O_RDONLY); + if (src_fd == -1) { + close (dst_fd); + continue; + } + + while (1) { + ret = read (src_fd, defrag->databuf, 131072); + if (!ret || (ret < 0)) { + close (dst_fd); + close (src_fd); + break; + } + ret = write (dst_fd, defrag->databuf, ret); + if (ret < 0) { + close (dst_fd); + close (src_fd); + break; + } + } + + ret = stat (full_path, &new_stbuf); + if (ret < 0) + continue; + if (new_stbuf.st_mtime != stbuf.st_mtime) + continue; + + ret = rename (tmp_filename, full_path); + if (ret != -1) { + LOCK (&defrag->lock); + { + defrag->total_files += 1; + defrag->total_data += stbuf.st_size; + } + UNLOCK (&defrag->lock); + } + } + ret = 0; + + LOCK (&defrag->lock); + { + if (S_ISREG (stbuf.st_mode)) + defrag->num_files_lookedup += 1; + if (volinfo->defrag_status == GF_DEFRAG_STATUS_STOPED) + ret = 1; + } + UNLOCK (&defrag->lock); + if (ret) + break; + + /* Write the full 'glusterfs-defrag' here */ + + } while (1); + + closedir (fd); + + if (!entry) + ret = 0; +out: + return ret; +} + +void * +glusterd_defrag_start (void *data) +{ + glusterd_volinfo_t *volinfo = data; + glusterd_defrag_info_t *defrag = NULL; + char cmd_str[1024] = {0,}; + int ret = -1; + + /* TODO: make it more generic.. */ + defrag = volinfo->defrag; + if (!defrag) + goto out; + + ret = glusterd_check_and_rebalance (volinfo, defrag->mount); + + /* TODO: This should run in a thread, and finish the thread when + the task is complete. While defrag is running, keep updating + files */ + + volinfo->defrag_status = GF_DEFRAG_STATUS_COMPLETE; + volinfo->rebalance_files = defrag->total_files; + volinfo->rebalance_data = defrag->total_data; + volinfo->lookedup_files = defrag->num_files_lookedup; +out: + gf_log ("defrag", GF_LOG_NORMAL, "defrag on %s complete", + defrag->mount); + + snprintf (cmd_str, 1024, "umount %s", defrag->mount); + system (cmd_str); + volinfo->defrag = NULL; + LOCK_DESTROY (&defrag->lock); + GF_FREE (defrag); + + return NULL; +} + +int +glusterd_defrag_stop (glusterd_volinfo_t *volinfo, + gf1_cli_defrag_vol_rsp *rsp) +{ + /* TODO: set a variaeble 'stop_defrag' here, it should be checked + in defrag loop */ + if (!volinfo || !volinfo->defrag) + goto out; + + LOCK (&volinfo->defrag->lock); + { + volinfo->defrag_status = GF_DEFRAG_STATUS_STOPED; + rsp->files = volinfo->defrag->total_files; + rsp->size = volinfo->defrag->total_data; + } + UNLOCK (&volinfo->defrag->lock); + rsp->op_ret = 0; +out: + return 0; +} + +int +glusterd_defrag_status_get (glusterd_volinfo_t *volinfo, + gf1_cli_defrag_vol_rsp *rsp) +{ + if (!volinfo) + goto out; + + if (volinfo->defrag) { + LOCK (&volinfo->defrag->lock); + { + rsp->files = volinfo->defrag->total_files; + rsp->size = volinfo->defrag->total_data; + rsp->lookedup_files = volinfo->defrag->num_files_lookedup; + } + UNLOCK (&volinfo->defrag->lock); + } else { + rsp->files = volinfo->rebalance_files; + rsp->size = volinfo->rebalance_data; + rsp->lookedup_files = volinfo->lookedup_files; + } + rsp->op_ret = 0; +out: + return 0; +} int glusterd_handle_defrag_volume (rpcsvc_request_t *req) @@ -603,7 +799,9 @@ glusterd_handle_defrag_volume (rpcsvc_request_t *req) gf1_cli_defrag_vol_req cli_req = {0,}; glusterd_conf_t *priv = NULL; char cmd_str[4096] = {0,}; - glusterd_volinfo_t *tmp_volinfo = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_defrag_info_t *defrag = NULL; + gf1_cli_defrag_vol_rsp rsp = {0,}; GF_ASSERT (req); @@ -617,46 +815,87 @@ glusterd_handle_defrag_volume (rpcsvc_request_t *req) gf_log ("glusterd", GF_LOG_NORMAL, "Received defrag volume on %s", cli_req.volname); - if (glusterd_volinfo_find(cli_req.volname, &tmp_volinfo)) { - gf_log ("glusterd", GF_LOG_NORMAL, "Received defrag on invalid" - " volname %s", cli_req.volname); - goto out; - } - - glusterd_op_set_op (GD_OP_DEFRAG_VOLUME); + rsp.volname = cli_req.volname; + rsp.op_ret = -1; + if (glusterd_volinfo_find(cli_req.volname, &volinfo)) { + gf_log ("glusterd", GF_LOG_NORMAL, "Received defrag on invalid" + " volname %s", cli_req.volname); + goto out; + } - glusterd_op_set_ctx (GD_OP_DEFRAG_VOLUME, cli_req.volname); + if (volinfo->status != GLUSTERD_STATUS_STARTED) { + gf_log ("glusterd", GF_LOG_NORMAL, "Received defrag on stopped" + " volname %s", cli_req.volname); + goto out; + } - /* TODO: make it more generic.. */ - /* Create a directory, mount glusterfs over it, start glusterfs-defrag */ - snprintf (cmd_str, 4096, "mkdir -p %s/mount/%s", - priv->workdir, cli_req.volname); - ret = system (cmd_str); - - if (ret) { - gf_log("glusterd", GF_LOG_DEBUG, "command: %s failed", cmd_str); - goto out; - } - - snprintf (cmd_str, 4096, "glusterfs -f %s/vols/%s/%s-tcp.vol " - "--xlator-option dht0.unhashed-sticky-bit=yes " - "--xlator-option dht0.lookup-unhashed=on %s/mount/%s", - priv->workdir, cli_req.volname, cli_req.volname, - priv->workdir, cli_req.volname); - ret = system (cmd_str); + switch (cli_req.cmd) { + case GF_DEFRAG_CMD_START: + { + if (volinfo->defrag) { + gf_log ("glusterd", GF_LOG_DEBUG, + "defrag on volume %s already started", + cli_req.volname); + goto out; + } - if (ret) { - gf_log("glusterd", GF_LOG_DEBUG, "command: %s failed", cmd_str); - goto out; - } + volinfo->defrag = GF_CALLOC (1, sizeof (glusterd_defrag_info_t), + gf_gld_mt_defrag_info); + if (!volinfo->defrag) + goto out; + + defrag = volinfo->defrag; + + LOCK_INIT (&defrag->lock); + snprintf (defrag->mount, 1024, "%s/mount/%s", + priv->workdir, cli_req.volname); + /* Create a directory, mount glusterfs over it, start glusterfs-defrag */ + snprintf (cmd_str, 4096, "mkdir -p %s", defrag->mount); + ret = system (cmd_str); + + if (ret) { + gf_log("glusterd", GF_LOG_DEBUG, "command: %s failed", cmd_str); + goto out; + } - snprintf (cmd_str, 4096, "glusterfs-defrag %s/mount/%s", - priv->workdir, cli_req.volname); - ret = system (cmd_str); + snprintf (cmd_str, 4096, "glusterfs -f %s/vols/%s/%s-tcp.vol " + "--xlator-option dht0.unhashed-sticky-bit=yes " + "--xlator-option dht0.lookup-unhashed=yes " + "--volume-name quickread %s", + priv->workdir, cli_req.volname, cli_req.volname, + defrag->mount); + ret = system (cmd_str); - if (ret) - gf_log("glusterd", GF_LOG_DEBUG, "command: %s failed",cmd_str); + if (ret) { + gf_log("glusterd", GF_LOG_DEBUG, "command: %s failed", cmd_str); + goto out; + } + rsp.op_ret = 0; + ret = pthread_create (&defrag->th, NULL, glusterd_defrag_start, + volinfo); + if (ret) { + snprintf (cmd_str, 1024, "umount -l %s", defrag->mount); + ret = system (cmd_str); + rsp.op_ret = -1; + } + break; + } + case GF_DEFRAG_CMD_STOP: + ret = glusterd_defrag_stop (volinfo, &rsp); + break; + case GF_DEFRAG_CMD_STATUS: + ret = glusterd_defrag_status_get (volinfo, &rsp); + break; + default: + break; + } + if (ret) + gf_log("glusterd", GF_LOG_DEBUG, "command: %s failed",cmd_str); out: + + ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL, + gf_xdr_serialize_cli_defrag_vol_rsp); + return ret; } diff --git a/xlators/mgmt/glusterd/src/glusterd-mem-types.h b/xlators/mgmt/glusterd/src/glusterd-mem-types.h index 8df94163d61..a5d7c4f27f2 100644 --- a/xlators/mgmt/glusterd/src/glusterd-mem-types.h +++ b/xlators/mgmt/glusterd/src/glusterd-mem-types.h @@ -54,6 +54,7 @@ enum gf_gld_mem_types_ { gf_gld_mt_ifreq, gf_gld_mt_store_handle_t, gf_gld_mt_store_iter_t, + gf_gld_mt_defrag_info, gf_gld_mt_end }; #endif diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 368c0a6847a..dce3275e73c 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -25,7 +25,10 @@ #include "config.h" #endif +#include <sys/types.h> +#include <dirent.h> #include <pthread.h> + #include "uuid.h" #include "rpc-clnt.h" @@ -84,6 +87,33 @@ struct glusterd_brickinfo { typedef struct glusterd_brickinfo glusterd_brickinfo_t; +struct gf_defrag_brickinfo_ { + char *name; + int files; + int size; +}; + +typedef enum gf_defrag_status_ { + GF_DEFRAG_STATUS_NOT_STARTED, + GF_DEFRAG_STATUS_STARTED, + GF_DEFRAG_STATUS_STOPED, + GF_DEFRAG_STATUS_COMPLETE, +} gf_defrag_status_t; + +struct glusterd_defrag_info_ { + uint64_t total_files; + uint64_t total_data; + uint64_t num_files_lookedup; + gf_lock_t lock; + pthread_t th; + char mount[1024]; + char databuf[131072]; + struct gf_defrag_brickinfo_ *bricks; /* volinfo->brick_count */ +}; + + +typedef struct glusterd_defrag_info_ glusterd_defrag_info_t; + struct glusterd_volinfo_ { char volname[GLUSTERD_MAX_VOLUME_NAME]; int type; @@ -94,6 +124,13 @@ struct glusterd_volinfo_ { int sub_count; int port; glusterd_store_handle_t *shandle; + + /* Defrag/rebalance related */ + gf_defrag_status_t defrag_status; + uint64_t rebalance_files; + uint64_t rebalance_data; + uint64_t lookedup_files; + glusterd_defrag_info_t *defrag; }; typedef struct glusterd_volinfo_ glusterd_volinfo_t; diff --git a/xlators/mgmt/glusterd/src/glusterd3_1-mops.c b/xlators/mgmt/glusterd/src/glusterd3_1-mops.c index 86d09194e11..59933e8ac7d 100644 --- a/xlators/mgmt/glusterd/src/glusterd3_1-mops.c +++ b/xlators/mgmt/glusterd/src/glusterd3_1-mops.c @@ -1199,7 +1199,7 @@ rpcsvc_actor_t glusterd1_mgmt_actors[] = { [GD_MGMT_COMMIT_OP] = { "COMMIT_OP", GD_MGMT_COMMIT_OP, glusterd_handle_rpc_msg, NULL, NULL}, [GD_MGMT_CLI_PROBE] = { "CLI_PROBE", GD_MGMT_CLI_PROBE, glusterd_handle_rpc_msg, NULL, NULL}, [GD_MGMT_CLI_CREATE_VOLUME] = { "CLI_CREATE_VOLUME", GD_MGMT_CLI_CREATE_VOLUME, glusterd_handle_rpc_msg, NULL,NULL}, - [GD_MGMT_CLI_DEFRAG_VOLUME] = { "CLI_DEFRAG_VOLUME", GD_MGMT_CLI_DEFRAG_VOLUME, glusterd_handle_rpc_msg, NULL,NULL}, + [GD_MGMT_CLI_DEFRAG_VOLUME] = { "CLI_DEFRAG_VOLUME", GD_MGMT_CLI_DEFRAG_VOLUME, glusterd_handle_defrag_volume, NULL,NULL}, [GD_MGMT_CLI_DEPROBE] = { "FRIEND_REMOVE", GD_MGMT_CLI_DEPROBE, glusterd_handle_rpc_msg, NULL, NULL}, [GD_MGMT_CLI_LIST_FRIENDS] = { "LIST_FRIENDS", GD_MGMT_CLI_LIST_FRIENDS, glusterd_handle_rpc_msg, NULL, NULL}, [GD_MGMT_CLI_START_VOLUME] = { "START_VOLUME", GD_MGMT_CLI_START_VOLUME, glusterd_handle_rpc_msg, NULL, NULL}, |