From 657d78dbad118e511e1fca8b1badb9f8ae7a6f60 Mon Sep 17 00:00:00 2001 From: karthik-us Date: Wed, 7 Jun 2017 15:56:13 +0530 Subject: cluster/afr: GFID split-brain resolution with existing CLI Problem: Currently there is no way for the admin from CLI to resolve gfid split-brain based on some policy like choice of the brick, mtime or size. Fix: With the existing CLI options based on size, mtime, and choice of brick, we do lookup on the parent for the specified file. As part of the lookup, if we find gfid mismatch, we resolve them based on the policy and return. If the file is not in gfid split- brain, then we check for the data and metadata split-brain in the getxattr code path, and resolve if any. This will work provided absolute path to the file with the CLI and not with gfid of the file. Hence the source-brick policy without any file path will also not resolve the gfid split-brain since it uses the gfid of the files. But it can resolve any other type of split-brains and skip the gfid mismatch resolution with the usual error message. Reverting the change https://review.gluster.org/17290. This patch resolves the issue. Fixes gluster/glusterfs#135 Change-Id: Iaeba6fc32f184a34255d03be87cda02773130a09 BUG: 1459530 Signed-off-by: karthik-us Reviewed-on: https://review.gluster.org/17485 Reviewed-by: Ravishankar N Reviewed-by: Pranith Kumar Karampuri CentOS-regression: Gluster Build System Smoke: Gluster Build System --- heal/src/glfs-heal.c | 114 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 101 insertions(+), 13 deletions(-) (limited to 'heal') diff --git a/heal/src/glfs-heal.c b/heal/src/glfs-heal.c index fb997948f57..27115f3ca6c 100644 --- a/heal/src/glfs-heal.c +++ b/heal/src/glfs-heal.c @@ -21,6 +21,7 @@ #include #include #include "glusterfs.h" +#include #if (HAVE_LIB_XML) #include @@ -1031,26 +1032,43 @@ _validate_directory (dict_t *xattr_req, char *file) int glfsh_heal_splitbrain_file (glfs_t *fs, xlator_t *top_subvol, loc_t *rootloc, - char *file, dict_t *xattr_req) + char *file, dict_t *xattr_req) { - int ret = -1; - int reval = 0; - loc_t loc = {0, }; - char *path = NULL; - char *filename = NULL; - struct iatt iatt = {0, }; - xlator_t *xl = top_subvol; - dict_t *xattr_rsp = NULL; - char *sh_fail_msg = NULL; - int32_t op_errno = 0; + int ret = -1; + int reval = 0; + loc_t loc = {0, }; + char *path = NULL; + char *path1 = NULL; + char *path2 = NULL; + char *filename = NULL; + char *filename1 = NULL; + struct iatt iatt = {0, }; + xlator_t *xl = top_subvol; + dict_t *xattr_rsp = NULL; + char *sh_fail_msg = NULL; + char *gfid_heal_msg = NULL; + int32_t op_errno = 0; + gf_boolean_t flag = _gf_false; if (!strncmp (file, "gfid:", 5)) { filename = gf_strdup(file); + if (!filename) { + printf ("Error allocating memory to filename\n"); + goto out; + } path = strtok (filename, ":"); path = strtok (NULL, ";"); gf_uuid_parse (path, loc.gfid); loc.path = gf_strdup (uuid_utoa (loc.gfid)); + if (!loc.path) { + printf ("Error allocating memory to path\n"); + goto out; + } loc.inode = inode_new (rootloc->inode->table); + if (!loc.inode) { + printf ("Error getting inode\n"); + goto out; + } ret = syncop_lookup (xl, &loc, &iatt, 0, xattr_req, &xattr_rsp); if (ret) { op_errno = -ret; @@ -1065,9 +1083,72 @@ glfsh_heal_splitbrain_file (glfs_t *fs, xlator_t *top_subvol, loc_t *rootloc, ret = -1; goto out; } -retry: + path1 = gf_strdup (file); + if (!path1) { + printf ("Error allocating memory to path\n"); + ret = -1; + goto out; + } + path2 = gf_strdup (file); + if (!path2) { + printf ("Error allocating memory to path\n"); + ret = -1; + goto out; + } + path = dirname (path1); + filename1 = basename (path2); +retry1: + ret = glfs_resolve (fs, xl, path, &loc, &iatt, reval); + ESTALE_RETRY (ret, errno, reval, &loc, retry1); + if (ret) { + printf("Lookup failed on %s:%s\n", + path, strerror (errno)); + goto out; + } + GF_FREE ((char *)loc.path); + loc.path = gf_strdup (file); + if (!loc.path) { + printf ("Error allocating memory for path\n"); + ret = -1; + goto out; + } + loc.parent = inode_unref (loc.parent); + loc.parent = inode_ref (loc.inode); + loc.inode = inode_unref (loc.inode); + loc.inode = inode_new (rootloc->inode->table); + if (!loc.inode) { + printf ("Error getting inode\n"); + ret = -1; + goto out; + } + loc.name = filename1; + gf_uuid_copy (loc.pargfid, loc.gfid); + gf_uuid_clear (loc.gfid); + + ret = syncop_lookup (xl, &loc, &iatt, 0, xattr_req, &xattr_rsp); + if (ret) { + op_errno = -ret; + printf ("Lookup failed on %s:%s.\n", file, + strerror(op_errno)); + flag = _gf_true; + } + + ret = dict_get_str (xattr_rsp, "gfid-heal-msg", &gfid_heal_msg); + if (!ret) { + printf ("%s for file %s\n", gfid_heal_msg, file); + loc_wipe (&loc); + goto out; + } + if (flag) + goto out; + + reval = 0; + loc_wipe (&loc); + memset (&iatt, 0, sizeof(iatt)); + +retry2: ret = glfs_resolve (fs, xl, file, &loc, &iatt, reval); - ESTALE_RETRY (ret, errno, reval, &loc, retry); + ESTALE_RETRY (ret, errno, reval, &loc, retry2); if (ret) { printf("Lookup failed on %s:%s\n", file, strerror (errno)); @@ -1098,6 +1179,13 @@ retry: out: if (xattr_rsp) dict_unref (xattr_rsp); + if (path1) + GF_FREE (path1); + if (path2) + GF_FREE (path2); + if (filename) + GF_FREE (filename); + loc_wipe (&loc); return ret; } -- cgit