diff options
-rw-r--r-- | libglusterfs/src/common-utils.c | 62 | ||||
-rw-r--r-- | libglusterfs/src/common-utils.h | 2 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-rebalance.c | 18 |
3 files changed, 69 insertions, 13 deletions
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 7e7eb461409..4b8807be1eb 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -58,6 +58,68 @@ struct dnscache6 { }; +/* works similar to mkdir(1) -p. + * @start returns the point in path from which components were created + * @start is -1 if the entire path existed before. + */ +int +mkdir_p (char *path, mode_t mode, gf_boolean_t allow_symlinks, int *start) +{ + int i = 0; + int ret = -1; + char dir[PATH_MAX] = {0,}; + struct stat stbuf = {0,}; + int created = -1; + + strcpy (dir, path); + i = (dir[0] == '/')? 1: 0; + do { + if (path[i] != '/' && path[i] != '\0') + continue; + + dir[i] = '\0'; + ret = mkdir (dir, mode); + if (ret && errno != EEXIST) { + gf_log ("", GF_LOG_ERROR, "Failed due to reason %s", + strerror (errno)); + goto out; + } + + if (ret && errno == EEXIST) + created = i; + + if (ret && errno == EEXIST && !allow_symlinks) { + ret = lstat (dir, &stbuf); + if (ret) + goto out; + + if (S_ISLNK (stbuf.st_mode)) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "%s is a symlink", + dir); + goto out; + } + } + dir[i] = '/'; + + } while (path[i++] != '\0'); + + ret = stat (dir, &stbuf); + if (ret || !S_ISDIR (stbuf.st_mode)) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "Failed to create directory, " + "possibly some of the components were not directories"); + goto out; + } + + ret = 0; + if (start) + *start = created; +out: + + return ret; +} + int log_base2 (unsigned long x) { diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index d5880291250..69d57c8d431 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -392,6 +392,8 @@ memdup (const void *ptr, size_t size) return newptr; } +int +mkdir_p (char *path, mode_t mode, gf_boolean_t allow_symlinks, int *start); /* * rounds up nr to power of two. If nr is already a power of two, just returns * nr diff --git a/xlators/mgmt/glusterd/src/glusterd-rebalance.c b/xlators/mgmt/glusterd/src/glusterd-rebalance.c index 010ff599cf9..686b9b36db3 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rebalance.c +++ b/xlators/mgmt/glusterd/src/glusterd-rebalance.c @@ -224,7 +224,6 @@ glusterd_handle_defrag_start (glusterd_volinfo_t *volinfo, char *op_errstr, runner_t runner = {0,}; glusterd_conf_t *priv = NULL; char defrag_path[PATH_MAX]; - struct stat buf = {0,}; char sockfile[PATH_MAX] = {0,}; char pidfile[PATH_MAX] = {0,}; char logfile[PATH_MAX] = {0,}; @@ -263,18 +262,11 @@ glusterd_handle_defrag_start (glusterd_volinfo_t *volinfo, char *op_errstr, glusterd_store_perform_node_state_store (volinfo); GLUSTERD_GET_DEFRAG_DIR (defrag_path, volinfo, priv); - ret = stat (defrag_path, &buf); - if (ret && (errno == ENOENT)) { - runinit (&runner); - runner_add_args (&runner, "mkdir", "-p", defrag_path, NULL); - ret = runner_run_reuse (&runner); - if (ret) { - runner_log (&runner, "glusterd", GF_LOG_DEBUG, - "command failed"); - runner_end (&runner); - goto out; - } - runner_end (&runner); + ret = mkdir_p (defrag_path, 0777, 0, NULL); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to create " + "directory %s", defrag_path); + goto out; } GLUSTERD_GET_DEFRAG_SOCK_FILE (sockfile, volinfo, priv); |