summaryrefslogtreecommitdiffstats
path: root/xlators/storage/posix/src/posix-helpers.c
diff options
context:
space:
mode:
authorKotresh HR <khiremat@redhat.com>2017-07-16 15:16:56 -0400
committerKrutika Dhananjay <kdhananj@redhat.com>2017-07-28 05:21:46 +0000
commitab2558a3e7a1b2de2d63a3812ab4ed58d10d8619 (patch)
tree8f0baa0697c37abd5a113334e6452138d8a7a5c0 /xlators/storage/posix/src/posix-helpers.c
parent1477fa442a733d7b1a5ea74884cac8f29fbe7e6a (diff)
storage/posix: Add virtual xattr to fetch path from gfid
The gfid2path infra stores the "pargfid/bname" as on xattr value for each non directory entry. Hardlinks would have a separate xattr. This xattr key is internal and is not exposed to applications. A virtual xattr is exposed for the applications to fetch the path from gfid. Internal xattr: trusted.gfid2path.<xxhash> Virtual xattr: glusterfs.gfidtopath getfattr -h -n glusterfs.gfidtopath /<aux-mnt>/.gfid/<gfid> If there are hardlinks, it returns all the paths separated by ':'. A volume set option is introduced to change the delimiter to required string of max length 7. gluster vol set gfid2path-separator ":::" Updates: #139 Change-Id: Ie3b0c3fd8bd5333c4a27410011e608333918c02a Signed-off-by: Kotresh HR <khiremat@redhat.com> Reviewed-on: https://review.gluster.org/17785 Smoke: Gluster Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.org> Reviewed-by: Krutika Dhananjay <kdhananj@redhat.com>
Diffstat (limited to 'xlators/storage/posix/src/posix-helpers.c')
-rw-r--r--xlators/storage/posix/src/posix-helpers.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c
index 1530b11..1a05d65 100644
--- a/xlators/storage/posix/src/posix-helpers.c
+++ b/xlators/storage/posix/src/posix-helpers.c
@@ -2379,6 +2379,102 @@ posix_fdget_objectsignature (int fd, dict_t *xattr)
return -EINVAL;
}
+/*
+ * posix_resolve_dirgfid_to_path:
+ * It converts given dirgfid to path by doing recursive readlinks at the
+ * backend. If bname is given, it suffixes bname to dir path 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 "/"
+ **/
+
+int32_t
+posix_resolve_dirgfid_to_path (const uuid_t dirgfid, const char *brick_path,
+ const char *bname, char **path)
+{
+ 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, };
+ uuid_t pargfid = {0, };
+ char gpath[PATH_MAX] = {0,};
+ char result[PATH_MAX] = {0,};
+ char result1[PATH_MAX] = {0,};
+ char *dir_name = NULL;
+ char pre_dir_name[PATH_MAX] = {0,};
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ gf_uuid_copy (pargfid, dirgfid);
+ if (!path || gf_uuid_is_null (pargfid)) {
+ ret = -1;
+ goto out;
+ }
+
+ if (__is_root_gfid (pargfid)) {
+ if (bname) {
+ snprintf (result, PATH_MAX, "/%s", bname);
+ *path = gf_strdup (result);
+ } else {
+ *path = gf_strdup ("/");
+ }
+ return ret;
+ }
+
+ dir_handle = alloca (PATH_MAX);
+ linkname = alloca (PATH_MAX);
+ (void) snprintf (gpath, PATH_MAX, "%s/.glusterfs/", brick_path);
+
+ while (!(__is_root_gfid (pargfid))) {
+ snprintf (dir_handle, PATH_MAX, "%s/%02x/%02x/%s", gpath,
+ pargfid[0], pargfid[1], uuid_utoa (pargfid));
+
+ len = sys_readlink (dir_handle, linkname, PATH_MAX);
+ if (len < 0) {
+ gf_msg (this->name, GF_LOG_ERROR, errno,
+ P_MSG_READLINK_FAILED,
+ "could not read the "
+ "link from the gfid handle %s", dir_handle);
+ ret = -1;
+ goto out;
+ }
+
+ linkname[len] = '\0';
+
+ pgfidstr = strtok_r (linkname + strlen("../../00/00/"), "/",
+ &saveptr);
+ dir_name = strtok_r (NULL, "/", &saveptr);
+
+ if (strlen(pre_dir_name) != 0) { /* Remove '/' at the end */
+ snprintf (result, PATH_MAX, "%s/%s", dir_name,
+ pre_dir_name);
+ } else {
+ snprintf (result, PATH_MAX, "%s", dir_name);
+ }
+
+ strncpy (pre_dir_name, result, sizeof(pre_dir_name));
+
+ gf_uuid_parse (pgfidstr, tmp_gfid);
+ gf_uuid_copy (pargfid, tmp_gfid);
+ }
+
+ if (bname) {
+ snprintf (result1, PATH_MAX, "/%s/%s", result, bname);
+ } else {
+ snprintf (result1, PATH_MAX, "/%s", result);
+ }
+
+ *path = gf_strdup (result1);
+
+out:
+ return ret;
+}
+
posix_inode_ctx_t *
__posix_inode_ctx_get (inode_t *inode, xlator_t *this)
{