diff options
Diffstat (limited to 'libglusterfsclient/src/libglusterfsclient-dentry.c')
-rw-r--r-- | libglusterfsclient/src/libglusterfsclient-dentry.c | 404 |
1 files changed, 0 insertions, 404 deletions
diff --git a/libglusterfsclient/src/libglusterfsclient-dentry.c b/libglusterfsclient/src/libglusterfsclient-dentry.c deleted file mode 100644 index 3fa5f6e1e74..00000000000 --- a/libglusterfsclient/src/libglusterfsclient-dentry.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> - This file is part of GlusterFS. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - -#include "libglusterfsclient.h" -#include "libglusterfsclient-internals.h" -#include <libgen.h> - -#define LIBGLUSTERFS_CLIENT_DENTRY_LOC_PREPARE(_new_loc, _loc, _parent, \ - _resolved) do { \ - size_t pathlen = 0; \ - size_t resolvedlen = 0; \ - char *path = NULL; \ - int pad = 0; \ - pathlen = strlen (_loc->path) + 1; \ - path = CALLOC (1, pathlen); \ - _new_loc.parent = _parent; \ - resolvedlen = strlen (_resolved); \ - strncpy (path, _resolved, resolvedlen); \ - if (resolvedlen == 1) /* only root resolved */ \ - pad = 0; \ - else { \ - pad = 1; \ - path[resolvedlen] = '/'; \ - } \ - strcpy_till (path + resolvedlen + pad, \ - loc->path + resolvedlen + pad, '/'); \ - _new_loc.path = path; \ - _new_loc.name = strrchr (path, '/'); \ - if (_new_loc.name) \ - _new_loc.name++; \ - }while (0); - - -/* strcpy_till - copy @dname to @dest, until 'delim' is encountered in @dest - * @dest - destination string - * @dname - source string - * @delim - delimiter character - * - * return - NULL is returned if '0' is encountered in @dname, otherwise returns - * a pointer to remaining string begining in @dest. - */ -static char * -strcpy_till (char *dest, const char *dname, char delim) -{ - char *src = NULL; - int idx = 0; - char *ret = NULL; - - src = (char *)dname; - while (src[idx] && (src[idx] != delim)) { - dest[idx] = src[idx]; - idx++; - } - - dest[idx] = 0; - - if (src[idx] == 0) - ret = NULL; - else - ret = &(src[idx]); - - return ret; -} - -/* __libgf_client_path_to_parenti - derive parent inode for @path. if immediate - * parent is not available in the dentry cache, return nearest - * available parent inode and set @reslv to the path of - * the returned directory. - * - * @itable - inode table - * @path - path whose parent has to be looked up. - * @reslv - if immediate parent is not available, reslv will be set to path of the - * resolved parent. - * - * return - should never return NULL. should at least return '/' inode. - */ -static inode_t * -__libgf_client_path_to_parenti (libglusterfs_client_ctx_t *ctx, - inode_table_t *itable, const char *path, - char **reslv) -{ - char *resolved_till = NULL; - char *strtokptr = NULL; - char *component = NULL; - char *next_component = NULL; - char *pathdup = NULL; - inode_t *curr = NULL; - inode_t *parent = NULL; - size_t pathlen = 0; - loc_t rootloc = {0, }; - int ret = -1; - - pathlen = STRLEN_0 (path); - resolved_till = CALLOC (1, pathlen); - - GF_VALIDATE_OR_GOTO("libglusterfsclient-dentry", resolved_till, out); - pathdup = strdup (path); - GF_VALIDATE_OR_GOTO("libglusterfsclient-dentry", pathdup, out); - - parent = inode_ref (itable->root); - /* If the root inode's is outdated, send a revalidate on it. - * A revalidate on root inode also reduces the window in which an - * op will fail over distribute because the layout of the root - * directory did not get constructed when we sent the lookup on - * root in glusterfs_init. That can happen when not all children of a - * distribute volume were up at the time of glusterfs_init. - */ - if (!libgf_is_iattr_cache_valid (ctx, parent, NULL, - LIBGF_VALIDATE_LOOKUP)) { - libgf_client_loc_fill (&rootloc, ctx, 1, 0, "/"); - ret = libgf_client_lookup (ctx, &rootloc, NULL, NULL, NULL); - if (ret == -1) { - gf_log ("libglusterfsclient-dentry", GF_LOG_ERROR, - "Root inode revalidation failed"); - inode_unref (parent); - parent = NULL; - goto out; - } - libgf_client_loc_wipe (&rootloc); - } - - curr = NULL; - - component = strtok_r (pathdup, "/", &strtokptr); - - while (component) { - curr = inode_search (itable, parent->ino, component); - if (!curr) { - break; - } - if (!libgf_is_iattr_cache_valid (ctx, curr, NULL, - LIBGF_VALIDATE_LOOKUP)) - break; - - /* It is OK to append the component even if it is the - last component in the path, because, if 'next_component' - returns NULL, @parent will remain the same and - @resolved_till will not be sent back - */ - strcat (resolved_till, "/"); - strcat (resolved_till, component); - - next_component = strtok_r (NULL, "/", &strtokptr); - - if (next_component) { - inode_unref (parent); - parent = curr; - curr = NULL; - } else { - /* will break */ - inode_unref (curr); - } - - component = next_component; - } - - if (resolved_till[0] == '\0') { - strcat (resolved_till, "/"); - } - - free (pathdup); - - if (reslv) { - *reslv = resolved_till; - } else { - FREE (resolved_till); - } - -out: - return parent; -} - -static inline void -libgf_client_update_resolved (const char *path, char *resolved) -{ - int32_t pathlen = 0; - char *tmp = NULL, *dest = NULL, *dname = NULL; - char append_slash = 0; - - pathlen = strlen (resolved); - tmp = (char *)(resolved + pathlen); - if (*((char *) (resolved + pathlen - 1)) != '/') { - tmp[0] = '/'; - append_slash = 1; - } - - if (append_slash) { - dest = tmp + 1; - } else { - dest = tmp; - } - - if (*((char *) path + pathlen) == '/') { - dname = (char *) path + pathlen + 1; - } else { - dname = (char *) path + pathlen; - } - - strcpy_till (dest, dname, '/'); -} - -/* __do_path_resolve - resolve @loc->path into @loc->inode and @loc->parent. also - * update the dentry cache - * - * @loc - loc to resolve. - * @ctx - libglusterfsclient context - * @lookup_basename - flag whether to lookup basename(loc->path) - * - * return - 0 on success - * -1 on failure - * - */ -static int32_t -__do_path_resolve (loc_t *loc, libglusterfs_client_ctx_t *ctx, - char lookup_basename) -{ - int32_t op_ret = -1; - char *resolved = NULL; - inode_t *parent = NULL, *inode = NULL; - dentry_t *dentry = NULL; - loc_t new_loc = {0, }; - char *pathname = NULL, *directory = NULL; - char *file = NULL; - - parent = loc->parent; - if (parent) { - inode_ref (parent); - gf_log ("libglusterfsclient-dentry", GF_LOG_DEBUG, - "loc->parent(%"PRId64") already present. sending " - "lookup for %"PRId64"/%s", parent->ino, parent->ino, - loc->path); - resolved = strdup (loc->path); - resolved = dirname (resolved); - } else { - parent = __libgf_client_path_to_parenti (ctx, ctx->itable, - loc->path, &resolved); - } - - if (parent == NULL) { - /* fire in the bush.. run! run!! run!!! */ - gf_log ("libglusterfsclient-dentry", - GF_LOG_CRITICAL, - "failed to get parent inode number"); - op_ret = -1; - goto out; - } - - gf_log ("libglusterfsclient-dentry", - GF_LOG_DEBUG, - "resolved path(%s) till %"PRId64"(%s). " - "sending lookup for remaining path", - loc->path, parent->ino, resolved); - - pathname = strdup (loc->path); - directory = dirname (pathname); - pathname = NULL; - - while (strcmp (resolved, directory) != 0) - { - dentry = NULL; - - LIBGLUSTERFS_CLIENT_DENTRY_LOC_PREPARE (new_loc, loc, parent, - resolved); - - if (pathname) { - free (pathname); - pathname = NULL; - } - - pathname = strdup (new_loc.path); - file = basename (pathname); - - new_loc.inode = inode_search (ctx->itable, parent->ino, file); - if (new_loc.inode) { - if (libgf_is_iattr_cache_valid (ctx, new_loc.inode, - NULL, - LIBGF_VALIDATE_LOOKUP)) - dentry = dentry_search_for_inode (new_loc.inode, - parent->ino, - file); - } - - if (dentry == NULL) { - op_ret = libgf_client_lookup (ctx, &new_loc, NULL, NULL, - 0); - if (op_ret == -1) { - inode_ref (new_loc.parent); - libgf_client_loc_wipe (&new_loc); - goto out; - } - } - - parent = inode_ref (new_loc.inode); - libgf_client_loc_wipe (&new_loc); - - libgf_client_update_resolved (loc->path, resolved); - } - - if (pathname) { - free (pathname); - pathname = NULL; - } - - if (lookup_basename) { - pathname = strdup (loc->path); - file = basename (pathname); - - inode = inode_search (ctx->itable, parent->ino, file); - if (!inode) { - libgf_client_loc_fill (&new_loc, ctx, 0, parent->ino, - file); - - op_ret = libgf_client_lookup (ctx, &new_loc, NULL, NULL, - 0); - if (op_ret == -1) { - libgf_client_loc_wipe (&new_loc); - goto out; - } - - inode = inode_ref (new_loc.inode); - libgf_client_loc_wipe (&new_loc); - } - } - - op_ret = 0; -out: - loc->inode = inode; - loc->parent = parent; - - FREE (resolved); - if (pathname) { - FREE (pathname); - } - - if (directory) { - FREE (directory); - } - - return op_ret; -} - - -/* resolves loc->path to loc->parent and loc->inode */ -int32_t -libgf_client_path_lookup (loc_t *loc, - libglusterfs_client_ctx_t *ctx, - char lookup_basename) -{ - char *pathname = NULL; - char *directory = NULL; - inode_t *inode = NULL; - inode_t *parent = NULL; - int32_t op_ret = 0; - - pathname = strdup (loc->path); - directory = dirname (pathname); - parent = inode_from_path (ctx->itable, directory); - - if (parent != NULL) { - loc->parent = parent; - - if (!lookup_basename) { - gf_log ("libglusterfsclient", - GF_LOG_DEBUG, - "resolved dirname(%s) to %"PRId64, - loc->path, parent->ino); - goto out; - } else { - inode = inode_from_path (ctx->itable, loc->path); - if (inode != NULL) { - gf_log ("libglusterfsclient", - GF_LOG_DEBUG, - "resolved path(%s) to %"PRId64"/%"PRId64, - loc->path, parent->ino, inode->ino); - loc->inode = inode; - goto out; - } - } - } - - if (parent) { - inode_unref (parent); - } else if (inode) { - inode_unref (inode); - gf_log ("libglusterfsclient", - GF_LOG_ERROR, - "undesired behaviour. inode(%"PRId64") for %s " - "exists without parent (%s)", - inode->ino, loc->path, directory); - } - op_ret = __do_path_resolve (loc, ctx, lookup_basename); -out: - if (pathname) - free (pathname); - - return op_ret; -} |