From 21515b3331d8d72011fef79008bcaff8ca43647a Mon Sep 17 00:00:00 2001 From: Kotresh HR Date: Tue, 14 Apr 2015 14:42:46 +0530 Subject: feature/changelog: Capture path for deletes PROBLEM: There is no way to get the path of deleted file if we have gfid from changelog since the file is already deleted. SOLUTION: Do a recursive readlink on parent gfid in backend .glusterfs path to get the complete path in I/O callpath in changelog translator and capture it in callback. The path captured is relative from the brick root. The field separator used is '\0'. e.g., ......\0/bname\0\0 ADDITIONAL REQUIRED CHANGES: 1. The changelog translator option called "changelog.capture-del-path" is introduced to enable or disable the capturing of deleted entry path. e.g., gluster vol set changelog.capture-del-path on/off If capture-del-path is disabled, '\0' is captured instead of relative path. e.g., ......\0/bname\0\0\0 2. The minor number in the version of changelog is bumped up from v1.1 to v1.2. 3. If recursive readlink is failed for some reason, it will capture \0 in place of . e.g., ......\0/bname\0\0\0 (same as when caputre-del-path option is disabled) 4. If bname argument passed to "resolve_pargfid_to_path" function is NULL and pargfid is ROOT, "." is returned. This is not the case with changelog, where bname is always passed. This is applicable to other consumers of "resolve_pargfid_to_path" routine. NOTE: Changelog parser should consider the above new changes and should parse accordingly. Change-Id: I040ed429b5aa7d391033fc6a540edbf07fc37827 BUG: 1214561 Signed-off-by: Kotresh HR Reviewed-on: http://review.gluster.org/10288 Tested-by: Gluster Build System Reviewed-by: Venky Shankar Tested-by: NetBSD Build System --- xlators/features/changelog/src/changelog-helpers.c | 85 ++++++++++++++++++++++ 1 file changed, 85 insertions(+) (limited to 'xlators/features/changelog/src/changelog-helpers.c') diff --git a/xlators/features/changelog/src/changelog-helpers.c b/xlators/features/changelog/src/changelog-helpers.c index 585214df635..8dae5efa454 100644 --- a/xlators/features/changelog/src/changelog-helpers.c +++ b/xlators/features/changelog/src/changelog-helpers.c @@ -1735,3 +1735,88 @@ err: inode_unref (parent); return -1; } + +/* + * resolve_pargfid_to_path: + * It converts given pargfid to path by doing recursive readlinks at the + * backend. If bname is given, it suffixes bname to pargfid to form the + * complete path else it doesn't. It allocates memory for the path and is + * caller's responsibility to free the same. If bname is NULL and pargfid + * is ROOT, then it returns "." + */ + +int +resolve_pargfid_to_path (xlator_t *this, uuid_t pargfid, + char **path, char *bname) +{ + char *linkname = NULL; + char *dir_handle = NULL; + char *pgfidstr = NULL; + char *saveptr = NULL; + ssize_t len = 0; + int ret = 0; + uuid_t tmp_gfid = {0, }; + changelog_priv_t *priv = NULL; + char gpath[PATH_MAX] = {0,}; + char result[PATH_MAX] = {0,}; + char *dir_name = NULL; + char pre_dir_name[PATH_MAX] = {0,}; + + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + if (!path || gf_uuid_is_null (pargfid)) { + ret = -1; + goto out; + } + + if (__is_root_gfid (pargfid)) { + if (bname) + *path = gf_strdup (bname); + else + *path = gf_strdup ("."); + return ret; + } + + dir_handle = alloca (PATH_MAX); + linkname = alloca (PATH_MAX); + (void) snprintf (gpath, PATH_MAX, "%s/.glusterfs/", + priv->changelog_brick); + + while (!(__is_root_gfid (pargfid))) { + snprintf (dir_handle, PATH_MAX, "%s/%02x/%02x/%s", gpath, + pargfid[0], pargfid[1], uuid_utoa (pargfid)); + + len = readlink (dir_handle, linkname, PATH_MAX); + if (len < 0) { + gf_log (this->name, GF_LOG_ERROR, "could not read the " + "link from the gfid handle %s (%s)", dir_handle, + strerror (errno)); + ret = -1; + goto out; + } + + linkname[len] = '\0'; + + pgfidstr = strtok_r (linkname + strlen("../../00/00/"), "/", + &saveptr); + dir_name = strtok_r (NULL, "/", &saveptr); + + strncpy (result, dir_name, PATH_MAX); + strncat (result, "/", 1); + strncat (result, pre_dir_name, PATH_MAX); + strncpy (pre_dir_name, result, PATH_MAX); + + gf_uuid_parse (pgfidstr, tmp_gfid); + gf_uuid_copy (pargfid, tmp_gfid); + } + + if (bname) + strncat (result, bname, PATH_MAX); + + *path = gf_strdup (result); + +out: + return ret; +} -- cgit