summaryrefslogtreecommitdiffstats
path: root/xlators/storage/posix/src/posix-gfid-path.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-gfid-path.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-gfid-path.c')
-rw-r--r--xlators/storage/posix/src/posix-gfid-path.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/xlators/storage/posix/src/posix-gfid-path.c b/xlators/storage/posix/src/posix-gfid-path.c
index 7529f55..2834c2f 100644
--- a/xlators/storage/posix/src/posix-gfid-path.c
+++ b/xlators/storage/posix/src/posix-gfid-path.c
@@ -13,6 +13,9 @@
#include "syscall.h"
#include "logging.h"
#include "posix-messages.h"
+#include "posix-mem-types.h"
+#include "posix-gfid-path.h"
+#include "posix.h"
int32_t
posix_set_gfid2path_xattr (xlator_t *this, const char *path, uuid_t pgfid,
@@ -96,3 +99,184 @@ posix_is_gfid2path_xattr (const char *name)
return _gf_false;
}
}
+
+static int gf_posix_xattr_enotsup_log;
+
+int32_t
+posix_get_gfid2path (xlator_t *this, inode_t *inode, const char *real_path,
+ int *op_errno, dict_t *dict)
+{
+ int ret = 0;
+ char *path = NULL;
+ ssize_t size = 0;
+ char *list = NULL;
+ int32_t list_offset = 0;
+ int32_t i = 0;
+ int32_t j = 0;
+ char *paths[MAX_GFID2PATH_LINK_SUP] = {NULL,};
+ char *value = NULL;
+ size_t remaining_size = 0;
+ size_t bytes = 0;
+ char keybuffer[4096] = {0,};
+ char value_buf[8192] = {0,};
+ uuid_t pargfid = {0,};
+ gf_boolean_t have_val = _gf_false;
+ struct posix_private *priv = NULL;
+ char pargfid_str[UUID_CANONICAL_FORM_LEN + 1] = {0,};
+
+ priv = this->private;
+
+ if (IA_ISDIR (inode->ia_type)) {
+ ret = posix_resolve_dirgfid_to_path (inode->gfid,
+ priv->base_path,
+ NULL, &path);
+ if (ret < 0) {
+ ret = -1;
+ goto err;
+ }
+ ret = dict_set_dynstr (dict, GFID2PATH_VIRT_XATTR_KEY, path);
+ if (ret < 0) {
+ gf_msg (this->name, GF_LOG_WARNING, -ret,
+ P_MSG_DICT_SET_FAILED, "could not set "
+ "value for key (%s)", GFID2PATH_VIRT_XATTR_KEY);
+ goto err;
+ }
+ } else {
+ have_val = _gf_false;
+ memset (value_buf, '\0', sizeof(value_buf));
+ size = sys_llistxattr (real_path, value_buf,
+ sizeof (value_buf) - 1);
+ if (size > 0) {
+ have_val = _gf_true;
+ } else {
+ if (errno == ERANGE) {
+ gf_msg (this->name, GF_LOG_DEBUG, errno,
+ P_MSG_XATTR_FAILED,
+ "listxattr failed due to overflow of"
+ " buffer on %s ", real_path);
+ size = sys_llistxattr (real_path, NULL, 0);
+ }
+ if (size == -1) {
+ *op_errno = errno;
+ if ((errno == ENOTSUP) || (errno == ENOSYS)) {
+ GF_LOG_OCCASIONALLY (
+ gf_posix_xattr_enotsup_log,
+ this->name, GF_LOG_WARNING,
+ "Extended attributes not "
+ "supported (try remounting"
+ " brick with 'user_xattr' "
+ "flag)");
+ } else {
+ gf_msg (this->name, GF_LOG_ERROR, errno,
+ P_MSG_XATTR_FAILED,
+ "listxattr failed on %s",
+ real_path);
+ }
+ goto err;
+ }
+ if (size == 0)
+ goto done;
+ }
+ list = alloca (size);
+ if (!list) {
+ *op_errno = errno;
+ goto err;
+ }
+ if (have_val) {
+ memcpy (list, value_buf, size);
+ } else {
+ size = sys_llistxattr (real_path, list, size);
+ if (size < 0) {
+ ret = -1;
+ *op_errno = errno;
+ goto err;
+ }
+ }
+ remaining_size = size;
+ list_offset = 0;
+ while (remaining_size > 0) {
+ strncpy (keybuffer, list + list_offset,
+ sizeof(keybuffer));
+
+ if (!posix_is_gfid2path_xattr (keybuffer)) {
+ goto ignore;
+ }
+
+ memset (value_buf, '\0', sizeof(value_buf));
+ size = sys_lgetxattr (real_path, keybuffer, value_buf,
+ sizeof (value_buf) - 1);
+ if (size == -1) {
+ ret = -1;
+ *op_errno = errno;
+ gf_msg (this->name, GF_LOG_ERROR, errno,
+ P_MSG_XATTR_FAILED, "getxattr failed on"
+ " %s: key = %s ", real_path, keybuffer);
+ break;
+ }
+
+ /* Parse pargfid from xattr value*/
+ strncpy (pargfid_str, value_buf, 36);
+ pargfid_str[36] = '\0';
+ gf_uuid_parse (pargfid_str, pargfid);
+
+ /* Convert pargfid to path */
+ ret = posix_resolve_dirgfid_to_path (pargfid,
+ priv->base_path,
+ &value_buf[37],
+ &paths[i]);
+ i++;
+
+ignore:
+ remaining_size -= strlen (keybuffer) + 1;
+ list_offset += strlen (keybuffer) + 1;
+ } /* while (remaining_size > 0) */
+
+ /* Calculate memory to be allocated */
+ for (j = 0; j < i; j++) {
+ bytes += strlen(paths[j]);
+ if (j < i-1)
+ bytes += strlen(priv->gfid2path_sep);
+ }
+ value = GF_CALLOC (bytes + 1, sizeof(char), gf_posix_mt_char);
+ if (!value) {
+ ret = -1;
+ *op_errno = errno;
+ goto err;
+ }
+
+ for (j = 0; j < i; j++) {
+ strcat (value, paths[j]);
+ if (j != i - 1)
+ strcat (value, priv->gfid2path_sep);
+ }
+ value[bytes] = '\0';
+
+ ret = dict_set_dynptr (dict, GFID2PATH_VIRT_XATTR_KEY,
+ value, bytes);
+ if (ret < 0) {
+ *op_errno = -ret;
+ gf_msg (this->name, GF_LOG_ERROR, *op_errno,
+ P_MSG_DICT_SET_FAILED, "dict set operation "
+ "on %s for the key %s failed.",
+ real_path, GFID2PATH_VIRT_XATTR_KEY);
+ GF_FREE (value);
+ goto err;
+ }
+ }
+
+done:
+ for (j = 0; j < i; j++) {
+ if (paths[j])
+ GF_FREE (paths[j]);
+ }
+ ret = 0;
+ return ret;
+err:
+ if (path)
+ GF_FREE (path);
+ for (j = 0; j < i; j++) {
+ if (paths[j])
+ GF_FREE (paths[j]);
+ }
+ return ret;
+}