summaryrefslogtreecommitdiffstats
path: root/xlators/storage/posix/src/posix-handle.c
diff options
context:
space:
mode:
authorRaghavendra G <rgowdapp@redhat.com>2013-09-16 17:50:25 +0530
committerAnand Avati <avati@redhat.com>2013-11-26 10:22:40 -0800
commitd6dc8d0e9e2052818c9858f6b073a8bacc3fca88 (patch)
tree8226967de497a4ff75c5ba5e509b465322dd5fd5 /xlators/storage/posix/src/posix-handle.c
parent1d554b179f63a5a56ae447f2a5b0044c49ae2642 (diff)
posix: placeholders for GFID to path conversion
what? ===== The following is an attempt to generate the paths of a file when only its gfid is known. To find the path of a directory, the symlink handle to the directory maintained in the ".glusterfs" backend directory is read. The symlink handle is generated using the gfid of the directory. It (handle) contains the directory's name and parent gfid, which are used to recursively construct the absolute path as seen by the user from the mount point. A similar approach cannot be used for a regular file or a symbolic link since its hardlink handle, generated using its gfid, doesn't contain its parent gfid and basename. So xattrs are set to store the parent gfids and the number of hardlinks to a file or a symlink having the same parent gfid. When an user/application requests for the paths of a regular file or a symlink with multiple hardlinks, using the parent gfids stored in the xattrs, the paths of the parent directories are generated as mentioned earlier. The base names of the hardlinks (with the same parent gfid) are determined by matching the actual backend inode numbers of each entry in the parent directory with that of the hardlink handle. Xattr is set on a regular file, link, and symbolic link as follows, Xattr name : trusted.pgfid.<pargfidstr> Xattr value : <number of hardlinks to a regular file/symlink with the same parentgfid> If a regular file, hard link, symbolic link is created then an xattr in the above format is set in the backend. how to use? =========== This functionality can be used through getxattr interface. Two keys - glusterfs.ancestry.dentry and glusterfs.ancestry.path - enable usage of this functionality. A successful getxattr will have the result stored under same keys. Values will be, glusterfs.ancestry.dentry: -------------------------- A linked list of gf-dirent structures for all possible paths from root to this gfid. If there are multiple paths, the linked-list will be a series of paths one after another. Each path will be a series of dentries representing all components of the path. This key is primarily for internal usage within glusterfs. glusterfs.ancestry.path: ------------------------ A string containing all possible paths from root to this gfid. Multiple hardlinks of a file or a symlink are displayed as a colon seperated list (this could interfere with path components containing ':'). e.g. If there is a file "file1" in root directory with two hardlinks, "/dir2/link2tofile1" and "/dir1/link1tofile1", then [root@alpha gfsmntpt]# getfattr -n glusterfs.ancestry.path -e text file1 glusterfs.ancestry.path="/file1:/dir2/link2tofile1:/dir1/link1tofile1" Thanks Amar, Avati and Venky for the inputs. Original Author: Ramana Raja <rraja@redhat.com> BUG: 990028 Signed-off-by: Raghavendra G <rgowdapp@redhat.com> Change-Id: I0eaa9101e333e0c1f66ccefd9e95944dd4a27497 Reviewed-on: http://review.gluster.org/5951 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Anand Avati <avati@redhat.com>
Diffstat (limited to 'xlators/storage/posix/src/posix-handle.c')
-rw-r--r--xlators/storage/posix/src/posix-handle.c162
1 files changed, 158 insertions, 4 deletions
diff --git a/xlators/storage/posix/src/posix-handle.c b/xlators/storage/posix/src/posix-handle.c
index 219a582c9..1d8e98631 100644
--- a/xlators/storage/posix/src/posix-handle.c
+++ b/xlators/storage/posix/src/posix-handle.c
@@ -26,13 +26,167 @@
#include "xlator.h"
#include "syscall.h"
+inode_t *
+posix_resolve (xlator_t *this, inode_table_t *itable, inode_t *parent,
+ char *bname, struct iatt *iabuf)
+{
+ inode_t *inode = NULL, *linked_inode = NULL;
+ int ret = -1;
+
+ ret = posix_istat (this, parent->gfid, bname, iabuf);
+ if (ret < 0)
+ goto out;
+
+ inode = inode_find (itable, iabuf->ia_gfid);
+ if (inode == NULL) {
+ inode = inode_new (itable);
+ }
+
+ linked_inode = inode_link (inode, parent, bname, iabuf);
+
+ inode_unref (inode);
+
+out:
+ return linked_inode;
+}
+
+int
+posix_make_ancestral_node (const char *priv_base_path, char *path, int pathsize,
+ gf_dirent_t *head,
+ char *dir_name, struct iatt *iabuf, inode_t *inode,
+ int type, dict_t *xdata)
+{
+ gf_dirent_t *entry = NULL;
+ char real_path[PATH_MAX + 1] = {0, }, len = 0;
+ loc_t loc = {0, };
+ int ret = -1;
+
+ len = strlen (path) + strlen (dir_name) + 1;
+ if (len > pathsize) {
+ goto out;
+ }
+
+ strcat (path, dir_name);
+
+ if (type & POSIX_ANCESTRY_DENTRY) {
+ entry = gf_dirent_for_name (dir_name);
+ if (!entry) {
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "could not create gf_dirent for entry %s: (%s)",
+ dir_name, strerror (errno));
+ goto out;
+ }
+
+ entry->d_stat = *iabuf;
+ entry->inode = inode_ref (inode);
+
+ list_add_tail (&entry->list, &head->list);
+ strcpy (real_path, priv_base_path);
+ strcat (real_path, "/");
+ strcat (real_path, path);
+ loc.inode = inode_ref (inode);
+ uuid_copy (loc.gfid, inode->gfid);
+
+ entry->dict = posix_lookup_xattr_fill (THIS, real_path, &loc,
+ xdata, iabuf);
+ loc_wipe (&loc);
+ }
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+int
+posix_make_ancestryfromgfid (xlator_t *this, char *path, int pathsize,
+ gf_dirent_t *head, int type, uuid_t gfid,
+ const size_t handle_size,
+ const char *priv_base_path, inode_table_t *itable,
+ inode_t **parent, dict_t *xdata)
+{
+ char *linkname = NULL; /* "../../<gfid[0]>/<gfid[1]/"
+ "<gfidstr>/<NAME_MAX>" */
+ char *dir_handle = NULL;
+ char *dir_name = NULL;
+ char *pgfidstr = NULL;
+ char *saveptr = NULL;
+ ssize_t len = 0;
+ inode_t *inode = NULL;
+ struct iatt iabuf = {0, };
+ int ret = -1;
+ uuid_t tmp_gfid = {0, };
+
+ if (!path || !parent || !priv_base_path || uuid_is_null (gfid)) {
+ goto out;
+ }
+
+ if (__is_root_gfid (gfid)) {
+ if (parent) {
+ if (*parent) {
+ inode_unref (*parent);
+ }
+
+ *parent = inode_ref (itable->root);
+ }
+
+ inode = itable->root;
+
+ memset (&iabuf, 0, sizeof (iabuf));
+ uuid_copy (iabuf.ia_gfid, inode->gfid);
+ iabuf.ia_type = inode->ia_type;
+
+ ret = posix_make_ancestral_node (priv_base_path, path, pathsize,
+ head, "/", &iabuf, inode, type,
+ xdata);
+ return ret;
+ }
+
+ dir_handle = alloca (handle_size);
+ linkname = alloca (PATH_MAX);
+ snprintf (dir_handle, handle_size, "%s/%s/%02x/%02x/%s",
+ priv_base_path, HANDLE_PFX, gfid[0], gfid[1],
+ uuid_utoa (gfid));
+
+ 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));
+ goto out;
+ }
+
+ linkname[len] = '\0';
+
+ pgfidstr = strtok_r (linkname + SLEN("../../00/00/"), "/", &saveptr);
+ dir_name = strtok_r (NULL, "/", &saveptr);
+ strcat (dir_name, "/");
-#define HANDLE_PFX ".glusterfs"
-#define TRASH_DIR "landfill"
+ uuid_parse (pgfidstr, tmp_gfid);
+
+ ret = posix_make_ancestryfromgfid (this, path, pathsize, head, type,
+ tmp_gfid, handle_size,
+ priv_base_path, itable, parent,
+ xdata);
+ if (ret < 0) {
+ goto out;
+ }
-#define UUID0_STR "00000000-0000-0000-0000-000000000000"
-#define SLEN(str) (sizeof(str) - 1)
+ memset (&iabuf, 0, sizeof (iabuf));
+ inode = posix_resolve (this, itable, *parent, dir_name, &iabuf);
+
+ ret = posix_make_ancestral_node (priv_base_path, path, pathsize, head,
+ dir_name, &iabuf, inode, type, xdata);
+ if (*parent != NULL) {
+ inode_unref (*parent);
+ }
+
+ *parent = inode;
+
+out:
+ return ret;
+}
int
posix_handle_relpath (xlator_t *this, uuid_t gfid, const char *basename,