diff options
| author | Krishnan Parthasarathi <kp@gluster.com> | 2012-05-07 13:31:24 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vijay@gluster.com> | 2012-05-16 03:53:52 -0700 | 
| commit | cb83c85511fc7fbfe34f97baebdda9d2bb309511 (patch) | |
| tree | 3ed6a68637d6000a8d3a7326869fbf8a00415593 | |
| parent | 74fbeb2d1a997a0238aa15ab2dccc98764b667a2 (diff) | |
glusterd: Fixed glusterd_brick_create_path algo.
- check if any prefix of the brick path has "trusted.gfid"
  or "trusted.glusterfs.volume-id" set.
- set trusted.glusterfs.volume-id on the bricks as soon as
  its induction into the volume is settled. Earlier, the setting of
  "volume-id" used to happen during the first run of the brick process,
  leaving of window for bricks part of one volume to be (ab)used by another
  volume inadvertently.
- removed creation of brick directory (if missing), during start volume force.
  This is to avoid directory creation as part 'force'ful starting of volume
  and leave the responsibility with the user, who understands the
  'availability' of the export directory (brick) better.
Change-Id: I4237ec4ea7a4e38a7501027e7de7112edd67de8c
BUG: 812214
Signed-off-by: Krishnan Parthasarathi <kp@gluster.com>
Reviewed-on: http://review.gluster.com/3280
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vijay@gluster.com>
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 1 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-brick-ops.c | 2 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-hooks.c | 10 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-replace-brick.c | 2 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 229 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 11 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 17 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.c | 19 | 
8 files changed, 166 insertions, 125 deletions
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index bd9763848..3eed8b163 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -73,6 +73,7 @@  #define GF_XATTR_CLRLK_CMD      "glusterfs.clrlk"  #define GF_XATTR_PATHINFO_KEY   "trusted.glusterfs.pathinfo"  #define GF_XATTR_NODE_UUID_KEY  "trusted.glusterfs.node-uuid" +#define GF_XATTR_VOL_ID_KEY   "trusted.glusterfs.volume-id"  #define XATTR_IS_PATHINFO(x)  (strncmp (x, GF_XATTR_PATHINFO_KEY,       \                                          strlen (GF_XATTR_PATHINFO_KEY)) == 0) diff --git a/xlators/mgmt/glusterd/src/glusterd-brick-ops.c b/xlators/mgmt/glusterd/src/glusterd-brick-ops.c index 724186846..120fd5027 100644 --- a/xlators/mgmt/glusterd/src/glusterd-brick-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-brick-ops.c @@ -1164,7 +1164,7 @@ glusterd_op_stage_add_brick (dict_t *dict, char **op_errstr)                          ret = glusterd_brick_create_path (brickinfo->hostname,                                                            brickinfo->path,                                                            volinfo->volume_id, -                                                          0777, op_errstr); +                                                          op_errstr);                          if (ret)                                  goto out;                  } diff --git a/xlators/mgmt/glusterd/src/glusterd-hooks.c b/xlators/mgmt/glusterd/src/glusterd-hooks.c index 2afdb1625..ba428b0f3 100644 --- a/xlators/mgmt/glusterd/src/glusterd-hooks.c +++ b/xlators/mgmt/glusterd/src/glusterd-hooks.c @@ -39,8 +39,6 @@  #include <fnmatch.h> -extern int mkdir_if_missing (char *dir); -  #define EMPTY ""  char glusterd_hook_dirnames[GD_OP_MAX][256] =  { @@ -95,7 +93,7 @@ glusterd_hooks_create_hooks_directory (char *basedir)          priv = THIS->private;          snprintf (path, sizeof (path), "%s/hooks", basedir); -        ret = mkdir_if_missing (path); +        ret = mkdir_if_missing (path, NULL);          if (ret) {                  gf_log (THIS->name, GF_LOG_CRITICAL, "Unable to create %s due"                           "to %s", path, strerror (errno)); @@ -103,7 +101,7 @@ glusterd_hooks_create_hooks_directory (char *basedir)          }          GLUSTERD_GET_HOOKS_DIR (version_dir, GLUSTERD_HOOK_VER, priv); -        ret = mkdir_if_missing (version_dir); +        ret = mkdir_if_missing (version_dir, NULL);          if (ret) {                  gf_log (THIS->name, GF_LOG_CRITICAL, "Unable to create %s due "                          "to %s", version_dir, strerror (errno)); @@ -117,7 +115,7 @@ glusterd_hooks_create_hooks_directory (char *basedir)                  snprintf (path, sizeof (path), "%s/%s", version_dir,                            cmd_subdir); -                ret = mkdir_if_missing (path); +                ret = mkdir_if_missing (path, NULL);                  if (ret) {                          gf_log (THIS->name, GF_LOG_CRITICAL,                                  "Unable to create %s due to %s", @@ -129,7 +127,7 @@ glusterd_hooks_create_hooks_directory (char *basedir)                       type++) {                          snprintf (path, sizeof (path), "%s/%s/%s",                                    version_dir, cmd_subdir, type_subdir[type]); -                        ret = mkdir_if_missing (path); +                        ret = mkdir_if_missing (path, NULL);                          if (ret) {                                  gf_log (THIS->name, GF_LOG_CRITICAL,                                          "Unable to create %s due to %s", diff --git a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c index fdfa9c020..c31d8c781 100644 --- a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c +++ b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c @@ -465,7 +465,7 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr,          if (!glusterd_is_local_addr (host)) {                  ret = glusterd_brick_create_path (host, path, -                                                  volinfo->volume_id, 0777, +                                                  volinfo->volume_id,                                                    op_errstr);                  if (ret)                          goto out; 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; diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 7b71f05a4..d149cb9d0 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -57,6 +57,15 @@ typedef struct glusterd_voldict_ctx_ {          char    *val_name;  } glusterd_voldict_ctx_t; +/* Moved the definition from gluster-utils.c avoiding + * extern'ing in multiple places. + * (Indeed, XXX: we'd rather need a general + * "mkdir -p" like routine in libglusterfs) +*/ + +int +mkdir_if_missing (char *path, gf_boolean_t *new); +  int  glusterd_compare_lines (const void *a, const void *b); @@ -319,7 +328,7 @@ glusterd_rb_check_bricks (glusterd_volinfo_t *volinfo,                            glusterd_brickinfo_t *dst_brick);  int -glusterd_brick_create_path (char *host, char *path, uuid_t uuid, mode_t mode, +glusterd_brick_create_path (char *host, char *path, uuid_t uuid,                              char **op_errstr);  int  glusterd_sm_tr_log_transition_add (glusterd_sm_tr_log_t *log, diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c index 4ee9582fd..9ee28733a 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c @@ -718,7 +718,7 @@ glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr)                          ret = glusterd_brick_create_path (brick_info->hostname,                                                            brick_info->path,                                                            volume_uuid, -                                                          0777, op_errstr); +                                                          op_errstr);                          if (ret)                                  goto out;                          brick_list = tmpptr; @@ -843,21 +843,6 @@ glusterd_op_stage_start_volume (dict_t *dict, char **op_errstr)                          goto out;                  } -                /* we should not be creating the directory if 'force' option -                   is not given. This may lead to issues where the actual data -                   disk is not mounted after a machine reboot, but because -                   'glusterd' restarts the processes, the export directories -                   can be automatically created and brick would start */ -                if ((flags & GF_CLI_FLAG_OP_FORCE) && -                    !uuid_compare (brickinfo->uuid, priv->uuid)) { -                        ret = glusterd_brick_create_path (brickinfo->hostname, -                                                          brickinfo->path, -                                                          volinfo->volume_id, -                                                          0777, op_errstr); -                        if (ret) -                                goto out; -                } -                  if (!(flags & GF_CLI_FLAG_OP_FORCE)) {                          if (glusterd_is_volume_started (volinfo)) {                                  snprintf (msg, sizeof (msg), "Volume %s already" diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c index 6acf3daff..61d770439 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -246,18 +246,6 @@ out:          return ret;  } -/* defined in glusterd-utils.c -- no - * glusterd header where it would be - * appropriate to put to, and too - * accidental routine to place in - * libglusterfs. - * - * (Indeed, XXX: we'd rather need a general - * "mkdir -p" like routine in - * libglusterfs) - */ -extern int mkdir_if_missing (char *path); -  #if SYNCDAEMON_COMPILE  static int  glusterd_check_gsync_present (int *valid_state) @@ -356,7 +344,7 @@ glusterd_crt_georep_folders (char *georepdir, glusterd_conf_t *conf)          }          snprintf (georepdir, PATH_MAX, "%s/"GEOREP, conf->workdir); -        ret = mkdir_if_missing (georepdir); +        ret = mkdir_if_missing (georepdir, NULL);          if (-1 == ret) {                  gf_log ("glusterd", GF_LOG_CRITICAL,                          "Unable to create "GEOREP" directory %s", @@ -371,7 +359,7 @@ glusterd_crt_georep_folders (char *georepdir, glusterd_conf_t *conf)                          georepdir);                  goto out;          } -        ret = mkdir_if_missing (DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP); +        ret = mkdir_if_missing (DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP, NULL);          if (-1 == ret) {                  gf_log ("glusterd", GF_LOG_CRITICAL,                          "Unable to create "GEOREP" log directory"); @@ -385,7 +373,8 @@ glusterd_crt_georep_folders (char *georepdir, glusterd_conf_t *conf)                          georepdir);                  goto out;          } -        ret = mkdir_if_missing (DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves"); +        ret = mkdir_if_missing (DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves", +                                NULL);          if (-1 == ret) {                  gf_log ("glusterd", GF_LOG_CRITICAL,                          "Unable to create "GEOREP" slave log directory");  | 
