diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-utils.c')
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 229 |
1 files changed, 144 insertions, 85 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 8e28a7a1b..f04792c7b 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -4367,115 +4367,158 @@ glusterd_rb_check_bricks (glusterd_volinfo_t *volinfo, return 0; } -int -glusterd_brick_create_path (char *host, char *path, uuid_t uuid, mode_t mode, - char **op_errstr) +/*path needs to be absolute; works only on gfid, volume-id*/ +static int +glusterd_is_uuid_present (char *path, char *xattr, gf_boolean_t *present) { - int ret = -1; - char msg[2048] = {0}; - struct stat st_buf = {0}; - uuid_t gfid = {0,}; - uuid_t old_uuid = {0,}; - - ret = stat (path, &st_buf); - if ((!ret) && (!S_ISDIR (st_buf.st_mode))) { - snprintf (msg, sizeof (msg), "brick %s:%s, " - "path %s is not a directory", host, path, path); - gf_log ("", GF_LOG_ERROR, "%s", msg); - ret = -1; + GF_ASSERT (path); + GF_ASSERT (xattr); + GF_ASSERT (present); + + int ret = -1; + uuid_t uid = {0,}; + + if (!path || !xattr || !present) goto out; - } else if (!ret) { - goto check_xattr; + + ret = sys_lgetxattr (path, xattr, &uid, 16); + if (ret < 0 && errno != ENODATA) { + goto out; + + } else if (ret >= 0) { + *present = _gf_true; + } else { - ret = mkdir (path, mode); - if (ret) { - snprintf (msg, sizeof (msg), "brick: %s:%s, path " - "creation failed, reason: %s", - host, path, strerror(errno)); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *present = _gf_false; + } + + ret = 0; +out: + return ret; +} + +/*path needs to be absolute*/ +static int +glusterd_is_path_in_use (char *path, gf_boolean_t *in_use, char **op_errstr) +{ + int i = 0; + int ret = -1; + gf_boolean_t used = _gf_false; + char dir[PATH_MAX] = {0,}; + char *curdir = NULL; + char msg[2048] = {0}; + char *keys[3] = {GFID_XATTR_KEY, + GF_XATTR_VOL_ID_KEY, + NULL}; + + GF_ASSERT (path); + if (!path) + goto out; + + strcpy (dir, path); + curdir = dir; + do { + for (i = 0; !used && keys[i]; i++) { + ret = glusterd_is_uuid_present (curdir, keys[i], &used); + if (ret) + goto out; + } + + if (used) + break; + + curdir = dirname (dir); + if (!strcmp (curdir, ".")) goto out; - } else { - goto check_xattr; + + + } while (strcmp (curdir, "/")); + + if (!strcmp (curdir, "/")) { + for (i = 0; !used && keys[i]; i++) { + ret = glusterd_is_uuid_present (curdir, keys[i], &used); + if (ret) + goto out; } } -/* To check if filesystem is read-only - and if it supports extended attributes */ -check_xattr: + ret = 0; + *in_use = used; +out: + if (ret) { + snprintf (msg, sizeof (msg), "Failed to get extended " + "attribute %s, reason: %s", keys[i], + strerror (errno)); + } + + if (*in_use) { + snprintf (msg, sizeof (msg), "%s or a prefix of it is " + "already part of a volume", path); + } + + if (strlen (msg)) { + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + } + + return ret; +} + +int +glusterd_brick_create_path (char *host, char *path, uuid_t uuid, + char **op_errstr) +{ + int ret = -1; + char msg[2048] = {0,}; + gf_boolean_t in_use = _gf_false; + gf_boolean_t created = _gf_true; + + ret = mkdir_if_missing (path, &created); + if (ret) + goto out; + + /* Check for xattr support in backend fs */ ret = sys_lsetxattr (path, "trusted.glusterfs.test", "working", 8, 0); if (ret) { - snprintf (msg, sizeof (msg), "glusterfs is not" + snprintf (msg, sizeof (msg), "Glusterfs is not" " supported on brick: %s:%s.\nSetting" " extended attributes failed, reason:" " %s.", host, path, strerror(errno)); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); goto out; + } else { - /* Remove xattr *cannot* fail after setting it succeeded */ sys_lremovexattr (path, "trusted.glusterfs.test"); + } - /* Now check if the export directory has some other 'gfid', - other than that of root '/' */ - ret = sys_lgetxattr (path, "trusted.gfid", gfid, 16); - if (ret == 16) { - if (!__is_root_gfid (gfid)) { - gf_log (THIS->name, GF_LOG_WARNING, - "%s: gfid (%s) is not that of glusterfs '/' ", - path, uuid_utoa (gfid)); - snprintf (msg, sizeof (msg), - "'%s:%s' gfid (%s) is not that of " - "glusterfs '/' ", host, path, uuid_utoa (gfid)); - ret = -1; - goto out; - } - } else if (ret != -1) { - /* Wrong 'gfid' is set, it should be error */ - ret = -1; - snprintf (msg, sizeof (msg), "'%s:%s' has wrong entry" - "for 'gfid'.", host, path); - goto out; - } else if ((ret == -1) && (errno != ENODATA)) { - /* Wrong 'gfid' is set, it should be error */ - snprintf (msg, sizeof (msg), "'%s:%s' has failed to fetch " - "'gfid' (%s)", host, path, strerror (errno)); + ret = glusterd_is_path_in_use (path, &in_use, op_errstr); + if (ret) goto out; - } - ret = 0; - if (!uuid) - goto out; - - /* This 'key' is set when the volume is started for the first time */ - ret = sys_lgetxattr (path, "trusted.glusterfs.volume-id", - old_uuid, 16); - if ((ret >= 0 && ret != 16) || ((ret == 16) && - uuid_compare (old_uuid, uuid))) { - snprintf (msg, sizeof (msg), "'%s:%s' has been part of " - "a volume with id %s. Please re-create the brick " - "directory.", host, path, uuid_utoa (old_uuid)); - gf_log (THIS->name, GF_LOG_WARNING, "%s", msg); + if (in_use) { ret = -1; goto out; + } - } else if ((ret == -1) && (errno != ENODATA)) { - snprintf (msg, sizeof (msg), "'%s:%s' : failed to fetch " - "'volume-id' (%s)", host, path, strerror (errno)); - gf_log (THIS->name, GF_LOG_WARNING, "%s", msg); + ret = sys_lsetxattr (path, GF_XATTR_VOL_ID_KEY, uuid, 16, + XATTR_CREATE); + if (ret) { + snprintf (msg, sizeof (msg), "Failed to set extended " + "attributes %s, reason: %s", + GF_XATTR_VOL_ID_KEY, strerror (errno)); + if (created) + rmdir (path); goto out; - } - /* if 'ret == -1' then 'volume-id' not set, seems to be a fresh - directory */ ret = 0; out: - if (msg[0] != '\0') + if (strlen (msg)) *op_errstr = gf_strdup (msg); - gf_log ("", GF_LOG_DEBUG, "returning %d", ret); return ret; + } int @@ -4816,19 +4859,35 @@ glusterd_delete_all_bricks (glusterd_volinfo_t* volinfo) return ret; } +/* @new should be used by caller only if ret is zero. + * caller should set @new to 'true' by default.*/ int -mkdir_if_missing (char *path) +mkdir_if_missing (char *path, gf_boolean_t *new) { struct stat st = {0,}; int ret = 0; + gf_boolean_t created = _gf_true; ret = mkdir (path, 0777); - if (!ret || errno == EEXIST) - ret = stat (path, &st); - if (ret == -1 || !S_ISDIR (st.st_mode)) + if (ret && errno != EEXIST) + goto out; + + if (ret && errno == EEXIST) + created = _gf_false; + + ret = stat (path, &st); + if (ret == -1 || !S_ISDIR (st.st_mode)) { + ret = -1; + goto out; + } + + if (new) + *new = created; + +out: + if (ret) gf_log ("", GF_LOG_WARNING, "Failed to create the" " directory %s", path); - return ret; } @@ -4859,7 +4918,7 @@ glusterd_start_gsync (glusterd_volinfo_t *master_vol, char *slave, goto out; snprintf (buf, PATH_MAX, "%s/"GEOREP"/%s", priv->workdir, master_vol->volname); - ret = mkdir_if_missing (buf); + ret = mkdir_if_missing (buf, NULL); if (ret) { errcode = -1; goto out; @@ -4867,7 +4926,7 @@ glusterd_start_gsync (glusterd_volinfo_t *master_vol, char *slave, snprintf (buf, PATH_MAX, DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"/%s", master_vol->volname); - ret = mkdir_if_missing (buf); + ret = mkdir_if_missing (buf, NULL); if (ret) { errcode = -1; goto out; |