diff options
author | Raghavendra G <raghavendra@zresearch.com> | 2009-03-25 06:52:05 -0700 |
---|---|---|
committer | Anand V. Avati <avati@amp.gluster.com> | 2009-04-03 19:24:09 +0530 |
commit | cf6f21928dbe3489de5dfdc3513f3be5f5ef529d (patch) | |
tree | d9a63fbab63fd185e3801d4c8b42da1efcf0227a /libglusterfsclient/src | |
parent | 6eb419f1ca68f536a700e63c1521e428560a0d9d (diff) |
libglusterfsclient code changes
- add dentry support to libglusterfsclient.
- changes related to using array, to store context in inode instead of
dictionary.
- code changes related to cleanup of libglusterfsclient interface.
- added glusterfs_mkdir and glusterfs_rmdir
- other changes in libglusterfsclient to make it work with code changes
in other parts of glusterfs.
Signed-off-by: Anand V. Avati <avati@amp.gluster.com>
Diffstat (limited to 'libglusterfsclient/src')
-rw-r--r-- | libglusterfsclient/src/Makefile.am | 2 | ||||
-rw-r--r-- | libglusterfsclient/src/libglusterfsclient-dentry.c | 385 | ||||
-rwxr-xr-x | libglusterfsclient/src/libglusterfsclient-internals.h | 21 | ||||
-rwxr-xr-x | libglusterfsclient/src/libglusterfsclient.c | 802 | ||||
-rwxr-xr-x | libglusterfsclient/src/libglusterfsclient.h | 399 |
5 files changed, 1173 insertions, 436 deletions
diff --git a/libglusterfsclient/src/Makefile.am b/libglusterfsclient/src/Makefile.am index 8382b2561..531f1fbb9 100644 --- a/libglusterfsclient/src/Makefile.am +++ b/libglusterfsclient/src/Makefile.am @@ -3,7 +3,7 @@ noinst_HEADERS = libglusterfsclient-internals.h libglusterfsclient_HEADERS = libglusterfsclient.h libglusterfsclientdir = $(includedir) -libglusterfsclient_la_SOURCES = libglusterfsclient.c +libglusterfsclient_la_SOURCES = libglusterfsclient.c libglusterfsclient-dentry.c libglusterfsclient_la_CFLAGS = -fPIC -Wall -pthread libglusterfsclient_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la libglusterfsclient_la_CPPFLAGS = -D_FILE_OFFSET_BITS=64 -D$(GF_HOST_OS) -D__USE_FILE_OFFSET64 -D_GNU_SOURCE -I$(top_srcdir)/libglusterfs/src -DDATADIR=\"$(localstatedir)\" -DCONFDIR=\"$(sysconfdir)/glusterfs\" $(GF_CFLAGS) diff --git a/libglusterfsclient/src/libglusterfsclient-dentry.c b/libglusterfsclient/src/libglusterfsclient-dentry.c new file mode 100644 index 000000000..f2e1e17ff --- /dev/null +++ b/libglusterfsclient/src/libglusterfsclient-dentry.c @@ -0,0 +1,385 @@ +/* + Copyright (c) 2008, 2009 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#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 (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; + + 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); + curr = NULL; + + component = strtok_r (pathdup, "/", &strtokptr); + + while (component) { + curr = inode_search (itable, parent->ino, component); + if (!curr) { + 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 + * + * return - 0 on success + * -1 on failure + * + */ +static int32_t +__do_path_resolve (loc_t *loc, + libglusterfs_client_ctx_t *ctx) +{ + 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->name); + resolved = strdup (loc->path); + resolved = dirname (resolved); + } else { + parent = __libgf_client_path_to_parenti (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 (resolved); + file = basename (pathname); + + new_loc.inode = inode_search (ctx->itable, parent->ino, file); + if (new_loc.inode) { + 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; + } + + 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) { + /* parent is resolved, file referred by the path may not be + present on the storage*/ + if (strcmp (loc->path, "/") != 0) { + op_ret = 0; + } + + libgf_client_loc_wipe (&new_loc); + goto out; + } + + inode = inode_ref (new_loc.inode); + libgf_client_loc_wipe (&new_loc); + } + +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 *pathname = NULL; + char *directory = NULL; + inode_t *inode = NULL; + inode_t *parent = NULL; + int32_t op_ret = 0; + loc_t new_loc = {0, }; + + /* workaround for xlators like dht which require lookup to be sent + on / */ + + libgf_client_loc_fill (&new_loc, ctx, 1, 0, "/"); + + op_ret = libgf_client_lookup (ctx, &new_loc, NULL, NULL, NULL); + if (op_ret == -1) { + gf_log ("libglusterfsclient-dentry", + GF_LOG_ERROR, + "lookup of / failed"); + goto out; + } + libgf_client_loc_wipe (&new_loc); + + inode = inode_from_path (ctx->itable, loc->path); + pathname = strdup (loc->path); + directory = dirname (pathname); + parent = inode_from_path (ctx->itable, directory); + + if (inode && parent) { + gf_log ("libglusterfsclient", + GF_LOG_DEBUG, + "resolved path(%s) to %"PRId64"/%"PRId64"(%s)", + loc->path, parent->ino, inode->ino, loc->name); + loc->inode = inode; + loc->parent = parent; + goto out; + } else { + gf_log ("libglusterfsclient", + GF_LOG_DEBUG, + "resolved path(%s) to %p(%"PRId64")/%p(%"PRId64")", + loc->path, parent, (parent ? parent->ino : 0), + inode, (inode ? inode->ino : 0)); + 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); + } + +out: + if (pathname) + free (pathname); + + return op_ret; +} diff --git a/libglusterfsclient/src/libglusterfsclient-internals.h b/libglusterfsclient/src/libglusterfsclient-internals.h index bf87f2a23..4296284fd 100755 --- a/libglusterfsclient/src/libglusterfsclient-internals.h +++ b/libglusterfsclient/src/libglusterfsclient-internals.h @@ -141,4 +141,25 @@ typedef struct { STACK_DESTROY (frame->root); \ } while (0) +void +libgf_client_loc_wipe (loc_t *loc); + +int32_t +libgf_client_loc_fill (loc_t *loc, + libglusterfs_client_ctx_t *ctx, + ino_t ino, + ino_t par, + const char *name); + +int32_t +libgf_client_path_lookup (loc_t *loc, + libglusterfs_client_ctx_t *ctx); + +int32_t +libgf_client_lookup (libglusterfs_client_ctx_t *ctx, + loc_t *loc, + struct stat *stbuf, + dict_t **dict, + dict_t *xattr_req); + #endif diff --git a/libglusterfsclient/src/libglusterfsclient.c b/libglusterfsclient/src/libglusterfsclient.c index 6de8ad879..6eac2ecf4 100755 --- a/libglusterfsclient/src/libglusterfsclient.c +++ b/libglusterfsclient/src/libglusterfsclient.c @@ -42,7 +42,7 @@ #include "compat-errno.h" #define XLATOR_NAME "libglusterfsclient" -#define LIBGLUSTERFS_INODE_TABLE_LRU_LIMIT 14057 +#define LIBGLUSTERFS_INODE_TABLE_LRU_LIMIT 1000 //14057 typedef struct { pthread_cond_t init_con_established; @@ -73,8 +73,8 @@ typedef struct libglusterfs_client_async_local { struct { fd_t *fd; - glusterfs_writev_cbk_t cbk; - }writev_cbk; + glusterfs_write_cbk_t cbk; + }write_cbk; struct { fd_t *fd; @@ -85,7 +85,7 @@ typedef struct libglusterfs_client_async_local { size_t size; loc_t *loc; char is_revalidate; - glusterfs_lookup_cbk_t cbk; + glusterfs_get_cbk_t cbk; }lookup_cbk; }fop; }libglusterfs_client_async_local_t; @@ -131,9 +131,12 @@ int32_t libgf_client_forget (xlator_t *this, inode_t *inode) { + uint64_t ptr = 0; libglusterfs_client_inode_ctx_t *ctx = NULL; - inode_ctx_del (inode, this, (uint64_t *)ctx); + inode_ctx_del (inode, this, &ptr); + ctx = (libglusterfs_client_inode_ctx_t *)ptr; + FREE (ctx); return 0; @@ -222,7 +225,7 @@ xlator_graph_fini (xlator_t *xl) } -static void +void libgf_client_loc_wipe (loc_t *loc) { if (loc->path) { @@ -238,64 +241,89 @@ libgf_client_loc_wipe (loc_t *loc) inode_unref (loc->inode); loc->inode = NULL; } + + loc->path = loc->name = NULL; } -static int32_t -libgf_client_loc_fill (loc_t *loc, const char *path, - ino_t ino, libglusterfs_client_ctx_t *ctx) +int32_t +libgf_client_loc_fill (loc_t *loc, + libglusterfs_client_ctx_t *ctx, + ino_t ino, + ino_t par, + const char *name) { - int32_t op_ret = -1; - int32_t ret = 0; - char *dentry_path = NULL; - - loc->inode = NULL; - /* directory structure is flat. All files are immediate children of root */ - if (path) { - /* libglusterfsclient accepts only absolute paths */ - if (path[0] != '/') { - asprintf ((char **) &loc->path, "/%s", path); - } else { - loc->path = strdup (path); - } + inode_t *inode = NULL, *parent = NULL; + int32_t ret = -1; + char *path = NULL; - loc->inode = inode_search (ctx->itable, 1, path); - } else { - loc->inode = inode_search (ctx->itable, ino, NULL); - if (loc->inode == NULL) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "cannot find inode for ino %"PRId64, - ino); - goto out; - } + /* resistance against multiple invocation of loc_fill not to get + reference leaks via inode_search() */ - ret = inode_path (loc->inode, NULL, &dentry_path); - if (ret <= 0) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "inode_path failed for %"PRId64, - loc->inode->ino); - inode_unref (loc->inode); - op_ret = ret; - goto out; - } else { - loc->path = dentry_path; - } - } - - loc->name = strrchr (loc->path, '/'); - if (loc->name) { - loc->name++; - } + inode = loc->inode; + + if (!inode) { + if (ino) + inode = inode_search (ctx->itable, ino, NULL); + if (par && name) + inode = inode_search (ctx->itable, par, name); - loc->parent = inode_ref (ctx->itable->root); + loc->inode = inode; + if (inode) + loc->ino = inode->ino; + } - if (loc->inode) { - loc->ino = loc->inode->ino; + parent = loc->parent; + if (!parent) { + if (inode) + parent = inode_parent (inode, par, name); + else + parent = inode_search (ctx->itable, par, NULL); + loc->parent = parent; } + + if (!loc->path) { + if (name && parent) { + ret = inode_path (parent, name, &path); + if (ret <= 0) { + gf_log ("glusterfs-fuse", GF_LOG_ERROR, + "inode_path failed for %"PRId64"/%s", + parent->ino, name); + goto fail; + } else { + loc->path = path; + } + } else if (inode) { + ret = inode_path (inode, NULL, &path); + if (ret <= 0) { + gf_log ("glusterfs-fuse", GF_LOG_ERROR, + "inode_path failed for %"PRId64, + inode->ino); + goto fail; + } else { + loc->path = path; + } + } + } + + if (loc->path) { + loc->name = strrchr (loc->path, '/'); + if (loc->name) + loc->name++; + else loc->name = ""; + } - op_ret = 0; -out: - return op_ret; + if ((ino != 1) && + (parent == NULL)) { + gf_log ("fuse-bridge", GF_LOG_ERROR, + "failed to search parent for %"PRId64"/%s (%"PRId64")", + (ino_t)par, name, (ino_t)ino); + ret = -1; + goto fail; + } + ret = 0; +fail: + return ret; } @@ -365,9 +393,8 @@ libgf_client_init (xlator_t *this) return 0; } - -libglusterfs_handle_t -glusterfs_init (glusterfs_init_ctx_t *init_ctx) +glusterfs_handle_t +glusterfs_init (glusterfs_init_params_t *init_ctx) { libglusterfs_client_ctx_t *ctx = NULL; libglusterfs_client_private_t *priv = NULL; @@ -408,12 +435,13 @@ glusterfs_init (glusterfs_init_ctx_t *init_ctx) LOCK_INIT (&pool->lock); INIT_LIST_HEAD (&pool->all_frames); + /* FIXME: why is count hardcoded to 16384 */ ctx->gf_ctx.event_pool = event_pool_new (16384); lim.rlim_cur = RLIM_INFINITY; lim.rlim_max = RLIM_INFINITY; setrlimit (RLIMIT_CORE, &lim); - setrlimit (RLIMIT_NOFILE, &lim); + setrlimit (RLIMIT_NOFILE, &lim); ctx->gf_ctx.cmd_args.log_level = GF_LOG_WARNING; @@ -589,6 +617,9 @@ glusterfs_init (glusterfs_init_ctx_t *init_ctx) return NULL; } + set_global_ctx_ptr (&ctx->gf_ctx); + ctx->gf_ctx.process_uuid = zr_build_process_uuid (); + if (xlator_graph_init (graph) == -1) { fprintf (stderr, "libglusterfsclient: %s:%s():%d: graph initialization failed\n", @@ -645,9 +676,6 @@ glusterfs_init (glusterfs_init_ctx_t *init_ctx) return NULL; } - set_global_ctx_ptr (&ctx->gf_ctx); - ctx->gf_ctx.process_uuid = zr_build_process_uuid (); - pthread_mutex_lock (&priv->lock); { while (!priv->complete) { @@ -683,8 +711,10 @@ void glusterfs_log_unlock (void) int -glusterfs_fini (libglusterfs_client_ctx_t *ctx) +glusterfs_fini (glusterfs_handle_t handle) { + libglusterfs_client_ctx_t *ctx = handle; + FREE (ctx->gf_ctx.cmd_args.log_file); FREE (ctx->gf_ctx.cmd_args.volume_file); FREE (ctx->gf_ctx.cmd_args.volume_name); @@ -732,12 +762,15 @@ libgf_client_lookup_cbk (call_frame_t *frame, dict_t *xattr_req = NULL; if (op_ret == 0) { - /* flat directory structure */ - inode_t *parent = inode_search (ctx->itable, 1, NULL); + inode_t *parent = NULL; - inode_link (inode, parent, local->fop.lookup.loc->path, buf); - inode_lookup (inode); - inode_unref (parent); + if (local->fop.lookup.loc->ino == 1) { + buf->st_ino = 1; + } + + parent = local->fop.lookup.loc->parent; + inode_link (inode, parent, local->fop.lookup.loc->name, buf); + /* inode_lookup (inode); */ } else { if (local->fop.lookup.is_revalidate == 0 && op_errno == ENOENT) { gf_log ("libglusterfsclient", GF_LOG_DEBUG, @@ -836,20 +869,14 @@ libgf_client_lookup (libglusterfs_client_ctx_t *ctx, uint64_t ptr = 0; this = ctx->gf_ctx.graph; - LOCK (&inode->lock); - { - ret = __inode_ctx_get (inode, this, &ptr); - if (ret == -1) { - inode_ctx = CALLOC (1, sizeof (*inode_ctx)); - ERR_ABORT (inode_ctx); - pthread_mutex_init (&inode_ctx->lock, NULL); - __inode_ctx_put (inode, this, - (uint64_t)(long)inode_ctx); - } else { - inode_ctx = (libglusterfs_client_inode_ctx_t *)(long)ptr; - } - } - UNLOCK (&inode->lock); + ret = inode_ctx_get (inode, this, &ptr); + if (ret == -1) { + inode_ctx = CALLOC (1, sizeof (*inode_ctx)); + ERR_ABORT (inode_ctx); + pthread_mutex_init (&inode_ctx->lock, NULL); + } else { + inode_ctx = (libglusterfs_client_inode_ctx_t *)(long)ptr; + } current = time (NULL); @@ -862,6 +889,11 @@ libgf_client_lookup (libglusterfs_client_ctx_t *ctx, } pthread_mutex_unlock (&inode_ctx->lock); + ret = inode_ctx_get (inode, this, NULL); + if (ret == -1) { + inode_ctx_put (inode, this, (uint64_t)(long)inode_ctx); + } + if (stbuf) *stbuf = stub->args.lookup_cbk.buf; @@ -874,19 +906,38 @@ libgf_client_lookup (libglusterfs_client_ctx_t *ctx, } int -glusterfs_lookup (libglusterfs_handle_t handle, - const char *path, - void *buf, - size_t size, - struct stat *stbuf) +glusterfs_get (glusterfs_handle_t handle, + const char *path, + void *buf, + size_t size, + struct stat *stbuf) { int32_t op_ret = 0; loc_t loc = {0, }; libglusterfs_client_ctx_t *ctx = handle; dict_t *dict = NULL; dict_t *xattr_req = NULL; + char *name = NULL, *pathname = NULL; + + if (!ctx || !path || path[0] != '/') { + errno = EINVAL; + op_ret = -1; + goto out; + } + + loc.path = strdup (path); + op_ret = libgf_client_path_lookup (&loc, ctx); + if (op_ret == -1) { + gf_log ("libglusterfsclient", + GF_LOG_ERROR, + "path lookup failed for (%s)", path); + goto out; + } - op_ret = libgf_client_loc_fill (&loc, path, 0, ctx); + pathname = strdup (path); + name = basename (pathname); + + op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, name); if (op_ret < 0) { gf_log ("libglusterfsclient", GF_LOG_ERROR, @@ -925,15 +976,19 @@ glusterfs_lookup (libglusterfs_handle_t handle, } } - if (dict) { - dict_unref (dict); - } - - libgf_client_loc_wipe (&loc); out: if (xattr_req) { dict_unref (xattr_req); } + + if (dict) { + dict_unref (dict); + } + + if (pathname) { + FREE (pathname); + } + libgf_client_loc_wipe (&loc); return op_ret; } @@ -945,40 +1000,34 @@ libgf_client_lookup_async_cbk (call_frame_t *frame, int32_t op_ret, int32_t op_errno, inode_t *inode, - struct stat *buf, + struct stat *stbuf, dict_t *dict) { libglusterfs_client_async_local_t *local = frame->local; - glusterfs_lookup_cbk_t lookup_cbk = local->fop.lookup_cbk.cbk; + glusterfs_get_cbk_t lookup_cbk = local->fop.lookup_cbk.cbk; libglusterfs_client_ctx_t *ctx = frame->root->state; + glusterfs_iobuf_t *iobuf = NULL; dict_t *xattr_req = NULL; - uint64_t ptr = 0; int32_t ret = 0; if (op_ret == 0) { time_t current = 0; + data_t *inode_ctx_data = NULL; libglusterfs_client_inode_ctx_t *inode_ctx = NULL; + inode_t *parent = NULL; + + parent = local->fop.lookup_cbk.loc->parent; + inode_link (inode, parent, local->fop.lookup_cbk.loc->name, stbuf); + + inode_ctx_data = dict_get (inode->ctx, XLATOR_NAME); + if (inode_ctx_data) { + inode_ctx = data_to_ptr (inode_ctx_data); + } - /* flat directory structure */ - inode_t *parent = inode_search (ctx->itable, 1, NULL); - - inode_link (inode, parent, local->fop.lookup_cbk.loc->path, - buf); - - LOCK (&inode->lock); - { - ret = __inode_ctx_get (inode, this, &ptr); - if (ret == -1) { - inode_ctx = CALLOC (1, sizeof (*inode_ctx)); - ERR_ABORT (inode_ctx); - pthread_mutex_init (&inode_ctx->lock, NULL); - __inode_ctx_put (inode, this, - (uint64_t)(long)inode_ctx); - } else { - inode_ctx = (libglusterfs_client_inode_ctx_t *)(long)ptr; - } + if (!inode_ctx) { + inode_ctx = CALLOC (1, sizeof (*inode_ctx)); + pthread_mutex_init (&inode_ctx->lock, NULL); } - UNLOCK (&inode->lock); current = time (NULL); @@ -986,12 +1035,16 @@ libgf_client_lookup_async_cbk (call_frame_t *frame, { inode_ctx->previous_lookup_time = current; inode_ctx->previous_stat_time = current; - memcpy (&inode_ctx->stbuf, buf, sizeof (inode_ctx->stbuf)); + memcpy (&inode_ctx->stbuf, stbuf, sizeof (inode_ctx->stbuf)); } pthread_mutex_unlock (&inode_ctx->lock); - inode_lookup (inode); - inode_unref (parent); + ret = inode_ctx_get (inode, this, NULL); + if (ret == -1) { + inode_ctx_put (inode, this, (uint64_t)(long)inode_ctx); + } + + /* inode_lookup (inode); */ } else { if (local->fop.lookup_cbk.is_revalidate == 0 && op_errno == ENOENT) { gf_log ("libglusterfsclient", GF_LOG_DEBUG, @@ -1022,7 +1075,7 @@ libgf_client_lookup_async_cbk (call_frame_t *frame, /* TODO: set proper error code */ op_errno = errno; inode = NULL; - buf = NULL; + stbuf = NULL; dict = NULL; dict_unref (xattr_req); goto out; @@ -1041,25 +1094,35 @@ libgf_client_lookup_async_cbk (call_frame_t *frame, return 0; } - } out: - if (!op_ret && local->fop.lookup_cbk.size && dict && local->fop.lookup_cbk.buf) { + if (!op_ret && local->fop.lookup_cbk.size && dict) { data_t *mem_data = NULL; void *mem = NULL; + struct iovec *vector = NULL; mem_data = dict_get (dict, "glusterfs.content"); if (mem_data) { mem = data_to_ptr (mem_data); } - if (mem && buf->st_size <= local->fop.lookup_cbk.size) { - memcpy (local->fop.lookup_cbk.buf, mem, buf->st_size); - } - } + if (mem && stbuf->st_size <= local->fop.lookup_cbk.size) { + iobuf = CALLOC (1, sizeof (*iobuf)); + ERR_ABORT (iobuf); - lookup_cbk(op_ret, op_errno, local->fop.lookup_cbk.buf, buf, local->cbk_data); + vector = CALLOC (1, sizeof (*vector)); + ERR_ABORT (vector); + vector->iov_base = mem; + vector->iov_len = stbuf->st_size; + + iobuf->vector = vector; + iobuf->count = 1; + iobuf->ref = dict_ref (dict); + } + } + + lookup_cbk (op_ret, op_errno, iobuf, stbuf, local->cbk_data); libgf_client_loc_wipe (local->fop.lookup_cbk.loc); free (local->fop.lookup_cbk.loc); @@ -1071,25 +1134,43 @@ out: return 0; } +/* TODO: implement async dentry lookup */ + int -glusterfs_lookup_async (libglusterfs_handle_t handle, - const char *path, - void *buf, - size_t size, - glusterfs_lookup_cbk_t cbk, - void *cbk_data) +glusterfs_get_async (glusterfs_handle_t handle, + const char *path, + size_t size, + glusterfs_get_cbk_t cbk, + void *cbk_data) { loc_t *loc = NULL; libglusterfs_client_ctx_t *ctx = handle; libglusterfs_client_async_local_t *local = NULL; int32_t op_ret = 0; dict_t *xattr_req = NULL; + char *name = NULL, *pathname = NULL; + if (!ctx || !path || path[0] != '/') { + errno = EINVAL; + op_ret = -1; + goto out; + } local = CALLOC (1, sizeof (*local)); local->fop.lookup_cbk.is_revalidate = 1; loc = CALLOC (1, sizeof (*loc)); - op_ret = libgf_client_loc_fill (loc, path, 0, ctx); + loc->path = strdup (path); + op_ret = libgf_client_path_lookup (loc, ctx); + if (op_ret == -1) { + gf_log ("libglusterfsclient", + GF_LOG_ERROR, + "path lookup failed for (%s)", path); + goto out; + } + + pathname = strdup (path); + name = basename (pathname); + op_ret = libgf_client_loc_fill (loc, ctx, 0, loc->parent->ino, name); if (op_ret < 0) { gf_log ("libglusterfsclient", GF_LOG_ERROR, @@ -1104,7 +1185,6 @@ glusterfs_lookup_async (libglusterfs_handle_t handle, } local->fop.lookup_cbk.cbk = cbk; - local->fop.lookup_cbk.buf = buf; local->fop.lookup_cbk.size = size; local->fop.lookup_cbk.loc = loc; local->cbk_data = cbk_data; @@ -1134,6 +1214,10 @@ glusterfs_lookup_async (libglusterfs_handle_t handle, } out: + if (pathname) { + FREE (pathname); + } + return op_ret; } @@ -1202,7 +1286,7 @@ libgf_client_getxattr (libglusterfs_client_ctx_t *ctx, } ssize_t -glusterfs_getxattr (libglusterfs_client_ctx_t *ctx, +glusterfs_getxattr (glusterfs_handle_t handle, const char *path, const char *name, void *value, @@ -1211,9 +1295,29 @@ glusterfs_getxattr (libglusterfs_client_ctx_t *ctx, int32_t op_ret = 0; loc_t loc = {0, }; dict_t *dict = NULL; + libglusterfs_client_ctx_t *ctx = handle; + char *file = NULL; + dict_t *xattr_req = NULL; - op_ret = libgf_client_loc_fill (&loc, path, 0, ctx); - if (op_ret < 0) { + if (!ctx || !path || path[0] != '/' || !name || name[0] == '\0') { + errno = EINVAL; + op_ret = -1; + goto out; + } + + loc.path = strdup (path); + op_ret = libgf_client_path_lookup (&loc, ctx); + if (op_ret == -1) { + gf_log ("libglusterfsclient", + GF_LOG_ERROR, + "path lookup failed for (%s)", path); + goto out; + } + + file = strdup (path); + file = basename (file); + op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, file); + if (op_ret == -1) { gf_log ("libglusterfsclient", GF_LOG_ERROR, "libgf_client_loc_fill returned -1, returning EINVAL"); @@ -1221,7 +1325,15 @@ glusterfs_getxattr (libglusterfs_client_ctx_t *ctx, goto out; } - op_ret = libgf_client_lookup (ctx, &loc, NULL, &dict, NULL); + xattr_req = dict_new (); + op_ret = dict_set (xattr_req, (char *)name, + data_from_uint64 (size)); + if (op_ret == -1) { + /* TODO: set proper error code */ + goto out; + } + + op_ret = libgf_client_lookup (ctx, &loc, NULL, &dict, xattr_req); if (op_ret == 0) { data_t *value_data = dict_get (dict, (char *)name); @@ -1237,13 +1349,21 @@ glusterfs_getxattr (libglusterfs_client_ctx_t *ctx, } } +out: + if (file) { + FREE (file); + } + + if (xattr_req) { + dict_unref (xattr_req); + } + if (dict) { dict_unref (dict); } libgf_client_loc_wipe (&loc); -out: return op_ret; } @@ -1331,15 +1451,15 @@ libgf_client_creat (libglusterfs_client_ctx_t *ctx, inode_t *libgf_inode = NULL; time_t current = 0; libglusterfs_client_inode_ctx_t *inode_ctx = NULL; - - /* flat directory structure */ - inode_t *parent = inode_search (ctx->itable, 1, NULL); + inode_t *parent = NULL; + + parent = loc->parent; + libgf_inode = stub->args.create_cbk.inode; inode_link (libgf_inode, parent, - loc->path, &stub->args.create_cbk.buf); + loc->name, &stub->args.create_cbk.buf); - inode_lookup (libgf_inode); - inode_unref (parent); + /* inode_lookup (libgf_inode); */ inode_ctx = CALLOC (1, sizeof (*inode_ctx)); ERR_ABORT (inode_ctx); @@ -1349,7 +1469,7 @@ libgf_client_creat (libglusterfs_client_ctx_t *ctx, inode_ctx->previous_lookup_time = current; inode_ctx->previous_stat_time = current; - memcpy (&inode_ctx->stbuf, &stub->args.lookup_cbk.buf, + memcpy (&inode_ctx->stbuf, &stub->args.create_cbk.buf, sizeof (inode_ctx->stbuf)); this = ctx->gf_ctx.graph; @@ -1403,8 +1523,8 @@ libgf_client_opendir (libglusterfs_client_ctx_t *ctx, return 0; } -unsigned long -glusterfs_open (libglusterfs_client_ctx_t *ctx, +glusterfs_file_t +glusterfs_open (glusterfs_handle_t handle, const char *path, int flags, mode_t mode) @@ -1416,24 +1536,38 @@ glusterfs_open (libglusterfs_client_ctx_t *ctx, char lookup_required = 1; int32_t ret = -1; xlator_t *this = NULL; + libglusterfs_client_ctx_t *ctx = handle; + char *name = NULL, *pathname = NULL; - if (!ctx || !path || path[0] != '/') { - errno = EINVAL; - return 0; - } + if (!ctx || !path || path[0] != '/') { + errno = EINVAL; + op_ret = -1; + goto out; + } - this = ctx->gf_ctx.graph; + loc.path = strdup (path); + op_ret = libgf_client_path_lookup (&loc, ctx); + if (op_ret == -1) { + gf_log ("libglusterfsclient", + GF_LOG_ERROR, + "path lookup failed for (%s)", path); + goto out; + } - op_ret = libgf_client_loc_fill (&loc, path, 0, ctx); - if (op_ret < 0) { + pathname = strdup (path); + name = basename (pathname); + + op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, name); + if (op_ret == -1) { gf_log ("libglusterfsclient", GF_LOG_ERROR, "libgf_client_loc_fill returned -1, returning EINVAL"); errno = EINVAL; - fd = NULL; goto out; } + this = ctx->gf_ctx.graph; + if (loc.inode) { libglusterfs_client_inode_ctx_t *inode_ctx = NULL; time_t current, prev; @@ -1528,19 +1662,23 @@ glusterfs_open (libglusterfs_client_ctx_t *ctx, } } +out: libgf_client_loc_wipe (&loc); -out: - return (long)fd; + if (pathname) { + FREE (pathname); + } + + return fd; } -unsigned long -glusterfs_creat (libglusterfs_client_ctx_t *ctx, +glusterfs_file_t +glusterfs_creat (glusterfs_handle_t handle, const char *path, mode_t mode) { - return glusterfs_open (ctx, path, + return glusterfs_open (handle, path, (O_CREAT | O_WRONLY | O_TRUNC), mode); } @@ -1585,7 +1723,7 @@ libgf_client_flush (libglusterfs_client_ctx_t *ctx, fd_t *fd) int -glusterfs_close (unsigned long fd) +glusterfs_close (glusterfs_file_t fd) { int32_t op_ret = -1; data_t *fd_ctx_data = NULL; @@ -1666,7 +1804,7 @@ libgf_client_setxattr (libglusterfs_client_ctx_t *ctx, } int -glusterfs_setxattr (libglusterfs_client_ctx_t *ctx, +glusterfs_setxattr (glusterfs_handle_t handle, const char *path, const char *name, const void *value, @@ -1677,9 +1815,29 @@ glusterfs_setxattr (libglusterfs_client_ctx_t *ctx, loc_t loc = {0, }; char lookup_required = 1; xlator_t *this = NULL; + libglusterfs_client_ctx_t *ctx = handle; + char *file = NULL; - op_ret = libgf_client_loc_fill (&loc, path, 0, ctx); - if (op_ret < 0) { + if (!ctx || !path || path[0] != '/') { + errno = EINVAL; + op_ret = -1; + goto out; + } + + loc.path = strdup (path); + op_ret = libgf_client_path_lookup (&loc, ctx); + if (op_ret == -1) { + gf_log ("libglusterfsclient", + GF_LOG_ERROR, + "path lookup failed for (%s)", path); + goto out; + } + + file = strdup (path); + file = basename (file); + + op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, file); + if (op_ret == -1) { gf_log ("libglusterfsclient", GF_LOG_ERROR, "libgf_client_loc_fill returned -1, returning EINVAL"); @@ -1721,14 +1879,17 @@ glusterfs_setxattr (libglusterfs_client_ctx_t *ctx, if (!op_ret) op_ret = libgf_client_setxattr (ctx, &loc, name, value, size, flags); - libgf_client_loc_wipe (&loc); - out: + if (file) { + FREE (file); + } + + libgf_client_loc_wipe (&loc); return op_ret; } int -glusterfs_lsetxattr (libglusterfs_client_ctx_t *ctx, +glusterfs_lsetxattr (glusterfs_handle_t handle, const char *path, const char *name, const void *value, @@ -1738,7 +1899,7 @@ glusterfs_lsetxattr (libglusterfs_client_ctx_t *ctx, } int -glusterfs_fsetxattr (unsigned long fd, +glusterfs_fsetxattr (glusterfs_file_t fd, const char *name, const void *value, size_t size, @@ -1764,7 +1925,7 @@ glusterfs_fsetxattr (unsigned long fd, fd_ctx = data_to_ptr (fd_ctx_data); ctx = fd_ctx->ctx; - op_ret = libgf_client_loc_fill (&loc, NULL, __fd->inode->ino, ctx); + op_ret = libgf_client_loc_fill (&loc, ctx, __fd->inode->ino, 0, NULL); if (op_ret < 0) { gf_log ("libglusterfsclient", GF_LOG_ERROR, @@ -1807,13 +1968,13 @@ glusterfs_fsetxattr (unsigned long fd, if (!op_ret) op_ret = libgf_client_setxattr (ctx, &loc, name, value, size, flags); - libgf_client_loc_wipe (&loc); out: + libgf_client_loc_wipe (&loc); return op_ret; } ssize_t -glusterfs_lgetxattr (libglusterfs_client_ctx_t *ctx, +glusterfs_lgetxattr (glusterfs_handle_t handle, const char *path, const char *name, void *value, @@ -1823,7 +1984,7 @@ glusterfs_lgetxattr (libglusterfs_client_ctx_t *ctx, } ssize_t -glusterfs_fgetxattr (unsigned long fd, +glusterfs_fgetxattr (glusterfs_file_t fd, const char *name, void *value, size_t size) @@ -1846,8 +2007,8 @@ glusterfs_fgetxattr (unsigned long fd, fd_ctx = data_to_ptr (fd_ctx_data); ctx = fd_ctx->ctx; - op_ret = libgf_client_loc_fill (&loc, NULL, __fd->inode->ino, ctx); - if (op_ret < 0) { + op_ret = libgf_client_loc_fill (&loc, ctx, __fd->inode->ino, 0, NULL); + if (op_ret == -1) { gf_log ("libglusterfsclient", GF_LOG_ERROR, "libgf_client_loc_fill returned -1, returning EINVAL"); @@ -1871,18 +2032,18 @@ glusterfs_fgetxattr (unsigned long fd, } } +out: if (dict) { dict_unref (dict); } libgf_client_loc_wipe (&loc); -out: return op_ret; } ssize_t -glusterfs_listxattr (libglusterfs_client_ctx_t *ctx, +glusterfs_listxattr (glusterfs_handle_t handle, const char *path, char *list, size_t size) @@ -1891,7 +2052,7 @@ glusterfs_listxattr (libglusterfs_client_ctx_t *ctx, } ssize_t -glusterfs_llistxattr (libglusterfs_client_ctx_t *ctx, +glusterfs_llistxattr (glusterfs_handle_t handle, const char *path, char *list, size_t size) @@ -1900,7 +2061,7 @@ glusterfs_llistxattr (libglusterfs_client_ctx_t *ctx, } ssize_t -glusterfs_flistxattr (unsigned long fd, +glusterfs_flistxattr (glusterfs_file_t fd, char *list, size_t size) { @@ -1908,7 +2069,7 @@ glusterfs_flistxattr (unsigned long fd, } int -glusterfs_removexattr (libglusterfs_client_ctx_t *ctx, +glusterfs_removexattr (glusterfs_handle_t handle, const char *path, const char *name) { @@ -1916,7 +2077,7 @@ glusterfs_removexattr (libglusterfs_client_ctx_t *ctx, } int -glusterfs_lremovexattr (libglusterfs_client_ctx_t *ctx, +glusterfs_lremovexattr (glusterfs_handle_t handle, const char *path, const char *name) { @@ -1924,7 +2085,7 @@ glusterfs_lremovexattr (libglusterfs_client_ctx_t *ctx, } int -glusterfs_fremovexattr (unsigned long fd, +glusterfs_fremovexattr (glusterfs_file_t fd, const char *name) { return ENOSYS; @@ -1990,7 +2151,7 @@ libgf_client_read (libglusterfs_client_ctx_t *ctx, } ssize_t -glusterfs_read (unsigned long fd, +glusterfs_read (glusterfs_file_t fd, void *buf, size_t nbytes) { @@ -2103,7 +2264,7 @@ libgf_client_readv (libglusterfs_client_ctx_t *ctx, ssize_t -glusterfs_readv (unsigned long fd, const struct iovec *vec, int count) +glusterfs_readv (glusterfs_file_t fd, const struct iovec *vec, int count) { int32_t op_ret = -1; off_t offset = 0; @@ -2148,7 +2309,7 @@ out: ssize_t -glusterfs_pread (unsigned long fd, +glusterfs_pread (glusterfs_file_t fd, void *buf, size_t count, off_t offset) @@ -2223,7 +2384,7 @@ libgf_client_writev (libglusterfs_client_ctx_t *ctx, ssize_t -glusterfs_write (unsigned long fd, +glusterfs_write (glusterfs_file_t fd, const void *buf, size_t n) { @@ -2278,9 +2439,9 @@ out: } ssize_t -glusterfs_writev (unsigned long fd, +glusterfs_writev (glusterfs_file_t fd, const struct iovec *vector, - size_t count) + int count) { int32_t op_ret = -1; off_t offset = 0; @@ -2332,7 +2493,7 @@ out: ssize_t -glusterfs_pwrite (unsigned long fd, +glusterfs_pwrite (glusterfs_file_t fd, const void *buf, size_t count, off_t offset) @@ -2449,7 +2610,7 @@ libgf_client_readdir (libglusterfs_client_ctx_t *ctx, } int -glusterfs_readdir (unsigned long fd, +glusterfs_readdir (glusterfs_dir_t fd, struct dirent *dirp, unsigned int count) { @@ -2491,7 +2652,7 @@ out: int -glusterfs_getdents (unsigned long fd, struct dirent *dirp, unsigned int count) +glusterfs_getdents (glusterfs_file_t fd, struct dirent *dirp, unsigned int count) { int op_ret = -1; libglusterfs_client_ctx_t *ctx = NULL; @@ -2539,7 +2700,7 @@ libglusterfs_readv_async_cbk (call_frame_t *frame, int32_t count, struct stat *stbuf) { - glusterfs_read_buf_t *buf; + glusterfs_iobuf_t *buf; libglusterfs_client_async_local_t *local = frame->local; fd_t *__fd = local->fop.readv_cbk.fd; glusterfs_readv_cbk_t readv_cbk = local->fop.readv_cbk.cbk; @@ -2552,8 +2713,6 @@ libglusterfs_readv_async_cbk (call_frame_t *frame, } buf->count = count; - buf->op_ret = op_ret; - buf->op_errno = op_errno; if (frame->root->rsp_refs) { buf->ref = dict_ref (frame->root->rsp_refs); @@ -2573,7 +2732,7 @@ libglusterfs_readv_async_cbk (call_frame_t *frame, pthread_mutex_unlock (&fd_ctx->lock); } - readv_cbk (buf, local->cbk_data); + readv_cbk (op_ret, op_errno, buf, local->cbk_data); FREE (local); frame->local = NULL; @@ -2583,7 +2742,7 @@ libglusterfs_readv_async_cbk (call_frame_t *frame, } void -glusterfs_free (glusterfs_read_buf_t *buf) +glusterfs_free (glusterfs_iobuf_t *buf) { //iov_free (buf->vector, buf->count); FREE (buf->vector); @@ -2591,8 +2750,8 @@ glusterfs_free (glusterfs_read_buf_t *buf) FREE (buf); } -int -glusterfs_read_async (unsigned long fd, +int +glusterfs_read_async (glusterfs_file_t fd, size_t nbytes, off_t offset, glusterfs_readv_cbk_t readv_cbk, @@ -2652,10 +2811,10 @@ libglusterfs_writev_async_cbk (call_frame_t *frame, { libglusterfs_client_async_local_t *local = frame->local; fd_t *fd = NULL; - glusterfs_writev_cbk_t writev_cbk; + glusterfs_write_cbk_t write_cbk; - writev_cbk = local->fop.writev_cbk.cbk; - fd = local->fop.writev_cbk.fd; + write_cbk = local->fop.write_cbk.cbk; + fd = local->fop.write_cbk.fd; if (op_ret > 0) { libglusterfs_client_fd_ctx_t *fd_ctx = NULL; @@ -2672,18 +2831,18 @@ libglusterfs_writev_async_cbk (call_frame_t *frame, pthread_mutex_unlock (&fd_ctx->lock); } - writev_cbk (op_ret, op_errno, local->cbk_data); + write_cbk (op_ret, op_errno, local->cbk_data); STACK_DESTROY (frame->root); return 0; } int32_t -glusterfs_write_async (unsigned long fd, +glusterfs_write_async (glusterfs_file_t fd, const void *buf, size_t nbytes, off_t offset, - glusterfs_writev_cbk_t writev_cbk, + glusterfs_write_cbk_t write_cbk, void *cbk_data) { fd_t *__fd = (fd_t *)fd; @@ -2697,8 +2856,8 @@ glusterfs_write_async (unsigned long fd, local = CALLOC (1, sizeof (*local)); ERR_ABORT (local); - local->fop.writev_cbk.fd = __fd; - local->fop.writev_cbk.cbk = writev_cbk; + local->fop.write_cbk.fd = __fd; + local->fop.write_cbk.cbk = write_cbk; local->cbk_data = cbk_data; vector.iov_base = (void *)buf; @@ -2736,7 +2895,7 @@ out: } off_t -glusterfs_lseek (unsigned long fd, off_t offset, int whence) +glusterfs_lseek (glusterfs_file_t fd, off_t offset, int whence) { off_t __offset = 0; int32_t op_ret = -1; @@ -2803,12 +2962,13 @@ glusterfs_lseek (unsigned long fd, off_t offset, int whence) if (cache_valid) { end = inode_ctx->stbuf.st_size; } else { - op_ret = libgf_client_loc_fill (&loc, NULL, __fd->inode->ino, ctx); - if (op_ret < 0) { + op_ret = libgf_client_loc_fill (&loc, ctx, __fd->inode->ino, 0, NULL); + if (op_ret == -1) { gf_log ("libglusterfsclient", GF_LOG_ERROR, "libgf_client_loc_fill returned -1, returning EINVAL"); errno = EINVAL; + libgf_client_loc_wipe (&loc); __offset = -1; goto out; } @@ -2816,6 +2976,7 @@ glusterfs_lseek (unsigned long fd, off_t offset, int whence) op_ret = libgf_client_lookup (ctx, &loc, &stbuf, NULL, NULL); if (op_ret < 0) { __offset = -1; + libgf_client_loc_wipe (&loc); goto out; } @@ -2823,6 +2984,7 @@ glusterfs_lseek (unsigned long fd, off_t offset, int whence) } __offset = end + offset; + libgf_client_loc_wipe (&loc); } break; @@ -2931,7 +3093,7 @@ out: } int32_t -glusterfs_stat (libglusterfs_handle_t handle, +glusterfs_stat (glusterfs_handle_t handle, const char *path, struct stat *buf) { @@ -2940,9 +3102,28 @@ glusterfs_stat (libglusterfs_handle_t handle, char lookup_required = 1; libglusterfs_client_ctx_t *ctx = handle; xlator_t *this = NULL; + char *name = NULL, *pathname = NULL; - op_ret = libgf_client_loc_fill (&loc, path, 0, ctx); - if (op_ret < 0) { + if (!ctx || !path || path[0] != '/') { + errno = EINVAL; + op_ret = -1; + goto out; + } + + loc.path = strdup (path); + op_ret = libgf_client_path_lookup (&loc, ctx); + if (op_ret == -1) { + gf_log ("libglusterfsclient", + GF_LOG_ERROR, + "path lookup failed for (%s)", path); + goto out; + } + + pathname = strdup (path); + name = basename (pathname); + + op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, name); + if (op_ret == -1) { gf_log ("libglusterfsclient", GF_LOG_ERROR, "libgf_client_loc_fill returned -1, returning EINVAL"); @@ -2986,12 +3167,17 @@ glusterfs_stat (libglusterfs_handle_t handle, op_ret = libgf_client_stat (ctx, &loc, buf); } - libgf_client_loc_wipe (&loc); out: + if (pathname) { + FREE (pathname); + } + + libgf_client_loc_wipe (&loc); return op_ret; } + static int32_t libgf_client_fstat_cbk (call_frame_t *frame, void *cookie, @@ -3079,7 +3265,7 @@ out: } int32_t -glusterfs_fstat (unsigned long fd, struct stat *buf) +glusterfs_fstat (glusterfs_file_t fd, struct stat *buf) { libglusterfs_client_ctx_t *ctx; fd_t *__fd = (fd_t *)fd; @@ -3102,7 +3288,195 @@ glusterfs_fstat (unsigned long fd, struct stat *buf) out: return op_ret; } - + + +static int32_t +libgf_client_mkdir_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf) +{ + libgf_client_local_t *local = frame->local; + + local->reply_stub = fop_mkdir_cbk_stub (frame, NULL, op_ret, op_errno, inode, buf); + + pthread_mutex_lock (&local->lock); + { + local->complete = 1; + pthread_cond_broadcast (&local->reply_cond); + } + pthread_mutex_unlock (&local->lock); + + return 0; +} + + +static int32_t +libgf_client_mkdir (libglusterfs_client_ctx_t *ctx, + loc_t *loc, + mode_t mode) +{ + int32_t op_ret = -1; + call_stub_t *stub = NULL; + libgf_client_local_t *local = NULL; + xlator_t *this = NULL; + + LIBGF_CLIENT_FOP (ctx, stub, mkdir, local, loc, mode); + + if (stub->args.mkdir_cbk.op_ret == 0) { + inode_t *libgf_inode = NULL; + time_t current = 0; + libglusterfs_client_inode_ctx_t *inode_ctx = NULL; + inode_t *parent = NULL; + + parent = loc->parent; + + libgf_inode = stub->args.mkdir_cbk.inode; + inode_link (libgf_inode, parent, + loc->name, &stub->args.mkdir_cbk.buf); + + /* inode_lookup (libgf_inode); */ + + inode_ctx = CALLOC (1, sizeof (*inode_ctx)); + ERR_ABORT (inode_ctx); + pthread_mutex_init (&inode_ctx->lock, NULL); + + current = time (NULL); + + inode_ctx->previous_lookup_time = current; + inode_ctx->previous_stat_time = current; + memcpy (&inode_ctx->stbuf, &stub->args.mkdir_cbk.buf, + sizeof (inode_ctx->stbuf)); + + this = ctx->gf_ctx.graph; + inode_ctx_put (libgf_inode, this, (uint64_t)(long)inode_ctx); + } + + op_ret = stub->args.mkdir_cbk.op_ret; + errno = stub->args.mkdir_cbk.op_errno; + + call_stub_destroy (stub); + + return op_ret; +} + + +int32_t +glusterfs_mkdir (glusterfs_handle_t handle, + const char *path, + mode_t mode) +{ + libglusterfs_client_ctx_t *ctx = handle; + loc_t loc = {0, }; + char *pathname = NULL, *name = NULL; + int32_t op_ret = -1; + + if (!ctx || !path || path[0] != '/') { + errno = EINVAL; + op_ret = -1; + goto out; + } + + loc.path = strdup (path); + op_ret = libgf_client_path_lookup (&loc, ctx); + if (op_ret == -1) { + gf_log ("libglusterfsclient", + GF_LOG_ERROR, + "path lookup failed for (%s)", path); + goto out; + } + + pathname = strdup (path); + name = basename (pathname); + + op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, name); + if (op_ret == -1) { + gf_log ("libglusterfsclient", + GF_LOG_ERROR, + "libgf_client_loc_fill returned -1, returning EINVAL"); + errno = EINVAL; + goto out; + } + + op_ret = libgf_client_mkdir (ctx, &loc, mode); + if (op_ret == -1) { + goto out; + } + +out: + libgf_client_loc_wipe (&loc); + if (pathname) { + free (pathname); + pathname = NULL; + } + + return op_ret; +} + + +static int32_t +libgf_client_rmdir (libglusterfs_client_ctx_t *ctx, + loc_t *loc) +{ + return 0; +} + + +int32_t +glusterfs_rmdir (glusterfs_handle_t handle, + const char *path) +{ + libglusterfs_client_ctx_t *ctx = handle; + loc_t loc = {0, }; + char *pathname = NULL, *name = NULL; + int32_t op_ret = -1; + + if (!ctx || !path || path[0] != '/') { + errno = EINVAL; + op_ret = -1; + goto out; + } + + loc.path = strdup (path); + op_ret = libgf_client_path_lookup (&loc, ctx); + if (op_ret == -1) { + gf_log ("libglusterfsclient", + GF_LOG_ERROR, + "path lookup failed for (%s)", path); + goto out; + } + + pathname = strdup (path); + name = basename (pathname); + + op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, name); + if (op_ret == -1) { + gf_log ("libglusterfsclient", + GF_LOG_ERROR, + "libgf_client_loc_fill returned -1, returning EINVAL"); + errno = EINVAL; + goto out; + } + + op_ret = libgf_client_rmdir (ctx, &loc); + if (op_ret == -1) { + goto out; + } + +out: + libgf_client_loc_wipe (&loc); + + if (pathname) { + free (pathname); + pathname = NULL; + } + + return op_ret; +} + static struct xlator_fops libgf_client_fops = { }; diff --git a/libglusterfsclient/src/libglusterfsclient.h b/libglusterfsclient/src/libglusterfsclient.h index 017d8a391..40d08eced 100755 --- a/libglusterfsclient/src/libglusterfsclient.h +++ b/libglusterfsclient/src/libglusterfsclient.h @@ -1,279 +1,236 @@ /* - Copyright (c) 2008-2009 Z RESEARCH, Inc. <http://www.zresearch.com> - This file is part of GlusterFS. - - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008, 2009 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. */ -#ifndef __LIBGLUSTERFSCLIENT_H -#define __LIBGLUSTERFSCLIENT_H +#ifndef _LIBGLUSTERFSCLIENT_H +#define _LIBGLUSTERFSCLIENT_H -#ifdef __cplusplus -extern "C" { -#endif +#include <sys/cdefs.h> +__BEGIN_DECLS + +#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> - //#include <unistd.h> #include <dirent.h> -#include <errno.h> -/* #include <logging.h> */ typedef struct { - int op_ret; - int op_errno; struct iovec *vector; - int count; + int count; void *ref; -}glusterfs_read_buf_t; - +} glusterfs_iobuf_t; typedef struct { char *logfile; char *loglevel; struct { - char *specfile; - FILE *specfp; + char *specfile; + FILE *specfp; }; char *volume_name; - unsigned long lookup_timeout; - unsigned long stat_timeout; -}glusterfs_init_ctx_t; + unsigned long lookup_timeout; + unsigned long stat_timeout; +} glusterfs_init_params_t; -typedef struct libglusterfs_client_ctx *libglusterfs_handle_t; +typedef void * glusterfs_handle_t; -typedef int (*glusterfs_readv_cbk_t) (glusterfs_read_buf_t *buf, - void *cbk_data); +/* FIXME: how is glusterfs_file_t different from glusterfs_dir_t? */ +typedef void * glusterfs_file_t; +typedef void * glusterfs_dir_t; -typedef int (*glusterfs_writev_cbk_t) (int op_ret, - int op_errno, - void *cbk_data); +typedef +int (*glusterfs_readv_cbk_t) (int op_ret, int op_errno, glusterfs_iobuf_t *buf, + void *cbk_data); -typedef int (*glusterfs_lookup_cbk_t) (int op_ret, - int op_errno, - void *buf, - struct stat *st, - void *cbk_data); +typedef +int (*glusterfs_write_cbk_t) (int op_ret, int op_errno, void *cbk_data); -/* Used to free the glusterfs_read_buf passed to the application from glusterfs_read_async_cbk */ -void -glusterfs_free (glusterfs_read_buf_t *buf); +typedef +int (*glusterfs_get_cbk_t) (int op_ret, int op_errno, glusterfs_iobuf_t *buf, + struct stat *stbuf, void *cbk_data); + +/* Used to free the glusterfs_read_buf passed to the application from + glusterfs_read_async_cbk +*/ +void +glusterfs_free (glusterfs_iobuf_t *buf); /* libglusterfsclient initialization function */ -libglusterfs_handle_t -glusterfs_init (glusterfs_init_ctx_t *ctx); +glusterfs_handle_t +glusterfs_init (glusterfs_init_params_t *ctx); int -glusterfs_fini (libglusterfs_handle_t handle); +glusterfs_fini (glusterfs_handle_t handle); -/* added for log related initialization for fork implementation in booster */ -void -glusterfs_reset (void); +/* For smaller files, application can use just glusterfs_get/glusterfs_get_async + * to read the whole content. Limit of the file-sizes to be read in + * glusterfs_get/glusterfs_get_async is passed in the size argument + */ -void -glusterfs_log_lock (void); +/* glusterfs_get: + * @handle : glusterfs handle + * @path : path to be looked upon + * @size : upper limit of file-sizes to be read in lookup + * @stbuf : attribute buffer + */ -void -glusterfs_log_unlock (void); +int +glusterfs_get (glusterfs_handle_t handle, const char *path, void *buf, + size_t size, struct stat *stbuf); -/* For smaller files, application can use just glusterfs_lookup/glusterfs_lookup_async to read - * the whole content. Limit of the file-sizes to be read in - * glusterfs_lookup/glusterfs_lookup_async is passed in the size argument */ +int +glusterfs_get_async (glusterfs_handle_t handle, const char *path, size_t size, + glusterfs_get_cbk_t cbk, void *cbk_data); -/* glusterfs_lookup: - * @handle: glusterfs handle - * @path: path to be looked upon - * @buf: pointer to pre-allocated buf, in which the file content is returned for files with sizes * less than the size argument. - * @size: upper limit of file-sizes to be read in lookup - * @stbuf: stat buffer - */ +glusterfs_file_t +glusterfs_open (glusterfs_handle_t handle, const char *path, int flags, + mode_t mode); -int -glusterfs_lookup (libglusterfs_handle_t handle, - const char *path, - void *buf, - size_t size, - struct stat *stbuf); +glusterfs_file_t +glusterfs_creat (glusterfs_handle_t handle, const char *path, mode_t mode); int -glusterfs_lookup_async (libglusterfs_handle_t handle, - const char *path, - void *buf, - size_t size, - glusterfs_lookup_cbk_t cbk, - void *cbk_data); - -unsigned long -glusterfs_open (libglusterfs_handle_t handle, - const char *path, - int flags, - mode_t mode); - -unsigned long -glusterfs_creat (libglusterfs_handle_t handle, - const char *path, - mode_t mode); - -int -glusterfs_close (unsigned long fd); - -int -glusterfs_stat (libglusterfs_handle_t handle, - const char *path, - struct stat *buf); - -int -glusterfs_fstat (unsigned long fd, - struct stat *buf) ; - -int -glusterfs_setxattr (libglusterfs_handle_t handle, - const char *path, - const char *name, - const void *value, - size_t size, - int flags); - -int -glusterfs_lsetxattr (libglusterfs_handle_t handle, - const char *path, - const char *name, - const void *value, - size_t size, - int flags); +glusterfs_mkdir (glusterfs_handle_t handle, const char *path, mode_t mode); -int -glusterfs_fsetxattr (unsigned long fd, - const char *name, - const void *value, - size_t size, +int +glusterfs_rmdir (glusterfs_handle_t handle, const char *path); + +int +glusterfs_close (glusterfs_file_t fd); + +int +glusterfs_stat (glusterfs_handle_t handle, const char *path, + struct stat *stbuf); + +int +glusterfs_fstat (glusterfs_file_t fd, struct stat *stbuf); + +int +glusterfs_setxattr (glusterfs_handle_t handle, const char *path, + const char *name, const void *value, size_t size, + int flags); + +int +glusterfs_lsetxattr (glusterfs_handle_t handle, const char *path, + const char *name, const void *value, size_t size, int flags); -ssize_t -glusterfs_getxattr (libglusterfs_handle_t handle, - const char *path, - const char *name, - void *value, - size_t size); - -ssize_t -glusterfs_lgetxattr (libglusterfs_handle_t handle, - const char *path, - const char *name, - void *value, - size_t size); +int +glusterfs_fsetxattr (glusterfs_file_t fd, const char *name, const void *value, + size_t size, int flags); -ssize_t -glusterfs_fgetxattr (unsigned long fd, - const char *name, - void *value, - size_t size); +ssize_t +glusterfs_getxattr (glusterfs_handle_t handle, const char *path, + const char *name, void *value, size_t size); + +ssize_t +glusterfs_lgetxattr (glusterfs_handle_t handle, const char *path, + const char *name, void *value, size_t size); -ssize_t -glusterfs_listxattr (libglusterfs_handle_t handle, - const char *path, - char *list, +ssize_t +glusterfs_fgetxattr (glusterfs_file_t fd, const char *name, void *value, + size_t size); + +ssize_t +glusterfs_listxattr (glusterfs_handle_t handle, const char *path, char *list, size_t size); -ssize_t -glusterfs_llistxattr (libglusterfs_handle_t handle, - const char *path, - char *list, +ssize_t +glusterfs_llistxattr (glusterfs_handle_t handle, const char *path, char *list, size_t size); -ssize_t -glusterfs_flistxattr (unsigned long fd, - char *list, - size_t size); +ssize_t +glusterfs_flistxattr (glusterfs_file_t fd, char *list, size_t size); -int -glusterfs_removexattr (libglusterfs_handle_t handle, - const char *path, - const char *name); - -int -glusterfs_lremovexattr (libglusterfs_handle_t handle, - const char *path, - const char *name); - -int -glusterfs_fremovexattr (unsigned long fd, - const char *name); - -ssize_t -glusterfs_read (unsigned long fd, - void *buf, - size_t nbytes); - -ssize_t -glusterfs_readv (unsigned long fd, - const struct iovec *vec, - int count); - -int -glusterfs_read_async (unsigned long fd, - size_t nbytes, - off_t offset, - glusterfs_readv_cbk_t readv_cbk, - void *cbk_data); - -ssize_t -glusterfs_write (unsigned long fd, - const void *buf, - size_t n); - -ssize_t -glusterfs_writev (unsigned long fd, - const struct iovec *vector, - size_t count); +int +glusterfs_removexattr (glusterfs_handle_t handle, const char *path, + const char *name); int -glusterfs_write_async (unsigned long fd, - const void *buf, - size_t nbytes, - off_t offset, - glusterfs_writev_cbk_t writev_cbk, - void *cbk_data); +glusterfs_lremovexattr (glusterfs_handle_t handle, const char *path, + const char *name); int -glusterfs_readdir (unsigned long fd, - struct dirent *dirp, - unsigned int count); +glusterfs_fremovexattr (glusterfs_file_t fd, const char *name); + +ssize_t +glusterfs_read (glusterfs_file_t fd, void *buf, size_t nbytes); + +ssize_t +glusterfs_readv (glusterfs_file_t fd, const struct iovec *vec, int count); int -glusterfs_getdents (unsigned long fd, - struct dirent *dirp, - unsigned int count); +glusterfs_read_async (glusterfs_file_t fd, size_t nbytes, off_t offset, + glusterfs_readv_cbk_t readv_cbk, void *cbk_data); -ssize_t -glusterfs_pread (unsigned long fd, - void *buf, - size_t count, - off_t offset); +ssize_t +glusterfs_write (glusterfs_file_t fd, const void *buf, size_t nbytes); -ssize_t -glusterfs_pwrite (unsigned long fd, - const void *buf, - size_t count, - off_t offset); +ssize_t +glusterfs_writev (glusterfs_file_t fd, const struct iovec *vector, int count); + +int +glusterfs_write_async (glusterfs_file_t fd, const void *buf, size_t nbytes, + off_t offset, glusterfs_write_cbk_t write_cbk, + void *cbk_data); + +int +glusterfs_writev_async (glusterfs_file_t fd, const struct iovec *vector, + int count, off_t offset, + glusterfs_write_cbk_t write_cbk, void *cbk_data); + +ssize_t +glusterfs_pread (glusterfs_file_t fd, void *buf, size_t nbytes, off_t offset); + +ssize_t +glusterfs_pwrite (glusterfs_file_t fd, const void *buf, size_t nbytes, + off_t offset); off_t -glusterfs_lseek (unsigned long fd, off_t offset, int whence); +glusterfs_lseek (glusterfs_file_t fd, off_t offset, int whence); + +int +glusterfs_mkdir (glusterfs_handle_t handle, const char *path, mode_t mode); + +int +glusterfs_rmdir (glusterfs_handle_t handle, const char *path); + +/* FIXME: implement man 3 readdir semantics */ +int +glusterfs_readdir (glusterfs_dir_t fd, struct dirent *dirp, + unsigned int count); + +/* FIXME: remove getdents */ +int +glusterfs_getdents (glusterfs_dir_t fd, struct dirent *dirp, + unsigned int count); + +/* FIXME: review the need for these apis */ +/* added for log related initialization in booster fork implementation */ +void +glusterfs_reset (void); + +void +glusterfs_log_lock (void); + +void +glusterfs_log_unlock (void); -#ifdef __cplusplus -} -#endif +__END_DECLS -#endif +#endif /* !_LIBGLUSTERFSCLIENT_H */ |