diff options
40 files changed, 0 insertions, 19881 deletions
diff --git a/doc/glusterfs.vol.sample b/doc/glusterfs.vol.sample deleted file mode 100644 index 977363b921b..00000000000 --- a/doc/glusterfs.vol.sample +++ /dev/null @@ -1,53 +0,0 @@ -### file: client-volume.vol.sample - -##################################### -### GlusterFS Client Volume File ## -##################################### - -#### CONFIG FILE RULES: -### "#" is comment character. -### - Config file is case sensitive -### - Options within a volume block can be in any order. -### - Spaces or tabs are used as delimitter within a line. -### - Each option should end within a line. -### - Missing or commented fields will assume default values. -### - Blank/commented lines are allowed. -### - Sub-volumes should already be defined above before referring. - -### Add client feature and attach to remote subvolume -volume client - type protocol/client - option transport-type tcp -# option transport-type unix -# option transport-type ib-sdp - option remote-host 127.0.0.1 # IP address of the remote brick -# option transport.socket.remote-port 24016 - -# option transport-type rdma -# option transport.rdma.remote-port 24016 -# option transport.rdma.work-request-send-count 16 -# option transport.rdma.work-request-recv-count 16 - - option remote-subvolume brick # name of the remote volume -end-volume - -### Add readahead feature -#volume readahead -# type performance/read-ahead -# option page-count 2 # cache per file = (page-count x page-size) -# subvolumes client -#end-volume - -### Add IO-Cache feature -#volume iocache -# type performance/io-cache -# subvolumes readahead -#end-volume - -### Add writeback feature -#volume writeback -# type performance/write-behind -# option window-size 2MB -# option flush-behind off -# subvolumes iocache -#end-volume diff --git a/doc/glusterfsd.vol.sample b/doc/glusterfsd.vol.sample deleted file mode 100644 index ec2fd341ef0..00000000000 --- a/doc/glusterfsd.vol.sample +++ /dev/null @@ -1,44 +0,0 @@ -### file: server-volume.vol.sample - -##################################### -### GlusterFS Server Volume File ## -##################################### - -#### CONFIG FILE RULES: -### "#" is comment character. -### - Config file is case sensitive -### - Options within a volume block can be in any order. -### - Spaces or tabs are used as delimitter within a line. -### - Multiple values to options will be : delimited. -### - Each option should end within a line. -### - Missing or commented fields will assume default values. -### - Blank/commented lines are allowed. -### - Sub-volumes should already be defined above before referring. - -### Export volume "brick" with the contents of "/home/export" directory. -volume brick - type storage/posix # POSIX FS translator - option directory /home/export # Export this directory -end-volume - -### Add network serving capability to above brick. -volume server - type protocol/server - option transport-type tcp -# option transport-type unix -# option transport-type ib-sdp -# option transport.socket.bind-address 192.168.1.10 # Default is to listen - # on all interfaces -# option transport.socket.listen-port 24016 - -# option transport-type rdma -# option transport.rdma.listen-port 24016 -# option transport.rdma.work-request-send-count 64 -# option transport.rdma.work-request-recv-count 64 - - subvolumes brick -# NOTE: Access to any volume through protocol/server is denied by -# default. You need to explicitly grant access through # "auth" -# option. - option auth.addr.brick.allow * # Allow access to "brick" volume -end-volume diff --git a/libglusterfsclient/Makefile.am b/libglusterfsclient/Makefile.am deleted file mode 100644 index d471a3f9243..00000000000 --- a/libglusterfsclient/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -SUBDIRS = src - -CLEANFILES = diff --git a/libglusterfsclient/src/Makefile.am b/libglusterfsclient/src/Makefile.am deleted file mode 100644 index 32811c0d5bf..00000000000 --- a/libglusterfsclient/src/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -lib_LTLIBRARIES = libglusterfsclient.la -noinst_HEADERS = libglusterfsclient-internals.h -libglusterfsclient_HEADERS = libglusterfsclient.h -libglusterfsclientdir = $(includedir) - -libglusterfsclient_la_SOURCES = libglusterfsclient.c libglusterfsclient-dentry.c -libglusterfsclient_la_CFLAGS = -fPIC -Wall -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) -libglusterfsclient_la_LDFLAGS = -shared -nostartfiles - -CLEANFILES = - -$(top_builddir)/libglusterfs/src/libglusterfs.la: - $(MAKE) -C $(top_builddir)/libglusterfs/src/ all - 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; -} diff --git a/libglusterfsclient/src/libglusterfsclient-internals.h b/libglusterfsclient/src/libglusterfsclient-internals.h deleted file mode 100755 index 7b62ce8efbf..00000000000 --- a/libglusterfsclient/src/libglusterfsclient-internals.h +++ /dev/null @@ -1,289 +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. -*/ - -#ifndef __LIBGLUSTERFSCLIENT_INTERNALS_H -#define __LIBGLUSTERFSCLIENT_INTERNALS_H - -#include <glusterfs.h> -#include <logging.h> -#include <inode.h> -#include <pthread.h> -#include <stack.h> -#include <list.h> -#include <signal.h> -#include <call-stub.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <fd.h> -#include <dirent.h> - -#define LIBGF_IOBUF_SIZE (128 *GF_UNIT_KB) -typedef void (*sighandler_t) (int); -typedef struct list_head list_head_t; - -typedef struct libglusterfs_client_ctx { - glusterfs_ctx_t gf_ctx; - inode_table_t *itable; - pthread_t reply_thread; - call_pool_t pool; - uint32_t counter; - time_t lookup_timeout; - time_t stat_timeout; - /* We generate a fake fsid for the subvolume being - * accessed through this context. - */ - dev_t fake_fsid; - pid_t pid; -}libglusterfs_client_ctx_t; - -typedef struct signal_handler { - int signo; - sighandler_t handler; - list_head_t next; -}libgf_client_signal_handler_t ; - -typedef struct { - pthread_mutex_t lock; - pthread_cond_t reply_cond; - call_stub_t *reply_stub; - char complete; - union { - struct { - char is_revalidate; - loc_t *loc; - int32_t size; - } lookup; - }fop; - fd_t *fd; /* Needed here because we need a ref to the dir - fd in the libgf_client_readdir_cbk in order - to process the dirents received, without - having them added to the reply stub. - Also used in updating iattr cache. See - readv_cbk for eg. - */ -}libgf_client_local_t; - -typedef struct { - pthread_cond_t init_con_established; - pthread_mutex_t lock; - char complete; -}libglusterfs_client_private_t; - -typedef struct { - pthread_mutex_t lock; - uint32_t previous_lookup_time; - uint32_t previous_stat_time; - struct iatt stbuf; -} libglusterfs_client_inode_ctx_t; - -/* Our dirent cache is very simplistic when it comes to directory - * reading workloads. It assumes that all directory traversal operations happen - * sequentially and that readdir callers dont go jumping around the directory - * using seekdir, rewinddir. Thats why you'll notice that seekdir, rewinddir - * API in libglusterfsclient only set the offset. The consequence is that when - * libgf_dcache_readdir finds that the offset presented to it, is not - * the same as the offset of the previous dirent returned by dcache (..stored - * in struct direntcache->prev_off..), it realises that a non-sequential - * directory read is in progress and returns 0 to signify that the cache is - * not valid. - * This could be made a bit more intelligent by using a data structure like - * a hash-table or a balanced binary tree that allows us to search for the - * existence of particular offsets in the cache without performing a list or - * array traversal. - * Dont use a simple binary search tree because - * there is no guarantee that offsets in a sequential reading of the directory - * will be just random integers. If for some reason they are sequential, a BST - * will end up becoming a list. - */ -struct direntcache { - gf_dirent_t entries; /* Head of list of cached dirents. */ - gf_dirent_t *next; /* Pointer to the next entry that - * should be sent by readdir */ - uint64_t prev_off; /* Offset where the next read will - * happen. - */ -}; - -typedef struct { - pthread_mutex_t lock; - off_t offset; - libglusterfs_client_ctx_t *ctx; - /* `man readdir` says readdir is non-re-entrant - * only if two readdirs are racing on the same - * handle. - */ - struct dirent dirp; - struct direntcache *dcache; - char vpath[PATH_MAX]; -} libglusterfs_client_fd_ctx_t; - -typedef struct libglusterfs_client_async_local { - void *cbk_data; - union { - struct { - fd_t *fd; - glusterfs_readv_cbk_t cbk; - char update_offset; - }readv_cbk; - - struct { - fd_t *fd; - glusterfs_write_cbk_t cbk; - }write_cbk; - - struct { - fd_t *fd; - }close_cbk; - - struct { - void *buf; - size_t size; - loc_t *loc; - char is_revalidate; - glusterfs_get_cbk_t cbk; - }lookup_cbk; - }fop; -}libglusterfs_client_async_local_t; - -#define LIBGF_STACK_WIND_AND_WAIT(frame, rfn, obj, fn, params ...) \ - do { \ - STACK_WIND (frame, rfn, obj, fn, params); \ - pthread_mutex_lock (&local->lock); \ - { \ - while (!local->complete) { \ - pthread_cond_wait (&local->reply_cond, \ - &local->lock); \ - } \ - } \ - pthread_mutex_unlock (&local->lock); \ - } while (0) - - -#define LIBGF_CLIENT_SIGNAL(signal_handler_list, signo, handler) \ - do { \ - libgf_client_signal_handler_t *libgf_handler = CALLOC (1, \ - sizeof (*libgf_handler)); \ - ERR_ABORT (libgf_handler); \ - libgf_handler->signo = signo; \ - libgf_handler->handler = signal (signo, handler); \ - list_add (&libgf_handler->next, signal_handler_list); \ - } while (0) - -#define LIBGF_INSTALL_SIGNAL_HANDLERS(signal_handlers) \ - do { \ - INIT_LIST_HEAD (&signal_handlers); \ - /* Handle SIGABORT and SIGSEGV */ \ - LIBGF_CLIENT_SIGNAL (&signal_handlers, SIGSEGV, gf_print_trace); \ - LIBGF_CLIENT_SIGNAL (&signal_handlers, SIGABRT, gf_print_trace); \ - LIBGF_CLIENT_SIGNAL (&signal_handlers, SIGHUP, gf_log_logrotate); \ - /* LIBGF_CLIENT_SIGNAL (SIGTERM, glusterfs_cleanup_and_exit); */ \ - } while (0) - -#define LIBGF_RESTORE_SIGNAL_HANDLERS(local) \ - do { \ - libgf_client_signal_handler_t *ptr = NULL, *tmp = NULL; \ - list_for_each_entry_safe (ptr, tmp, &local->signal_handlers,\ - next) { \ - signal (ptr->signo, ptr->handler); \ - FREE (ptr); \ - } \ - } while (0) - -#define LIBGF_CLIENT_FOP_ASYNC(ctx, local, ret_fn, op, args ...) \ - do { \ - call_frame_t *frame = get_call_frame_for_req (ctx, 1); \ - xlator_t *xl = frame->this->children ? \ - frame->this->children->xlator : NULL; \ - frame->root->state = ctx; \ - frame->local = local; \ - STACK_WIND (frame, ret_fn, xl, xl->fops->op, args); \ - } while (0) - -#define LIBGF_CLIENT_FOP(ctx, stub, op, local, args ...) \ - do { \ - call_frame_t *frame = get_call_frame_for_req (ctx, 1); \ - xlator_t *xl = frame->this->children ? \ - frame->this->children->xlator : NULL; \ - if (!local) { \ - local = CALLOC (1, sizeof (*local)); \ - } \ - ERR_ABORT (local); \ - frame->local = local; \ - frame->root->state = ctx; \ - pthread_cond_init (&local->reply_cond, NULL); \ - pthread_mutex_init (&local->lock, NULL); \ - LIBGF_STACK_WIND_AND_WAIT (frame, libgf_client_##op##_cbk, xl, \ - xl->fops->op, args); \ - stub = local->reply_stub; \ - FREE (frame->local); \ - frame->local = NULL; \ - STACK_DESTROY (frame->root); \ - } while (0) - -#define LIBGF_REPLY_NOTIFY(local) \ - do { \ - pthread_mutex_lock (&local->lock); \ - { \ - local->complete = 1; \ - pthread_cond_broadcast (&local->reply_cond); \ - } \ - pthread_mutex_unlock (&local->lock); \ - } 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, - char lookup_basename); - -int32_t -libgf_client_lookup (libglusterfs_client_ctx_t *ctx, - loc_t *loc, - struct iatt *stbuf, - dict_t **dict, - dict_t *xattr_req); - -/* We're not expecting more than 10-15 - * VMPs per process so a list is acceptable. - */ -struct vmp_entry { - struct list_head list; - char * vmp; - int vmplen; - glusterfs_handle_t handle; -}; - -#define LIBGF_UPDATE_LOOKUP 0x1 -#define LIBGF_UPDATE_STAT 0x2 -#define LIBGF_UPDATE_ALL (LIBGF_UPDATE_LOOKUP | LIBGF_UPDATE_STAT) - -#define LIBGF_VALIDATE_LOOKUP 0x1 -#define LIBGF_VALIDATE_STAT 0x2 - -#define LIBGF_INVALIDATE_LOOKUP 0x1 -#define LIBGF_INVALIDATE_STAT 0x2 -int -libgf_is_iattr_cache_valid (libglusterfs_client_ctx_t *ctx, inode_t *inode, - struct iatt *sbuf, int flags); - -int -libgf_update_iattr_cache (inode_t *inode, int flags, struct iatt *buf); - -#endif diff --git a/libglusterfsclient/src/libglusterfsclient.c b/libglusterfsclient/src/libglusterfsclient.c deleted file mode 100755 index 3881ad64296..00000000000 --- a/libglusterfsclient/src/libglusterfsclient.c +++ /dev/null @@ -1,8161 +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. -*/ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include <stdio.h> -#include <errno.h> -#include <libgen.h> -#include <stddef.h> - -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#ifdef GF_SOLARIS_HOST_OS -#include <sys/statfs.h> -#endif -#include <unistd.h> -#include <xlator.h> -#include <timer.h> -#include "defaults.h" -#include <time.h> -#include <poll.h> -#include "transport.h" -#include "event.h" -#include "libglusterfsclient.h" -#include "libglusterfsclient-internals.h" -#include "compat.h" -#include "compat-errno.h" -#ifndef GF_SOLARIS_HOST_OS -#include <sys/vfs.h> -#endif -#include <utime.h> -#include <sys/param.h> -#include <list.h> -#include <stdarg.h> -#include <sys/statvfs.h> -#include "hashfn.h" -#include <sys/select.h> - -#define LIBGF_XL_NAME "libglusterfsclient" -#define LIBGLUSTERFS_INODE_TABLE_LRU_LIMIT 1000 //14057 -#define LIBGF_SENDFILE_BLOCK_SIZE 4096 -#define LIBGF_READDIR_BLOCK 4096 -#define libgf_path_absolute(path) ((path)[0] == '/') - -static inline xlator_t * -libglusterfs_graph (xlator_t *graph); -int32_t libgf_client_readlink (libglusterfs_client_ctx_t *ctx, loc_t *loc, - char *buf, size_t bufsize); - -int -libgf_realpath_loc_fill (libglusterfs_client_ctx_t *ctx, char *link, - loc_t *targetloc); -static int first_init = 1; - -/* The global list of virtual mount points */ -struct { - struct list_head list; - int entries; -}vmplist; - - -/* Protects the VMP list above. */ -pthread_mutex_t vmplock = PTHREAD_MUTEX_INITIALIZER; - -/* Ensures only one thread is ever calling glusterfs_mount. - * Since that function internally calls routines which - * use the yacc parser code using global vars, this process - * needs to be syncronised. - */ -pthread_mutex_t mountlock = PTHREAD_MUTEX_INITIALIZER; - -static char cwd[PATH_MAX]; -static char cwd_inited = 0; -static pthread_mutex_t cwdlock = PTHREAD_MUTEX_INITIALIZER; - -char * -libgf_vmp_virtual_path (struct vmp_entry *entry, const char *path, char *vpath) -{ - char *tmp = NULL; - - tmp = ((char *)(path + (entry->vmplen-1))); - if (strlen (tmp) > 0) { - if (tmp[0] != '/') { - vpath[0] = '/'; - vpath[1] = '\0'; - strcat (&vpath[1], tmp); - } else - strcpy (vpath, tmp); - } else { - vpath[0] = '/'; - vpath[1] = '\0'; - } - - return vpath; -} - -char * -zr_build_process_uuid () -{ - char tmp_str[1024] = {0,}; - char hostname[256] = {0,}; - struct timeval tv = {0,}; - char now_str[32]; - - if (-1 == gettimeofday(&tv, NULL)) { - gf_log ("", GF_LOG_ERROR, - "gettimeofday: failed %s", - strerror (errno)); - } - - if (-1 == gethostname (hostname, 256)) { - gf_log ("", GF_LOG_ERROR, - "gethostname: failed %s", - strerror (errno)); - } - - gf_time_fmt (now_str, sizeof now_str, tv.tv_sec, gf_timefmt_Ymd_T); - snprintf (tmp_str, sizeof tmp_str, "%s-%d-%s:%ld", - hostname, getpid(), now_str, tv.tv_usec); - - return strdup (tmp_str); -} - - -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, &ptr); - ctx = (libglusterfs_client_inode_ctx_t *)(long) ptr; - - FREE (ctx); - - return 0; -} - -xlator_t * -libgf_inode_to_xlator (inode_t *inode) -{ - if (!inode) - return NULL; - - if (!inode->table) - return NULL; - - if (!inode->table->xl) - return NULL; - - if (!inode->table->xl->ctx) - return NULL; - - return inode->table->xl->ctx->top; -} - -libglusterfs_client_fd_ctx_t * -libgf_get_fd_ctx (fd_t *fd) -{ - uint64_t ctxaddr = 0; - libglusterfs_client_fd_ctx_t *ctx = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, fd, out); - - if (fd_ctx_get (fd, libgf_inode_to_xlator (fd->inode), &ctxaddr) == -1) - goto out; - - ctx = (libglusterfs_client_fd_ctx_t *)(long)ctxaddr; - -out: - return ctx; -} - -libglusterfs_client_fd_ctx_t * -libgf_alloc_fd_ctx (libglusterfs_client_ctx_t *ctx, fd_t *fd, char *vpath) -{ - libglusterfs_client_fd_ctx_t *fdctx = NULL; - uint64_t ctxaddr = 0; - - fdctx = CALLOC (1, sizeof (*fdctx)); - if (fdctx == NULL) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, - "memory allocation failure"); - fdctx = NULL; - goto out; - } - - pthread_mutex_init (&fdctx->lock, NULL); - fdctx->ctx = ctx; - ctxaddr = (uint64_t) (long)fdctx; - - if (fd->inode) { - if (IA_ISDIR (fd->inode->ia_type)) { - fdctx->dcache = CALLOC (1, sizeof (struct direntcache)); - if (fdctx->dcache) - INIT_LIST_HEAD (&fdctx->dcache->entries.list); - /* If the calloc fails, we can still continue - * working as the dcache is not required for correct - * operation. - */ - } - } - - if (vpath != NULL) { - strcpy (fdctx->vpath, vpath); - assert (strlen(vpath) > 0); - if (vpath[strlen(vpath) - 1] != '/') { - strcat (fdctx->vpath, "/"); - } - } - - fd_ctx_set (fd, libgf_inode_to_xlator (fd->inode), ctxaddr); -out: - return fdctx; -} - -libglusterfs_client_fd_ctx_t * -libgf_del_fd_ctx (fd_t *fd) -{ - uint64_t ctxaddr = 0; - libglusterfs_client_fd_ctx_t *ctx = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, fd, out); - - if (fd_ctx_del (fd, libgf_inode_to_xlator (fd->inode) , &ctxaddr) == -1) - goto out; - - ctx = (libglusterfs_client_fd_ctx_t *)(long)ctxaddr; - -out: - return ctx; -} - -void -libgf_dcache_invalidate (fd_t *fd) -{ - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - if (!fd) - return; - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - return; - } - - if (!fd_ctx->dcache) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No dcache present"); - return; - } - - if (!list_empty (&fd_ctx->dcache->entries.list)) - gf_dirent_free (&fd_ctx->dcache->entries); - - INIT_LIST_HEAD (&fd_ctx->dcache->entries.list); - - fd_ctx->dcache->next = NULL; - fd_ctx->dcache->prev_off = 0; - - return; -} - -/* The first entry in the entries is always a placeholder - * or the list head. The real entries begin from entries->next. - */ -int -libgf_dcache_update (libglusterfs_client_ctx_t *ctx, fd_t *fd, - gf_dirent_t *entries) -{ - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - int op_ret = -1; - - if ((!ctx) || (!fd) || (!entries)) { - errno = EINVAL; - goto out; - } - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - goto out; - } - - /* dcache is not enabled. */ - if (!fd_ctx->dcache) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No dcache present"); - op_ret = 0; - goto out; - } - - /* If we're updating, we must begin with invalidating any previous - * entries. - */ - libgf_dcache_invalidate (fd); - - fd_ctx->dcache->next = entries->next; - /* We still need to store a pointer to the head - * so we start free'ing from the head when invalidation - * is required. - * - * Need to delink the entries from the list - * given to us by an underlying translators. Most translators will - * free this list after this call so we must preserve the dirents in - * order to cache them. - */ - list_splice_init (&entries->list, &fd_ctx->dcache->entries.list); - op_ret = 0; -out: - return op_ret; -} - -int -libgf_dcache_readdir (libglusterfs_client_ctx_t *ctx, fd_t *fd, - struct dirent *dirp, off_t *offset) -{ - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - int cachevalid = 0; - - if ((!ctx) || (!fd) || (!dirp) || (!offset)) - return 0; - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - goto out; - } - - if (!fd_ctx->dcache) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No dcache present"); - goto out; - } - - /* We've either run out of entries in the cache - * or the cache is empty. - */ - if (!fd_ctx->dcache->next) { - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "No entries present"); - goto out; - } - - /* The dirent list is created as a circular linked list - * so this check is needed to ensure, we dont start - * reading old entries again. - * If we're reached this situation, the cache is exhausted - * and we'll need to pre-fetch more entries to continue serving. - */ - if (fd_ctx->dcache->next == &fd_ctx->dcache->entries) { - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Entries exhausted"); - goto out; - } - - /* During sequential reading we generally expect that the offset - * requested is the same as the offset we served in the previous call - * to readdir. But, seekdir, rewinddir and libgf_dcache_invalidate - * require special handling because seekdir/rewinddir change the offset - * in the fd_ctx and libgf_dcache_invalidate changes the prev_off. - */ - if (*offset != fd_ctx->dcache->prev_off) { - /* For all cases of the if branch above, we know that the - * cache is now invalid except for the case below. It handles - * the case where the two offset values above are different - * but different because the previous readdir block was - * exhausted, resulting in a prev_off being set to 0 in - * libgf_dcache_invalidate, while the requested offset is non - * zero because that is what we returned for the last dirent - * of the previous readdir block. - */ - if ((*offset != 0) && (fd_ctx->dcache->prev_off == 0)) { - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Entries" - " exhausted"); - cachevalid = 1; - } else - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Dcache" - " invalidated previously"); - } else - cachevalid = 1; - - if (!cachevalid) - goto out; - - dirp->d_ino = fd_ctx->dcache->next->d_ino; - strncpy (dirp->d_name, fd_ctx->dcache->next->d_name, - fd_ctx->dcache->next->d_len); - - *offset = fd_ctx->dcache->next->d_off; - dirp->d_off = *offset; - fd_ctx->dcache->prev_off = fd_ctx->dcache->next->d_off; - fd_ctx->dcache->next = fd_ctx->dcache->next->next; - -out: - return cachevalid; -} - - -int32_t -libgf_client_release (xlator_t *this, - fd_t *fd) -{ - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - fd_ctx = libgf_get_fd_ctx (fd); - if (IA_ISDIR (fd->inode->ia_type)) { - libgf_dcache_invalidate (fd); - FREE (fd_ctx->dcache); - } - - libgf_del_fd_ctx (fd); - if (fd_ctx != NULL) { - pthread_mutex_destroy (&fd_ctx->lock); - FREE (fd_ctx); - } - - return 0; -} - -libglusterfs_client_inode_ctx_t * -libgf_get_inode_ctx (inode_t *inode) -{ - uint64_t ctxaddr = 0; - libglusterfs_client_inode_ctx_t *ictx = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, inode, out); - if (inode_ctx_get (inode, libgf_inode_to_xlator (inode), &ctxaddr) < 0) - goto out; - - ictx = (libglusterfs_client_inode_ctx_t *)(long)ctxaddr; - -out: - return ictx; -} - -libglusterfs_client_inode_ctx_t * -libgf_del_inode_ctx (inode_t *inode) -{ - uint64_t ctxaddr = 0; - libglusterfs_client_inode_ctx_t *ictx = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, inode, out); - if (inode_ctx_del (inode, libgf_inode_to_xlator (inode), &ctxaddr) < 0) - goto out; - - ictx = (libglusterfs_client_inode_ctx_t *)(long)ctxaddr; - -out: - return ictx; -} - -libglusterfs_client_inode_ctx_t * -libgf_alloc_inode_ctx (libglusterfs_client_ctx_t *ctx, inode_t *inode) -{ - uint64_t ctxaddr = 0; - libglusterfs_client_inode_ctx_t *ictx = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, inode, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - ictx = CALLOC (1, sizeof (*ictx)); - if (ictx == NULL) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, - "memory allocation failure"); - goto out; - } - - pthread_mutex_init (&ictx->lock, NULL); - ctxaddr = (uint64_t) (long)ictx; - if (inode_ctx_put (inode, libgf_inode_to_xlator (inode), ctxaddr) < 0){ - FREE (ictx); - ictx = NULL; - } - -out: - return ictx; -} - -int -libgf_transform_iattr (libglusterfs_client_ctx_t *libctx, inode_t *inode, - struct iatt *buf) -{ - - if ((!libctx) || (!buf) || (!inode)) - return -1; - - buf->ia_dev = libctx->fake_fsid; - /* If the inode is root, the inode number must be 1 not the - * ino received from the file system. - */ - if ((inode->ino == 1) && (buf)) - buf->ia_ino = 1; - - return 0; -} - -int -libgf_update_iattr_cache (inode_t *inode, int flags, struct iatt *buf) -{ - libglusterfs_client_inode_ctx_t *inode_ctx = NULL; - time_t current = 0; - int op_ret = -1; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, inode, out); - - inode_ctx = libgf_get_inode_ctx (inode); - if (!inode_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No inode context" - " present"); - errno = EINVAL; - op_ret = -1; - goto out; - } - - pthread_mutex_lock (&inode_ctx->lock); - { - /* Take a timestamp only after we've acquired the - * lock. - */ - current = time (NULL); - if (flags & LIBGF_UPDATE_LOOKUP) { - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Updating lookup"); - inode_ctx->previous_lookup_time = current; - } - - if (flags & LIBGF_UPDATE_STAT) { - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Updating stat"); - - /* Update the cached stat struct only if a new - * stat buf is given. - */ - if (buf != NULL) { - inode_ctx->previous_stat_time = current; - memcpy (&inode_ctx->stbuf, buf, - sizeof (inode_ctx->stbuf)); - } - } - } - pthread_mutex_unlock (&inode_ctx->lock); - op_ret = 0; - -out: - return op_ret; -} - - -int -libgf_invalidate_iattr_cache (inode_t *inode, int flags) -{ - libglusterfs_client_inode_ctx_t *ictx = NULL; - - if (!inode) - return -1; - - ictx = libgf_get_inode_ctx (inode); - if (!ictx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No inode context" - " present"); - return -1; - } - - pthread_mutex_lock (&ictx->lock); - { - if (flags & LIBGF_INVALIDATE_LOOKUP) { - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Invalidating" - " lookup"); - ictx->previous_lookup_time = 0; - } - - if (flags & LIBGF_INVALIDATE_STAT) { - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Invalidating" - " stat"); - ictx->previous_stat_time = 0; - } - - } - pthread_mutex_unlock (&ictx->lock); - - return 0; -} - - -int -libgf_is_iattr_cache_valid (libglusterfs_client_ctx_t *ctx, inode_t *inode, - struct iatt *sbuf, int flags) -{ - time_t current = 0; - time_t prev = 0; - libglusterfs_client_inode_ctx_t *inode_ctx = NULL; - int cache_valid = 0; - time_t timeout = 0; - - if (inode == NULL) - return 0; - - inode_ctx = libgf_get_inode_ctx (inode); - if (!inode_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No inode context" - " present\n"); - return 0; - } - - pthread_mutex_lock (&inode_ctx->lock); - { - current = time (NULL); - if (flags & LIBGF_VALIDATE_LOOKUP) { - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Checking lookup"); - prev = inode_ctx->previous_lookup_time; - timeout = ctx->lookup_timeout; - } else { - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Checking stat"); - prev = inode_ctx->previous_stat_time; - timeout = ctx->stat_timeout; - } - - /* Even if the timeout is set to -1 to cache - * infinitely, fops like write must invalidate the - * stat cache because writev_cbk cannot update - * the cache using the stat returned to it. This is - * because write-behind can return a stat bufs filled - * with zeroes. - */ - if (prev == 0) { - cache_valid = 0; - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Cache Invalid"); - goto iattr_unlock_out; - } - - /* Cache infinitely */ - if (timeout == (time_t)-1) { - cache_valid = 1; - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Caching On and " - "valid"); - goto iattr_unlock_out; - } - - /* Disable caching completely */ - if (timeout == 0) { - cache_valid = 0; - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Cache disabled"); - goto iattr_unlock_out; - } - - if ((prev > 0) && (timeout >= (current - prev))) { - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Cache valid"); - cache_valid = 1; - } - - if (flags & LIBGF_VALIDATE_LOOKUP) - goto iattr_unlock_out; - - if ((cache_valid) && (sbuf)) - *sbuf = inode_ctx->stbuf; - } -iattr_unlock_out: - pthread_mutex_unlock (&inode_ctx->lock); - - return cache_valid; -} - -int32_t -libgf_client_releasedir (xlator_t *this, - fd_t *fd) -{ - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - fd_ctx = libgf_get_fd_ctx (fd); - if (IA_ISDIR (fd->inode->ia_type)) { - libgf_dcache_invalidate (fd); - FREE (fd_ctx->dcache); - } - - libgf_del_fd_ctx (fd); - if (fd_ctx != NULL) { - pthread_mutex_destroy (&fd_ctx->lock); - FREE (fd_ctx); - } - - return 0; -} - -void *poll_proc (void *ptr) -{ - glusterfs_ctx_t *ctx = ptr; - - event_dispatch (ctx->event_pool); - - return NULL; -} - - -int32_t -xlator_graph_init (xlator_t *xl) -{ - xlator_t *trav = xl; - int32_t ret = -1; - - while (trav->prev) - trav = trav->prev; - - while (trav) { - if (!trav->ready) { - ret = xlator_tree_init (trav); - if (ret < 0) - break; - } - trav = trav->next; - } - - return ret; -} - - -void -xlator_graph_fini (xlator_t *xl) -{ - xlator_t *trav = xl; - while (trav->prev) - trav = trav->prev; - - while (trav) { - if (!trav->init_succeeded) { - break; - } - - xlator_tree_fini (trav); - trav = trav->next; - } -} - -/* Returns a pointer to the @n'th char matching - * @c in string @str, starting the search from right or - * end-of-string, rather than starting from left, as rindex - * function does. - */ -char * -libgf_rrindex (char *str, int c, int n) -{ - size_t len; - int occurrence = 0; - - if (str == NULL) - return NULL; - - len = strlen (str); - /* Point to last character of string. */ - if (len) - str += (len - 1); - while (len > 0) { - if ((int)*str == c) { - ++occurrence; - if (occurrence == n) - break; - } - --len; - --str; - } - - return str; -} - -char * -libgf_trim_to_prev_dir (char * path) -{ - char *idx = NULL; - int len = 0; - - if (!path) - return NULL; - - /* Check if we're already at root, if yes - * then there is no prev dir. - */ - len = strlen (path); - if (len <= 1) - return path; - - if (path[len - 1] == '/') { - path[len - 1] = '\0'; - } - - idx = libgf_rrindex (path, '/', 1); - /* Move to the char after the / */ - ++idx; - *idx = '\0'; - - return path; -} - - -char * -libgf_prepend_cwd (const char *userpath, char *abspath, int size) -{ - if ((!userpath) || (!abspath)) - return NULL; - - if (!getcwd (abspath, size)) - return NULL; - - strcat (abspath, "/"); - strcat (abspath, userpath); - - return abspath; -} - - -/* Performs a lightweight path resolution that only - * looks for . and .. and replaces those with the - * proper names. - * - * FIXME: This is a stop-gap measure till we have full - * fledge path resolution going in here. - * Function returns path strdup'ed so remember to FREE the - * string as required. - */ -char * -libgf_resolve_path_light (char *path) -{ - char *respath = NULL; - char *saveptr = NULL; - char *tok = NULL; - int len = 0; - int addslash = 0; - char mypath[PATH_MAX]; - - if (!path) - goto out; - - memset (mypath, 0, PATH_MAX); - - if (!libgf_path_absolute (path)) - libgf_prepend_cwd (path, mypath, PATH_MAX); - else - strcpy (mypath, path); - - len = strlen (mypath); - if (len == 0) { - goto out; - } - - respath = calloc (PATH_MAX, sizeof (char)); - if (respath == NULL) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR,"Memory allocation failed"); - goto out; - } - - /* The path only contains a / or a //, so simply add a / - * and return. - * This needs special handling because the loop below does - * not allow us to do so through strtok. - */ - if (((mypath[0] == '/') && (len == 1)) - || (strcmp (mypath, "//") == 0)) { - strcat (respath, "/"); - goto out; - } - - tok = strtok_r (mypath, "/", &saveptr); - addslash = 0; - strcat (respath, "/"); - while (tok) { - if (addslash) { - if ((strcmp (tok, ".") != 0) - && (strcmp (tok, "..") != 0)) { - strcat (respath, "/"); - } - } - - if ((strcmp (tok, ".") != 0) && (strcmp (tok, "..") != 0)) { - strcat (respath, tok); - addslash = 1; - } else if ((strcmp (tok, "..") == 0)) { - libgf_trim_to_prev_dir (respath); - addslash = 0; - } - - tok = strtok_r (NULL, "/", &saveptr); - } - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Path: %s, Resolved Path: %s", - path, respath); -out: - return respath; -} - -void -libgf_client_loc_wipe (loc_t *loc) -{ - if (loc->path) { - FREE (loc->path); - } - - if (loc->parent) { - inode_unref (loc->parent); - loc->parent = NULL; - } - - if (loc->inode) { - inode_unref (loc->inode); - loc->inode = NULL; - } - - loc->path = loc->name = NULL; - loc->ino = 0; -} - - -int32_t -libgf_client_loc_fill (loc_t *loc, - libglusterfs_client_ctx_t *ctx, - ino_t ino, - ino_t par, - const char *name) -{ - inode_t *inode = NULL, *parent = NULL; - int32_t ret = -1; - char *path = NULL; - - /* resistance against multiple invocation of loc_fill not to get - reference leaks via inode_search() */ - - inode = loc->inode; - - if (!inode) { - if (ino) - inode = inode_search (ctx->itable, ino, NULL); - - if (inode) - goto inode_found; - - if (par && name) - inode = inode_search (ctx->itable, par, name); - } - -inode_found: - if (inode) { - loc->ino = inode->ino; - loc->inode = inode; - } - - 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 = ""; - } - - 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; -} - - -static call_frame_t * -get_call_frame_for_req (libglusterfs_client_ctx_t *ctx, char d) -{ - call_pool_t *pool = ctx->gf_ctx.pool; - xlator_t *this = ctx->gf_ctx.graph; - call_frame_t *frame = NULL; - - - frame = create_frame (this, pool); - - frame->root->uid = geteuid (); - frame->root->gid = getegid (); - frame->root->pid = ctx->pid; - frame->root->unique = ctx->counter++; - - return frame; -} - -void -libgf_client_fini (xlator_t *this) -{ - FREE (this->private); - return; -} - - -int32_t -libgf_client_notify (xlator_t *this, - int32_t event, - void *data, - ...) -{ - libglusterfs_client_private_t *priv = this->private; - - switch (event) - { - case GF_EVENT_CHILD_UP: - pthread_mutex_lock (&priv->lock); - { - priv->complete = 1; - pthread_cond_broadcast (&priv->init_con_established); - } - pthread_mutex_unlock (&priv->lock); - break; - - default: - default_notify (this, event, data); - } - - return 0; -} - -int32_t -libgf_client_init (xlator_t *this) -{ - return 0; -} - -glusterfs_handle_t -glusterfs_init (glusterfs_init_params_t *init_ctx, uint32_t fakefsid) -{ - libglusterfs_client_ctx_t *ctx = NULL; - libglusterfs_client_private_t *priv = NULL; - FILE *specfp = NULL; - xlator_t *graph = NULL, *trav = NULL; - call_pool_t *pool = NULL; - int32_t ret = 0; - struct rlimit lim; - uint32_t xl_count = 0; - loc_t new_loc = {0, }; - struct timeval tv = {0, }; - uint32_t len = 0; - char buf[PATH_MAX]; - - if (!init_ctx || (!init_ctx->specfile && !init_ctx->specfp)) { - errno = EINVAL; - return NULL; - } - - ctx = CALLOC (1, sizeof (*ctx)); - if (!ctx) { - fprintf (stderr, - "libglusterfsclient: %s:%s():%d: out of memory\n", - __FILE__, __PRETTY_FUNCTION__, __LINE__); - - errno = ENOMEM; - return NULL; - } - - ctx->lookup_timeout = init_ctx->lookup_timeout; - ctx->stat_timeout = init_ctx->stat_timeout; - ctx->fake_fsid = fakefsid; - ctx->pid = getpid (); - pthread_mutex_init (&ctx->gf_ctx.lock, NULL); - - pool = ctx->gf_ctx.pool = CALLOC (1, sizeof (call_pool_t)); - if (!pool) { - errno = ENOMEM; - FREE (ctx); - return NULL; - } - - 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); - ctx->gf_ctx.page_size = LIBGF_IOBUF_SIZE; - ctx->gf_ctx.iobuf_pool = iobuf_pool_new (8 * 1048576, - ctx->gf_ctx.page_size); - - lim.rlim_cur = RLIM_INFINITY; - lim.rlim_max = RLIM_INFINITY; - setrlimit (RLIMIT_CORE, &lim); - setrlimit (RLIMIT_NOFILE, &lim); - - ctx->gf_ctx.cmd_args.log_level = GF_LOG_WARNING; - - if (init_ctx->logfile) - ctx->gf_ctx.cmd_args.log_file = strdup (init_ctx->logfile); - else - ctx->gf_ctx.cmd_args.log_file = strdup ("/dev/stderr"); - - if (init_ctx->loglevel) { - if (!strncasecmp (init_ctx->loglevel, "DEBUG", - strlen ("DEBUG"))) { - ctx->gf_ctx.cmd_args.log_level = GF_LOG_DEBUG; - } else if (!strncasecmp (init_ctx->loglevel, "WARNING", - strlen ("WARNING"))) { - ctx->gf_ctx.cmd_args.log_level = GF_LOG_WARNING; - } else if (!strncasecmp (init_ctx->loglevel, "CRITICAL", - strlen ("CRITICAL"))) { - ctx->gf_ctx.cmd_args.log_level = GF_LOG_CRITICAL; - } else if (!strncasecmp (init_ctx->loglevel, "NONE", - strlen ("NONE"))) { - ctx->gf_ctx.cmd_args.log_level = GF_LOG_NONE; - } else if (!strncasecmp (init_ctx->loglevel, "ERROR", - strlen ("ERROR"))) { - ctx->gf_ctx.cmd_args.log_level = GF_LOG_ERROR; - } else if (!strncasecmp (init_ctx->loglevel, "TRACE", - strlen ("TRACE"))) { - ctx->gf_ctx.cmd_args.log_level = GF_LOG_TRACE; - } else { - fprintf (stderr, - "libglusterfsclient: %s:%s():%d: Unrecognized log-level \"%s\", possible values are \"DEBUG|WARNING|[ERROR]|CRITICAL|NONE|TRACE\"\n", - __FILE__, __PRETTY_FUNCTION__, __LINE__, - init_ctx->loglevel); - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - FREE (ctx); - errno = EINVAL; - return NULL; - } - } - - if (first_init) - { - memset (buf, 0, PATH_MAX); - - if (getcwd (buf, PATH_MAX) == NULL) { - fprintf (stderr, "libglusterfsclient: cannot get " - "current working directory (%s)", - strerror (errno)); - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - FREE (ctx); - return NULL; - } - - len = strlen (buf); - if ((buf[len - 1] != '/')) { - if ((len + 2) > PATH_MAX) { - errno = ENAMETOOLONG; - fprintf (stderr, "libglusterfsclient: cannot" - "get current working directory (%s)", - strerror (errno)); - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - FREE (ctx); - return NULL; - } - - strcat (buf, "/"); - } - - pthread_mutex_lock (&cwdlock); - { - strcpy (cwd, buf); - cwd_inited = 1; - } - pthread_mutex_unlock (&cwdlock); - - ret = gf_log_init (ctx->gf_ctx.cmd_args.log_file); - if (ret == -1) { - fprintf (stderr, - "libglusterfsclient: %s:%s():%d: failed to open logfile \"%s\"\n", - __FILE__, __PRETTY_FUNCTION__, __LINE__, - ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - FREE (ctx); - return NULL; - } - - gf_log_set_loglevel (ctx->gf_ctx.cmd_args.log_level); - } - - if (init_ctx->specfp) { - specfp = init_ctx->specfp; - if (fseek (specfp, 0L, SEEK_SET)) { - fprintf (stderr, - "libglusterfsclient: %s:%s():%d: fseek on volume file stream failed (%s)\n", - __FILE__, __PRETTY_FUNCTION__, __LINE__, - strerror (errno)); - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - FREE (ctx); - return NULL; - } - } else if (init_ctx->specfile) { - specfp = fopen (init_ctx->specfile, "r"); - ctx->gf_ctx.cmd_args.volume_file = strdup (init_ctx->specfile); - } - - if (!specfp) { - fprintf (stderr, - "libglusterfsclient: %s:%s():%d: could not open volfile: %s\n", - __FILE__, __PRETTY_FUNCTION__, __LINE__, - strerror (errno)); - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.cmd_args.volume_file); - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - FREE (ctx); - return NULL; - } - - if (init_ctx->volume_name) { - ctx->gf_ctx.cmd_args.volume_name = strdup (init_ctx->volume_name); - } - - graph = file_to_xlator_tree (&ctx->gf_ctx, specfp); - if (!graph) { - fprintf (stderr, - "libglusterfsclient: %s:%s():%d: cannot create configuration graph (%s)\n", - __FILE__, __PRETTY_FUNCTION__, __LINE__, - strerror (errno)); - - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.cmd_args.volume_file); - FREE (ctx->gf_ctx.cmd_args.volume_name); - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - FREE (ctx); - return NULL; - } - - if (init_ctx->volume_name) { - trav = graph; - while (trav) { - if (strcmp (trav->name, init_ctx->volume_name) == 0) { - graph = trav; - break; - } - trav = trav->next; - } - } - - ctx->gf_ctx.graph = libglusterfs_graph (graph); - if (!ctx->gf_ctx.graph) { - fprintf (stderr, - "libglusterfsclient: %s:%s():%d: graph creation failed (%s)\n", - __FILE__, __PRETTY_FUNCTION__, __LINE__, - strerror (errno)); - - xlator_tree_free (graph); - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.cmd_args.volume_file); - FREE (ctx->gf_ctx.cmd_args.volume_name); - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - FREE (ctx); - return NULL; - } - graph = ctx->gf_ctx.graph; - ctx->gf_ctx.top = graph; - - trav = graph; - while (trav) { - xl_count++; /* Getting this value right is very important */ - trav = trav->next; - } - - ctx->gf_ctx.xl_count = xl_count + 1; - - priv = CALLOC (1, sizeof (*priv)); - if (!priv) { - fprintf (stderr, - "libglusterfsclient: %s:%s():%d: cannot allocate memory (%s)\n", - __FILE__, __PRETTY_FUNCTION__, __LINE__, - strerror (errno)); - - xlator_tree_free (graph); - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.cmd_args.volume_file); - FREE (ctx->gf_ctx.cmd_args.volume_name); - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - /* inode_table_destroy (ctx->itable); */ - FREE (ctx); - - return NULL; - } - - pthread_cond_init (&priv->init_con_established, NULL); - pthread_mutex_init (&priv->lock, NULL); - - graph->private = priv; - ctx->itable = inode_table_new (LIBGLUSTERFS_INODE_TABLE_LRU_LIMIT, - graph); - if (!ctx->itable) { - fprintf (stderr, - "libglusterfsclient: %s:%s():%d: cannot create inode table\n", - __FILE__, __PRETTY_FUNCTION__, __LINE__); - xlator_tree_free (graph); - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.cmd_args.volume_file); - FREE (ctx->gf_ctx.cmd_args.volume_name); - - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - xlator_tree_free (graph); - /* TODO: destroy graph */ - /* inode_table_destroy (ctx->itable); */ - FREE (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", - __FILE__, __PRETTY_FUNCTION__, __LINE__); - xlator_tree_free (graph); - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.cmd_args.volume_file); - FREE (ctx->gf_ctx.cmd_args.volume_name); - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - /* TODO: destroy graph */ - /* inode_table_destroy (ctx->itable); */ - FREE (ctx); - return NULL; - } - - /* Send notify to all translator saying things are ready */ - graph->notify (graph, GF_EVENT_PARENT_UP, graph); - - if (gf_timer_registry_init (&ctx->gf_ctx) == NULL) { - fprintf (stderr, - "libglusterfsclient: %s:%s():%d: timer init failed (%s)\n", - __FILE__, __PRETTY_FUNCTION__, __LINE__, - strerror (errno)); - - xlator_graph_fini (graph); - xlator_tree_free (graph); - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.cmd_args.volume_file); - FREE (ctx->gf_ctx.cmd_args.volume_name); - - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - /* TODO: destroy graph */ - /* inode_table_destroy (ctx->itable); */ - FREE (ctx); - return NULL; - } - - if ((ret = pthread_create (&ctx->reply_thread, NULL, poll_proc, - (void *)&ctx->gf_ctx))) { - fprintf (stderr, - "libglusterfsclient: %s:%s():%d: reply thread creation failed\n", - __FILE__, __PRETTY_FUNCTION__, __LINE__); - xlator_graph_fini (graph); - xlator_tree_free (graph); - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.cmd_args.volume_file); - FREE (ctx->gf_ctx.cmd_args.volume_name); - - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - /* TODO: destroy graph */ - /* inode_table_destroy (ctx->itable); */ - FREE (ctx); - return NULL; - } - - pthread_mutex_lock (&priv->lock); - { - while (!priv->complete) { - pthread_cond_wait (&priv->init_con_established, - &priv->lock); - } - } - pthread_mutex_unlock (&priv->lock); - - /* - * wait for some time to allow initialization of all children of - * distribute before sending lookup on '/' - */ - - tv.tv_sec = 0; - tv.tv_usec = (100 * 1000); - select (0, NULL, NULL, NULL, &tv); - - /* workaround for xlators like dht which require lookup to be sent - * on / */ - libgf_client_loc_fill (&new_loc, ctx, 1, 0, "/"); - ret = libgf_client_lookup (ctx, &new_loc, NULL, NULL, NULL); - if (ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, "lookup of /" - " failed"); - return NULL; - } - libgf_client_loc_wipe (&new_loc); - - first_init = 0; - - return ctx; -} - -struct vmp_entry * -libgf_init_vmpentry (char *vmp, glusterfs_handle_t *vmphandle) -{ - struct vmp_entry *entry = NULL; - size_t vmplen = 0; - int appendslash = 0; - int ret = -1; - - entry = CALLOC (1, sizeof (struct vmp_entry)); - if (!entry) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR,"Memory allocation failed"); - return NULL; - } - - vmplen = strlen (vmp); - assert (vmplen > 0); - if (vmp[vmplen - 1] != '/') { - vmplen++; - appendslash = 1; - } - - entry->vmp = CALLOC (vmplen + 1, sizeof (char)); - if (!entry->vmp) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Memory allocation " - "failed"); - goto free_entry; - } - - strcpy (entry->vmp, vmp); - if (appendslash) { - entry->vmp[vmplen-1] = '/'; - entry->vmp[vmplen] = '\0'; - } - - entry->vmplen = vmplen; - entry->handle = vmphandle; - INIT_LIST_HEAD (&entry->list); - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "New VMP entry: %s", vmp); - - ret = 0; - -free_entry: - if (ret == -1) { - if (entry->vmp) - FREE (entry->vmp); - if (entry) - FREE (entry); - entry = NULL; - } - return entry; -} - -void -libgf_free_vmp_entry (struct vmp_entry *entry) -{ - FREE (entry->vmp); - FREE (entry); -} - -int -libgf_count_path_components (char *path) -{ - int compos = 0; - char *pathdup = NULL; - int len = 0; - - if (!path || !*path) - return -1; - - pathdup = strdup (path); - if (!pathdup) - return -1; - - len = strlen (pathdup); - if (pathdup[len - 1] == '/') - pathdup[len - 1] = '\0'; - - path = pathdup; - while ((path = strchr (path, '/'))) { - compos++; - ++path; - } - - free (pathdup); - return compos; -} - -/* Returns the number of components that match between - * the VMP and the path. Assumes string1 is vmp entry. - * Assumes both are absolute paths. - */ -int -libgf_strmatchcount (char *string1, char *string2) -{ - int matchcount = 0; - char *s1dup = NULL, *s2dup = NULL; - char *tok1 = NULL, *saveptr1 = NULL; - char *tok2 = NULL, *saveptr2 = NULL; - - if ((!string1) || (!string2)) - return 0; - - s1dup = strdup (string1); - if (!s1dup) - return 0; - - s2dup = strdup (string2); - if (!s2dup) - goto free_s1; - - string1 = s1dup; - string2 = s2dup; - - tok1 = strtok_r(string1, "/", &saveptr1); - tok2 = strtok_r (string2, "/", &saveptr2); - while (tok1) { - if (!tok2) - break; - - if (strcmp (tok1, tok2) != 0) - break; - - matchcount++; - tok1 = strtok_r(NULL, "/", &saveptr1); - tok2 = strtok_r (NULL, "/", &saveptr2); - } - - free (s2dup); -free_s1: - free (s1dup); - return matchcount; -} - -int -libgf_vmp_entry_match (struct vmp_entry *entry, char *path) -{ - return libgf_strmatchcount (entry->vmp, path); -} - -#define LIBGF_VMP_EXACT 1 -#define LIBGF_VMP_LONGESTPREFIX 0 - - -/* copies vmp from the vmp-entry having glusterfs handle @handle, into @vmp */ -char * -libgf_vmp_search_vmp (glusterfs_handle_t handle, char *vmp, size_t vmp_size) -{ - char *res = NULL; - struct vmp_entry *entry = NULL; - - if (handle == NULL) { - goto out; - } - - pthread_mutex_lock (&vmplock); - { - if (vmplist.entries == 0) { - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Virtual Mount Point " - "list is empty."); - goto unlock; - } - - list_for_each_entry(entry, &vmplist.list, list) { - if (entry->handle == handle) { - if ((vmp_size) < (strlen (entry->vmp) + 1)) { - errno = ENAMETOOLONG; - goto unlock; - } - - strcpy (vmp, entry->vmp); - res = vmp; - break; - } - } - } -unlock: - pthread_mutex_unlock (&vmplock); - -out: - return res; -} - - -struct vmp_entry * -_libgf_vmp_search_entry (char *path, int searchtype) -{ - struct vmp_entry *entry = NULL; - int matchcount = 0; - struct vmp_entry *maxentry = NULL; - int maxcount = 0; - int vmpcompcount = 0; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "VMP Search: path %s, type: %s", - path, (searchtype == LIBGF_VMP_EXACT)?"Exact":"LongestPrefix"); - if (vmplist.entries == 0) { - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Virtual Mount Point " - "list is empty."); - goto out; - } - - list_for_each_entry(entry, &vmplist.list, list) { - vmpcompcount = libgf_count_path_components (entry->vmp); - matchcount = libgf_vmp_entry_match (entry, path); - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Candidate VMP: %s," - " Matchcount: %d", entry->vmp, matchcount); - if ((matchcount > maxcount) && (matchcount == vmpcompcount)) { - maxcount = matchcount; - maxentry = entry; - } - } - - /* To ensure that the longest prefix matched entry is also an exact - * match, this is used to check whether duplicate entries are present - * in the vmplist. - */ - vmpcompcount = 0; - if ((searchtype == LIBGF_VMP_EXACT) && (maxentry)) { - vmpcompcount = libgf_count_path_components (maxentry->vmp); - matchcount = libgf_count_path_components (path); - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Exact Check: VMP: %s," - " CompCount: %d, Path: %s, CompCount: %d", - maxentry->vmp, vmpcompcount, path, matchcount); - if (vmpcompcount != matchcount) { - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "No Match"); - maxentry = NULL; - } else - gf_log (LIBGF_XL_NAME, GF_LOG_TRACE, "Matches!"); - } - -out: - return maxentry; -} - -/* Used to search for a exactly matching VMP entry. - */ -struct vmp_entry * -libgf_vmp_search_exact_entry (char *path) -{ - struct vmp_entry *entry = NULL; - - if (!path) - goto out; - - pthread_mutex_lock (&vmplock); - { - entry = _libgf_vmp_search_entry (path, LIBGF_VMP_EXACT); - } - pthread_mutex_unlock (&vmplock); - -out: - if (entry) - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "VMP Entry found: path :%s" - " vmp: %s", path, entry->vmp); - else - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "VMP Entry not found: path" - ": %s", path); - - return entry; -} - - -/* Used to search for a longest prefix matching VMP entry. - */ -struct vmp_entry * -libgf_vmp_search_entry (char *path) -{ - struct vmp_entry *entry = NULL; - - if (!path) - goto out; - - pthread_mutex_lock (&vmplock); - { - entry = _libgf_vmp_search_entry (path, LIBGF_VMP_LONGESTPREFIX); - } - pthread_mutex_unlock (&vmplock); - -out: - if (entry) - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "VMP Entry found: path :%s" - " vmp: %s", path, entry->vmp); - else - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "VMP Entry not found: path" - ": %s", path); - - return entry; -} - -int -libgf_vmp_map_ghandle (char *vmp, glusterfs_handle_t *vmphandle) -{ - int ret = -1; - struct vmp_entry *vmpentry = NULL; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "New Entry: %s", vmp); - vmpentry = libgf_init_vmpentry (vmp, vmphandle); - if (!vmpentry) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Failed to create VMP" - " entry"); - goto out; - } - - pthread_mutex_lock (&vmplock); - { - if (vmplist.entries == 0) { - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Empty list"); - INIT_LIST_HEAD (&vmplist.list); - } - - list_add_tail (&vmpentry->list, &vmplist.list); - ++vmplist.entries; - } - pthread_mutex_unlock (&vmplock); - ret = 0; - -out: - return ret; -} - -/* Path must be validated already. */ -glusterfs_handle_t -libgf_vmp_get_ghandle (char * path) -{ - struct vmp_entry *entry = NULL; - - entry = libgf_vmp_search_entry (path); - - if (entry == NULL) - return NULL; - - return entry->handle; -} - - -/* Returns the handle for the path given in @path, - * @path can be a relative path. The point is, here we - * perform any path resolution that is needed and then - * search for the corresponding vmp handle. - * @vpath is a result-value argument in that the virtual - * path inside the handle is copied into it. - */ -glusterfs_handle_t -libgf_resolved_path_handle (const char *path, char *vpath) -{ - char *respath = NULL; - struct vmp_entry *entry = NULL; - glusterfs_handle_t handle = NULL; - char *tmp = NULL; - - if ((!path) || (!vpath)) - return NULL; - - /* We only want compaction before VMP entry search because the - * VMP cannot be search unless we have an absolute path. - * For absolute paths, we search for VMP first, then perform the - * path compaction on the given virtual path. - */ - if (!libgf_path_absolute (path)) { - respath = libgf_resolve_path_light ((char *)path); - if (respath == NULL) - return NULL; - } - - /* This condition is needed because in case of absolute paths, the path - * would already include the VMP and we want to ensure that any path - * compaction that happens does not exclude the VMP. In the absence of - * this condition an absolute path might get compacted to "/", i.e. - * exclude the VMP, and the search will fail. - * - * For relative paths, respath will aleady include a potential VMP - * as a consequence of us prepending the CWD in resolve_light above. - */ - if (libgf_path_absolute (path)) { - entry = libgf_vmp_search_entry ((char *)path); - if (!entry) - goto free_respath; - tmp = libgf_vmp_virtual_path (entry, path, vpath); - if (!tmp) - goto free_respath; - - respath = libgf_resolve_path_light (vpath); - strcpy (vpath, respath); - } else { - entry = libgf_vmp_search_entry (respath); - if (!entry) - goto free_respath; - tmp = libgf_vmp_virtual_path (entry, respath, vpath); - if (!tmp) - goto free_respath; - } - - handle = entry->handle; -free_respath: - if (respath) - free (respath); /* Alloced in libgf_resolve_path_light */ - - return handle; -} - - -int -glusterfs_mount (char *vmp, glusterfs_init_params_t *ipars) -{ - glusterfs_handle_t vmphandle = NULL; - int ret = -1; - char *vmp_resolved = NULL; - struct vmp_entry *vmp_entry = NULL; - uint32_t vmphash = 0; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, vmp, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ipars, out); - - vmp_resolved = libgf_resolve_path_light (vmp); - if (!vmp_resolved) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Path compaction failed"); - goto out; - } - - vmphash = (dev_t)ReallySimpleHash (vmp, strlen (vmp)); - pthread_mutex_lock (&mountlock); - { - vmp_entry = libgf_vmp_search_exact_entry (vmp); - if (vmp_entry) { - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Entry exists"); - ret = 0; - goto unlock; - } - - vmphandle = glusterfs_init (ipars, vmphash); - if (!vmphandle) { - errno = EINVAL; - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "GlusterFS context" - " init failed"); - goto unlock; - } - - ret = libgf_vmp_map_ghandle (vmp_resolved, vmphandle); - if (ret == -1) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Failed to map new" - " handle: %s", vmp); - glusterfs_fini (vmphandle); - } - } -unlock: - pthread_mutex_unlock (&mountlock); - -out: - if (vmp_resolved) - FREE (vmp_resolved); - - return ret; -} - -inline int -_libgf_umount (char *vmp) -{ - struct vmp_entry *entry= NULL; - int ret = -1; - - entry = _libgf_vmp_search_entry (vmp, LIBGF_VMP_EXACT); - if (entry == NULL) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path (%s) not mounted", vmp); - goto out; - } - - if (entry->handle == NULL) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path (%s) has no corresponding glusterfs handle", - vmp); - goto out; - } - -/* ret = glusterfs_fini (entry->handle); */ - list_del_init (&entry->list); - libgf_free_vmp_entry (entry); - - vmplist.entries--; - -out: - return ret; -} - -inline int -libgf_umount (char *vmp) -{ - int ret = -1; - - pthread_mutex_lock (&vmplock); - { - ret = _libgf_umount (vmp); - } - pthread_mutex_unlock (&vmplock); - - return ret; -} - -int -glusterfs_umount (char *vmp) -{ - int ret = -1; - char *vmp_resolved = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, vmp, out); - - vmp_resolved = libgf_resolve_path_light (vmp); - if (!vmp_resolved) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Path compaction failed"); - goto out; - } - - ret = libgf_umount (vmp_resolved); - -out: - if (vmp_resolved) - FREE (vmp_resolved); - - return ret; -} - -int -glusterfs_umount_all (void) -{ - struct vmp_entry *entry = NULL, *tmp = NULL; - - pthread_mutex_lock (&vmplock); - { - if (vmplist.entries > 0) { - list_for_each_entry_safe (entry, tmp, &vmplist.list, - list) { - /* even if there are errors, continue with other - mounts - */ - _libgf_umount (entry->vmp); - } - } - } - pthread_mutex_unlock (&vmplock); - - return 0; -} - -void -glusterfs_reset (void) -{ - INIT_LIST_HEAD (&vmplist.list); - vmplist.entries = 0; - - memset (&vmplock, 0, sizeof (vmplock)); - pthread_mutex_init (&vmplock, NULL); - - first_init = 1; -} - -void -glusterfs_log_lock (void) -{ - gf_log_lock (); -} - - -void glusterfs_log_unlock (void) -{ - gf_log_unlock (); -} - - -void -libgf_wait_for_frames_unwind (libglusterfs_client_ctx_t *ctx) -{ - call_pool_t *pool = NULL; - int canreturn = 0; - - if (!ctx) - return; - - pool = (call_pool_t *)ctx->gf_ctx.pool; - while (1) { - LOCK (&pool->lock); - { - if (pool->cnt == 0) { - canreturn = 1; - goto unlock_out; - } - } -unlock_out: - UNLOCK (&pool->lock); - - if (canreturn) - break; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Waiting for call frames"); - sleep (1); - } - - return; -} - - -int -glusterfs_fini (glusterfs_handle_t handle) -{ - libglusterfs_client_ctx_t *ctx = handle; - - libgf_wait_for_frames_unwind (ctx); - - FREE (ctx->gf_ctx.cmd_args.log_file); - FREE (ctx->gf_ctx.cmd_args.volume_file); - FREE (ctx->gf_ctx.cmd_args.volume_name); - FREE (ctx->gf_ctx.pool); - FREE (ctx->gf_ctx.event_pool); - mem_pool_destroy (ctx->itable->inode_pool); - mem_pool_destroy (ctx->itable->dentry_pool); - mem_pool_destroy (ctx->itable->fd_mem_pool); - /* iobuf_pool_destroy (ctx->gf_ctx.iobuf_pool); */ - ((gf_timer_registry_t *)ctx->gf_ctx.timer)->fin = 1; - - xlator_graph_fini (ctx->gf_ctx.graph); - xlator_tree_free (ctx->gf_ctx.graph); - ctx->gf_ctx.graph = NULL; - pthread_cancel (ctx->reply_thread); - - FREE (ctx); - - return 0; -} - - -int32_t -libgf_client_lookup_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - dict_t *dict, - struct iatt *postparent) -{ - libgf_client_local_t *local = frame->local; - libglusterfs_client_ctx_t *ctx = frame->root->state; - dict_t *xattr_req = NULL; - - if (op_ret == 0) { - inode_t *parent = NULL; - - if (local->fop.lookup.loc->ino == 1) { - buf->ia_ino = 1; - } - - parent = local->fop.lookup.loc->parent; - if (inode->ino != 1) { - inode = inode_link (inode, parent, - local->fop.lookup.loc->name, buf); - } - - libgf_transform_iattr (ctx, inode, buf); - inode_lookup (inode); - } else { - if ((local->fop.lookup.is_revalidate == 0) - && (op_errno == ENOENT)) { - gf_log ("libglusterfsclient", GF_LOG_DEBUG, - "%"PRId64": (op_num=%d) %s => -1 (%s)", - frame->root->unique, frame->root->op, - local->fop.lookup.loc->path, - strerror (op_errno)); - } else { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "%"PRId64": (op_num=%d) %s => -1 (%s)", - frame->root->unique, frame->root->op, - local->fop.lookup.loc->path, - strerror (op_errno)); - } - - if (local->fop.lookup.is_revalidate == 1) { - int32_t ret = 0; - inode_unref (local->fop.lookup.loc->inode); - local->fop.lookup.loc->inode = inode_new (ctx->itable); - local->fop.lookup.is_revalidate = 2; - - if (local->fop.lookup.size > 0) { - xattr_req = dict_new (); - ret = dict_set (xattr_req, "glusterfs.content", - data_from_uint64 (local->fop.lookup.size)); - if (ret == -1) { - op_ret = -1; - /* TODO: set proper error code */ - op_errno = errno; - inode = NULL; - buf = NULL; - dict = NULL; - dict_unref (xattr_req); - goto out; - } - } - - STACK_WIND (frame, libgf_client_lookup_cbk, - FIRST_CHILD (this), - FIRST_CHILD (this)->fops->lookup, - local->fop.lookup.loc, xattr_req); - - if (xattr_req) { - dict_unref (xattr_req); - xattr_req = NULL; - } - - return 0; - } - } - -out: - local->reply_stub = fop_lookup_cbk_stub (frame, NULL, op_ret, op_errno, - inode, buf, dict, postparent); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int32_t -libgf_client_lookup (libglusterfs_client_ctx_t *ctx, - loc_t *loc, - struct iatt *stbuf, - dict_t **dict, - dict_t *xattr_req) -{ - call_stub_t *stub = NULL; - int32_t op_ret; - libgf_client_local_t *local = NULL; - inode_t *inode = NULL; - - local = CALLOC (1, sizeof (*local)); - if (!local) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Memory allocation" - " failed"); - errno = ENOMEM; - return -1; - } - - if (loc->inode) { - local->fop.lookup.is_revalidate = 1; - loc->ino = loc->inode->ino; - } - else - loc->inode = inode_new (ctx->itable); - - local->fop.lookup.loc = loc; - - LIBGF_CLIENT_FOP(ctx, stub, lookup, local, loc, xattr_req); - - op_ret = stub->args.lookup_cbk.op_ret; - errno = stub->args.lookup_cbk.op_errno; - - if (op_ret == -1) - goto out; - - inode = stub->args.lookup_cbk.inode; - if (!(libgf_get_inode_ctx (inode))) - libgf_alloc_inode_ctx (ctx, inode); - libgf_transform_iattr (ctx, inode, &stub->args.lookup_cbk.buf); - libgf_update_iattr_cache (inode, LIBGF_UPDATE_ALL, - &stub->args.lookup_cbk.buf); - if (stbuf) - *stbuf = stub->args.lookup_cbk.buf; - - if (dict) - *dict = dict_ref (stub->args.lookup_cbk.dict); - - if (inode != loc->inode) { - inode_unref (loc->inode); - loc->inode = inode_ref (inode); - } - -out: - call_stub_destroy (stub); - return op_ret; -} - -int -glusterfs_glh_get (glusterfs_handle_t handle, const char *path, void *buf, - size_t size, struct stat *stbuf) -{ - int32_t op_ret = -1; - loc_t loc = {0, }; - libglusterfs_client_ctx_t *ctx = handle; - dict_t *dict = NULL; - dict_t *xattr_req = NULL; - char *name = NULL, *pathname = NULL; - struct iatt iatt = {0,}; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, size %lu", path, - (long unsigned)size); - if (size < 0) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Invalid size"); - errno = EINVAL; - goto out; - } - - if (size == 0) { - op_ret = 0; - goto out; - } - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Path compaction failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 0); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", loc.path); - goto out; - } - - pathname = strdup (loc.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, - "libgf_client_loc_fill returned -1, returning EINVAL"); - errno = EINVAL; - goto out; - } - - if (size) { - xattr_req = dict_new (); - op_ret = dict_set (xattr_req, "glusterfs.content", - data_from_uint64 (size)); - if (op_ret < 0) { - gf_log ("libglusterfsclient", - GF_LOG_ERROR, - "setting requested content size dictionary failed"); - goto out; - } - } - - op_ret = libgf_client_lookup (ctx, &loc, &iatt, &dict, xattr_req); - iatt_to_stat (&iatt, stbuf); - if (!op_ret && stbuf && (iatt.ia_size <= size) && dict && buf) { - data_t *mem_data = NULL; - void *mem = NULL; - - mem_data = dict_get (dict, "glusterfs.content"); - if (mem_data) { - mem = data_to_ptr (mem_data); - } - - if (mem != NULL) { - memcpy (buf, mem, iatt.ia_size); - } - } - -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; -} - -int -glusterfs_get (const char *path, void *buf, size_t size, struct stat *stbuf) -{ - int op_ret = -1; - glusterfs_handle_t h = NULL; - char vpath[PATH_MAX]; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, buf, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, stbuf, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, size %lu", path, - (long unsigned)size); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_get (h, vpath, buf, size, stbuf); - -out: - return op_ret; -} - -int -libgf_client_lookup_async_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *stbuf, - dict_t *dict, - struct iatt *postparent) -{ - libglusterfs_client_async_local_t *local = frame->local; - 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; - inode_t *parent = NULL; - struct stat stat = {0,}; - - if (op_ret == 0) { - parent = local->fop.lookup_cbk.loc->parent; - inode_link (inode, parent, local->fop.lookup_cbk.loc->name, - stbuf); - libgf_transform_iattr (ctx, inode, stbuf); - if (!(libgf_get_inode_ctx (inode))) - libgf_alloc_inode_ctx (ctx, inode); - libgf_update_iattr_cache (inode, LIBGF_UPDATE_ALL, stbuf); - inode_lookup (inode); - } else { - if ((local->fop.lookup_cbk.is_revalidate == 0) - && (op_errno == ENOENT)) { - gf_log ("libglusterfsclient", GF_LOG_DEBUG, - "%"PRId64": (op_num=%d) %s => -1 (%s)", - frame->root->unique, frame->root->op, - local->fop.lookup_cbk.loc->path, - strerror (op_errno)); - } else { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "%"PRId64": (op_num=%d) %s => -1 (%s)", - frame->root->unique, frame->root->op, - local->fop.lookup_cbk.loc->path, - strerror (op_errno)); - } - - if (local->fop.lookup_cbk.is_revalidate == 1) { - int32_t ret = 0; - inode_unref (local->fop.lookup_cbk.loc->inode); - local->fop.lookup_cbk.loc->inode = inode_new (ctx->itable); - local->fop.lookup_cbk.is_revalidate = 2; - - if (local->fop.lookup_cbk.size > 0) { - xattr_req = dict_new (); - ret = dict_set (xattr_req, "glusterfs.content", - data_from_uint64 (local->fop.lookup_cbk.size)); - if (ret == -1) { - op_ret = -1; - /* TODO: set proper error code */ - op_errno = errno; - inode = NULL; - stbuf = NULL; - dict = NULL; - dict_unref (xattr_req); - goto out; - } - } - - - STACK_WIND (frame, libgf_client_lookup_async_cbk, - FIRST_CHILD (this), - FIRST_CHILD (this)->fops->lookup, - local->fop.lookup_cbk.loc, xattr_req); - - if (xattr_req) { - dict_unref (xattr_req); - xattr_req = NULL; - } - - return 0; - } - } - -out: - 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 && stbuf->ia_size <= local->fop.lookup_cbk.size) { - iobuf = CALLOC (1, sizeof (*iobuf)); - ERR_ABORT (iobuf); - - vector = CALLOC (1, sizeof (*vector)); - ERR_ABORT (vector); - vector->iov_base = mem; - vector->iov_len = stbuf->ia_size; - - iobuf->vector = vector; - iobuf->count = 1; - iobuf->dictref = dict_ref (dict); - } - } - - iatt_to_stat (stbuf, &stat); - lookup_cbk (op_ret, op_errno, iobuf, &stat, local->cbk_data); - - libgf_client_loc_wipe (local->fop.lookup_cbk.loc); - free (local->fop.lookup_cbk.loc); - - free (local); - frame->local = NULL; - STACK_DESTROY (frame->root); - - return 0; -} - -/* TODO: implement async dentry lookup */ - -int -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; - } - - if (size < 0) { - errno = EINVAL; - op_ret = -1; - goto out; - } - - if (size == 0) { - op_ret = 0; - goto out; - } - - local = CALLOC (1, sizeof (*local)); - local->fop.lookup_cbk.is_revalidate = 1; - - loc = CALLOC (1, sizeof (*loc)); - loc->path = strdup (path); - op_ret = libgf_client_path_lookup (loc, ctx, 1); - 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, - "libgf_client_loc_fill returned -1, returning EINVAL"); - errno = EINVAL; - goto out; - } - - if (!loc->inode) { - loc->inode = inode_new (ctx->itable); - local->fop.lookup_cbk.is_revalidate = 0; - } - - local->fop.lookup_cbk.cbk = cbk; - local->fop.lookup_cbk.size = size; - local->fop.lookup_cbk.loc = loc; - local->cbk_data = cbk_data; - - if (size > 0) { - xattr_req = dict_new (); - op_ret = dict_set (xattr_req, "glusterfs.content", - data_from_uint64 (size)); - if (op_ret < 0) { - dict_unref (xattr_req); - xattr_req = NULL; - goto out; - } - } - - LIBGF_CLIENT_FOP_ASYNC (ctx, - local, - libgf_client_lookup_async_cbk, - lookup, - loc, - xattr_req); - if (xattr_req) { - dict_unref (xattr_req); - xattr_req = NULL; - } - -out: - if (pathname) { - FREE (pathname); - } - - return op_ret; -} - -int32_t -libgf_client_getxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) -{ - - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_getxattr_cbk_stub (frame, NULL, op_ret, - op_errno, dict); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -size_t -libgf_client_getxattr (libglusterfs_client_ctx_t *ctx, - loc_t *loc, - const char *name, - void *value, - size_t size) -{ - call_stub_t *stub = NULL; - int32_t op_ret = 0; - libgf_client_local_t *local = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, getxattr, local, loc, name); - - op_ret = stub->args.getxattr_cbk.op_ret; - errno = stub->args.getxattr_cbk.op_errno; - - if (op_ret >= 0) { - /* - gf_log ("LIBGF_CLIENT", GF_LOG_DEBUG, - "%"PRId64": %s => %d", frame->root->unique, - state->fuse_loc.loc.path, op_ret); - */ - - data_t *value_data = dict_get (stub->args.getxattr_cbk.dict, - (char *)name); - - if (value_data) { - int32_t copy_len = 0; - - /* Don't return the value for '\0' */ - op_ret = value_data->len; - if ((size > 0) && (value != NULL)) { - copy_len = size < value_data->len ? - size : value_data->len; - memcpy (value, value_data->data, copy_len); - op_ret = copy_len; - } - } else { - errno = ENODATA; - op_ret = -1; - } - } - - call_stub_destroy (stub); - return op_ret; -} - -#define LIBGF_DO_GETXATTR 1 -#define LIBGF_DO_LGETXATTR 2 - -ssize_t -__glusterfs_glh_getxattr (glusterfs_handle_t handle, const char *path, - const char *name, void *value, size_t size, - int whichop) -{ - int32_t op_ret = -1; - loc_t loc = {0, }; - libglusterfs_client_ctx_t *ctx = handle; - char *file = NULL; - char *pathres = NULL, *tmp = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, name, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, name %s, size %lu," - " op %d", path, name, (long unsigned)size, whichop); - if (name[0] == '\0') { - errno = EINVAL; - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Invalid argument: Name" - " not NULL terminated"); - goto out; - } - - if (size < 0) { - errno = EINVAL; - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Invalid argument: size is" - " less than zero"); - goto out; - } - - pathres = strdup (path); - if (!pathres) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - loc.path = strdup (pathres); - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", loc.path); - goto out; - } - - tmp = strdup (pathres); - file = basename (tmp); - 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"); - errno = EINVAL; - goto out; - } - - if (whichop == LIBGF_DO_LGETXATTR) - goto do_getx; - - if (!IA_ISLNK (loc.inode->ia_type)) - goto do_getx; - - libgf_client_loc_wipe (&loc); - op_ret = libgf_realpath_loc_fill (ctx, (char *)pathres, &loc); - if (op_ret == -1) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "realpath failed"); - goto out; - } - -do_getx: - op_ret = libgf_client_getxattr (ctx, &loc, name, value, size); - -out: - if (tmp) { - FREE (tmp); - } - - if (pathres) - FREE (pathres); - - libgf_client_loc_wipe (&loc); - - return op_ret; -} - -ssize_t -glusterfs_glh_getxattr (glusterfs_handle_t handle, const char *path, - const char *name, void *value, size_t size) -{ - return __glusterfs_glh_getxattr (handle, path, name, value, size, - LIBGF_DO_GETXATTR); -} - -ssize_t -glusterfs_glh_lgetxattr (glusterfs_handle_t handle, const char *path, - const char *name, void *value, size_t size) -{ - return __glusterfs_glh_getxattr (handle, path, name, value, size, - LIBGF_DO_LGETXATTR); -} - -ssize_t -glusterfs_getxattr (const char *path, const char *name, void *value, - size_t size) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, name, out); - - if ((size > 0) && (value == NULL)) { - errno = EINVAL; - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Invalid argument value"); - goto out; - } - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, name %s, size %lu", - path, name, (long unsigned)size); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = __glusterfs_glh_getxattr (h, vpath, name, value, size, - LIBGF_DO_GETXATTR); - -out: - return op_ret; -} - -ssize_t -glusterfs_lgetxattr (const char *path, const char *name, void *value, - size_t size) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, name, out); - - if ((size > 0) && (value == NULL)) { - errno = EINVAL; - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Invalid argument value"); - goto out; - } - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, name %s, size %lu", - path, name, (long unsigned)size); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = __glusterfs_glh_getxattr (h, vpath, name, value, size, - LIBGF_DO_LGETXATTR); - -out: - return op_ret; -} - -static int32_t -libgf_client_open_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_open_cbk_stub (frame, NULL, op_ret, op_errno, - fd); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - - -int -libgf_client_open (libglusterfs_client_ctx_t *ctx, - loc_t *loc, - fd_t *fd, - int flags) -{ - call_stub_t *stub = NULL; - int32_t op_ret = 0; - libgf_client_local_t *local = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, open, local, loc, flags, fd, 0); - - op_ret = stub->args.open_cbk.op_ret; - errno = stub->args.open_cbk.op_errno; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "open: path %s, status: %d, errno" - " %d", loc->path, op_ret, errno); - if (op_ret != -1) - fd_bind (fd); - call_stub_destroy (stub); - return op_ret; -} - -static int32_t -libgf_client_create_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_create_cbk_stub (frame, NULL, op_ret, op_errno, - fd, inode, buf, preparent, - postparent); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int -libgf_client_creat (libglusterfs_client_ctx_t *ctx, - loc_t *loc, - fd_t *fd, - int flags, - mode_t mode) -{ - call_stub_t *stub = NULL; - int32_t op_ret = 0; - libgf_client_local_t *local = NULL; - inode_t *libgf_inode = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, create, local, loc, flags, mode, fd); - - op_ret = stub->args.create_cbk.op_ret; - errno = stub->args.create_cbk.op_errno; - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Create: path %s, status: %d," - " errno: %d", loc->path, op_ret, errno); - if (op_ret == -1) - goto out; - - libgf_inode = stub->args.create_cbk.inode; - inode_link (libgf_inode, loc->parent, loc->name, - &stub->args.create_cbk.buf); - libgf_transform_iattr (ctx, libgf_inode, &stub->args.create_cbk.buf); - - inode_lookup (libgf_inode); - - libgf_alloc_inode_ctx (ctx, libgf_inode); - libgf_update_iattr_cache (libgf_inode, LIBGF_UPDATE_ALL, - &stub->args.create_cbk.buf); - -out: - call_stub_destroy (stub); - return op_ret; -} - -int32_t -libgf_client_opendir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_opendir_cbk_stub (frame, NULL, op_ret, op_errno, - fd); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int -libgf_client_opendir (libglusterfs_client_ctx_t *ctx, - loc_t *loc, - fd_t *fd) -{ - call_stub_t *stub = NULL; - int32_t op_ret = -1; - libgf_client_local_t *local = NULL; - - if (((fd->flags & O_ACCMODE) == O_WRONLY) - || ((fd->flags & O_ACCMODE) == O_RDWR)) { - errno = EISDIR; - goto out; - } - LIBGF_CLIENT_FOP (ctx, stub, opendir, local, loc, fd); - - op_ret = stub->args.opendir_cbk.op_ret; - errno = stub->args.opendir_cbk.op_errno; - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "opendir: path %s, status %d," - " errno %d", loc->path, op_ret, errno); - if (op_ret != -1) - fd_bind (fd); - - call_stub_destroy (stub); -out: - return op_ret; -} - -glusterfs_file_t -glusterfs_glh_open (glusterfs_handle_t handle, const char *path, int flags,...) -{ - loc_t loc = {0, }; - long op_ret = -1; - fd_t *fd = NULL; - int32_t ret = -1; - libglusterfs_client_ctx_t *ctx = handle; - char *name = NULL, *pathname = NULL; - libglusterfs_client_inode_ctx_t *inode_ctx = NULL; - mode_t mode = 0; - va_list ap; - char *pathres = NULL; - char *vpath = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - pathres = strdup (path); - if (!pathres) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - loc.path = strdup (pathres); - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - - if ((op_ret == -1) && ((flags & O_CREAT) != O_CREAT)) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", loc.path); - goto out; - } - - if (!op_ret && ((flags & O_CREAT) == O_CREAT) - && ((flags & O_EXCL) == O_EXCL)) { - errno = EEXIST; - op_ret = -1; - goto out; - } - - if (op_ret == 0) { - flags &= ~O_CREAT; - } - - if ((op_ret == -1) && ((flags & O_CREAT) == O_CREAT)) { - libgf_client_loc_wipe (&loc); - loc.path = strdup (pathres); - - op_ret = libgf_client_path_lookup (&loc, ctx, 0); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for parent while trying to" - " create (%s)", pathres); - goto out; - } - - loc.inode = inode_new (ctx->itable); - } - - pathname = strdup (pathres); - name = basename (pathname); - - ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, name); - if (ret == -1) { - gf_log ("libglusterfsclient", - GF_LOG_ERROR, - "libgf_client_loc_fill returned -1, returning EINVAL"); - errno = EINVAL; - goto out; - } - - fd = fd_create (loc.inode, ctx->pid); - fd->flags = flags; - - if (((flags & O_CREAT) == O_CREAT)) { - /* If we have the st_mode for the basename, check if - * it is a directory here itself, rather than sending - * a network message through libgf_client_creat, and - * then receiving a EISDIR. - */ - if (IA_ISDIR (loc.inode->ia_type)) { - errno = EISDIR; - op_ret = -1; - goto op_over; - } - va_start (ap, flags); - mode = va_arg (ap, mode_t); - va_end (ap); - op_ret = libgf_client_creat (ctx, &loc, fd, flags, mode); - } else { - if (IA_ISDIR (loc.inode->ia_type)) - op_ret = libgf_client_opendir (ctx, &loc, fd); - else - op_ret = libgf_client_open (ctx, &loc, fd, flags); - } - -op_over: - if (op_ret == -1) { - fd_unref (fd); - fd = NULL; - goto out; - } - - vpath = NULL; - if (IA_ISDIR (loc.inode->ia_type)) { - vpath = (char *)path; - } - - if (!libgf_get_fd_ctx (fd)) { - if (!libgf_alloc_fd_ctx (ctx, fd, vpath)) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Failed to" - " allocate fd context"); - errno = EINVAL; - op_ret = -1; - goto out; - } - } - - if ((flags & O_TRUNC) && (((flags & O_ACCMODE) == O_RDWR) - || ((flags & O_ACCMODE) == O_WRONLY))) { - inode_ctx = libgf_get_inode_ctx (fd->inode); - if (IA_ISREG (inode_ctx->stbuf.ia_type)) { - inode_ctx->stbuf.ia_size = 0; - inode_ctx->stbuf.ia_blocks = 0; - } - } - -out: - libgf_client_loc_wipe (&loc); - - if (pathname) { - FREE (pathname); - } - - if (pathres) - FREE (pathres); - - return fd; -} - -glusterfs_file_t -glusterfs_open (const char *path, int flags, ...) -{ - va_list ap; - glusterfs_file_t fh = NULL; - glusterfs_handle_t h = NULL; - mode_t mode = 0; - char vpath[PATH_MAX]; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - if (flags & O_CREAT) { - va_start (ap, flags); - mode = va_arg (ap, mode_t); - va_end (ap); - fh = glusterfs_glh_open (h, vpath, flags, mode); - } else - fh = glusterfs_glh_open (h, vpath, flags); -out: - return fh; -} - -glusterfs_file_t -glusterfs_glh_creat (glusterfs_handle_t handle, const char *path, mode_t mode) -{ - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - return glusterfs_glh_open (handle, path, - (O_CREAT | O_WRONLY | O_TRUNC), mode); -} - -glusterfs_file_t -glusterfs_creat (const char *path, mode_t mode) -{ - glusterfs_file_t fh = NULL; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - fh = glusterfs_glh_creat (h, vpath, mode); - -out: - return fh; -} - -int32_t -libgf_client_flush_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_flush_cbk_stub (frame, NULL, op_ret, op_errno); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - - -int -libgf_client_flush (libglusterfs_client_ctx_t *ctx, fd_t *fd) -{ - call_stub_t *stub; - int32_t op_ret; - libgf_client_local_t *local = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, flush, local, fd); - - op_ret = stub->args.flush_cbk.op_ret; - errno = stub->args.flush_cbk.op_errno; - - call_stub_destroy (stub); - return op_ret; -} - - -int -glusterfs_close (glusterfs_file_t fd) -{ - int32_t op_ret = -1; - libglusterfs_client_ctx_t *ctx = NULL; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - if (!fd) { - errno = EINVAL; - goto out; - } - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - goto out; - } - ctx = fd_ctx->ctx; - - op_ret = libgf_client_flush (ctx, (fd_t *)fd); - - fd_unref ((fd_t *)fd); - -out: - return op_ret; -} - -int32_t -libgf_client_setxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_setxattr_cbk_stub (frame, NULL, op_ret, - op_errno); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int -libgf_client_setxattr (libglusterfs_client_ctx_t *ctx, - loc_t *loc, - const char *name, - const void *value, - size_t size, - int flags) -{ - call_stub_t *stub = NULL; - int32_t op_ret = 0; - dict_t *dict; - libgf_client_local_t *local = NULL; - - dict = get_new_dict (); - - dict_set (dict, (char *)name, - bin_to_data ((void *)value, size)); - dict_ref (dict); - - - LIBGF_CLIENT_FOP (ctx, stub, setxattr, local, loc, dict, flags); - - op_ret = stub->args.setxattr_cbk.op_ret; - errno = stub->args.setxattr_cbk.op_errno; - - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "path %s, name %s, status %d," - "errno %d", loc->path, name, op_ret, errno); - dict_unref (dict); - call_stub_destroy (stub); - return op_ret; -} - - -#define LIBGF_DO_SETXATTR 1 -#define LIBGF_DO_LSETXATTR 2 - -int -__glusterfs_glh_setxattr (glusterfs_handle_t handle, const char *path, - const char *name, const void *value, - size_t size, int flags, int whichop) -{ - int32_t op_ret = -1; - loc_t loc = {0, }; - libglusterfs_client_ctx_t *ctx = handle; - char *tmppath = NULL; - loc_t *realloc = NULL; - char *pathres = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "path %s, name %s, op %d", path - ,name, whichop); - if (size <= 0) { - errno = EINVAL; - goto out; - } - - pathres = strdup (path); - if (!pathres) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - loc.path = strdup (pathres); - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", pathres); - goto out; - } - - tmppath = strdup (pathres); - - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename (tmppath)); - FREE (tmppath); - if (op_ret == -1) { - gf_log ("libglusterfsclient", - GF_LOG_ERROR, - "libgf_client_loc_fill returned -1, returning EINVAL"); - errno = EINVAL; - goto out; - } - - realloc = &loc; - if (whichop == LIBGF_DO_LSETXATTR) - goto do_setx; - - if (!IA_ISLNK (loc.inode->ia_type)) - goto do_setx; - - libgf_client_loc_wipe (&loc); - realloc = &loc; - libgf_realpath_loc_fill (ctx, (char *)pathres, realloc); - -do_setx: - if (!op_ret) - op_ret = libgf_client_setxattr (ctx, realloc, name, value, - size, flags); - -out: - if (pathres) - FREE (pathres); - - libgf_client_loc_wipe (realloc); - return op_ret; -} - -int -glusterfs_glh_setxattr (glusterfs_handle_t handle, const char *path, - const char *name, const void *value, size_t size, - int flags) -{ - return __glusterfs_glh_setxattr (handle, path, name, value, size, flags - , LIBGF_DO_SETXATTR); -} - -int -glusterfs_glh_lsetxattr (glusterfs_handle_t handle, const char *path, - const char *name, const void *value, size_t size, - int flags) -{ - return __glusterfs_glh_setxattr (handle, path, name, value, size, flags - , LIBGF_DO_LSETXATTR); -} - -int -glusterfs_setxattr (const char *path, const char *name, const void *value, - size_t size, int flags) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, name, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, value, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "path %s, name %s", path, name); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = __glusterfs_glh_setxattr (h, vpath, name, value, size, flags, - LIBGF_DO_SETXATTR); - -out: - return op_ret; -} - -int -glusterfs_lsetxattr (const char *path, const char *name, const void *value, - size_t size, int flags) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, name, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, value, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "path %s, name %s", path, name); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = __glusterfs_glh_setxattr (h, vpath, name, value, size, flags, - LIBGF_DO_LSETXATTR); - -out: - return op_ret; -} - -int32_t -libgf_client_fsetxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_fsetxattr_cbk_stub (frame, NULL, op_ret, - op_errno); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int -libgf_client_fsetxattr (libglusterfs_client_ctx_t *ctx, - fd_t *fd, - const char *name, - const void *value, - size_t size, - int flags) -{ - call_stub_t *stub = NULL; - int32_t op_ret = 0; - dict_t *dict; - libgf_client_local_t *local = NULL; - - dict = get_new_dict (); - - dict_set (dict, (char *)name, - bin_to_data ((void *)value, size)); - dict_ref (dict); - - LIBGF_CLIENT_FOP (ctx, stub, fsetxattr, local, fd, dict, flags); - - op_ret = stub->args.fsetxattr_cbk.op_ret; - errno = stub->args.fsetxattr_cbk.op_errno; - - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "name %s, status %d, errno %d", - name, op_ret, errno); - dict_unref (dict); - call_stub_destroy (stub); - - return op_ret; -} - -int -glusterfs_fsetxattr (glusterfs_file_t fd, - const char *name, - const void *value, - size_t size, - int flags) -{ - int32_t op_ret = 0; - fd_t *__fd = fd; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - libglusterfs_client_ctx_t *ctx = NULL; - - if (!fd) { - errno = EINVAL; - op_ret = -1; - gf_log("libglusterfsclient", - GF_LOG_ERROR, - "invalid fd"); - goto out; - } - - if (size <= 0) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Invalid argument: size is" - " less than or equal to zero"); - errno = EINVAL; - op_ret = -1; - goto out; - } - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - op_ret = -1; - goto out; - } - - ctx = fd_ctx->ctx; - op_ret = libgf_client_fsetxattr (ctx, __fd, name, value, size, - flags); - -out: - return op_ret; -} - -int32_t -libgf_client_fgetxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) -{ - - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_fgetxattr_cbk_stub (frame, NULL, op_ret, - op_errno, dict); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -size_t -libgf_client_fgetxattr (libglusterfs_client_ctx_t *ctx, - fd_t *fd, - const char *name, - void *value, - size_t size) -{ - call_stub_t *stub = NULL; - int32_t op_ret = 0; - libgf_client_local_t *local = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, fgetxattr, local, fd, name); - - op_ret = stub->args.fgetxattr_cbk.op_ret; - errno = stub->args.fgetxattr_cbk.op_errno; - - if (op_ret >= 0) { - /* - gf_log ("LIBGF_CLIENT", GF_LOG_DEBUG, - "%"PRId64": %s => %d", frame->root->unique, - state->fuse_loc.loc.path, op_ret); - */ - - data_t *value_data = dict_get (stub->args.fgetxattr_cbk.dict, - (char *)name); - - if (value_data) { - int32_t copy_len = 0; - - /* Don't return the value for '\0' */ - op_ret = value_data->len; - copy_len = size < value_data->len ? - size : value_data->len; - memcpy (value, value_data->data, copy_len); - } else { - errno = ENODATA; - op_ret = -1; - } - } - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "name %s, status %d, errno %d", - name, op_ret, errno); - call_stub_destroy (stub); - return op_ret; -} - -ssize_t -glusterfs_fgetxattr (glusterfs_file_t fd, - const char *name, - void *value, - size_t size) -{ - int32_t op_ret = 0; - libglusterfs_client_ctx_t *ctx; - fd_t *__fd = (fd_t *)fd; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "name %s", name); - if (size < 0) { - errno = EINVAL; - op_ret = -1; - goto out; - } - - if (size == 0) - goto out; - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - op_ret = -1; - goto out; - } - - ctx = fd_ctx->ctx; - op_ret = libgf_client_fgetxattr (ctx, __fd, name, value, size); -out: - return op_ret; -} - -ssize_t -glusterfs_listxattr (glusterfs_handle_t handle, - const char *path, - char *list, - size_t size) -{ - return ENOSYS; -} - -ssize_t -glusterfs_llistxattr (glusterfs_handle_t handle, - const char *path, - char *list, - size_t size) -{ - return ENOSYS; -} - -ssize_t -glusterfs_flistxattr (glusterfs_file_t fd, - char *list, - size_t size) -{ - return ENOSYS; -} - -int -glusterfs_removexattr (glusterfs_handle_t handle, - const char *path, - const char *name) -{ - return ENOSYS; -} - -int -glusterfs_lremovexattr (glusterfs_handle_t handle, - const char *path, - const char *name) -{ - return ENOSYS; -} - -int -glusterfs_fremovexattr (glusterfs_file_t fd, - const char *name) -{ - return ENOSYS; -} - -int32_t -libgf_client_readv_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iovec *vector, - int32_t count, - struct iatt *stbuf, - struct iobref *iobref) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_readv_cbk_stub (frame, NULL, op_ret, op_errno, - vector, count, stbuf, iobref); - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int -libgf_client_iobuf_read (libglusterfs_client_ctx_t *ctx, fd_t *fd, void *buf, - size_t size, off_t offset) -{ - call_stub_t *stub = NULL; - struct iovec *vector = NULL; - int32_t op_ret = -1; - int count = 0; - libgf_client_local_t *local = NULL; - struct iatt *stbuf = NULL; - - local = CALLOC (1, sizeof (*local)); - ERR_ABORT (local); - local->fd = fd; - LIBGF_CLIENT_FOP (ctx, stub, readv, local, fd, size, offset); - - op_ret = stub->args.readv_cbk.op_ret; - errno = stub->args.readv_cbk.op_errno; - count = stub->args.readv_cbk.count; - vector = stub->args.readv_cbk.vector; - if (op_ret > 0) { - int i = 0; - op_ret = 0; - while (size && (i < count)) { - int len = (size < vector[i].iov_len) ? - size : vector[i].iov_len; - memcpy (buf, vector[i++].iov_base, len); - buf += len; - size -= len; - op_ret += len; - } - stbuf = &stub->args.readv_cbk.stbuf; - libgf_transform_iattr (ctx, fd->inode, stbuf); - libgf_invalidate_iattr_cache (fd->inode, LIBGF_INVALIDATE_STAT); - } - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "size %lu, offset %"PRIu64, - (long unsigned)size, offset); - call_stub_destroy (stub); - return op_ret; -} - -int -libgf_client_read (libglusterfs_client_ctx_t *ctx, fd_t *fd, void *buf, - size_t size, off_t offset) -{ - int32_t op_ret = -1; - int32_t ret = 0; - size_t tmp = 0; - - while (size != 0) { - tmp = ((size > LIBGF_IOBUF_SIZE) ? LIBGF_IOBUF_SIZE : - size); - op_ret = libgf_client_iobuf_read (ctx, fd, buf, tmp, offset); - if (op_ret < 0) { - ret = op_ret; - break; - } - - ret += op_ret; - - if (op_ret < tmp) - break; - - size -= op_ret; - offset += op_ret; - buf = (char *)buf + op_ret; - } - - return ret; -} - -ssize_t -glusterfs_read (glusterfs_file_t fd, void *buf, size_t nbytes) -{ - int32_t op_ret = -1; - off_t offset = 0; - libglusterfs_client_ctx_t *ctx = NULL; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - if (nbytes < 0) { - errno = EINVAL; - goto out; - } - - if (nbytes == 0) { - op_ret = 0; - goto out; - } - - if (fd == 0) { - errno = EINVAL; - goto out; - } - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - goto out; - } - - pthread_mutex_lock (&fd_ctx->lock); - { - ctx = fd_ctx->ctx; - offset = fd_ctx->offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - - op_ret = libgf_client_read (ctx, (fd_t *)fd, buf, nbytes, offset); - - if (op_ret > 0) { - offset += op_ret; - pthread_mutex_lock (&fd_ctx->lock); - { - fd_ctx->offset = offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - } - -out: - return op_ret; -} - - -ssize_t -libgf_client_iobuf_readv (libglusterfs_client_ctx_t *ctx, fd_t *fd, - const struct iovec *dst_vector, int count, - size_t size, off_t offset, int *idx, - off_t *vec_offset) -{ - call_stub_t *stub = NULL; - struct iovec *src_vector = NULL; - int32_t op_ret = -1; - libgf_client_local_t *local = NULL; - int src = 0, dst = 0; - int src_count = 0, dst_count = 0; - int len = 0, src_len = 0, dst_len = 0; - off_t src_offset = 0, dst_offset = 0; - struct iatt *stbuf = NULL; - - dst = *idx; - dst_offset = *vec_offset; - - local = CALLOC (1, sizeof (*local)); - ERR_ABORT (local); - local->fd = fd; - LIBGF_CLIENT_FOP (ctx, stub, readv, local, fd, size, offset); - - op_ret = stub->args.readv_cbk.op_ret; - errno = stub->args.readv_cbk.op_errno; - src_count = stub->args.readv_cbk.count; - src_vector = stub->args.readv_cbk.vector; - if (op_ret > 0) { - while ((size != 0) && (dst < dst_count) && (src < src_count)) { - src_len = src_vector[src].iov_len - src_offset; - dst_len = dst_vector[dst].iov_len - dst_offset; - - len = (src_len < dst_len) ? src_len : dst_len; - if (len > size) { - len = size; - } - - memcpy (dst_vector[dst].iov_base + dst_offset, - src_vector[src].iov_base + src_offset, len); - - size -= len; - src_offset += len; - dst_offset += len; - - if (src_offset == src_vector[src].iov_len) { - src_offset = 0; - src++; - } - - if (dst_offset == dst_vector[dst].iov_len) { - dst_offset = 0; - dst++; - } - } - - stbuf = &stub->args.readv_cbk.stbuf; - libgf_transform_iattr (ctx, fd->inode, stbuf); - libgf_invalidate_iattr_cache (fd->inode, LIBGF_UPDATE_STAT); - } - - *idx = dst; - *vec_offset = dst_offset; - - call_stub_destroy (stub); - return op_ret; -} - - -ssize_t -libgf_client_readv (libglusterfs_client_ctx_t *ctx, fd_t *fd, - const struct iovec *dst_vector, int dst_count, off_t offset) -{ - int32_t op_ret = -1; - size_t size = 0, tmp = 0, ret = 0; - int i = 0; - int dst_idx = 0; - off_t dst_offset = 0; - - for (i = 0; i < dst_count; i++) - { - size += dst_vector[i].iov_len; - } - - while (size != 0) { - tmp = ((size > LIBGF_IOBUF_SIZE) ? LIBGF_IOBUF_SIZE : size); - op_ret = libgf_client_iobuf_readv (ctx, fd, dst_vector, - dst_count, tmp, offset, - &dst_idx, &dst_offset); - if (op_ret <= 0) { - break; - } - - offset += op_ret; - size -= op_ret; - ret += op_ret; - } - - return ret; -} - - -ssize_t -glusterfs_readv (glusterfs_file_t fd, const struct iovec *vec, int count) -{ - int32_t op_ret = -1; - off_t offset = 0; - libglusterfs_client_ctx_t *ctx = NULL; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - if (count < 0) { - errno = EINVAL; - goto out; - } - - if (count == 0) { - op_ret = 0; - goto out; - } - - if (!fd) { - errno = EINVAL; - goto out; - } - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - errno = EBADF; - goto out; - } - - pthread_mutex_lock (&fd_ctx->lock); - { - ctx = fd_ctx->ctx; - offset = fd_ctx->offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - - op_ret = libgf_client_readv (ctx, (fd_t *)fd, vec, count, offset); - - if (op_ret > 0) { - offset += op_ret; - pthread_mutex_lock (&fd_ctx->lock); - { - fd_ctx->offset = offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - } - -out: - return op_ret; -} - - -ssize_t -glusterfs_pread (glusterfs_file_t fd, - void *buf, - size_t count, - off_t offset) -{ - int32_t op_ret = -1; - libglusterfs_client_ctx_t *ctx = NULL; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - if (count < 0) { - errno = EINVAL; - goto out; - } - - if (count == 0) { - op_ret = 0; - goto out; - } - - if (!fd) { - errno = EINVAL; - goto out; - } - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - errno = EBADF; - goto out; - } - - ctx = fd_ctx->ctx; - - op_ret = libgf_client_read (ctx, (fd_t *)fd, buf, count, offset); - -out: - return op_ret; -} - - -int -libgf_client_writev_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *prebuf, - struct iatt *postbuf) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_writev_cbk_stub (frame, NULL, op_ret, op_errno, - prebuf, postbuf); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - - -int -libgf_client_iobuf_write (libglusterfs_client_ctx_t *ctx, fd_t *fd, char *addr, - size_t size, off_t offset) -{ - struct iobref *ioref = NULL; - struct iobuf *iob = NULL; - int op_ret = -1; - struct iovec iov = {0, }; - call_stub_t *stub = NULL; - libgf_client_local_t *local = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, fd, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, addr, out); - - ioref = iobref_new (); - if (!ioref) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Out of memory"); - goto out; - } - - iob = iobuf_get (ctx->gf_ctx.iobuf_pool); - if (!iob) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Out of memory"); - goto out; - } - - memcpy (iob->ptr, addr, size); - iobref_add (ioref, iob); - - iov.iov_base = iob->ptr; - iov.iov_len = size; - - LIBGF_CLIENT_FOP (ctx, stub, writev, local, fd, &iov, - 1, offset, ioref); - - op_ret = stub->args.writev_cbk.op_ret; - errno = stub->args.writev_cbk.op_errno; - - /* We need to invalidate because it is possible that write-behind - * is a translator below us and returns a stat filled with zeroes. - */ - libgf_invalidate_iattr_cache (fd->inode, LIBGF_INVALIDATE_STAT); - -out: - if (iob) { - iobuf_unref (iob); - } - - if (ioref) { - iobref_unref (ioref); - } - - call_stub_destroy (stub); - return op_ret; -} - -int -libgf_client_writev (libglusterfs_client_ctx_t *ctx, - fd_t *fd, - struct iovec *vector, - int count, - off_t offset) -{ - int op_ret = 0; - int written = 0; - int writesize = 0; - int size = 0; - char *base = NULL; - int i = 0; - - for (i = 0; i < count; i++) { - size = vector[i].iov_len; - base = vector[i].iov_base; - - while (size > 0) { - writesize = (size > LIBGF_IOBUF_SIZE) ? - LIBGF_IOBUF_SIZE : size; - - written = libgf_client_iobuf_write (ctx, fd, base, - writesize, offset); - - if (written == -1) - goto out; - - op_ret += written; - base += written; - size -= written; - offset += written; - } - } - -out: - return op_ret; -} - - -ssize_t -glusterfs_write (glusterfs_file_t fd, - const void *buf, - size_t n) -{ - int32_t op_ret = -1; - off_t offset = 0; - struct iovec vector; - libglusterfs_client_ctx_t *ctx = NULL; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - if (n < 0) { - errno = EINVAL; - goto out; - } - - if (n == 0) { - op_ret = 0; - goto out; - } - - if (!fd) { - errno = EINVAL; - goto out; - } - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - errno = EBADF; - goto out; - } - - ctx = fd_ctx->ctx; - - pthread_mutex_lock (&fd_ctx->lock); - { - offset = fd_ctx->offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - - vector.iov_base = (void *)buf; - vector.iov_len = n; - - op_ret = libgf_client_writev (ctx, - (fd_t *)fd, - &vector, - 1, - offset); - - if (op_ret >= 0) { - offset += op_ret; - pthread_mutex_lock (&fd_ctx->lock); - { - fd_ctx->offset = offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - } - -out: - return op_ret; -} - -ssize_t -glusterfs_writev (glusterfs_file_t fd, - const struct iovec *vector, - int count) -{ - int32_t op_ret = -1; - off_t offset = 0; - libglusterfs_client_ctx_t *ctx = NULL; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - if (count < 0) { - errno = EINVAL; - goto out; - } - - if (count == 0) { - op_ret = 0; - goto out; - } - - if (!fd) { - errno = EINVAL; - goto out; - } - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - errno = EBADF; - goto out; - } - - ctx = fd_ctx->ctx; - - pthread_mutex_lock (&fd_ctx->lock); - { - offset = fd_ctx->offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - - - op_ret = libgf_client_writev (ctx, - (fd_t *)fd, - (struct iovec *)vector, - count, - offset); - - if (op_ret >= 0) { - offset += op_ret; - pthread_mutex_lock (&fd_ctx->lock); - { - fd_ctx->offset = offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - } - -out: - return op_ret; -} - - -ssize_t -glusterfs_pwrite (glusterfs_file_t fd, - const void *buf, - size_t count, - off_t offset) -{ - int32_t op_ret = -1; - struct iovec vector; - libglusterfs_client_ctx_t *ctx = NULL; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - if (count < 0) { - errno = EINVAL; - goto out; - } - - if (count == 0) { - op_ret = 0; - goto out; - } - - if (!fd) { - errno = EINVAL; - goto out; - } - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - errno = EBADF; - goto out; - } - - ctx = fd_ctx->ctx; - - vector.iov_base = (void *)buf; - vector.iov_len = count; - - op_ret = libgf_client_writev (ctx, - (fd_t *)fd, - &vector, - 1, - offset); - -out: - return op_ret; -} - - -int32_t -libgf_client_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, - gf_dirent_t *entries) -{ - libgf_client_local_t *local = frame->local; - - /* Note, we dont let entries reach the stub because there it gets copied - * while we can simply delink the entries here and link them into our - * dcache, thereby avoiding the need to perform more allocations and - * copies. - */ - local->reply_stub = fop_readdirp_cbk_stub (frame, NULL, op_ret, - op_errno, NULL); - if (op_ret > 0) - libgf_dcache_update (frame->root->state, local->fd, entries); - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int -libgf_client_readdir (libglusterfs_client_ctx_t *ctx, fd_t *fd, - struct dirent *dirp, off_t *offset) -{ - call_stub_t *stub = NULL; - int op_ret = -1; - libgf_client_local_t *local = NULL; - - if (libgf_dcache_readdir (ctx, fd, dirp, offset)) - return 1; - local = CALLOC (1, sizeof (*local)); - ERR_ABORT (local); - local->fd = fd; - LIBGF_CLIENT_FOP (ctx, stub, readdirp, local, fd, - LIBGF_READDIR_BLOCK, *offset); - - errno = stub->args.readdir_cbk.op_errno; - - op_ret = libgf_dcache_readdir (ctx, fd, dirp, offset); - call_stub_destroy (stub); - return op_ret; -} - - -int -glusterfs_readdir_r (glusterfs_dir_t dirfd, struct dirent *entry, - struct dirent **result) -{ - int op_ret = -1; - libglusterfs_client_ctx_t *ctx = NULL; - off_t offset = 0; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - struct dirent *dirp = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, entry, out); - - fd_ctx = libgf_get_fd_ctx (dirfd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "fd context not present"); - errno = EBADF; - goto out; - } - - pthread_mutex_lock (&fd_ctx->lock); - { - ctx = fd_ctx->ctx; - offset = fd_ctx->offset; - dirp = &fd_ctx->dirp; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "offset %"PRIu64, offset); - memset (dirp, 0, sizeof (struct dirent)); - op_ret = libgf_client_readdir (ctx, (fd_t *)dirfd, dirp, - &offset); - if (op_ret <= 0) { - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "readdir failed:" - " %s", strerror (errno)); - if (result && (op_ret == 0)) { - *result = NULL; - } else if (op_ret < 0){ - op_ret = errno; - } - goto unlock; - } - - fd_ctx->offset = offset; - - if (result) { - *result = memcpy (entry, dirp, sizeof (*entry)); - } else { - memcpy (entry, dirp, sizeof (*entry)); - } - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "new offset %"PRIu64", " - " entry %s", offset, entry->d_name); - op_ret = 0; - } -unlock: - pthread_mutex_unlock (&fd_ctx->lock); - -out: - return op_ret; -} - - -void * -glusterfs_readdir (glusterfs_dir_t dirfd) -{ - int op_ret = -1; - libglusterfs_client_ctx_t *ctx = NULL; - off_t offset = 0; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - struct dirent *dirp = NULL; - - fd_ctx = libgf_get_fd_ctx (dirfd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "fd context not present"); - errno = EBADF; - goto out; - } - - pthread_mutex_lock (&fd_ctx->lock); - { - ctx = fd_ctx->ctx; - offset = fd_ctx->offset; - dirp = &fd_ctx->dirp; - } - pthread_mutex_unlock (&fd_ctx->lock); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "offset %"PRIu64, offset); - memset (dirp, 0, sizeof (struct dirent)); - op_ret = libgf_client_readdir (ctx, (fd_t *)dirfd, dirp, &offset); - - if (op_ret <= 0) { - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "readdir failed: %s", - strerror (errno)); - dirp = NULL; - goto out; - } - - pthread_mutex_lock (&fd_ctx->lock); - { - fd_ctx->offset = offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "new offset %"PRIu64", entry %s", - offset, dirp->d_name); -out: - return dirp; -} - - -int -glusterfs_getdents (glusterfs_file_t fd, struct dirent *dirp, - unsigned int count) -{ - int op_ret = -1; - libglusterfs_client_ctx_t *ctx = NULL; - off_t offset = 0; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - errno = EBADF; - goto out; - } - - pthread_mutex_lock (&fd_ctx->lock); - { - ctx = fd_ctx->ctx; - offset = fd_ctx->offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - - op_ret = libgf_client_readdir (ctx, (fd_t *)fd, dirp, &offset); - - if (op_ret > 0) { - pthread_mutex_lock (&fd_ctx->lock); - { - fd_ctx->offset = offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - } - -out: - return op_ret; -} - - -static int32_t -libglusterfs_readv_async_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iovec *vector, - int32_t count, - struct iatt *stbuf, - struct iobref *iobref) -{ - 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; - - buf = CALLOC (1, sizeof (*buf)); - ERR_ABORT (buf); - - if (vector) { - buf->vector = iov_dup (vector, count); - } - - buf->count = count; - - if (iobref) { - buf->iobref = iobref_ref (iobref); - } - - if (op_ret > 0) { - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - fd_ctx = libgf_get_fd_ctx (__fd); - - /* update offset only if we have used offset stored in fd_ctx */ - if (local->fop.readv_cbk.update_offset) { - pthread_mutex_lock (&fd_ctx->lock); - { - fd_ctx->offset += op_ret; - } - pthread_mutex_unlock (&fd_ctx->lock); - } - } - - readv_cbk (op_ret, op_errno, buf, local->cbk_data); - - FREE (local); - frame->local = NULL; - STACK_DESTROY (frame->root); - - return 0; -} - -void -glusterfs_free (glusterfs_iobuf_t *buf) -{ - //iov_free (buf->vector, buf->count); - FREE (buf->vector); - if (buf->iobref) - iobref_unref ((struct iobref *) buf->iobref); - if (buf->dictref) - dict_unref ((dict_t *) buf->dictref); - FREE (buf); -} - -int -glusterfs_read_async (glusterfs_file_t fd, - size_t nbytes, - off_t offset, - glusterfs_readv_cbk_t readv_cbk, - void *cbk_data) -{ - libglusterfs_client_ctx_t *ctx; - fd_t *__fd = (fd_t *)fd; - libglusterfs_client_async_local_t *local = NULL; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - int32_t op_ret = 0; - - if (nbytes < 0) { - errno = EINVAL; - op_ret = -1; - goto out; - } - - if (nbytes == 0) { - op_ret = 0; - goto out; - } - - local = CALLOC (1, sizeof (*local)); - ERR_ABORT (local); - local->fop.readv_cbk.fd = __fd; - local->fop.readv_cbk.cbk = readv_cbk; - local->cbk_data = cbk_data; - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - errno = EBADF; - op_ret = -1; - goto out; - } - - ctx = fd_ctx->ctx; - - if (offset < 0) { - pthread_mutex_lock (&fd_ctx->lock); - { - offset = fd_ctx->offset; - local->fop.readv_cbk.update_offset = 1; - } - pthread_mutex_unlock (&fd_ctx->lock); - } - - LIBGF_CLIENT_FOP_ASYNC (ctx, - local, - libglusterfs_readv_async_cbk, - readv, - __fd, - nbytes, - offset); - -out: - return op_ret; -} - -static int32_t -libglusterfs_writev_async_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *prebuf, - struct iatt *postbuf) -{ - libglusterfs_client_async_local_t *local = frame->local; - fd_t *fd = NULL; - glusterfs_write_cbk_t write_cbk; - - 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; - fd_ctx = libgf_get_fd_ctx (fd); - pthread_mutex_lock (&fd_ctx->lock); - { - fd_ctx->offset += op_ret; - } - pthread_mutex_unlock (&fd_ctx->lock); - } - - write_cbk (op_ret, op_errno, local->cbk_data); - - STACK_DESTROY (frame->root); - return 0; -} - -int32_t -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) -{ - fd_t *__fd = (fd_t *)fd; - struct iovec vector; - off_t __offset = offset; - libglusterfs_client_ctx_t *ctx = NULL; - libglusterfs_client_async_local_t *local = NULL; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - int32_t op_ret = 0; - struct iobref *iobref = NULL; - - if (nbytes == 0) { - op_ret = 0; - goto out; - } - - if (nbytes < 0) { - op_ret = -1; - errno = EINVAL; - goto out; - } - - local = CALLOC (1, sizeof (*local)); - ERR_ABORT (local); - local->fop.write_cbk.fd = __fd; - local->fop.write_cbk.cbk = write_cbk; - local->cbk_data = cbk_data; - - vector.iov_base = (void *)buf; - vector.iov_len = nbytes; - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - errno = EBADF; - op_ret = -1; - goto out; - } - - ctx = fd_ctx->ctx; - - if (offset < 0) { - pthread_mutex_lock (&fd_ctx->lock); - { - __offset = fd_ctx->offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - } - - iobref = iobref_new (); - LIBGF_CLIENT_FOP_ASYNC (ctx, - local, - libglusterfs_writev_async_cbk, - writev, - __fd, - &vector, - 1, - __offset, - iobref); - iobref_unref (iobref); - -out: - return op_ret; -} - -off_t -glusterfs_lseek (glusterfs_file_t fd, off_t offset, int whence) -{ - off_t __offset = 0; - int32_t op_ret = -1; - fd_t *__fd = (fd_t *)fd; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - libglusterfs_client_ctx_t *ctx = NULL; - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - errno = EBADF; - __offset = -1; - goto out; - } - - ctx = fd_ctx->ctx; - - switch (whence) - { - case SEEK_SET: - __offset = offset; - break; - - case SEEK_CUR: - pthread_mutex_lock (&fd_ctx->lock); - { - __offset = fd_ctx->offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - - __offset += offset; - break; - - case SEEK_END: - { - char cache_valid = 0; - off_t end = 0; - loc_t loc = {0, }; - struct iatt stbuf = {0, }; - - cache_valid = libgf_is_iattr_cache_valid (ctx, __fd->inode, - &stbuf, - LIBGF_VALIDATE_STAT); - if (cache_valid) { - end = stbuf.ia_size; - } else { - 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; - } - - op_ret = libgf_client_lookup (ctx, &loc, &stbuf, NULL, - NULL); - if (op_ret < 0) { - __offset = -1; - libgf_client_loc_wipe (&loc); - goto out; - } - - end = stbuf.ia_size; - } - - __offset = end + offset; - libgf_client_loc_wipe (&loc); - } - break; - - default: - gf_log ("libglusterfsclient", - GF_LOG_ERROR, - "invalid value for whence"); - __offset = -1; - errno = EINVAL; - goto out; - } - - pthread_mutex_lock (&fd_ctx->lock); - { - fd_ctx->offset = __offset; - } - pthread_mutex_unlock (&fd_ctx->lock); - -out: - return __offset; -} - - -int32_t -libgf_client_stat_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *buf) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_stat_cbk_stub (frame, - NULL, - op_ret, - op_errno, - buf); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int32_t -libgf_client_stat (libglusterfs_client_ctx_t *ctx, - loc_t *loc, - struct iatt *stbuf) -{ - call_stub_t *stub = NULL; - int32_t op_ret = 0; - libgf_client_local_t *local = NULL; - struct iatt cachedbuf = {0, }; - - if (libgf_is_iattr_cache_valid (ctx, loc->inode, &cachedbuf, - LIBGF_VALIDATE_STAT)) { - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Cache will be used"); - if (stbuf) - memcpy (stbuf, &cachedbuf, sizeof (struct stat)); - goto out; - } - - LIBGF_CLIENT_FOP (ctx, stub, stat, local, loc); - - op_ret = stub->args.stat_cbk.op_ret; - errno = stub->args.stat_cbk.op_errno; - libgf_transform_iattr (ctx, loc->inode, &stub->args.stat_cbk.buf); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, status %d, errno %d", - loc->path, op_ret, errno); - - if (op_ret == 0) { - if (stbuf) - *stbuf = stub->args.stat_cbk.buf; - - libgf_update_iattr_cache (loc->inode, LIBGF_UPDATE_STAT, - &stub->args.stat_cbk.buf); - } - - call_stub_destroy (stub); - -out: - return op_ret; -} - -int -libgf_realpath_loc_fill (libglusterfs_client_ctx_t *ctx, char *link, - loc_t *targetloc) -{ - int op_ret = -1; - char *target = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, link, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, targetloc, out); - - targetloc->path = glusterfs_glh_realpath (ctx, link, NULL); - - if (targetloc->path == NULL) - goto out; - - op_ret = libgf_client_path_lookup (targetloc, ctx, 1); - if (op_ret == -1) - goto out; - - target = strdup (targetloc->path); - op_ret = libgf_client_loc_fill (targetloc, ctx, 0, - targetloc->parent->ino, - basename (target)); - if (op_ret == -1) { - errno = EINVAL; - goto out; - } - -out: - if (target) - FREE (target); - - return op_ret; -} - -#define LIBGF_DO_LSTAT 0x01 -#define LIBGF_DO_STAT 0x02 - -int -__glusterfs_stat (glusterfs_handle_t handle, const char *path, - struct stat *buf, int whichstat) -{ - int32_t op_ret = -1; - loc_t loc = {0, }; - libglusterfs_client_ctx_t *ctx = handle; - char *name = NULL, *pathname = NULL; - loc_t targetloc = {0, }; - loc_t *real_loc = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, op: %d", path, - whichstat); - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", loc.path); - goto out; - } - - pathname = strdup (loc.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; - } - real_loc = &loc; - /* The stat fop in glusterfs calls lstat. So we have to - * provide the POSIX compatible stat fop. To do so, we need to ensure - * that if the @path is a symlink, we must perform a stat on the - * target of that symlink than the symlink itself(..because if - * do a stat on the symlink, we're actually doing what lstat - * should do. See posix_stat - */ - if (whichstat & LIBGF_DO_LSTAT) - goto lstat_fop; - - if (!IA_ISLNK (loc.inode->ia_type)) - goto lstat_fop; - - op_ret = libgf_realpath_loc_fill (ctx, (char *)loc.path, &targetloc); - if (op_ret == -1) - goto out; - real_loc = &targetloc; - -lstat_fop: - - if (!op_ret) { - struct iatt iatt; - op_ret = libgf_client_stat (ctx, real_loc, &iatt); - iatt_to_stat (&iatt, buf); - } - -out: - if (pathname) { - FREE (pathname); - } - - libgf_client_loc_wipe (&loc); - libgf_client_loc_wipe (&targetloc); - - return op_ret; -} - -int -glusterfs_glh_stat (glusterfs_handle_t handle, const char *path, - struct stat *buf) -{ - return __glusterfs_stat (handle, path, buf, LIBGF_DO_STAT); -} - -int -glusterfs_stat (const char *path, struct stat *buf) -{ - glusterfs_handle_t h = NULL; - int op_ret = -1; - char vpath[PATH_MAX]; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, buf, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_stat (h, vpath, buf); - -out: - return op_ret; -} - -int -glusterfs_glh_lstat (glusterfs_handle_t handle, const char *path, struct stat *buf) -{ - return __glusterfs_stat (handle, path, buf, LIBGF_DO_LSTAT); -} - -int -glusterfs_lstat (const char *path, struct stat *buf) -{ - glusterfs_handle_t h = NULL; - int op_ret = -1; - char vpath[PATH_MAX]; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, buf, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_lstat (h, vpath, buf); -out: - return op_ret; -} - -static int32_t -libgf_client_fstat_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *buf) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_fstat_cbk_stub (frame, - NULL, - op_ret, - op_errno, - buf); - - LIBGF_REPLY_NOTIFY (local); - return 0; - -} - -int32_t -libgf_client_fstat (libglusterfs_client_ctx_t *ctx, - fd_t *fd, - struct stat *buf) -{ - call_stub_t *stub = NULL; - int32_t op_ret = 0; - libgf_client_local_t *local = NULL; - struct iatt cachedbuf = {0, }; - - if (libgf_is_iattr_cache_valid (ctx, fd->inode, &cachedbuf, - LIBGF_VALIDATE_STAT)) { - if (buf) - memcpy (buf, &cachedbuf, sizeof (struct stat)); - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Cache will be used"); - goto out; - } - - LIBGF_CLIENT_FOP (ctx, stub, fstat, local, fd); - - op_ret = stub->args.fstat_cbk.op_ret; - errno = stub->args.fstat_cbk.op_errno; - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "status %d, errno %d", op_ret, - errno); - - if (op_ret == 0) { - libgf_transform_iattr (ctx, fd->inode, - &stub->args.fstat_cbk.buf); - if (buf) - iatt_to_stat (&stub->args.fstat_cbk.buf, buf); - libgf_update_iattr_cache (fd->inode, LIBGF_UPDATE_STAT, - &stub->args.fstat_cbk.buf); - } - call_stub_destroy (stub); - -out: - return op_ret; -} - -int32_t -glusterfs_fstat (glusterfs_file_t fd, struct stat *buf) -{ - libglusterfs_client_ctx_t *ctx; - fd_t *__fd = (fd_t *)fd; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - int32_t op_ret = -1; - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - op_ret = -1; - goto out; - } - - ctx = fd_ctx->ctx; - - op_ret = libgf_client_fstat (ctx, __fd, 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 iatt *buf, - struct iatt *preparent, - struct iatt *postparent) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_mkdir_cbk_stub (frame, NULL, op_ret, op_errno, - inode, buf, preparent, - postparent); - - LIBGF_REPLY_NOTIFY (local); - 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; - inode_t *libgf_inode = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, mkdir, local, loc, mode); - op_ret = stub->args.mkdir_cbk.op_ret; - errno = stub->args.mkdir_cbk.op_errno; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, status %d, errno %d", - loc->path, op_ret, errno); - if (op_ret == -1) - goto out; - - libgf_inode = stub->args.mkdir_cbk.inode; - inode_link (libgf_inode, loc->parent, loc->name, - &stub->args.mkdir_cbk.buf); - libgf_transform_iattr (ctx, libgf_inode, &stub->args.mkdir_cbk.buf); - - inode_lookup (libgf_inode); - - libgf_alloc_inode_ctx (ctx, libgf_inode); - libgf_update_iattr_cache (libgf_inode, LIBGF_UPDATE_ALL, - &stub->args.mkdir_cbk.buf); - -out: - call_stub_destroy (stub); - - return op_ret; -} - - -int32_t -glusterfs_glh_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; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == 0) { - op_ret = -1; - errno = EEXIST; - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 0); - if (op_ret == -1) { - errno = ENOENT; - goto out; - } - - pathname = strdup (loc.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; - } - - loc.inode = inode_new (ctx->itable); - 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; -} - -int32_t -glusterfs_mkdir (const char *path, mode_t mode) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_mkdir (h, vpath, mode); -out: - return op_ret; -} - -static int32_t -libgf_client_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno,struct iatt *preparent, - struct iatt *postparent) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_rmdir_cbk_stub (frame, NULL, op_ret, op_errno, - preparent, postparent); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -static int32_t -libgf_client_rmdir (libglusterfs_client_ctx_t *ctx, loc_t *loc) -{ - int32_t op_ret = -1; - call_stub_t *stub = NULL; - libgf_client_local_t *local = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, rmdir, local, loc); - - op_ret = stub->args.rmdir_cbk.op_ret; - errno = stub->args.rmdir_cbk.op_errno; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, status %d, errno %d", - loc->path, op_ret, errno); - if (stub->args.rmdir_cbk.op_ret != 0) - goto out; - - inode_unlink (loc->inode, loc->parent, loc->name); - -out: - call_stub_destroy (stub); - - return op_ret; -} - -int32_t -glusterfs_glh_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; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - loc.path = libgf_resolve_path_light ((char *)path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Path compaction failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", loc.path); - goto out; - } - - pathname = strdup (loc.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; -} - -int32_t -glusterfs_rmdir (const char *path) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_rmdir (h, vpath); -out: - return op_ret; -} - -int -libgf_client_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, - struct iatt *preop, struct iatt *postop) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_setattr_cbk_stub (frame, NULL, - op_ret, op_errno, - preop, postop); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int -libgf_client_setattr (libglusterfs_client_ctx_t *ctx, loc_t * loc, - struct iatt *stbuf, int32_t valid) -{ - int op_ret = -1; - libgf_client_local_t *local = NULL; - call_stub_t *stub = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, setattr, local, loc, - stbuf, valid); - - op_ret = stub->args.setattr_cbk.op_ret; - errno = stub->args.setattr_cbk.op_errno; - - if (op_ret == -1) - goto out; - - libgf_transform_iattr (ctx, loc->inode, - &stub->args.setattr_cbk.statpost); - libgf_update_iattr_cache (loc->inode, LIBGF_UPDATE_STAT, - &stub->args.setattr_cbk.statpost); -out: - call_stub_destroy (stub); - return op_ret; -} - - -int -glusterfs_glh_chmod (glusterfs_handle_t handle, const char *path, mode_t mode) -{ - int op_ret = -1; - libglusterfs_client_ctx_t *ctx = handle; - loc_t loc = {0, }; - char *name = NULL; - struct iatt stbuf = {0,}; - int32_t valid = 0; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - stbuf.ia_prot = ia_prot_from_st_mode (mode); - valid |= GF_SET_ATTR_MODE; - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) - goto out; - - name = strdup (loc.path); - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename (name)); - if (op_ret == -1) { - errno = EINVAL; - goto out; - } - - op_ret = libgf_client_setattr (ctx, &loc, &stbuf, valid); - -out: - if (name) - FREE (name); - - libgf_client_loc_wipe (&loc); - return op_ret; -} - -int -glusterfs_chmod (const char *path, mode_t mode) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_chmod (h, vpath, mode); -out: - return op_ret; -} - - -#define LIBGF_DO_CHOWN 1 -#define LIBGF_DO_LCHOWN 2 - -int -__glusterfs_chown (glusterfs_handle_t handle, const char *path, uid_t owner, - gid_t group, int whichop) -{ - int op_ret = -1; - libglusterfs_client_ctx_t *ctx = handle; - loc_t loc = {0, }; - char *name = NULL; - loc_t *oploc = NULL; - loc_t targetloc = {0, }; - struct iatt stbuf = {0,}; - int32_t valid = 0; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, op %d", path, whichop); - stbuf.ia_uid = owner; - stbuf.ia_gid = group; - valid |= (GF_SET_ATTR_UID | GF_SET_ATTR_GID); - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) - goto out; - - name = strdup (loc.path); - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename ((char *)name)); - if (op_ret == -1) { - errno = EINVAL; - goto out; - } - - oploc = &loc; - if (whichop == LIBGF_DO_LCHOWN) - goto do_lchown; - - if (!IA_ISLNK (loc.inode->ia_type)) - goto do_lchown; - - op_ret = libgf_realpath_loc_fill (ctx, (char *)loc.path, &targetloc); - if (op_ret == -1) - goto out; - - oploc = &targetloc; -do_lchown: - op_ret = libgf_client_setattr (ctx, oploc, &stbuf, valid); -out: - if (name) - FREE (name); - libgf_client_loc_wipe (&loc); - libgf_client_loc_wipe (&targetloc); - return op_ret; -} - -int -glusterfs_glh_chown (glusterfs_handle_t handle, const char *path, uid_t owner, - gid_t group) -{ - return __glusterfs_chown (handle, path, owner, group, LIBGF_DO_CHOWN); -} - -int -glusterfs_chown (const char *path, uid_t owner, gid_t group) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_chown (h, vpath, owner, group); - -out: - return op_ret; -} - -int -glusterfs_glh_lchown (glusterfs_handle_t handle, const char *path, uid_t owner, - gid_t group) -{ - return __glusterfs_chown (handle, path, owner, group, LIBGF_DO_LCHOWN); -} - -int -glusterfs_lchown (const char *path, uid_t owner, gid_t group) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_lchown (h, vpath, owner, group); -out: - return op_ret; -} - -glusterfs_dir_t -glusterfs_glh_opendir (glusterfs_handle_t handle, const char *path) -{ - int op_ret = -1; - libglusterfs_client_ctx_t *ctx = handle; - loc_t loc = {0, }; - fd_t *dirfd = NULL; - char *name = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - - if (op_ret == -1) - goto out; - - name = strdup (loc.path); - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename (name)); - if (op_ret == -1) { - errno = EINVAL; - goto out; - } - - if (!IA_ISDIR (loc.inode->ia_type) && !IA_ISLNK (loc.inode->ia_type)) { - errno = ENOTDIR; - op_ret = -1; - goto out; - } - - dirfd = fd_create (loc.inode, ctx->pid); - op_ret = libgf_client_opendir (ctx, &loc, dirfd); - - if (op_ret == -1) { - fd_unref (dirfd); - dirfd = NULL; - goto out; - } - - if (!libgf_get_fd_ctx (dirfd)) { - if (!(libgf_alloc_fd_ctx (ctx, dirfd, (char *)path))) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Context " - "allocation failed"); - op_ret = -1; - errno = EINVAL; - goto out; - } - } - -out: - if (name) - FREE (name); - - if (op_ret == -1) { - fd_unref (dirfd); - dirfd = NULL; - } - - libgf_client_loc_wipe (&loc); - return dirfd; -} - -glusterfs_dir_t -glusterfs_opendir (const char *path) -{ - char vpath[PATH_MAX]; - glusterfs_dir_t dir = NULL; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - dir = glusterfs_glh_opendir (h, vpath); -out: - return dir; -} - -int -glusterfs_closedir (glusterfs_dir_t dirfd) -{ - int op_ret = -1; - libglusterfs_client_fd_ctx_t *fdctx = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, dirfd, out); - fdctx = libgf_get_fd_ctx (dirfd); - - if (fdctx == NULL) { - errno = EBADF; - op_ret = -1; - goto out; - } - - op_ret = libgf_client_flush (fdctx->ctx, (fd_t *)dirfd); - fd_unref ((fd_t *)dirfd); - -out: - return op_ret; -} - - -int -libgf_client_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, - struct iatt *preop, struct iatt *postop) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_fsetattr_cbk_stub (frame, NULL, - op_ret, op_errno, - preop, postop); - LIBGF_REPLY_NOTIFY (local); - return 0; -} - - -int -libgf_client_fsetattr (libglusterfs_client_ctx_t *ctx, fd_t *fd, - struct iatt *stbuf, int32_t valid) -{ - int op_ret = -1; - libgf_client_local_t *local = NULL; - call_stub_t *stub = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, fsetattr, local, fd, stbuf, valid); - - op_ret = stub->args.fsetattr_cbk.op_ret; - errno = stub->args.fsetattr_cbk.op_errno; - - if (op_ret == -1) - goto out; - - libgf_transform_iattr (ctx, fd->inode, - &stub->args.fsetattr_cbk.statpost); - libgf_update_iattr_cache (fd->inode, LIBGF_UPDATE_STAT, - &stub->args.fsetattr_cbk.statpost); -out: - call_stub_destroy (stub); - return op_ret; -} - - -int -glusterfs_fchmod (glusterfs_file_t fd, mode_t mode) -{ - libglusterfs_client_fd_ctx_t *fdctx = NULL; - int op_ret = -1; - struct iatt stbuf = {0,}; - int32_t valid = 0; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, fd, out); - fdctx = libgf_get_fd_ctx (fd); - - if (!fdctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "No fd context present"); - errno = EBADF; - goto out; - } - - stbuf.ia_prot = ia_prot_from_st_mode (mode); - valid |= GF_SET_ATTR_MODE; - - op_ret = libgf_client_fsetattr (fdctx->ctx, fd, &stbuf, valid); -out: - return op_ret; -} - - -int -glusterfs_fchown (glusterfs_file_t fd, uid_t uid, gid_t gid) -{ - int op_ret = -1; - libglusterfs_client_fd_ctx_t *fdctx = NULL; - struct iatt stbuf = {0,}; - int32_t valid = 0; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, fd, out); - - fdctx = libgf_get_fd_ctx (fd); - if (!fd) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - goto out; - } - stbuf.ia_uid = uid; - stbuf.ia_gid = gid; - - valid |= (GF_SET_ATTR_UID | GF_SET_ATTR_GID); - - op_ret = libgf_client_fsetattr (fdctx->ctx, fd, &stbuf, valid); - -out: - return op_ret; -} - -int -libgf_client_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *xlator, - int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_fsync_cbk_stub (frame, NULL, op_ret, op_errno, - prebuf, postbuf); - - LIBGF_REPLY_NOTIFY (local); - - return 0; -} - -int -libgf_client_fsync (libglusterfs_client_ctx_t *ctx, fd_t *fd) -{ - libgf_client_local_t *local = NULL; - call_stub_t *stub = NULL; - int op_ret = -1; - - LIBGF_CLIENT_FOP (ctx, stub, fsync, local, fd, 0); - - op_ret = stub->args.fsync_cbk.op_ret; - errno = stub->args.fsync_cbk.op_errno; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "status %d, errno %d", op_ret, - errno); - call_stub_destroy (stub); - - return op_ret; -} - -int -glusterfs_fsync (glusterfs_file_t *fd) -{ - libglusterfs_client_fd_ctx_t *fdctx = NULL; - int op_ret = -1; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, fd, out); - - fdctx = libgf_get_fd_ctx ((fd_t *)fd); - if (!fdctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - goto out; - } - - op_ret = libgf_client_fsync (fdctx->ctx, (fd_t *)fd); - -out: - return op_ret; -} - -int -libgf_client_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *xlator - ,int32_t op_ret, int32_t op_errno, - struct iatt *prebuf, struct iatt *postbuf) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_ftruncate_cbk_stub (frame, NULL, op_ret, - op_errno, prebuf, postbuf); - - LIBGF_REPLY_NOTIFY (local); - - return 0; -} - -int -libgf_client_ftruncate (libglusterfs_client_ctx_t *ctx, fd_t *fd, - off_t length) -{ - libgf_client_local_t *local = NULL; - call_stub_t *stub = NULL; - int op_ret = -1; - libglusterfs_client_fd_ctx_t *fdctx = NULL; - - if (!(((fd->flags & O_ACCMODE) == O_RDWR) - || ((fd->flags & O_ACCMODE) == O_WRONLY))) { - errno = EBADF; - goto out; - } - - LIBGF_CLIENT_FOP (ctx, stub, ftruncate, local, fd, length); - - op_ret = stub->args.ftruncate_cbk.op_ret; - errno = stub->args.ftruncate_cbk.op_errno; - - if (op_ret == -1) - goto out; - - libgf_transform_iattr (ctx, fd->inode, - &stub->args.ftruncate_cbk.postbuf); - libgf_update_iattr_cache (fd->inode, LIBGF_UPDATE_STAT, - &stub->args.ftruncate_cbk.postbuf); - - fdctx = libgf_get_fd_ctx (fd); - if (!fd) { - errno = EINVAL; - op_ret = -1; - goto out; - } - - pthread_mutex_lock (&fdctx->lock); - { - fdctx->offset = stub->args.ftruncate_cbk.postbuf.ia_size; - } - pthread_mutex_unlock (&fdctx->lock); - -out: - call_stub_destroy (stub); - return op_ret; -} - -int -glusterfs_ftruncate (glusterfs_file_t fd, off_t length) -{ - libglusterfs_client_fd_ctx_t *fdctx = NULL; - int op_ret = -1; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, fd, out); - - fdctx = libgf_get_fd_ctx (fd); - if (!fdctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - goto out; - } - - op_ret = libgf_client_ftruncate (fdctx->ctx, fd, length); - -out: - return op_ret; -} - -int -libgf_client_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, - inode_t *inode, struct iatt *buf, - struct iatt *preparent, struct iatt *postparent) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_link_cbk_stub (frame, NULL, op_ret, op_errno, - inode, buf, preparent, - postparent); - - LIBGF_REPLY_NOTIFY (local); - - return 0; -} - -int -libgf_client_link (libglusterfs_client_ctx_t *ctx, loc_t *old, loc_t *new) -{ - call_stub_t *stub = NULL; - libgf_client_local_t *local = NULL; - int op_ret = -1; - inode_t *inode = NULL; - struct iatt *sbuf = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, link, local, old, new); - - op_ret = stub->args.link_cbk.op_ret; - errno = stub->args.link_cbk.op_errno; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "old %s, new %s, status %d," - " errno %d", old->path, new->path, op_ret, errno); - if (op_ret == -1) - goto out; - - inode = stub->args.link_cbk.inode; - sbuf = &stub->args.link_cbk.buf; - inode_link (inode, new->parent, basename ((char *)new->path), sbuf); - libgf_transform_iattr (ctx, inode, sbuf); - inode_lookup (inode); - libgf_update_iattr_cache (inode, LIBGF_UPDATE_STAT, sbuf); - -out: - call_stub_destroy (stub); - return op_ret; -} - -int -glusterfs_glh_link (glusterfs_handle_t handle, const char *oldpath, - const char *newpath) -{ - libglusterfs_client_ctx_t *ctx = handle; - int op_ret = -1; - loc_t old = {0,}; - loc_t new = {0,}; - char *oldname = NULL; - char *newname = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, oldpath, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, newpath, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "old %s, new %s", oldpath, - newpath); - - old.path = strdup (oldpath); - if (!old.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&old, ctx, 1); - if (op_ret == -1) { - errno = ENOENT; - goto out; - } - - oldname = strdup (old.path); - op_ret = libgf_client_loc_fill (&old, ctx, 0, old.parent->ino, - basename (oldname)); - if (op_ret == -1) { - errno = EINVAL; - goto out; - } - - if (IA_ISDIR (old.inode->ia_type)) { - errno = EPERM; - op_ret = -1; - goto out; - } - - new.path = strdup (newpath); - if (!new.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&new, ctx, 1); - if (op_ret == 0) { - errno = EEXIST; - op_ret = -1; - goto out; - } - - newname = strdup (new.path); - new.inode = inode_ref (old.inode); - libgf_client_loc_fill (&new, ctx, 0, new.parent->ino, - basename (newname)); - op_ret = libgf_client_link (ctx, &old, &new); - -out: - if (oldname) - FREE (oldname); - if (newname) - FREE (newname); - libgf_client_loc_wipe (&old); - libgf_client_loc_wipe (&new); - - return op_ret; -} - -int -glusterfs_link (const char *oldpath, const char *newpath) -{ - int op_ret = -1; - char oldvpath[PATH_MAX]; - char newvpath[PATH_MAX]; - glusterfs_handle_t oldh = NULL; - glusterfs_handle_t newh = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, oldpath, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, newpath, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "old %s, new %s", oldpath, - newpath); - - oldh = libgf_resolved_path_handle (oldpath, oldvpath); - if (!oldh) { - errno = ENODEV; - goto out; - } - - newh = libgf_resolved_path_handle (newpath, newvpath); - if (!newh) { - errno = ENODEV; - goto out; - } - - /* Cannot hard link across glusterfs mounts. */ - if (newh != oldh) { - errno = EXDEV; - goto out; - } - - op_ret = glusterfs_glh_link (newh, oldvpath, newvpath); -out: - return op_ret; -} - -int32_t -libgf_client_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct statvfs *buf) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_statfs_cbk_stub (frame, NULL, op_ret, op_errno, - buf); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int32_t -libgf_client_statvfs (libglusterfs_client_ctx_t *ctx, loc_t *loc, - struct statvfs *buf) -{ - call_stub_t *stub = NULL; - libgf_client_local_t *local = NULL; - int32_t op_ret = -1; - - /* statfs fop receives struct statvfs as an argument */ - - /* libgf_client_statfs_cbk will be the callback, not - libgf_client_statvfs_cbk. see definition of LIBGF_CLIENT_FOP - */ - LIBGF_CLIENT_FOP (ctx, stub, statfs, local, loc); - - op_ret = stub->args.statfs_cbk.op_ret; - errno = stub->args.statfs_cbk.op_errno; - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, status %d, errno %d", - loc->path, op_ret, errno); - if (op_ret == -1) - goto out; - - if (buf) - memcpy (buf, &stub->args.statfs_cbk.buf, sizeof (*buf)); -out: - call_stub_destroy (stub); - return op_ret; -} - -int -glusterfs_glh_statfs (glusterfs_handle_t handle, const char *path, - struct statfs *buf) -{ - struct statvfs stvfs = {0, }; - int32_t op_ret = -1; - loc_t loc = {0, }; - libglusterfs_client_ctx_t *ctx = handle; - char *name = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", loc.path); - goto out; - } - - name = strdup (loc.path); - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename (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_statvfs (ctx, &loc, &stvfs); - if (op_ret == 0) { -#ifdef GF_SOLARIS_HOST_OS - buf->f_fstyp = 0; - buf->f_bsize = stvfs.f_bsize; - buf->f_blocks = stvfs.f_blocks; - buf->f_bfree = stvfs.f_bfree; - buf->f_files = stvfs.f_bavail; - buf->f_ffree = stvfs.f_ffree; -#else - buf->f_type = 0; - buf->f_bsize = stvfs.f_bsize; - buf->f_blocks = stvfs.f_blocks; - buf->f_bfree = stvfs.f_bfree; - buf->f_bavail = stvfs.f_bavail; - buf->f_files = stvfs.f_bavail; - buf->f_ffree = stvfs.f_ffree; - /* FIXME: buf->f_fsid has either "val" or "__val" as member - based on conditional macro expansion. see definition of - fsid_t - Raghu - It seems have different structure member names on - different archs, so I am stepping down to doing a struct - to struct copy. :Shehjar - */ - memcpy (&buf->f_fsid, &stvfs.f_fsid, sizeof (stvfs.f_fsid)); - buf->f_namelen = stvfs.f_namemax; -#endif - } - -out: - if (name) - FREE (name); - libgf_client_loc_wipe (&loc); - return op_ret; -} - -int -glusterfs_statfs (const char *path, struct statfs *buf) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, buf, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_statfs (h, vpath, buf); -out: - return op_ret; -} - -int -glusterfs_glh_statvfs (glusterfs_handle_t handle, const char *path, - struct statvfs *buf) -{ - int32_t op_ret = -1; - loc_t loc = {0, }; - libglusterfs_client_ctx_t *ctx = handle; - char *name = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", loc.path); - goto out; - } - - name = strdup (loc.path); - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename (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_statvfs (ctx, &loc, buf); - if (op_ret != -1) - /* Should've been a call to libgf_transform_iattr but - * that only handles struct stat - */ - buf->f_fsid = (unsigned long)ctx->fake_fsid; - -out: - if (name) - FREE (name); - libgf_client_loc_wipe (&loc); - return op_ret; -} - -int -glusterfs_statvfs (const char *path, struct statvfs *buf) -{ - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - int op_ret = -1; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, buf, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_statvfs (h, vpath, buf); -out: - return op_ret; -} - -int32_t -libgf_client_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *buf, - struct iatt *preoldparent, struct iatt *postoldparent, - struct iatt *prenewparent, struct iatt *postnewparent) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_rename_cbk_stub (frame, NULL, op_ret, op_errno, - buf, preoldparent, - postoldparent, prenewparent, - postnewparent); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int32_t -libgf_client_rename (libglusterfs_client_ctx_t *ctx, loc_t *oldloc, - loc_t *newloc) -{ - int op_ret = -1; - libgf_client_local_t *local = NULL; - call_stub_t *stub = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, rename, local, oldloc, newloc); - - op_ret = stub->args.rename_cbk.op_ret; - errno = stub->args.rename_cbk.op_errno; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "old %s, new %s, status %d, errno" - " %d", oldloc->path, newloc->path, op_ret, errno); - if (op_ret == -1) - goto out; - - if (!libgf_get_inode_ctx (newloc->inode)) - libgf_alloc_inode_ctx (ctx, newloc->inode); - - libgf_transform_iattr (ctx, newloc->inode, &stub->args.rename_cbk.buf); - libgf_update_iattr_cache (newloc->inode, LIBGF_UPDATE_STAT, - &stub->args.rename_cbk.buf); - - inode_unlink (oldloc->inode, oldloc->parent, oldloc->name); -out: - call_stub_destroy (stub); - return op_ret; -} - -int -glusterfs_glh_rename (glusterfs_handle_t handle, const char *oldpath, - const char *newpath) -{ - int32_t op_ret = -1; - loc_t oldloc = {0, }, newloc = {0, }; - libglusterfs_client_ctx_t *ctx = handle; - char *newname = NULL; - char *oldname = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, oldpath, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, newpath, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "old %s, new %s", oldpath, - newpath); - - oldloc.path = strdup (oldpath); - if (!oldloc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&oldloc, ctx, 1); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", oldloc.path); - goto out; - } - - newloc.path = strdup (newpath); - if (!newloc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&newloc, ctx, 1); - - oldname = strdup (oldloc.path); - op_ret = libgf_client_loc_fill (&oldloc, ctx, 0, oldloc.parent->ino, - basename (oldname)); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "libgf_client_loc_fill returned -1," - " returning EINVAL"); - errno = EINVAL; - goto out; - } - - newname = strdup (newloc.path); - op_ret = libgf_client_loc_fill (&newloc, ctx, 0, newloc.parent->ino, - basename (newname)); - 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_rename (ctx, &oldloc, &newloc); - -out: - if (oldname) - FREE (oldname); - if (newname) - FREE (newname); - libgf_client_loc_wipe (&newloc); - libgf_client_loc_wipe (&oldloc); - - return op_ret; -} - - -int -glusterfs_rename (const char *oldpath, const char *newpath) -{ - int op_ret = -1; - char oldvpath[PATH_MAX]; - char newvpath[PATH_MAX]; - glusterfs_handle_t oldh = NULL; - glusterfs_handle_t newh = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, oldpath, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, newpath, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Old %s, new %s", oldpath, - newpath); - - oldh = libgf_resolved_path_handle (oldpath, oldvpath); - if (!oldh) { - errno = ENODEV; - goto out; - } - - newh = libgf_resolved_path_handle (newpath, newvpath); - if (!newh) { - errno = ENODEV; - goto out; - } - - if (oldh != newh) { - errno = EXDEV; - goto out; - } - - op_ret = glusterfs_glh_rename (oldh, oldvpath, newvpath); -out: - return op_ret; -} - - -int -glusterfs_glh_utimes (glusterfs_handle_t handle, const char *path, - const struct timeval times[2]) -{ - int32_t op_ret = -1; - loc_t loc = {0, }; - libglusterfs_client_ctx_t *ctx = handle; - char *name = NULL; - struct iatt stbuf = {0,}; - int32_t valid = 0; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - stbuf.ia_atime = times[0].tv_sec; - stbuf.ia_atime_nsec = times[0].tv_usec * 1000; - stbuf.ia_mtime = times[1].tv_sec; - stbuf.ia_mtime_nsec = times[1].tv_usec * 1000; - - valid |= (GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME); - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", loc.path); - goto out; - } - - name = strdup (loc.path); - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename (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_setattr (ctx, &loc, &stbuf, valid); -out: - if (name) - FREE (name); - libgf_client_loc_wipe (&loc); - return op_ret; -} - -int -glusterfs_utimes (const char *path, const struct timeval times[2]) -{ - char vpath[PATH_MAX]; - int op_ret = -1; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_utimes (h, vpath, times); -out: - return op_ret; -} - -int -glusterfs_glh_utime (glusterfs_handle_t handle, const char *path, - const struct utimbuf *buf) -{ - int32_t op_ret = -1; - loc_t loc = {0, }; - libglusterfs_client_ctx_t *ctx = handle; - char *name = NULL; - struct iatt stbuf = {0,}; - int32_t valid = 0; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - if (buf) { - stbuf.ia_atime = buf->actime; - stbuf.ia_atime_nsec = 0; - - stbuf.ia_mtime = buf->modtime; - stbuf.ia_mtime_nsec = 0; - } - - valid |= (GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME); - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", loc.path); - goto out; - } - - name = strdup (loc.path); - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename (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_setattr (ctx, &loc, &stbuf, valid); -out: - if (name) - FREE (name); - libgf_client_loc_wipe (&loc); - return op_ret; -} - -int -glusterfs_utime (const char *path, const struct utimbuf *buf) -{ - char vpath[PATH_MAX]; - int op_ret = -1; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, buf, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_utime (h, vpath, buf); -out: - return op_ret; -} - -static int32_t -libgf_client_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, - inode_t *inode, struct iatt *buf, - struct iatt *preparent, struct iatt *postparent) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_mknod_cbk_stub (frame, NULL, op_ret, op_errno, - inode, buf, preparent, - postparent); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -static int32_t -libgf_client_mknod (libglusterfs_client_ctx_t *ctx, loc_t *loc, mode_t mode, - dev_t rdev) -{ - int32_t op_ret = -1; - call_stub_t *stub = NULL; - libgf_client_local_t *local = NULL; - inode_t *inode = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, mknod, local, loc, mode, rdev); - - op_ret = stub->args.mknod_cbk.op_ret; - errno = stub->args.mknod_cbk.op_errno; - if (op_ret == -1) - goto out; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, status %d, errno %d", - loc->path, op_ret, errno); - inode = stub->args.mknod_cbk.inode; - inode_link (inode, loc->parent, loc->name, &stub->args.mknod_cbk.buf); - libgf_transform_iattr (ctx, inode, &stub->args.mknod_cbk.buf); - inode_lookup (inode); - - if (!libgf_alloc_inode_ctx (ctx, inode)) - libgf_alloc_inode_ctx (ctx, inode); - - libgf_update_iattr_cache (inode, LIBGF_UPDATE_STAT, - &stub->args.mknod_cbk.buf); - -out: - call_stub_destroy (stub); - return op_ret; -} - -int -glusterfs_glh_mknod(glusterfs_handle_t handle, const char *path, mode_t mode, - dev_t dev) -{ - libglusterfs_client_ctx_t *ctx = handle; - loc_t loc = {0, }; - char *name = NULL; - int32_t op_ret = -1; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == 0) { - op_ret = -1; - errno = EEXIST; - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 0); - if (op_ret == -1) { - errno = ENOENT; - goto out; - } - - name = strdup (loc.path); - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename (name)); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "libgf_client_loc_fill returned -1, " - " returning EINVAL"); - errno = EINVAL; - goto out; - } - - loc.inode = inode_new (ctx->itable); - op_ret = libgf_client_mknod (ctx, &loc, mode, dev); - -out: - libgf_client_loc_wipe (&loc); - if (name) - FREE (name); - - return op_ret; -} - -int -glusterfs_mknod(const char *pathname, mode_t mode, dev_t dev) -{ - char vpath[PATH_MAX]; - int op_ret = -1; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, pathname, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", pathname); - - h = libgf_resolved_path_handle (pathname, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - -out: - return op_ret; -} - -int -glusterfs_glh_mkfifo (glusterfs_handle_t handle, const char *path, mode_t mode) -{ - - libglusterfs_client_ctx_t *ctx = handle; - loc_t loc = {0, }; - char *name = NULL; - int32_t op_ret = -1; - dev_t dev = 0; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - loc.path = libgf_resolve_path_light ((char *)path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Failed to resolve name"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == 0) { - op_ret = -1; - errno = EEXIST; - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 0); - if (op_ret == -1) { - errno = ENOENT; - goto out; - } - - name = strdup (loc.path); - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename (name)); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "libgf_client_loc_fill returned -1, " - "returning EINVAL"); - errno = EINVAL; - goto out; - } - - loc.inode = inode_new (ctx->itable); - op_ret = libgf_client_mknod (ctx, &loc, mode | S_IFIFO, dev); - -out: - libgf_client_loc_wipe (&loc); - if (name) - free (name); - - return op_ret; -} - -int -glusterfs_mkfifo (const char *path, mode_t mode) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_mkfifo (h, vpath, mode); -out: - return op_ret; -} - -int32_t -libgf_client_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, - struct iatt *preparent, struct iatt *postparent) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_unlink_cbk_stub (frame, NULL, op_ret, op_errno, - preparent, postparent); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int -libgf_client_unlink (libglusterfs_client_ctx_t *ctx, loc_t *loc) -{ - int op_ret = -1; - libgf_client_local_t *local = NULL; - call_stub_t *stub = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, unlink, local, loc); - - op_ret = stub->args.unlink_cbk.op_ret; - errno = stub->args.unlink_cbk.op_errno; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", loc->path); - if (op_ret == -1) - goto out; - - inode_unlink (loc->inode, loc->parent, loc->name); - -out: - call_stub_destroy (stub); - return op_ret; -} - -int -glusterfs_glh_unlink (glusterfs_handle_t handle, const char *path) -{ - int32_t op_ret = -1; - loc_t loc = {0, }; - libglusterfs_client_ctx_t *ctx = handle; - char *name = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", loc.path); - goto out; - } - - name = strdup (loc.path); - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename (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_unlink (ctx, &loc); - -out: - if (name) - FREE (name); - libgf_client_loc_wipe (&loc); - return op_ret; -} - -int -glusterfs_unlink (const char *path) -{ - char vpath[PATH_MAX]; - int op_ret = -1; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_unlink (h, vpath); - -out: - return op_ret; -} - -static int32_t -libgf_client_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, - inode_t *inode, struct iatt *buf, - struct iatt *preparent, struct iatt *postparent) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_symlink_cbk_stub (frame, NULL, op_ret, - op_errno, inode, buf, - preparent, postparent); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int32_t -libgf_client_symlink (libglusterfs_client_ctx_t *ctx, const char *linkpath, - loc_t *loc) -{ - int op_ret = -1; - libgf_client_local_t *local = NULL; - call_stub_t *stub = NULL; - inode_t *inode = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, symlink, local, linkpath, loc); - - op_ret = stub->args.symlink_cbk.op_ret; - errno = stub->args.symlink_cbk.op_errno; - if (op_ret == -1) - goto out; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "target: %s, link: %s, status %d" - " errno %d", linkpath, loc->path, op_ret, errno); - inode = stub->args.symlink_cbk.inode; - inode_link (inode, loc->parent, loc->name, - &stub->args.symlink_cbk.buf); - libgf_transform_iattr (ctx, inode, &stub->args.symlink_cbk.buf); - inode_lookup (inode); - if (!libgf_get_inode_ctx (inode)) - libgf_alloc_inode_ctx (ctx, inode); - - libgf_update_iattr_cache (inode, LIBGF_UPDATE_STAT, - &stub->args.symlink_cbk.buf); -out: - call_stub_destroy (stub); - return op_ret; -} - -int -glusterfs_glh_symlink (glusterfs_handle_t handle, const char *oldpath, - const char *newpath) -{ - int32_t op_ret = -1; - libglusterfs_client_ctx_t *ctx = handle; - loc_t oldloc = {0, }; - loc_t newloc = {0, }; - char *oldname = NULL; - char *newname = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, newpath, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "target: %s, link: %s", oldpath, - newpath); - /* Old path does not need to be interpreted or looked up */ - oldloc.path = strdup (oldpath); - - newloc.path = strdup (newpath); - if (!newloc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&newloc, ctx, 1); - if (op_ret == 0) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "new path (%s) already exists, " - " returning EEXIST", newloc.path); - op_ret = -1; - errno = EEXIST; - goto out; - } - - op_ret = libgf_client_path_lookup (&newloc, ctx, 0); - if (op_ret == -1) { - errno = ENOENT; - goto out; - } - - newloc.inode = inode_new (ctx->itable); - newname = strdup (newloc.path); - op_ret = libgf_client_loc_fill (&newloc, ctx, 0, newloc.parent->ino, - basename (newname)); - - 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_symlink (ctx, oldpath, &newloc); - -out: - if (newname) - FREE (newname); - - if (oldname) - FREE (oldname); - libgf_client_loc_wipe (&oldloc); - libgf_client_loc_wipe (&newloc); - return op_ret; -} - -int -glusterfs_symlink (const char *oldpath, const char *newpath) -{ - char vpath[PATH_MAX]; - int op_ret = -1; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, oldpath, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, newpath, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "target: %s, link: %s", oldpath, - newpath); - - h = libgf_resolved_path_handle (newpath, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_symlink (h, oldpath, vpath); -out: - return op_ret; -} - - -int32_t -libgf_client_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, - const char *path, struct iatt *sbuf) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_readlink_cbk_stub (frame, NULL, op_ret, - op_errno, path, sbuf); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int32_t -libgf_client_readlink (libglusterfs_client_ctx_t *ctx, loc_t *loc, char *buf, - size_t bufsize) -{ - int op_ret = -1; - libgf_client_local_t *local = NULL; - call_stub_t *stub = NULL; - size_t cpy_size = 0; - - LIBGF_CLIENT_FOP (ctx, stub, readlink, local, loc, bufsize); - - op_ret = stub->args.readlink_cbk.op_ret; - errno = stub->args.readlink_cbk.op_errno; - - if (op_ret != -1) { - cpy_size = ((op_ret <= bufsize) ? op_ret : bufsize); - memcpy (buf, stub->args.readlink_cbk.buf, cpy_size); - op_ret = cpy_size; - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "link: %s, target: %s," - " status %d, errno %d", loc->path, buf, op_ret, errno); - } else - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "link: %s, status %d, " - "errno %d", loc->path, op_ret, errno); - - call_stub_destroy (stub); - return op_ret; -} - -ssize_t -glusterfs_glh_readlink (glusterfs_handle_t handle, const char *path, char *buf, - size_t bufsize) -{ - int32_t op_ret = -1; - loc_t loc = {0, }; - libglusterfs_client_ctx_t *ctx = handle; - char *name = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - if (bufsize < 0) { - errno = EINVAL; - goto out; - } - - if (bufsize == 0) { - op_ret = 0; - goto out; - } - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", loc.path); - goto out; - } - - name = strdup (loc.path); - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename (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_readlink (ctx, &loc, buf, bufsize); - -out: - if (name) - FREE (name); - - libgf_client_loc_wipe (&loc); - return op_ret; -} - -ssize_t -glusterfs_readlink (const char *path, char *buf, size_t bufsize) -{ - char vpath[PATH_MAX]; - int op_ret = -1; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, buf, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_readlink (h, vpath, buf, bufsize); -out: - return op_ret; -} - -char * -glusterfs_glh_realpath (glusterfs_handle_t handle, const char *path, - char *resolved_path) -{ - char *buf = NULL; - char *rpath = NULL; - char *start = NULL, *end = NULL; - char *dest = NULL; - libglusterfs_client_ctx_t *ctx = handle; - long int path_max = 0; - char *ptr = NULL; - struct stat stbuf = {0, }; - long int new_size = 0; - char *new_rpath = NULL; - int dest_offset = 0; - char *rpath_limit = 0; - int ret = 0, num_links = 0; - char *vpath = NULL, *tmppath = NULL; - char absolute_path[PATH_MAX]; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - -#ifdef PATH_MAX - path_max = PATH_MAX; -#else - path_max = pathconf (path, _PC_PATH_MAX); - if (path_max <= 0) { - path_max = 1024; - } -#endif - - if (resolved_path == NULL) { - rpath = CALLOC (1, path_max); - if (rpath == NULL) { - errno = ENOMEM; - goto out; - } - } else { - rpath = resolved_path; - } - - rpath_limit = rpath + path_max; - - if (path[0] == '/') { - rpath[0] = '/'; - dest = rpath + 1; - } else { - /* - FIXME: can $CWD be a valid path on glusterfs server? hence is - it better to handle this case or just return EINVAL for - relative paths? - */ - ptr = getcwd (rpath, path_max); - if (ptr == NULL) { - goto err; - } - dest = rpath + strlen (rpath); - } - - for (start = end = (char *)path; *end; start = end) { - if (dest[-1] != '/') { - *dest++ = '/'; - } - - while (*start == '/') { - start++; - } - - for (end = start; *end && *end != '/'; end++); - - if ((end - start) == 0) { - break; - } - - if ((end - start == 1) && (start[0] == '.')) { - /* do nothing */ - } else if (((end - start) == 2) && (start[0] == '.') - && (start[1] == '.')) { - if (dest > rpath + 1) { - while (--dest[-1] != '/'); - } - } else { - if ((dest + (end - start + 1)) >= rpath_limit) { - if (resolved_path == NULL) { - errno = ENAMETOOLONG; - if (dest > rpath + 1) - dest--; - *dest = '\0'; - goto err; - } - - dest_offset = dest - rpath; - new_size = rpath_limit - rpath; - if ((end - start + 1) > path_max) { - new_size = (end - start + 1); - } else { - new_size = path_max; - } - - new_rpath = realloc (rpath, new_size); - if (new_rpath == NULL) { - goto err; - } - - - dest = new_rpath + dest_offset; - rpath = new_rpath; - rpath_limit = rpath + new_size; - } - - memcpy (dest, start, end - start); - dest += end - start; - *dest = '\0'; - - ret = glusterfs_glh_lstat (handle, rpath, &stbuf); - if (ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "glusterfs_glh_stat returned -1 for" - " path (%s):(%s)", rpath, - strerror (errno)); - goto err; - } - - if (S_ISLNK (stbuf.st_mode)) { - buf = calloc (1, path_max); - if (buf == NULL) { - errno = ENOMEM; - goto err; - } - - if (++num_links > MAXSYMLINKS) - { - errno = ELOOP; - FREE (buf); - goto err; - } - - ret = glusterfs_glh_readlink (handle, rpath, - buf, - path_max - 1); - if (ret < 0) { - gf_log ("libglusterfsclient", - GF_LOG_ERROR, - "glusterfs_readlink returned %d" - " for path (%s):(%s)", - ret, rpath, strerror (errno)); - FREE (buf); - goto err; - } - buf[ret] = '\0'; - - if (buf[0] != '/') { - tmppath = strdup (rpath); - tmppath = dirname (tmppath); - sprintf (absolute_path, "%s/%s", - tmppath, buf); - FREE (buf); - buf = libgf_resolve_path_light ((char *)absolute_path); - FREE (tmppath); - } - - rpath = glusterfs_glh_realpath (handle, buf, - rpath); - FREE (buf); - if (rpath == NULL) { - goto out; - } - dest = rpath + strlen (rpath); - - } else if (!S_ISDIR (stbuf.st_mode) && *end != '\0') { - errno = ENOTDIR; - goto err; - } - } - } - if (dest > rpath + 1 && dest[-1] == '/') - --dest; - *dest = '\0'; - -out: - if (vpath) - FREE (vpath); - return rpath; - -err: - if (vpath) - FREE (vpath); - if (resolved_path == NULL) { - FREE (rpath); - } - - return NULL; -} - -char * -glusterfs_realpath (const char *path, char *resolved_path) -{ - char *res = NULL; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - char *realp = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - realp = CALLOC (PATH_MAX, sizeof (char)); - if (!realp) - goto out; - - libgf_vmp_search_vmp (h, realp, PATH_MAX); - res = glusterfs_glh_realpath (h, vpath, resolved_path); - if (!res) - goto out; - - /* This copy is needed to ensure that when we return the real resolved - * path, we return a path that accounts for the app's view of the - * path, i.e. it starts with the VMP, in case this is an absolute path. - */ - if (libgf_path_absolute (path)) { - strcat (realp, resolved_path); - strcpy (resolved_path, realp); - } - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, resolved %s", path, - resolved_path); -out: - if (realp) - FREE (realp); - - return res; -} - -int -glusterfs_glh_remove (glusterfs_handle_t handle, const char *path) -{ - loc_t loc = {0, }; - int op_ret = -1; - libglusterfs_client_ctx_t *ctx = handle; - char *name = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, handle, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", path); - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) - goto out; - - name = strdup (loc.path); - op_ret = libgf_client_loc_fill (&loc, ctx, 0, loc.parent->ino, - basename (name)); - if (op_ret == -1) - goto out; - - if (IA_ISDIR (loc.inode->ia_type)) - op_ret = libgf_client_rmdir (ctx, &loc); - else - op_ret = libgf_client_unlink (ctx, &loc); - -out: - if (name) - FREE (name); - return op_ret; - -} - -int -glusterfs_remove(const char *pathname) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, pathname, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s", pathname); - - h = libgf_resolved_path_handle (pathname, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_remove (h, vpath); -out: - return op_ret; -} - -void -glusterfs_rewinddir (glusterfs_dir_t dirfd) -{ - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - fd_ctx = libgf_get_fd_ctx ((fd_t *)dirfd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - goto out; - } - - pthread_mutex_lock (&fd_ctx->lock); - { - fd_ctx->offset = 0; - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Offset: %"PRIu64, - fd_ctx->offset); - } - pthread_mutex_unlock (&fd_ctx->lock); - -out: - return; -} - -void -glusterfs_seekdir (glusterfs_dir_t dirfd, off_t offset) -{ - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - fd_ctx = libgf_get_fd_ctx ((fd_t *)dirfd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - goto out; - } - - pthread_mutex_lock (&fd_ctx->lock); - { - fd_ctx->offset = offset; - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Offset: %"PRIu64, - fd_ctx->offset); - } - pthread_mutex_unlock (&fd_ctx->lock); - -out: - return; -} - -off_t -glusterfs_telldir (glusterfs_dir_t dirfd) -{ - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - off_t off = -1; - - fd_ctx = libgf_get_fd_ctx ((fd_t *)dirfd); - if (!fd_ctx) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "No fd context present"); - errno = EBADF; - goto out; - } - - pthread_mutex_lock (&fd_ctx->lock); - { - off = fd_ctx->offset; - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Offset: %"PRIu64, - fd_ctx->offset); - } - pthread_mutex_unlock (&fd_ctx->lock); - -out: - return off; -} - -struct libgf_client_sendfile_data { - int reads_sent; - int reads_completed; - int out_fd; - int32_t op_ret; - int32_t op_errno; - pthread_mutex_t lock; - pthread_cond_t cond; -}; - -int -libgf_client_sendfile_read_cbk (int op_ret, int op_errno, - glusterfs_iobuf_t *buf, void *cbk_data) -{ - struct libgf_client_sendfile_data *sendfile_data = cbk_data; - int bytes = 0; - - if (op_ret > 0) { - bytes = writev (sendfile_data->out_fd, buf->vector, buf->count); - if (bytes != op_ret) { - op_ret = -1; - op_errno = errno; - } - - glusterfs_free (buf); - } - - pthread_mutex_lock (&sendfile_data->lock); - { - if (sendfile_data->op_ret != -1) { - if (op_ret == -1) { - sendfile_data->op_ret = -1; - sendfile_data->op_errno = op_errno; - } else { - sendfile_data->op_ret += op_ret; - } - } - - sendfile_data->reads_completed++; - - if (sendfile_data->reads_completed - == sendfile_data->reads_sent) { - pthread_cond_broadcast (&sendfile_data->cond); - } - } - pthread_mutex_unlock (&sendfile_data->lock); - - return 0; -} - - -ssize_t -glusterfs_sendfile (int out_fd, glusterfs_file_t in_fd, off_t *offset, - size_t count) -{ - ssize_t ret = -1; - struct libgf_client_sendfile_data cbk_data = {0, }; - off_t off = -1; - size_t size = 0; - int flags = 0; - int non_block = 0; - - - pthread_mutex_init (&cbk_data.lock, NULL); - pthread_cond_init (&cbk_data.cond, NULL); - cbk_data.out_fd = out_fd; - - if (offset) { - off = *offset; - } - - flags = fcntl (out_fd, F_GETFL); - - if (flags != -1) { - non_block = flags & O_NONBLOCK; - - if (non_block) { - ret = fcntl (out_fd, F_SETFL, flags & ~O_NONBLOCK); - } - } - - while (count != 0) { - /* - * FIXME: what's the optimal size for reads and writes? - */ - size = (count > LIBGF_SENDFILE_BLOCK_SIZE) ? - LIBGF_SENDFILE_BLOCK_SIZE : count; - - /* - * we don't wait for reply to previous read, we just send all - * reads in a single go. - */ - ret = glusterfs_read_async (in_fd, size, off, - libgf_client_sendfile_read_cbk, - &cbk_data); - if (ret == -1) { - break; - } - - pthread_mutex_lock (&cbk_data.lock); - { - cbk_data.reads_sent++; - } - pthread_mutex_unlock (&cbk_data.lock); - - if (offset) { - off += size; - } - - count -= size; - } - - pthread_mutex_lock (&cbk_data.lock); - { - /* - * if we've not received replies to all the reads we've sent, - * wait for them - */ - if (cbk_data.reads_sent > cbk_data.reads_completed) { - pthread_cond_wait (&cbk_data.cond, - &cbk_data.lock); - } - } - pthread_mutex_unlock (&cbk_data.lock); - - if (offset != NULL) { - *offset = off; - } - - /* if we were able to stack_wind all the reads */ - - if (ret == 0) { - ret = cbk_data.op_ret; - errno = cbk_data.op_errno; - } - - if (non_block) { - fcntl (out_fd, F_SETFL, flags); - } - - return ret; -} - - -static int32_t -libgf_client_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct flock *lock) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_lk_cbk_stub (frame, NULL, op_ret, op_errno, - lock); - - LIBGF_REPLY_NOTIFY (local); - - return 0; -} - - -int -libgf_client_lk (libglusterfs_client_ctx_t *ctx, fd_t *fd, int cmd, - struct flock *lock) -{ - call_stub_t *stub = NULL; - int32_t op_ret; - libgf_client_local_t *local = NULL; - - LIBGF_CLIENT_FOP(ctx, stub, lk, local, fd, cmd, lock); - - op_ret = stub->args.lk_cbk.op_ret; - errno = stub->args.lk_cbk.op_errno; - if (op_ret == 0) { - *lock = stub->args.lk_cbk.lock; - } - - call_stub_destroy (stub); - return op_ret; -} - - -int -glusterfs_fcntl (glusterfs_file_t fd, int cmd, ...) -{ - int ret = -1; - struct flock *lock = NULL; - va_list ap; - libglusterfs_client_ctx_t *ctx = NULL; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, fd, out); - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - errno = EBADF; - goto out; - } - - ctx = fd_ctx->ctx; - - switch (cmd) { - case F_SETLK: - case F_SETLKW: - case F_GETLK: -#if F_SETLK != F_SETLK64 - case F_SETLK64: -#endif -#if F_SETLKW != F_SETLKW64 - case F_SETLKW64: -#endif -#if F_GETLK != F_GETLK64 - case F_GETLK64: -#endif - va_start (ap, cmd); - lock = va_arg (ap, struct flock *); - va_end (ap); - - if (!lock) { - errno = EINVAL; - goto out; - } - - ret = libgf_client_lk (ctx, fd, cmd, lock); - break; - - default: - errno = EINVAL; - break; - } - -out: - return ret; -} - - -int -libgf_client_chdir (const char *path) -{ - int op_ret = 0; - uint32_t resulting_cwd_len = 0; - - pthread_mutex_lock (&cwdlock); - { - if (!libgf_path_absolute (path)) { - resulting_cwd_len = strlen (path) + strlen (cwd) - + ((strlen (path) && path[strlen (path) - 1] == '/') - ? 0 : 1) + 1; - - if (resulting_cwd_len > PATH_MAX) { - op_ret = -1; - errno = ENAMETOOLONG; - goto unlock; - } - strcat (cwd, path); - } else { - resulting_cwd_len = strlen (path) - + ((path[strlen (path) - 1] == '/') - ? 0 : 1) + 1; - - if (resulting_cwd_len > PATH_MAX) { - op_ret = -1; - errno = ENAMETOOLONG; - goto unlock; - } - - strcpy (cwd, path); - } - - if (cwd[strlen (cwd) - 1] != '/') { - strcat (cwd, "/"); - } - } -unlock: - pthread_mutex_unlock (&cwdlock); - - return op_ret; -} - - -int -glusterfs_fchdir (glusterfs_file_t fd) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - char vmp[PATH_MAX]; - char *res = NULL; - libglusterfs_client_fd_ctx_t *fd_ctx = NULL; - glusterfs_handle_t handle = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, fd, out); - - /* FIXME: there is a race-condition between glusterfs_fchdir and - glusterfs_close. If two threads of application call glusterfs_fchdir - and glusterfs_close on the same fd, there is a possibility of - glusterfs_fchdir accessing freed memory of fd_ctx. - */ - - fd_ctx = libgf_get_fd_ctx (fd); - if (!fd_ctx) { - errno = EBADF; - goto out; - } - - pthread_mutex_lock (&fd_ctx->lock); - { - handle = fd_ctx->ctx; - strcpy (vpath, fd_ctx->vpath); - } - pthread_mutex_unlock (&fd_ctx->lock); - - if (vpath[0] == '\0') { - errno = ENOTDIR; - goto out; - } - - res = libgf_vmp_search_vmp (handle, vmp, PATH_MAX); - if (res == NULL) { - errno = EBADF; - goto out; - } - - /* both vmp and vpath are terminated with '/'. Also path starts with a - '/'. Hence the extra '/' amounts to NULL character at the end of the - string. - */ - if ((strlen (vmp) + strlen (vpath)) > PATH_MAX) { - errno = ENAMETOOLONG; - goto out; - } - - pthread_mutex_lock (&cwdlock); - { - strcpy (cwd, vmp); - res = vpath; - if (res[0] == '/') { - res++; - } - - strcat (cwd, res); - } - pthread_mutex_unlock (&cwdlock); - - op_ret = 0; -out: - return op_ret; -} - - -int -glusterfs_chdir (const char *path) -{ - int32_t op_ret = -1; - glusterfs_handle_t handle = NULL; - loc_t loc = {0, }; - char vpath[PATH_MAX]; - - handle = libgf_resolved_path_handle (path, vpath); - - if (handle != NULL) { - loc.path = strdup (vpath); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Path compaction " - "failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, handle, 0); - } - - if ((handle == NULL) || (op_ret == 0)) { - op_ret = libgf_client_chdir (path); - } - -out: - return op_ret; -} - - -char * -glusterfs_getcwd (char *buf, size_t size) -{ - char *res = NULL; - size_t len = 0; - loc_t loc = {0, }; - glusterfs_handle_t handle = NULL; - char vpath[PATH_MAX]; - int32_t op_ret = 0; - - pthread_mutex_lock (&cwdlock); - { - if (!cwd_inited) { - errno = ENODEV; - goto unlock; - } - - if (buf == NULL) { - buf = CALLOC (1, len); - if (buf == NULL) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, - "out of memory"); - goto unlock; - } - } else { - if (size == 0) { - errno = EINVAL; - goto unlock; - } - - if (len > size) { - errno = ERANGE; - goto unlock; - } - } - - strcpy (buf, cwd); - res = buf; - } -unlock: - pthread_mutex_unlock (&cwdlock); - - if (res != NULL) { - handle = libgf_resolved_path_handle (res, vpath); - - if (handle != NULL) { - loc.path = strdup (vpath); - if (loc.path == NULL) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, - "strdup failed"); - } else { - op_ret = libgf_client_path_lookup (&loc, handle, - 0); - if (op_ret == -1) { - res = NULL; - } - } - } - } - - return res; -} - -int32_t -libgf_client_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, - struct iatt *prebuf, struct iatt *postbuf) -{ - libgf_client_local_t *local = frame->local; - - local->reply_stub = fop_truncate_cbk_stub (frame, NULL, op_ret, - op_errno, prebuf, postbuf); - - LIBGF_REPLY_NOTIFY (local); - return 0; -} - -int32_t -libgf_client_truncate (libglusterfs_client_ctx_t *ctx, - loc_t *loc, off_t length) -{ - call_stub_t *stub = NULL; - int32_t op_ret = 0; - libgf_client_local_t *local = NULL; - - LIBGF_CLIENT_FOP (ctx, stub, truncate, local, loc, length); - - op_ret = stub->args.truncate_cbk.op_ret; - errno = stub->args.truncate_cbk.op_errno; - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path %s, status %d, errno %d", - loc->path, op_ret, errno); - - if (op_ret == -1) { - goto out; - } - - libgf_transform_iattr (ctx, loc->inode, - &stub->args.truncate_cbk.postbuf); - - libgf_update_iattr_cache (loc->inode, LIBGF_UPDATE_STAT, - &stub->args.truncate_cbk.postbuf); - call_stub_destroy (stub); - -out: - return op_ret; -} - -int -glusterfs_glh_truncate (glusterfs_handle_t handle, const char *path, - off_t length) -{ - int32_t op_ret = -1; - loc_t loc = {0, }; - libglusterfs_client_ctx_t *ctx = handle; - char *name = NULL, *pathname = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); - GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); - - loc.path = strdup (path); - if (!loc.path) { - gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "strdup failed"); - goto out; - } - - op_ret = libgf_client_path_lookup (&loc, ctx, 1); - if (op_ret == -1) { - gf_log ("libglusterfsclient", GF_LOG_ERROR, - "path lookup failed for (%s)", loc.path); - goto out; - } - - pathname = strdup (loc.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_truncate (ctx, &loc, length); - -out: - libgf_client_loc_wipe (&loc); - - return op_ret; -} - -int -glusterfs_truncate (const char *path, off_t length) -{ - int op_ret = -1; - char vpath[PATH_MAX]; - glusterfs_handle_t h = NULL; - - GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, path, out); - - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "path:%s length:%"PRIu64, path, - length); - h = libgf_resolved_path_handle (path, vpath); - if (!h) { - errno = ENODEV; - goto out; - } - - op_ret = glusterfs_glh_truncate (h, vpath, length); -out: - return op_ret; -} - -static struct xlator_fops libgf_client_fops = { -}; - -static struct xlator_cbks libgf_client_cbks = { - .forget = libgf_client_forget, - .release = libgf_client_release, - .releasedir = libgf_client_releasedir, -}; - -static inline xlator_t * -libglusterfs_graph (xlator_t *graph) -{ - int ret = 0; - xlator_t *top = NULL; - xlator_list_t *xlchild, *xlparent; - - top = CALLOC (1, sizeof (*top)); - ERR_ABORT (top); - - xlchild = CALLOC (1, sizeof(*xlchild)); - ERR_ABORT (xlchild); - xlchild->xlator = graph; - top->children = xlchild; - top->ctx = graph->ctx; - top->next = graph; - top->name = strdup (LIBGF_XL_NAME); - - xlparent = CALLOC (1, sizeof(*xlparent)); - xlparent->xlator = top; - graph->parents = xlparent; - ret = asprintf (&top->type, LIBGF_XL_NAME); - if (-1 == ret) { - fprintf (stderr, "failed to set the top xl's type"); - } - - top->init = libgf_client_init; - top->fops = &libgf_client_fops; - top->mops = &libgf_client_mops; - top->cbks = &libgf_client_cbks; - top->notify = libgf_client_notify; - top->fini = libgf_client_fini; - // fill_defaults (top); - - return top; -} diff --git a/libglusterfsclient/src/libglusterfsclient.h b/libglusterfsclient/src/libglusterfsclient.h deleted file mode 100755 index 1691a2faad3..00000000000 --- a/libglusterfsclient/src/libglusterfsclient.h +++ /dev/null @@ -1,1363 +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. -*/ - -#ifndef _LIBGLUSTERFSCLIENT_H -#define _LIBGLUSTERFSCLIENT_H - -#ifndef __BEGIN_DECLS -#ifdef __cplusplus -#define __BEGIN_DECLS extern "C" { -#else -#define __BEGIN_DECLS -#endif -#endif - -#ifndef __END_DECLS -#ifdef __cplusplus -#define __END_DECLS } -#else -#define __END_DECLS -#endif -#endif - - -__BEGIN_DECLS - -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#include <sys/statfs.h> -#include <sys/statvfs.h> -#include <utime.h> -#include <sys/time.h> -#include <stdint.h> - -typedef struct { - struct iovec *vector; - int count; - void *iobref; - void *dictref; -} glusterfs_iobuf_t; - - -typedef -int (*glusterfs_readv_cbk_t) (int op_ret, int op_errno, glusterfs_iobuf_t *buf, - void *cbk_data); - -typedef -int (*glusterfs_write_cbk_t) (int op_ret, int op_errno, void *cbk_data); - -typedef -int (*glusterfs_get_cbk_t) (int op_ret, int op_errno, glusterfs_iobuf_t *buf, - struct stat *stbuf, void *cbk_data); - - -/* Data Interface - * The first section describes the data structures required for - * using libglusterfsclient. - */ - -/* This structure needs to be filled up and - * passed to te glusterfs_init function which uses - * the params passed herein to initialize a glusterfs - * client context and then connect to a glusterfs server. - */ -typedef struct { - char *logfile; /* Path to the file which will store - the log. - */ - char *loglevel; /* The log level required for - reporting various events within - libglusterfsclient. - */ - struct { - char *specfile; /* Users can either open a volume or - specfile and assign the pointer to - specfp, or just refer to the volume - /spec file path in specfile. - */ - FILE *specfp; - }; - char *volume_name; /* The volume file could describe many - volumes but the specific volume - within that file is chosen by - specifying the volume name here. - */ - unsigned long lookup_timeout; /* libglusterclient provides the inode - numbers to be cached by the library. - The duration for which these are - cached are defined by lookup_timeout - . In Seconds. - */ - unsigned long stat_timeout; /* The file attributes received from - a stat syscall can also be cached - for the duration specified in this - member. In Seconds. - */ -} glusterfs_init_params_t; - - - -/* This is the handle returned by glusterfs_init - * once the initialization is complete. - * Users should treat this as an opaque handle. - */ -typedef void * glusterfs_handle_t; - - - -/* These identifiers are used as handles for files and dirs. - * Users of libglusterfsclient should not in anyway try to interpret - * the actual structures these will point to. - */ -typedef void * glusterfs_file_t; -typedef void * glusterfs_dir_t; - - -/* Function Call Interface */ -/* libglusterfsclient initialization function. - * @ctx : the structure described above filled with required values. - * @fakefsid: User generated fsid to be used to identify this - * volume. - * - * Returns NULL on failure and the non-NULL pointer on success. - * On failure, the error description might be present in the logfile - * depending on the log level. - */ -glusterfs_handle_t -glusterfs_init (glusterfs_init_params_t *ctx, uint32_t fakefsid); - - - -/* Used to destroy a glusterfs client context and the - * connection to the glusterfs server. - * - * @handle : The glusterfs handle returned by glusterfs_init. - */ -int -glusterfs_fini (glusterfs_handle_t handle); - - - -/* libglusterfs client provides two interfaces. - * 1. handle-based interface - * Functions that comprise the handle-based interface accept the - * glusterfs_handle_t as the first argument. It specifies the - * glusterfs client context over which to perform the operation. - * - * 2. Virtual Mount Point based interface: - * Functions that do not require a handle to be given in order to - * identify which client context to operate on. This interface - * internally determines the corresponding client context for the - * given path. The down-side is that a virtual mount point (VMP) needs to be - * registered with the library. A VMP is just a string that maps to a - * glusterfs_handle_t. The advantage of a VMP based interface is that - * a user program using multiple client contexts does not need to - * maintain its own mapping between paths and the corresponding - * handles. - */ - - - -/* glusterfs_mount is the function that allows users to register a VMP - * along with the parameters, which will be used to initialize a - * context. Applications calling glusterfs_mount do not need to - * initialized a context using the glusterfs_init interface. - * - * @vmp : The virtual mount point. - * @ipars : Initialization parameters populated as described - * earlier. - * - * Returns 0 on success, and -1 on failure. - */ -int -glusterfs_mount (char *vmp, glusterfs_init_params_t *ipars); - - - -/* glusterfs_umount is the VMP equivalent of glusterfs_fini. - * - * @vmp : The VMP which was initialized using glusterfs_mount. - * - * Returns 0 on sucess, and -1 on failure. - */ -int -glusterfs_umount (char *vmp); - - -/* glusterfs_umount_all unmounts all the mounts */ -int -glusterfs_umount_all (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 - */ - -/* glusterfs_glh_get: - * @handle : glusterfs handle - * @path : path to be looked upon - * @size : upper limit of file-sizes to be read in lookup - * @stbuf : attribute buffer - */ - -int -glusterfs_glh_get (glusterfs_handle_t handle, const char *path, void *buf, - size_t size, struct stat *stbuf); - -int -glusterfs_get (const char *path, void *buf, size_t size, struct stat *stbuf); - -int -glusterfs_get_async (glusterfs_handle_t handle, const char *path, size_t size, - glusterfs_get_cbk_t cbk, void *cbk_data); - - - -/* Opens a file. Corresponds to the open syscall. - * - * @handle : Handle returned from glusterfs_init - * @path : Path to the file or directory on the glusterfs - * export. Must be absolute to the export on the server. - * @flags : flags to control open behaviour. - * @... : The mode_t argument that defines the mode for a new - * file, in case a new file is being created using the - * O_CREAT flag in @flags. - * - * Returns a non-NULL handle on success. NULL on failure and sets - * errno accordingly. - */ -glusterfs_file_t -glusterfs_glh_open (glusterfs_handle_t handle, const char *path, int flags, - ...); - - -/* Opens a file without having to specify a handle. - * - * @path : Path to the file to open in the glusterfs export. - * The path to the file in glusterfs export must be - * pre-fixed with the VMP string registered with - * glusterfs_mount. - * @flags : flags to control open behaviour. - * @... : The mode_t argument that defines the mode for a new - * file, in case a new file is being created using the - * O_CREAT flag in @flags. - * - * Returns 0 on success, -1 on failure with errno set accordingly. - */ -glusterfs_file_t -glusterfs_open (const char *path, int flags, ...); - - - -/* Creates a file. Corresponds to the creat syscall. - * - * @handle : Handle returned from glusterfs_init - * @path : Path to the file that needs to be created in the - * glusterfs export. - * @mode : File creation mode. - * - * Returns the file handle on success. NULL on error with errno set as - * required. - */ -glusterfs_file_t -glusterfs_glh_creat (glusterfs_handle_t handle, const char *path, mode_t mode); - - - -/* VMP-based creat. - * @path : Path to the file to be created. Must be - * pre-prepended with the VMP string registered with - * glusterfs_mount. - * @mode : File creation mode. - * - * Returns file handle on success. NULL handle on error with errno set - * accordingly. - */ -glusterfs_file_t -glusterfs_creat (const char *path, mode_t mode); - - - -/* Close the file identified by the handle. - * - * @fd : Closes the file. - * - * Returns 0 on success, -1 on error with errno set accordingly. - */ -int -glusterfs_close (glusterfs_file_t fd); - - - -/* Get struct stat for the file in path. - * - * @handle : The handle that identifies a glusterfs client - * context. - * @path : The file for which we need to get struct stat. - * @stbuf : The buffer into which the file's stat is copied. - * - * Returns 0 on success and -1 on error with errno set accordingly. - */ -int -glusterfs_glh_stat (glusterfs_handle_t handle, const char *path, - struct stat *stbuf); - - -/* Get struct stat for file in path. - * - * @path : The file for which struct stat is required. - * @sbuf : The buffer into which the stat structure is copied. - * - * Returns 0 on success and -1 on error with errno set accordingly. - */ -int -glusterfs_stat (const char *path, struct stat *buf); - - - -/* Gets stat struct for the file. - * - * @handle : The handle identifying a glusterfs client context. - * @path : Path to the file for which stat structure is - * required. If path is a symlink, the symlink is - * interpreted and the stat structure returned for the - * target of the link. - * @buf : The buffer into which the stat structure is copied. - * - * Returns 0 on success and -1 on error with errno set accordingly. - */ -int -glusterfs_glh_lstat (glusterfs_handle_t handle, const char *path, - struct stat *buf); - - - -/* Gets stat struct for a file. - * - * @path : The file to get the struct stat for. - * @buf : The receiving struct stat buffer. - * - * Returns 0 on success and -1 on error with errno set accordingly. - */ -int -glusterfs_lstat (const char *path, struct stat *buf); - - - -/* Get stat structure for a file. - * - * @fd : The file handle identifying a file on the glusterfs - * server. - * @stbuf : The buffer into which the stat data is copied. - * - * Returns 0 on success and -1 on error with errno set accordingly. - */ -int -glusterfs_fstat (glusterfs_file_t fd, struct stat *stbuf); - -int -glusterfs_glh_setxattr (glusterfs_handle_t handle, const char *path, - const char *name, const void *value, - size_t size, int flags); - -int -glusterfs_glh_lsetxattr (glusterfs_handle_t handle, const char *path, - const char *name, const void *value, size_t size, - int flags); - -int -glusterfs_setxattr (const char *path, const char *name, const void *value, - size_t size, int flags); - -int -glusterfs_lsetxattr (const char *path, const char *name, const void *value, - size_t size, int flags); - -int -glusterfs_fsetxattr (glusterfs_file_t fd, const char *name, const void *value, - size_t size, int flags); - -ssize_t -glusterfs_glh_getxattr (glusterfs_handle_t handle, const char *path, - const char *name, void *value, size_t size); - -ssize_t -glusterfs_glh_lgetxattr (glusterfs_handle_t handle, const char *path, - const char *name, void *value, size_t size); - -ssize_t -glusterfs_getxattr (const char *path, const char *name, void *value, - size_t size); - -ssize_t -glusterfs_lgetxattr (const char *path, const char *name, void *value, - size_t size); - -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 (glusterfs_handle_t handle, const char *path, char *list, - size_t size); - -ssize_t -glusterfs_flistxattr (glusterfs_file_t fd, char *list, size_t size); - -int -glusterfs_removexattr (glusterfs_handle_t handle, const char *path, - const char *name); - -int -glusterfs_lremovexattr (glusterfs_handle_t handle, const char *path, - const char *name); - -int -glusterfs_fremovexattr (glusterfs_file_t fd, const char *name); - - - -/* Read data from a file. - * @fd : Handle returned by glusterfs_open or - * glusterfs_glh_open. - * @buf : Buffer to read the data into. - * @nbytes : Number of bytes to read. - * - * Returns number of bytes actually read on success or -1 on error - * with errno set to the appropriate error number. - */ -ssize_t -glusterfs_read (glusterfs_file_t fd, void *buf, size_t nbytes); - - - -/* Read data into an array of buffers. - * - * @fd : File handle returned by glusterfs_open or - * glusterfs_glh_open. - * @vec : Array of buffers into which the data is read. - * @count : Number of iovecs referred to by vec. - * - * Returns number of bytes read on success or -1 on error with errno - * set appropriately. - */ -ssize_t -glusterfs_readv (glusterfs_file_t fd, const struct iovec *vec, int count); - -int -glusterfs_read_async (glusterfs_file_t fd, size_t nbytes, off_t offset, - glusterfs_readv_cbk_t readv_cbk, void *cbk_data); - - - -/* Write data into a file. - * - * @fd : File handle returned from glusterfs_open or - * glusterfs_glh_open. - * @buf : Buffer which is written to the file. - * @nbytes : Number bytes of the @buf written to the file. - * - * On success, returns number of bytes written. On error, returns -1 - * with errno set appropriately. - */ -ssize_t -glusterfs_write (glusterfs_file_t fd, const void *buf, size_t nbytes); - - - -/* Writes an array of buffers into a file. - * - * @fd : The file handle returned from glusterfs_open or - * glusterfs_glh_open. - * @vector : Array of buffers to be written to the file. - * @count : Number of separate buffers in the @vector array. - * - * Returns number of bytes written on success or -1 on error with - * errno set approriately. - */ -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); - - - -/* Read from a file starting at a given offset. - * - * @fd : File handle returned from glusterfs_open or - * glusterfs_glh_open. - * @buf : Buffer to read the data into. - * @nbytes : Number of bytes to read. - * @offset : The offset to start reading @nbytes from. - * - * Returns number of bytes read on success or -1 on error with errno - * set appropriately. - */ -ssize_t -glusterfs_pread (glusterfs_file_t fd, void *buf, size_t nbytes, off_t offset); - - - -/* Write to a file starting at a given offset. - * - * @fd : Flie handle returned from glusterfs_open or - * glusterfs_glh_open. - * @buf : Buffer that will be written to the file. - * @nbytes : Number of bytes to write from @buf. - * @offset : The starting offset from where @nbytes will be - * written. - * - * Returns number of bytes written on success and -1 on error with - * errno set appropriately. - */ -ssize_t -glusterfs_pwrite (glusterfs_file_t fd, const void *buf, size_t nbytes, - off_t offset); - - - -/* Seek to an offset in the file. - * - * @fd : File handle in which to seek to. File handle - * returned by glusterfs_open or glusterfs_glh_open. - * @offset : Offset to seek to in the given file. - * @whence : Determines how the offset is interpreted by this - * syscall. The behaviour is similar to the options - * provided by the POSIX lseek system call. See man lseek - * for more details. - * - * On success, returns the resulting absolute offset in the file after the seek - * operation is performed. ON error, returns -1 with errno set - * appropriately. - */ -off_t -glusterfs_lseek (glusterfs_file_t fd, off_t offset, int whence); - - - -/* Create a directory. - * - * @handle : The handle of the glusterfs context in which the - * directory needs to be created. - * @path : The absolute path within the glusterfs context where - * the directory needs to be created. - * @mode : The mode bits for the newly created directory. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_mkdir (glusterfs_handle_t handle, const char *path, mode_t mode); - - - -/* Create a directory. - * - * @path : Path to the directory that needs to be created. This - * path must be prefixed with the VMP of the particular glusterfs - * context. - * @mode : Mode flags for the newly created directory. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_mkdir (const char *path, mode_t mode); - - - -/* Remove a directory. - * - * @handle : Handle of the glusterfs context from which to remove - * the directory. - * @path : The path of the directory to be removed in the glusterfs - * context. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_rmdir (glusterfs_handle_t handle, const char *path); - - - -/* Remove a directory. - * - * @path : The absolute path to the directory to be removed. - * This path must be pre-fixed with the VMP of the - * particular glusterfs context in which this directory - * resides. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_rmdir (const char *path); - - - -/* Read directory entries. - * - * @fd : The handle of the directory to be read. This handle - * is the one returned by opendir. - * - * Returns the directory entry on success and NULL pointer on error - * with errno set appropriately. - */ -void * -glusterfs_readdir (glusterfs_dir_t dirfd); - - - -/* re-entrant version of glusterfs_readdir. - * - * @dirfd : The handle of directory to be read. This handle is the one - * returned by opendir. - * @entry : Pointer to storage to store a directory entry. The storage - * pointed to by entry shall be large enough for a dirent with - * an array of char d_name members containing at least - * {NAME_MAX}+1 elements. - * @result : Upon successful return, the pointer returned at *result shall - * have the same value as the argument entry. Upon reaching the - * end of the directory stream, this pointer shall have the - * value NULL. - */ -int -glusterfs_readdir_r (glusterfs_dir_t dirfd, struct dirent *entry, - struct dirent **result); - -/* Close a directory handle. - * - * @fd : The directory handle to be closed. - * - * Returns 0 on success and -1 on error with errno set to 0. - */ -int -glusterfs_closedir (glusterfs_dir_t dirfd); -/* FIXME: remove getdents */ -int -glusterfs_getdents (glusterfs_dir_t fd, struct dirent *dirp, - unsigned int count); - - - -/* Create device node. - * - * @handle : glusterfs context in which to create the device - * node. - * @pathname : The absolute path of the device to be created in the - * given glusterfs context. - * - * @mode : Mode flags to apply to the newly created node. - * @dev : Device numbers that will apply to the node. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_mknod(glusterfs_handle_t handle, const char *pathname, - mode_t mode, dev_t dev); - - - -/* Create a device node. - * - * @pathname : The full path of the node to be created. This path - * should be pre-pended with the VMP of the glusterfs - * context in which this node is to be created. - * @mode : Mode flags that will be applied to the newly created - * device file. - * @dev : The device numbers that will be associated with the - * device node. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_mknod(const char *pathname, mode_t mode, dev_t dev); - - - -/* Returns the real absolute path of the given path. - * - * @handle : The glusterfs context in which the path resides in. - * @path : The path to be resolved. - * @resolved_path : The resolved path is stored in this buffer - * provided by the caller. - * - * Returns a pointer to resolved_path on success and NULL on error - * with errno set appropriately. - * - * See man realpath for details. - */ -char * -glusterfs_glh_realpath (glusterfs_handle_t handle, const char *path, - char *resolved_path); - - -/* Returns the real absolute path of the given path. - * - * @path : The path to be resolved. This path must be - * pre-fixed with the VMP of the glusterfs - * context in which the file resides. - * - * @resolved_path : The resolved path is stored in this user - * provided buffer. - * - * Returns a pointer to resolved_path on success, and NULL on error - * with errno set appropriately. - */ -char * -glusterfs_realpath (const char *path, char *resolved_path); - - - -/* Change mode flags on a path. - * - * @handle : Handle of the glusterfs instance in which the path - * resides. - * @path : The path whose mode bits need to be changed. - * @mode : The new mode bits. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_chmod (glusterfs_handle_t handle, const char *path, mode_t mode); - - - -/* Change mode flags on a path. - * - * @path : The path whose mode bits need to be changed. The - * path should be pre-fixed with the VMP that identifies the - * glusterfs context within which the path resides. - * @mode : The new mode bits. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_chmod (const char *path, mode_t mode); - - - -/* Change the owner of a path. - * If @path is a symlink, it is dereferenced and the ownership change - * happens on the target. - * - * @handle : Handle of the glusterfs context in which the path - * resides. - * @path : The path whose owner needs to be changed. - * @owner : ID of the new owner. - * @group : ID of the new group. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_chown (glusterfs_handle_t handle, const char *path, uid_t owner, - gid_t group); - - - -/* Change the owner of a path. - * - * If @path is a symlink, it is dereferenced and the ownership change - * happens on the target. - * @path : The path whose owner needs to be changed. Path must - * be pre-fixed with the VMP that identifies the - * glusterfs context in which the path resides. - * @owner : ID of the new owner. - * @group : ID of the new group. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_chown (const char *path, uid_t owner, gid_t group); - - - -/* Change the owner of the file. - * - * @fd : Handle of the file whose owner needs to be changed. - * @owner : ID of the new owner. - * @group : ID of the new group. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_fchown (glusterfs_file_t fd, uid_t owner, gid_t group); - - - -/* Open a directory. - * - * @handle : Handle that identifies a glusterfs context. - * @path : Path to the directory in the glusterfs context. - * - * Returns a non-NULL handle on success and NULL on failure with errno - * set appropriately. - */ -glusterfs_dir_t -glusterfs_glh_opendir (glusterfs_handle_t handle, const char *path); - - - -/* Open a directory. - * - * @path : Path to the directory. The path must be prepended - * with the VMP in order to identify the glusterfs - * context in which path resides. - * - * Returns a non-NULL handle on success and NULL on failure with errno - * set appropriately. - */ -glusterfs_dir_t -glusterfs_opendir (const char *path); - - - -/* Change the mode bits on an open file. - * - * @fd : The file whose mode bits need to be changed. - * @mode : The new mode bits. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_fchmod (glusterfs_file_t fd, mode_t mode); - - - -/* Sync the file contents to storage. - * - * @fd : The file whose contents need to be sync'ed to - * storage. - * - * Return 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_fsync (glusterfs_file_t *fd); - - - -/* Truncate an open file. - * - * @fd : The file to truncate. - * @length : The length to truncate to. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_ftruncate (glusterfs_file_t fd, off_t length); - - - -/* Create a hard link between two paths. - * - * @handle : glusterfs context in which both paths should reside. - * @oldpath : The existing path to link to. - * @newpath : The new path which will be linked to @oldpath. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_link (glusterfs_handle_t handle, const char *oldpath, - const char *newpath); - - - -/* Create a hard link between two paths. - * - * @oldpath : The existing path to link to. - * @newpath : The new path which will be linked to @oldpath. - * - * Both paths should exist on the same glusterfs context and should be - * prefixed with the same VMP. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_link (const char *oldpath, const char *newpath); - - - -/* Get stats about the underlying file system. - * - * @handle : Identifies the glusterfs context in which resides - * the given path. - * @path : stats are returned for the file system on which file - * is located. - * @buf : The buffer into which the stats are copied. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_statfs (glusterfs_handle_t handle, const char *path, - struct statfs *buf); - - - -/* Get stats about the underlying file system. - * - * @path : stats are returned for the file system on which file - * is located. @path must start with the VMP of the - * glusterfs context on which the file reside. - * @buf : The buffer into which the stats are copied. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_statfs (const char *path, struct statfs *buf); - - - -/* Get stats about the underlying file system. - * - * @handle : Identifies the glusterfs context in which resides - * the given path. - * @path : stats are returned for the file system on which file - * is located. - * @buf : The buffer into which the stats are copied. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_statvfs (glusterfs_handle_t handle, const char *path, - struct statvfs *buf); - - - -/* Get stats about the underlying file system. - * - * @path : stats are returned for the file system on which file - * is located. @path must start with the VMP of the - * glusterfs context on which the file reside. - * @buf : The buffer into which the stats are copied. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_statvfs (const char *path, struct statvfs *buf); - - - -/* Set the atime and mtime values for a given path. - * - * @handle : The handle identifying the glusterfs context. - * @path : The path for which the times need to be changed. - * @times : The array containing new time stamps for the file. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_utimes (glusterfs_handle_t handle, const char *path, - const struct timeval times[2]); - - - -/* Set the atime and mtime values for a given path. - * - * @path : The path for which the times need to be changed. - * @times : The array containing new time stamps for the file. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_utimes (const char *path, const struct timeval times[2]); - - - -/* Set the atime and mtime values for a given path. - * - * @handle : The handle identifying the glusterfs context. - * @path : The path for which the times need to be changed. - * @buf : The structure containing new time stamps for the file. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_utime (glusterfs_handle_t handle, const char *path, - const struct utimbuf *buf); - - - -/* Set the atime and mtime values for a given path. - * - * @path : The path for which the times need to be changed. - * @buf : The structure containing new time stamps for the file. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_utime (const char *path, const struct utimbuf *buf); - - - -/* Create FIFO at the given path. - * - * @handle : The glusterfs context in which to create that FIFO. - * @path : The path within the context where the FIFO is to be - * created. - * @mode : The mode bits for the newly create FIFO. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_mkfifo (glusterfs_handle_t handle, const char *path, - mode_t mode); - - - -/* Create FIFO at the given path. - * - * @path : The path within the context where the FIFO is to be - * created. @path should begin with the VMP of the - * glusterfs context in which the FIFO needs to be - * created. - * @mode : The mode bits for the newly create FIFO. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_mkfifo (const char *path, mode_t mode); - - - -/* Unlink a file. - * - * @handle : Handle that identifies a glusterfs instance. - * @path : Path in the glusterfs instance that needs to be - * unlinked. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_unlink (glusterfs_handle_t handle, const char *path); - - - -/* Unlink a file. - * - * @path : Path in the glusterfs instance that needs to be - * unlinked. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_unlink (const char *path); - - - -/* Create a symbolic link. - * - * @handle : The handle identifying the glusterfs context. - * @oldpath : The existing path to which a symlink needs to be - * created. - * @newpath : The new path which will be symlinked to the - * @oldpath. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_symlink (glusterfs_handle_t handle, const char *oldpath, - const char *newpath); - - - -/* Create a symbolic link. - * - * @oldpath : The existing path to which a symlink needs to be - * created. - * @newpath : The new path which will be symlinked to the - * @oldpath. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_symlink (const char *oldpath, const char *newpath); - - - -/* Read a symbolic link. - * - * @handle : Handle identifying the glusterfs context. - * @path : The symlink that needs to be read. - * @buf : The buffer into which the target of @path will be - * stored. - * @bufsize : Size of the buffer allocated to @buf. - * - * Returns number of bytes copied into @buf and -1 on error with errno - * set appropriately. - */ -ssize_t -glusterfs_glh_readlink (glusterfs_handle_t handle, const char *path, char *buf, - size_t bufsize); - - - -/* Read a symbolic link. - * - * @path : The symlink that needs to be read. - * @buf : The buffer into which the target of @path will be - * stored. - * @bufsize : Size of the buffer allocated to @buf. - * - * Returns number of bytes copied into @buf and -1 on error with errno - * set appropriately. - */ -ssize_t -glusterfs_readlink (const char *path, char *buf, size_t bufsize); - - - -/* Rename a file or directory. - * - * @handle : The identifier of a glusterfs context. - * @oldpath : The path to be renamed. - * @newpath : The new name for the @oldpath. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_rename (glusterfs_handle_t handle, const char *oldpath, - const char *newpath); - - - -/* Rename a file or directory. - * @oldpath : The path to be renamed. - * @newpath : The new name for the @oldpath. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_rename (const char *oldpath, const char *newpath); - - - -/* Remove a file or directory in the given glusterfs context. - * - * @handle : Handle identifying the glusterfs context. - * @path : Path of the file or directory to be removed. - * - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_remove (glusterfs_handle_t handle, const char *path); - - - -/* Remove a file or directory. - * - * @path : Path of the file or directory to be removed. The - * path must be pre-fixed with the VMP. - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_remove (const char *path); - - - -/* Change the owner of the given path. - * - * If @path is a symlink, the ownership change happens on the symlink. - * - * @handle : Handle identifying the glusterfs client context. - * @path : Path whose owner needs to be changed. - * @owner : New owner ID - * @group : New Group ID - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ -int -glusterfs_glh_lchown (glusterfs_handle_t handle, const char *path, uid_t owner, - gid_t group); - - - -/* Change the owner of the given path. - * - * If @path is a symlink, the ownership change happens on the symlink. - * - * @path : Path whose owner needs to be changed. - * @owner : New owner ID - * @group : New Group ID - * - * Returns 0 on success and -1 on error with errno set appropriately. - */ - -int -glusterfs_lchown (const char *path, uid_t owner, gid_t group); - - - -/* Rewind directory stream pointer to beginning of the directory. - * - * @dirfd : Directory handle returned by glusterfs_open on - * glusterfs_opendir. - * - * Returns no value. - */ -void -glusterfs_rewinddir (glusterfs_dir_t dirfd); - - - -/* Seek to the given offset in the directory handle. - * - * @dirfd : Directory handle returned by glusterfs_open on - * glusterfs_opendir. - * @offset : The offset to seek to. - * - * Returns no value. - */ -void -glusterfs_seekdir (glusterfs_dir_t dirfd, off_t offset); - - - -/* Return the current offset in a directory stream. - * - * @dirfd : Directory handle returned by glusterfs_open on - * glusterfs_opendir. - * - * Returns the offset in the directory or -1 on error with errno set - * appropriately. - */ -off_t -glusterfs_telldir (glusterfs_dir_t dirfd); - - -/* Write count bytes from in_fd to out_fd, starting at *offset. - * glusterfs_sendfile aims at eliminating memory copy at the end of - * each read from in_fd, copying the file directly to out_fd from the buffer - * provided by glusterfs. - * - * @out_fd: file descriptor opened for writing - * - * @in_fd: glusterfs file handle to the file to be read from. - * - * @offset: If offset is not NULL, then it points to a variable holding the file - * offset from which glusterfs_sendfile() will start reading data - * from in_fd. When glusterfs_sendfile() returns, this variable will - * be set to the offset of the byte following the last byte that was - * read. If offset is not NULL, then glusterfs_sendfile() does not - * modify the current file offset of in_fd; otherwise the current file - * offset is adjusted to reflect the number of bytes read from in_fd. - * - * @count: number of bytes to copy between the file descriptors. - */ - -ssize_t -glusterfs_sendfile (int out_fd, glusterfs_file_t in_fd, off_t *offset, - size_t count); - -/* manipulate file descriptor - * This api can have 3 forms similar to fcntl(2). - * - * int - * glusterfs_fcntl (glusterfs_file_t fd, int cmd) - * - * int - * glusterfs_fcntl (glusterfs_file_t fd, int cmd, long arg) - * - * int - * glusterfs_fcntl (glusterfs_file_t fd, int cmd, struct flock *lock) - * - * @fd : file handle returned by glusterfs_open or glusterfs_create. - * @cmd : Though the aim is to implement all possible commands supported by - * fcntl(2), currently following commands are supported. - * F_SETLK, F_SETLKW, F_GETLK - used to acquire, release, and test for - * the existence of record locks (also - * known as file-segment or file-region - * locks). More detailed explanation is - * found in 'man 2 fcntl' - */ - -int -glusterfs_fcntl (glusterfs_file_t fd, int cmd, ...); - -/* - * Change the current working directory to @path - * - * @path : path to change the current working directory to. - * - * Returns 0 on success and -1 on failure with errno set appropriately. - */ -int -glusterfs_chdir (const char *path); - -/* - * Change the current working directory to the path @fd is opened on. - * - * @fd : current working directory will be changed to path @fd is opened on. - * - * Returns 0 on success and -1 on with errno set appropriately. - */ -int -glusterfs_fchdir (glusterfs_file_t fd); - -/* copies the current working directory into @buf if it is big enough - * - * @buf: buffer to copy into it. If @buf is NULL, a buffer will be allocated. - * The size of the buffer will be @size if it is not zero, otherwise the - * size will be big enough to hold the current working directory. - * @size: size of the buffer. - * - * Returns the pointer to buffer holding current working directory on success - * and NULL on failure. - */ - -char * -glusterfs_getcwd (char *buf, size_t size); - -/* - * Truncate the file to a specified length. - * - * @path : path to the file. - * @length : length to which the file has to be truncated. - * - * Returns 0 on success and -1 on failure with errno set appropriately - */ - -int -glusterfs_truncate (const char *path, off_t length); - - -/* 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); -/* Used to free the glusterfs_read_buf passed to the application from - glusterfs_read_async_cbk -*/ -void -glusterfs_free (glusterfs_iobuf_t *buf); - -__END_DECLS - -#endif /* !_LIBGLUSTERFSCLIENT_H */ diff --git a/scheduler/Makefile.am b/scheduler/Makefile.am deleted file mode 100644 index 618fa7dd8b8..00000000000 --- a/scheduler/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -SUBDIRS = alu random nufa rr switch - -CLEANFILES = diff --git a/scheduler/alu/Makefile.am b/scheduler/alu/Makefile.am deleted file mode 100644 index d471a3f9243..00000000000 --- a/scheduler/alu/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -SUBDIRS = src - -CLEANFILES = diff --git a/scheduler/alu/src/Makefile.am b/scheduler/alu/src/Makefile.am deleted file mode 100644 index eb7d0db07e0..00000000000 --- a/scheduler/alu/src/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -sched_LTLIBRARIES = alu.la -scheddir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/scheduler - -alu_la_LDFLAGS = -module -avoidversion - -alu_la_SOURCES = alu.c -alu_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la - -noinst_HEADERS = alu.h - -AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS)\ - -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS) - -CLEANFILES = diff --git a/scheduler/alu/src/alu-mem-types.h b/scheduler/alu/src/alu-mem-types.h deleted file mode 100644 index 92702f28690..00000000000 --- a/scheduler/alu/src/alu-mem-types.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.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 __ALU_MEM_TYPES_H__ -#define __ALU_MEM_TYPES_H__ - -#include "mem-types.h" - -enum gf_alu_mem_types_ { - gf_alu_mt_alu_threshold = gf_common_mt_end + 1, - gf_alu_mt_alu_sched, - gf_alu_mt_alu_limits, - gf_alu_mt_alu_sched_struct, - gf_alu_mt_alu_sched_node, - gf_alu_mt_end -}; -#endif - diff --git a/scheduler/alu/src/alu.c b/scheduler/alu/src/alu.c deleted file mode 100644 index 58bef60ae9f..00000000000 --- a/scheduler/alu/src/alu.c +++ /dev/null @@ -1,1019 +0,0 @@ -/* - Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.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/>. -*/ - - - -/* ALU code needs a complete re-write. This is one of the most important - * part of GlusterFS and so needs more and more reviews and testing - */ - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include <sys/time.h> -#include <stdint.h> -#include "stack.h" -#include "alu.h" -#include "alu-mem-types.h" - -#define ALU_DISK_USAGE_ENTRY_THRESHOLD_DEFAULT (1 * GF_UNIT_GB) -#define ALU_DISK_USAGE_EXIT_THRESHOLD_DEFAULT (512 * GF_UNIT_MB) - -#define ALU_WRITE_USAGE_ENTRY_THRESHOLD_DEFAULT 25 -#define ALU_WRITE_USAGE_EXIT_THRESHOLD_DEFAULT 5 - -#define ALU_READ_USAGE_ENTRY_THRESHOLD_DEFAULT 25 -#define ALU_READ_USAGE_EXIT_THRESHOLD_DEFAULT 5 - -#define ALU_OPEN_FILES_USAGE_ENTRY_THRESHOLD_DEFAULT 1000 -#define ALU_OPEN_FILES_USAGE_EXIT_THRESHOLD_DEFAULT 100 - -#define ALU_LIMITS_TOTAL_DISK_SIZE_DEFAULT 100 - -#define ALU_REFRESH_INTERVAL_DEFAULT 5 -#define ALU_REFRESH_CREATE_COUNT_DEFAULT 5 - - -static int64_t -get_stats_disk_usage (struct xlator_stats *this) -{ - return this->disk_usage; -} - -static int64_t -get_stats_write_usage (struct xlator_stats *this) -{ - return this->write_usage; -} - -static int64_t -get_stats_read_usage (struct xlator_stats *this) -{ - return this->read_usage; -} - -static int64_t -get_stats_disk_speed (struct xlator_stats *this) -{ - return this->disk_speed; -} - -static int64_t -get_stats_file_usage (struct xlator_stats *this) -{ - /* Avoid warning "defined but not used" */ - (void) &get_stats_file_usage; - - return this->nr_files; -} - -static int64_t -get_stats_free_disk (struct xlator_stats *this) -{ - if (this->total_disk_size > 0) - return (this->free_disk * 100) / this->total_disk_size; - return 0; -} - -static int64_t -get_max_diff_write_usage (struct xlator_stats *max, struct xlator_stats *min) -{ - return (max->write_usage - min->write_usage); -} - -static int64_t -get_max_diff_read_usage (struct xlator_stats *max, struct xlator_stats *min) -{ - return (max->read_usage - min->read_usage); -} - -static int64_t -get_max_diff_disk_usage (struct xlator_stats *max, struct xlator_stats *min) -{ - return (max->disk_usage - min->disk_usage); -} - -static int64_t -get_max_diff_disk_speed (struct xlator_stats *max, struct xlator_stats *min) -{ - return (max->disk_speed - min->disk_speed); -} - -static int64_t -get_max_diff_file_usage (struct xlator_stats *max, struct xlator_stats *min) -{ - return (max->nr_files - min->nr_files); -} - - -int -alu_parse_options (xlator_t *xl, struct alu_sched *alu_sched) -{ - data_t *order = dict_get (xl->options, "scheduler.alu.order"); - if (!order) { - gf_log (xl->name, GF_LOG_ERROR, - "option 'scheduler.alu.order' not specified"); - return -1; - } - struct alu_threshold *_threshold_fn; - struct alu_threshold *tmp_threshold; - data_t *entry_fn = NULL; - data_t *exit_fn = NULL; - char *tmp_str = NULL; - char *order_str = strtok_r (order->data, ":", &tmp_str); - /* Get the scheduling priority order, specified by the user. */ - while (order_str) { - gf_log ("alu", GF_LOG_DEBUG, - "alu_init: order string: %s", - order_str); - if (strcmp (order_str, "disk-usage") == 0) { - /* Disk usage */ - _threshold_fn = - GF_CALLOC (1, - sizeof (struct alu_threshold), - gf_alu_mt_alu_threshold); - ERR_ABORT (_threshold_fn); - _threshold_fn->diff_value = get_max_diff_disk_usage; - _threshold_fn->sched_value = get_stats_disk_usage; - entry_fn = - dict_get (xl->options, - "scheduler.alu.disk-usage.entry-threshold"); - if (entry_fn) { - if (gf_string2bytesize (entry_fn->data, - &alu_sched->entry_limit.disk_usage) != 0) { - gf_log (xl->name, GF_LOG_ERROR, - "invalid number format \"%s\" " - "of \"option scheduler.alu." - "disk-usage.entry-threshold\"", - entry_fn->data); - return -1; - } - } else { - alu_sched->entry_limit.disk_usage = ALU_DISK_USAGE_ENTRY_THRESHOLD_DEFAULT; - } - _threshold_fn->entry_value = get_stats_disk_usage; - exit_fn = dict_get (xl->options, - "scheduler.alu.disk-usage.exit-threshold"); - if (exit_fn) { - if (gf_string2bytesize (exit_fn->data, &alu_sched->exit_limit.disk_usage) != 0) { - gf_log (xl->name, GF_LOG_ERROR, - "invalid number format \"%s\" " - "of \"option scheduler.alu." - "disk-usage.exit-threshold\"", - exit_fn->data); - return -1; - } - } else { - alu_sched->exit_limit.disk_usage = ALU_DISK_USAGE_EXIT_THRESHOLD_DEFAULT; - } - _threshold_fn->exit_value = get_stats_disk_usage; - tmp_threshold = alu_sched->threshold_fn; - if (!tmp_threshold) { - alu_sched->threshold_fn = _threshold_fn; - } else { - while (tmp_threshold->next) { - tmp_threshold = tmp_threshold->next; - } - tmp_threshold->next = _threshold_fn; - } - gf_log ("alu", - GF_LOG_DEBUG, "alu_init: = %"PRId64",%"PRId64"", - alu_sched->entry_limit.disk_usage, - alu_sched->exit_limit.disk_usage); - - } else if (strcmp (order_str, "write-usage") == 0) { - /* Handle "write-usage" */ - - _threshold_fn = GF_CALLOC (1, sizeof (struct alu_threshold), gf_alu_mt_alu_threshold); - ERR_ABORT (_threshold_fn); - _threshold_fn->diff_value = get_max_diff_write_usage; - _threshold_fn->sched_value = get_stats_write_usage; - entry_fn = dict_get (xl->options, - "scheduler.alu.write-usage.entry-threshold"); - if (entry_fn) { - if (gf_string2bytesize (entry_fn->data, - &alu_sched->entry_limit.write_usage) != 0) { - gf_log (xl->name, GF_LOG_ERROR, - "invalid number format \"%s\" " - "of option scheduler.alu." - "write-usage.entry-threshold", - entry_fn->data); - return -1; - } - } else { - alu_sched->entry_limit.write_usage = ALU_WRITE_USAGE_ENTRY_THRESHOLD_DEFAULT; - } - _threshold_fn->entry_value = get_stats_write_usage; - exit_fn = dict_get (xl->options, - "scheduler.alu.write-usage.exit-threshold"); - if (exit_fn) { - if (gf_string2bytesize (exit_fn->data, - &alu_sched->exit_limit.write_usage) != 0) { - gf_log (xl->name, GF_LOG_ERROR, - "invalid number format \"%s\"" - " of \"option scheduler.alu." - "write-usage.exit-threshold\"", - exit_fn->data); - return -1; - } - } else { - alu_sched->exit_limit.write_usage = ALU_WRITE_USAGE_EXIT_THRESHOLD_DEFAULT; - } - _threshold_fn->exit_value = get_stats_write_usage; - tmp_threshold = alu_sched->threshold_fn; - if (!tmp_threshold) { - alu_sched->threshold_fn = _threshold_fn; - } else { - while (tmp_threshold->next) { - tmp_threshold = tmp_threshold->next; - } - tmp_threshold->next = _threshold_fn; - } - gf_log (xl->name, GF_LOG_DEBUG, - "alu_init: = %"PRId64",%"PRId64"", - alu_sched->entry_limit.write_usage, - alu_sched->exit_limit.write_usage); - - } else if (strcmp (order_str, "read-usage") == 0) { - /* Read usage */ - - _threshold_fn = GF_CALLOC (1, sizeof (struct alu_threshold), gf_alu_mt_alu_threshold); - ERR_ABORT (_threshold_fn); - _threshold_fn->diff_value = get_max_diff_read_usage; - _threshold_fn->sched_value = get_stats_read_usage; - entry_fn = dict_get (xl->options, - "scheduler.alu.read-usage.entry-threshold"); - if (entry_fn) { - if (gf_string2bytesize (entry_fn->data, - &alu_sched->entry_limit.read_usage) != 0) { - gf_log (xl->name, - GF_LOG_ERROR, - "invalid number format \"%s\" " - "of \"option scheduler.alu." - "read-usage.entry-threshold\"", - entry_fn->data); - return -1; - } - } else { - alu_sched->entry_limit.read_usage = ALU_READ_USAGE_ENTRY_THRESHOLD_DEFAULT; - } - _threshold_fn->entry_value = get_stats_read_usage; - exit_fn = dict_get (xl->options, - "scheduler.alu.read-usage.exit-threshold"); - if (exit_fn) - { - if (gf_string2bytesize (exit_fn->data, - &alu_sched->exit_limit.read_usage) != 0) - { - gf_log ("alu", GF_LOG_ERROR, - "invalid number format \"%s\" " - "of \"option scheduler.alu." - "read-usage.exit-threshold\"", - exit_fn->data); - return -1; - } - } - else - { - alu_sched->exit_limit.read_usage = ALU_READ_USAGE_EXIT_THRESHOLD_DEFAULT; - } - _threshold_fn->exit_value = get_stats_read_usage; - tmp_threshold = alu_sched->threshold_fn; - if (!tmp_threshold) { - alu_sched->threshold_fn = _threshold_fn; - } - else { - while (tmp_threshold->next) { - tmp_threshold = tmp_threshold->next; - } - tmp_threshold->next = _threshold_fn; - } - gf_log ("alu", GF_LOG_DEBUG, - "alu_init: = %"PRId64",%"PRId64"", - alu_sched->entry_limit.read_usage, - alu_sched->exit_limit.read_usage); - - } else if (strcmp (order_str, "open-files-usage") == 0) { - /* Open files counter */ - - _threshold_fn = GF_CALLOC (1, sizeof (struct alu_threshold), gf_alu_mt_alu_threshold); - ERR_ABORT (_threshold_fn); - _threshold_fn->diff_value = get_max_diff_file_usage; - _threshold_fn->sched_value = get_stats_file_usage; - entry_fn = dict_get (xl->options, - "scheduler.alu.open-files-usage.entry-threshold"); - if (entry_fn) { - if (gf_string2uint64 (entry_fn->data, - &alu_sched->entry_limit.nr_files) != 0) - { - gf_log ("alu", GF_LOG_ERROR, - "invalid number format \"%s\" " - "of \"option scheduler.alu." - "open-files-usage.entry-" - "threshold\"", entry_fn->data); - return -1; - } - } - else - { - alu_sched->entry_limit.nr_files = ALU_OPEN_FILES_USAGE_ENTRY_THRESHOLD_DEFAULT; - } - _threshold_fn->entry_value = get_stats_file_usage; - exit_fn = dict_get (xl->options, - "scheduler.alu.open-files-usage.exit-threshold"); - if (exit_fn) - { - if (gf_string2uint64 (exit_fn->data, - &alu_sched->exit_limit.nr_files) != 0) - { - gf_log ("alu", GF_LOG_ERROR, - "invalid number format \"%s\" " - "of \"option scheduler.alu." - "open-files-usage.exit-" - "threshold\"", exit_fn->data); - return -1; - } - } - else - { - alu_sched->exit_limit.nr_files = ALU_OPEN_FILES_USAGE_EXIT_THRESHOLD_DEFAULT; - } - _threshold_fn->exit_value = get_stats_file_usage; - tmp_threshold = alu_sched->threshold_fn; - if (!tmp_threshold) { - alu_sched->threshold_fn = _threshold_fn; - } - else { - while (tmp_threshold->next) { - tmp_threshold = tmp_threshold->next; - } - tmp_threshold->next = _threshold_fn; - } - gf_log ("alu", GF_LOG_DEBUG, - "alu.c->alu_init: = %"PRIu64",%"PRIu64"", - alu_sched->entry_limit.nr_files, - alu_sched->exit_limit.nr_files); - - } else if (strcmp (order_str, "disk-speed-usage") == 0) { - /* Disk speed */ - - _threshold_fn = GF_CALLOC (1, sizeof (struct alu_threshold), gf_alu_mt_alu_threshold); - ERR_ABORT (_threshold_fn); - _threshold_fn->diff_value = get_max_diff_disk_speed; - _threshold_fn->sched_value = get_stats_disk_speed; - entry_fn = dict_get (xl->options, - "scheduler.alu.disk-speed-usage.entry-threshold"); - if (entry_fn) { - gf_log ("alu", GF_LOG_DEBUG, - "entry-threshold is given, " - "value is constant"); - } - _threshold_fn->entry_value = NULL; - exit_fn = dict_get (xl->options, - "scheduler.alu.disk-speed-usage.exit-threshold"); - if (exit_fn) { - gf_log ("alu", GF_LOG_DEBUG, - "exit-threshold is given, " - "value is constant"); - } - _threshold_fn->exit_value = NULL; - tmp_threshold = alu_sched->threshold_fn; - if (!tmp_threshold) { - alu_sched->threshold_fn = _threshold_fn; - } - else { - while (tmp_threshold->next) { - tmp_threshold = tmp_threshold->next; - } - tmp_threshold->next = _threshold_fn; - } - - } else { - gf_log ("alu", GF_LOG_DEBUG, - "%s, unknown option provided to scheduler", - order_str); - } - order_str = strtok_r (NULL, ":", &tmp_str); - } - - return 0; -} - -static int32_t -alu_init (xlator_t *xl) -{ - struct alu_sched *alu_sched = NULL; - struct alu_limits *_limit_fn = NULL; - struct alu_limits *tmp_limits = NULL; - uint32_t min_free_disk = 0; - data_t *limits = NULL; - - alu_sched = GF_CALLOC (1, sizeof (struct alu_sched), - gf_alu_mt_alu_sched); - ERR_ABORT (alu_sched); - - { - alu_parse_options (xl, alu_sched); - } - - /* Get the limits */ - - limits = dict_get (xl->options, - "scheduler.limits.min-free-disk"); - if (limits) { - _limit_fn = GF_CALLOC (1, sizeof (struct alu_limits), - gf_alu_mt_alu_limits); - ERR_ABORT (_limit_fn); - _limit_fn->min_value = get_stats_free_disk; - _limit_fn->cur_value = get_stats_free_disk; - tmp_limits = alu_sched->limits_fn ; - _limit_fn->next = tmp_limits; - alu_sched->limits_fn = _limit_fn; - - if (gf_string2percent (limits->data, - &min_free_disk) != 0) { - gf_log ("alu", GF_LOG_ERROR, - "invalid number format \"%s\" " - "of \"option scheduler.limits." - "min-free-disk\"", limits->data); - return -1; - } - alu_sched->spec_limit.free_disk = min_free_disk; - - if (alu_sched->spec_limit.free_disk >= 100) { - gf_log ("alu", GF_LOG_ERROR, - "check the \"option scheduler." - "limits.min-free-disk\", it should " - "be percentage value"); - return -1; - } - alu_sched->spec_limit.total_disk_size = ALU_LIMITS_TOTAL_DISK_SIZE_DEFAULT; /* Its in % */ - gf_log ("alu", GF_LOG_DEBUG, - "alu.limit.min-disk-free = %"PRId64"", - _limit_fn->cur_value (&(alu_sched->spec_limit))); - } - - limits = dict_get (xl->options, - "scheduler.limits.max-open-files"); - if (limits) { - // Update alu_sched->priority properly - _limit_fn = GF_CALLOC (1, sizeof (struct alu_limits), - gf_alu_mt_alu_limits); - ERR_ABORT (_limit_fn); - _limit_fn->max_value = get_stats_file_usage; - _limit_fn->cur_value = get_stats_file_usage; - tmp_limits = alu_sched->limits_fn ; - _limit_fn->next = tmp_limits; - alu_sched->limits_fn = _limit_fn; - if (gf_string2uint64_base10 (limits->data, - &alu_sched->spec_limit.nr_files) != 0) - { - gf_log ("alu", GF_LOG_ERROR, - "invalid number format '%s' of option " - "scheduler.limits.max-open-files", - limits->data); - return -1; - } - - gf_log ("alu", GF_LOG_DEBUG, - "alu_init: limit.max-open-files = %"PRId64"", - _limit_fn->cur_value (&(alu_sched->spec_limit))); - } - - - /* Stats refresh options */ - limits = dict_get (xl->options, - "scheduler.refresh-interval"); - if (limits) { - if (gf_string2time (limits->data, - &alu_sched->refresh_interval) != 0) { - gf_log ("alu", GF_LOG_ERROR, - "invalid number format \"%s\" of " - "option scheduler.refresh-interval", - limits->data); - return -1; - } - } else { - alu_sched->refresh_interval = ALU_REFRESH_INTERVAL_DEFAULT; - } - gettimeofday (&(alu_sched->last_stat_fetch), NULL); - - - limits = dict_get (xl->options, - "scheduler.alu.stat-refresh.num-file-create"); - if (limits) { - if (gf_string2uint32 (limits->data, - &alu_sched->refresh_create_count) != 0) - { - gf_log ("alu", GF_LOG_ERROR, - "invalid number format \"%s\" of \"option " - "alu.stat-refresh.num-file-create\"", - limits->data); - return -1; - } - } else { - alu_sched->refresh_create_count = ALU_REFRESH_CREATE_COUNT_DEFAULT; - } - - { - /* Build an array of child_nodes */ - struct alu_sched_struct *sched_array = NULL; - xlator_list_t *trav_xl = xl->children; - data_t *data = NULL; - int32_t index = 0; - - while (trav_xl) { - index++; - trav_xl = trav_xl->next; - } - alu_sched->child_count = index; - sched_array = GF_CALLOC (index, sizeof (struct alu_sched_struct), gf_alu_mt_alu_sched_struct); - ERR_ABORT (sched_array); - trav_xl = xl->children; - index = 0; - while (trav_xl) { - sched_array[index].xl = trav_xl->xlator; - sched_array[index].eligible = 1; - index++; - trav_xl = trav_xl->next; - } - alu_sched->array = sched_array; - - data = dict_get (xl->options, - "scheduler.read-only-subvolumes"); - if (data) { - char *child = NULL; - char *tmp = NULL; - char *childs_data = gf_strdup (data->data); - - child = strtok_r (childs_data, ",", &tmp); - while (child) { - for (index = 1; index < alu_sched->child_count; index++) { - if (strcmp (alu_sched->array[index -1].xl->name, child) == 0) { - memcpy (&(alu_sched->array[index -1]), - &(alu_sched->array[alu_sched->child_count -1]), - sizeof (struct alu_sched_struct)); - alu_sched->child_count--; - break; - } - } - child = strtok_r (NULL, ",", &tmp); - } - } - } - - *((long *)xl->private) = (long)alu_sched; - - /* Initialize all the alu_sched structure's elements */ - { - alu_sched->sched_nodes_pending = 0; - - alu_sched->min_limit.free_disk = 0x00FFFFFF; - alu_sched->min_limit.disk_usage = 0xFFFFFFFF; - alu_sched->min_limit.total_disk_size = 0xFFFFFFFF; - alu_sched->min_limit.disk_speed = 0xFFFFFFFF; - alu_sched->min_limit.write_usage = 0xFFFFFFFF; - alu_sched->min_limit.read_usage = 0xFFFFFFFF; - alu_sched->min_limit.nr_files = 0xFFFFFFFF; - alu_sched->min_limit.nr_clients = 0xFFFFFFFF; - } - - pthread_mutex_init (&alu_sched->alu_mutex, NULL); - return 0; -} - -static void -alu_fini (xlator_t *xl) -{ - if (!xl) - return; - struct alu_sched *alu_sched = (struct alu_sched *)*((long *)xl->private); - struct alu_limits *limit = alu_sched->limits_fn; - struct alu_threshold *threshold = alu_sched->threshold_fn; - void *tmp = NULL; - pthread_mutex_destroy (&alu_sched->alu_mutex); - GF_FREE (alu_sched->array); - while (limit) { - tmp = limit; - limit = limit->next; - GF_FREE (tmp); - } - while (threshold) { - tmp = threshold; - threshold = threshold->next; - GF_FREE (tmp); - } - GF_FREE (alu_sched); -} - -static int32_t -update_stat_array_cbk (call_frame_t *frame, - void *cookie, - xlator_t *xl, - int32_t op_ret, - int32_t op_errno, - struct xlator_stats *trav_stats) -{ - struct alu_sched *alu_sched = (struct alu_sched *)*((long *)xl->private); - struct alu_limits *limits_fn = alu_sched->limits_fn; - int32_t idx = 0; - - pthread_mutex_lock (&alu_sched->alu_mutex); - for (idx = 0; idx < alu_sched->child_count; idx++) { - if (alu_sched->array[idx].xl == (xlator_t *)cookie) - break; - } - pthread_mutex_unlock (&alu_sched->alu_mutex); - - if (op_ret == -1) { - alu_sched->array[idx].eligible = 0; - } else { - memcpy (&(alu_sched->array[idx].stats), trav_stats, sizeof (struct xlator_stats)); - - /* Get stats from all the child node */ - /* Here check the limits specified by the user to - consider the nodes to be used by scheduler */ - alu_sched->array[idx].eligible = 1; - limits_fn = alu_sched->limits_fn; - while (limits_fn){ - if (limits_fn->max_value && - (limits_fn->cur_value (trav_stats) > - limits_fn->max_value (&(alu_sched->spec_limit)))) { - alu_sched->array[idx].eligible = 0; - } - if (limits_fn->min_value && - (limits_fn->cur_value (trav_stats) < - limits_fn->min_value (&(alu_sched->spec_limit)))) { - alu_sched->array[idx].eligible = 0; - } - limits_fn = limits_fn->next; - } - - /* Select minimum and maximum disk_usage */ - if (trav_stats->disk_usage > alu_sched->max_limit.disk_usage) { - alu_sched->max_limit.disk_usage = trav_stats->disk_usage; - } - if (trav_stats->disk_usage < alu_sched->min_limit.disk_usage) { - alu_sched->min_limit.disk_usage = trav_stats->disk_usage; - } - - /* Select minimum and maximum disk_speed */ - if (trav_stats->disk_speed > alu_sched->max_limit.disk_speed) { - alu_sched->max_limit.disk_speed = trav_stats->disk_speed; - } - if (trav_stats->disk_speed < alu_sched->min_limit.disk_speed) { - alu_sched->min_limit.disk_speed = trav_stats->disk_speed; - } - - /* Select minimum and maximum number of open files */ - if (trav_stats->nr_files > alu_sched->max_limit.nr_files) { - alu_sched->max_limit.nr_files = trav_stats->nr_files; - } - if (trav_stats->nr_files < alu_sched->min_limit.nr_files) { - alu_sched->min_limit.nr_files = trav_stats->nr_files; - } - - /* Select minimum and maximum write-usage */ - if (trav_stats->write_usage > alu_sched->max_limit.write_usage) { - alu_sched->max_limit.write_usage = trav_stats->write_usage; - } - if (trav_stats->write_usage < alu_sched->min_limit.write_usage) { - alu_sched->min_limit.write_usage = trav_stats->write_usage; - } - - /* Select minimum and maximum read-usage */ - if (trav_stats->read_usage > alu_sched->max_limit.read_usage) { - alu_sched->max_limit.read_usage = trav_stats->read_usage; - } - if (trav_stats->read_usage < alu_sched->min_limit.read_usage) { - alu_sched->min_limit.read_usage = trav_stats->read_usage; - } - - /* Select minimum and maximum free-disk */ - if (trav_stats->free_disk > alu_sched->max_limit.free_disk) { - alu_sched->max_limit.free_disk = trav_stats->free_disk; - } - if (trav_stats->free_disk < alu_sched->min_limit.free_disk) { - alu_sched->min_limit.free_disk = trav_stats->free_disk; - } - } - - STACK_DESTROY (frame->root); - - return 0; -} - -static void -update_stat_array (xlator_t *xl) -{ - /* This function schedules the file in one of the child nodes */ - struct alu_sched *alu_sched = (struct alu_sched *)*((long *)xl->private); - int32_t idx = 0; - call_frame_t *frame = NULL; - call_pool_t *pool = xl->ctx->pool; - - for (idx = 0 ; idx < alu_sched->child_count; idx++) { - frame = create_frame (xl, pool); - - STACK_WIND_COOKIE (frame, - update_stat_array_cbk, - alu_sched->array[idx].xl, //cookie - alu_sched->array[idx].xl, - (alu_sched->array[idx].xl)->mops->stats, - 0); //flag - } - return; -} - -static void -alu_update (xlator_t *xl) -{ - struct timeval tv; - struct alu_sched *alu_sched = (struct alu_sched *)*((long *)xl->private); - - gettimeofday (&tv, NULL); - if (tv.tv_sec > (alu_sched->refresh_interval + alu_sched->last_stat_fetch.tv_sec)) { - /* Update the stats from all the server */ - update_stat_array (xl); - alu_sched->last_stat_fetch.tv_sec = tv.tv_sec; - } -} - -static xlator_t * -alu_scheduler (xlator_t *xl, const void *path) -{ - /* This function schedules the file in one of the child nodes */ - struct alu_sched *alu_sched = (struct alu_sched *)*((long *)xl->private); - int32_t sched_index = 0; - int32_t sched_index_orig = 0; - int32_t idx = 0; - - alu_update (xl); - - /* Now check each threshold one by one if some nodes are classified */ - { - struct alu_threshold *trav_threshold = alu_sched->threshold_fn; - struct alu_threshold *tmp_threshold = alu_sched->sched_method; - struct alu_sched_node *tmp_sched_node; - - /* This pointer 'trav_threshold' contains function pointers according to spec file - give by user, */ - while (trav_threshold) { - /* This check is needed for seeing if already there are nodes in this criteria - to be scheduled */ - if (!alu_sched->sched_nodes_pending) { - for (idx = 0; idx < alu_sched->child_count; idx++) { - if (!alu_sched->array[idx].eligible) { - continue; - } - if (trav_threshold->entry_value) { - if (trav_threshold->diff_value (&(alu_sched->max_limit), - &(alu_sched->array[idx].stats)) < - trav_threshold->entry_value (&(alu_sched->entry_limit))) { - continue; - } - } - tmp_sched_node = GF_CALLOC (1, sizeof (struct alu_sched_node), gf_alu_mt_alu_sched_node); - ERR_ABORT (tmp_sched_node); - tmp_sched_node->index = idx; - if (!alu_sched->sched_node) { - alu_sched->sched_node = tmp_sched_node; - } else { - pthread_mutex_lock (&alu_sched->alu_mutex); - tmp_sched_node->next = alu_sched->sched_node; - alu_sched->sched_node = tmp_sched_node; - pthread_mutex_unlock (&alu_sched->alu_mutex); - } - alu_sched->sched_nodes_pending++; - } - } /* end of if (sched_nodes_pending) */ - - /* This loop is required to check the eligible nodes */ - struct alu_sched_node *trav_sched_node; - while (alu_sched->sched_nodes_pending) { - trav_sched_node = alu_sched->sched_node; - sched_index = trav_sched_node->index; - if (alu_sched->array[sched_index].eligible) - break; - alu_sched->sched_node = trav_sched_node->next; - GF_FREE (trav_sched_node); - alu_sched->sched_nodes_pending--; - } - if (alu_sched->sched_nodes_pending) { - /* There are some node in this criteria to be scheduled, no need - * to sort and check other methods - */ - if (tmp_threshold && tmp_threshold->exit_value) { - /* verify the exit value && whether node is eligible or not */ - if (tmp_threshold->diff_value (&(alu_sched->max_limit), - &(alu_sched->array[sched_index].stats)) > - tmp_threshold->exit_value (&(alu_sched->exit_limit))) { - /* Free the allocated info for the node :) */ - pthread_mutex_lock (&alu_sched->alu_mutex); - alu_sched->sched_node = trav_sched_node->next; - GF_FREE (trav_sched_node); - trav_sched_node = alu_sched->sched_node; - alu_sched->sched_nodes_pending--; - pthread_mutex_unlock (&alu_sched->alu_mutex); - } - } else { - /* if there is no exit value, then exit after scheduling once */ - pthread_mutex_lock (&alu_sched->alu_mutex); - alu_sched->sched_node = trav_sched_node->next; - GF_FREE (trav_sched_node); - trav_sched_node = alu_sched->sched_node; - alu_sched->sched_nodes_pending--; - pthread_mutex_unlock (&alu_sched->alu_mutex); - } - - alu_sched->sched_method = tmp_threshold; /* this is the method used for selecting */ - - /* */ - if (trav_sched_node) { - tmp_sched_node = trav_sched_node; - while (trav_sched_node->next) { - trav_sched_node = trav_sched_node->next; - } - if (tmp_sched_node->next) { - pthread_mutex_lock (&alu_sched->alu_mutex); - alu_sched->sched_node = tmp_sched_node->next; - tmp_sched_node->next = NULL; - trav_sched_node->next = tmp_sched_node; - pthread_mutex_unlock (&alu_sched->alu_mutex); - } - } - /* return the scheduled node */ - return alu_sched->array[sched_index].xl; - } /* end of if (pending_nodes) */ - - tmp_threshold = trav_threshold; - trav_threshold = trav_threshold->next; - } - } - - /* This is used only when there is everything seems ok, or no eligible nodes */ - sched_index_orig = alu_sched->sched_index; - alu_sched->sched_method = NULL; - while (1) { - //lock - pthread_mutex_lock (&alu_sched->alu_mutex); - sched_index = alu_sched->sched_index++; - alu_sched->sched_index = alu_sched->sched_index % alu_sched->child_count; - pthread_mutex_unlock (&alu_sched->alu_mutex); - //unlock - if (alu_sched->array[sched_index].eligible) - break; - if (sched_index_orig == (sched_index + 1) % alu_sched->child_count) { - gf_log ("alu", GF_LOG_WARNING, "No node is eligible to schedule"); - //lock - pthread_mutex_lock (&alu_sched->alu_mutex); - alu_sched->sched_index++; - alu_sched->sched_index = alu_sched->sched_index % alu_sched->child_count; - pthread_mutex_unlock (&alu_sched->alu_mutex); - //unlock - break; - } - } - return alu_sched->array[sched_index].xl; -} - -/** - * notify - */ -void -alu_notify (xlator_t *xl, int32_t event, void *data) -{ - struct alu_sched *alu_sched = NULL; - int32_t idx = 0; - - alu_sched = (struct alu_sched *)*((long *)xl->private); - if (!alu_sched) - return; - - for (idx = 0; idx < alu_sched->child_count; idx++) { - if (alu_sched->array[idx].xl == (xlator_t *)data) - break; - } - - switch (event) - { - case GF_EVENT_CHILD_UP: - { - //alu_sched->array[idx].eligible = 1; - } - break; - case GF_EVENT_CHILD_DOWN: - { - alu_sched->array[idx].eligible = 0; - } - break; - default: - { - ; - } - break; - } - -} - -int32_t -alu_mem_acct_init (xlator_t *this) -{ - int ret = -1; - - if (!this) - return ret; - - ret = xlator_mem_acct_init (this, gf_alu_mt_end + 1); - - if (ret != 0) { - gf_log (this->name, GF_LOG_ERROR, "Memory accounting init" - "failed"); - return ret; - } - - return ret; -} - -struct sched_ops sched = { - .init = alu_init, - .fini = alu_fini, - .update = alu_update, - .schedule = alu_scheduler, - .notify = alu_notify, - .mem_acct_init = alu_mem_acct_init, -}; - -struct volume_options options[] = { - { .key = { "scheduler.alu.order", "alu.order" }, - .type = GF_OPTION_TYPE_ANY - }, - { .key = { "scheduler.alu.disk-usage.entry-threshold", - "alu.disk-usage.entry-threshold" }, - .type = GF_OPTION_TYPE_SIZET - }, - { .key = { "scheduler.alu.disk-usage.exit-threshold", - "alu.disk-usage.exit-threshold" }, - .type = GF_OPTION_TYPE_SIZET - }, - { .key = { "scheduler.alu.write-usage.entry-threshold", - "alu.write-usage.entry-threshold" }, - .type = GF_OPTION_TYPE_SIZET - }, - { .key = { "scheduler.alu.write-usage.exit-threshold", - "alu.write-usage.exit-threshold" }, - .type = GF_OPTION_TYPE_SIZET - }, - { .key = { "scheduler.alu.read-usage.entry-threshold", - "alu.read-usage.entry-threshold" }, - .type = GF_OPTION_TYPE_SIZET - }, - { .key = { "scheduler.alu.read-usage.exit-threshold", - "alu.read-usage.exit-threshold" }, - .type = GF_OPTION_TYPE_SIZET - }, - { .key = { "scheduler.alu.open-files-usage.entry-threshold", - "alu.open-files-usage.entry-threshold" }, - .type = GF_OPTION_TYPE_INT - }, - { .key = { "scheduler.alu.open-files-usage.exit-threshold", - "alu.open-files-usage.exit-threshold" }, - .type = GF_OPTION_TYPE_INT - }, - { .key = { "scheduler.read-only-subvolumes", - "alu.read-only-subvolumes" }, - .type = GF_OPTION_TYPE_ANY - }, - { .key = { "scheduler.refresh-interval", - "alu.refresh-interval", - "alu.stat-refresh.interval" }, - .type = GF_OPTION_TYPE_TIME - }, - { .key = { "scheduler.limits.min-free-disk", - "alu.limits.min-free-disk" }, - .type = GF_OPTION_TYPE_PERCENT - }, - { .key = { "scheduler.alu.stat-refresh.num-file-create" - "alu.stat-refresh.num-file-create"}, - .type = GF_OPTION_TYPE_INT - }, - { .key = {NULL}, } -}; diff --git a/scheduler/alu/src/alu.h b/scheduler/alu/src/alu.h deleted file mode 100644 index c716ad8e5e7..00000000000 --- a/scheduler/alu/src/alu.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.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 _ALU_H -#define _ALU_H - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include "scheduler.h" - -struct alu_sched; - -struct alu_sched_struct { - xlator_t *xl; - struct xlator_stats stats; - unsigned char eligible; -}; - -// Write better name for these functions -struct alu_limits { - struct alu_limits *next; - int64_t (*max_value) (struct xlator_stats *); /* Max limit, specified by the user */ - int64_t (*min_value) (struct xlator_stats *); /* Min limit, specified by the user */ - int64_t (*cur_value) (struct xlator_stats *); /* Current values of variables got from stats call */ -}; - -struct alu_threshold { - struct alu_threshold *next; - int64_t (*diff_value) (struct xlator_stats *max, struct xlator_stats *min); /* Diff b/w max and min */ - int64_t (*entry_value) (struct xlator_stats *); /* Limit specified user */ - int64_t (*exit_value) (struct xlator_stats *); /* Exit point for the limit */ - int64_t (*sched_value) (struct xlator_stats *); /* This will return the index of the child area */ -}; - -struct alu_sched_node { - struct alu_sched_node *next; - int32_t index; -}; - -struct alu_sched { - struct alu_limits *limits_fn; - struct alu_threshold *threshold_fn; - struct alu_sched_struct *array; - struct alu_sched_node *sched_node; - struct alu_threshold *sched_method; - struct xlator_stats max_limit; - struct xlator_stats min_limit; - struct xlator_stats entry_limit; - struct xlator_stats exit_limit; - struct xlator_stats spec_limit; /* User given limit */ - - pthread_mutex_t alu_mutex; - struct timeval last_stat_fetch; - uint32_t refresh_interval; /* in seconds */ - uint32_t refresh_create_count; /* num-file-create */ - - int32_t sched_nodes_pending; - - int32_t sched_index; /* used for round robin scheduling in case of many nodes getting the criteria match. */ - int32_t child_count; - -}; - -struct _alu_local_t { - int32_t call_count; -}; - -typedef struct _alu_local_t alu_local_t; - -#endif /* _ALU_H */ diff --git a/scheduler/nufa/Makefile.am b/scheduler/nufa/Makefile.am deleted file mode 100644 index d471a3f9243..00000000000 --- a/scheduler/nufa/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -SUBDIRS = src - -CLEANFILES = diff --git a/scheduler/nufa/src/Makefile.am b/scheduler/nufa/src/Makefile.am deleted file mode 100644 index 6eb3d39f1e2..00000000000 --- a/scheduler/nufa/src/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -sched_LTLIBRARIES = nufa.la -scheddir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/scheduler - -nufa_la_LDFLAGS = -module -avoidversion - -nufa_la_SOURCES = nufa.c -nufa_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la - -AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS)\ - -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS) - -CLEANFILES = diff --git a/scheduler/nufa/src/nufa-mem-types.h b/scheduler/nufa/src/nufa-mem-types.h deleted file mode 100644 index 945dafa7c31..00000000000 --- a/scheduler/nufa/src/nufa-mem-types.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.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 __NUFA_MEM_TYPES_H__ -#define __NUFA_MEM_TYPES_H__ - -#include "mem-types.h" - -enum gf_locks_mem_types_ { - gf_nufa_mt_nufa_struct = gf_common_mt_end + 1, - gf_nufa_mt_nufa_sched_struct, - gf_nufa_mt_int32_t, - gf_nufa_mt_end -}; -#endif - diff --git a/scheduler/nufa/src/nufa.c b/scheduler/nufa/src/nufa.c deleted file mode 100644 index 1bf477bdc2c..00000000000 --- a/scheduler/nufa/src/nufa.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.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 _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include <sys/time.h> - -#include "scheduler.h" -#include "common-utils.h" -#include "nufa-mem-types.h" - -struct nufa_sched_struct { - xlator_t *xl; - struct timeval last_stat_fetch; - int64_t free_disk; - int32_t refresh_interval; - unsigned char eligible; -}; - -struct nufa_struct { - struct nufa_sched_struct *array; - struct timeval last_stat_fetch; - - int32_t *local_array; /* Used to keep the index of the local xlators */ - int32_t local_xl_index; /* index in the above array */ - int32_t local_xl_count; /* Count of the local subvolumes */ - - uint32_t refresh_interval; - uint32_t min_free_disk; - - gf_lock_t nufa_lock; - int32_t child_count; - int32_t sched_index; -}; - -#define NUFA_LIMITS_MIN_FREE_DISK_DEFAULT 15 -#define NUFA_REFRESH_INTERVAL_DEFAULT 30 - -static int32_t -nufa_init (xlator_t *xl) -{ - int32_t index = 0; - data_t *local_name = NULL; - data_t *data = NULL; - xlator_list_t *trav_xl = xl->children; - struct nufa_struct *nufa_buf = NULL; - - nufa_buf = GF_CALLOC (1, sizeof (struct nufa_struct), - gf_nufa_mt_nufa_struct); - ERR_ABORT (nufa_buf); - - data = dict_get (xl->options, "scheduler.limits.min-free-disk"); - if (data) { - if (gf_string2percent (data->data, - &nufa_buf->min_free_disk) != 0) { - gf_log ("nufa", GF_LOG_ERROR, - "invalid number format \"%s\" of " - "\"option scheduler.limits.min-free-disk\"", - data->data); - return -1; - } - if (nufa_buf->min_free_disk >= 100) { - gf_log ("nufa", GF_LOG_ERROR, - "check \"option scheduler.limits.min-free-disk" - "\", it should be percentage value"); - return -1; - } - } else { - gf_log ("nufa", GF_LOG_WARNING, - "No option for limit min-free-disk given, " - "defaulting it to 15%%"); - nufa_buf->min_free_disk = NUFA_LIMITS_MIN_FREE_DISK_DEFAULT; - } - data = dict_get (xl->options, "scheduler.refresh-interval"); - if (data != NULL) { - if (gf_string2time (data->data, - &nufa_buf->refresh_interval) != 0) { - gf_log ("nufa", GF_LOG_ERROR, - "invalid number format \"%s\" of " - "\"option scheduler.refresh-interval\"", - data->data); - return -1; - } - } else { - gf_log ("nufa", GF_LOG_WARNING, - "No option for scheduler.refresh-interval given, " - "defaulting it to 30"); - nufa_buf->refresh_interval = NUFA_REFRESH_INTERVAL_DEFAULT; - } - - /* Get the array built */ - while (trav_xl) { - index++; - trav_xl = trav_xl->next; - } - nufa_buf->child_count = index; - nufa_buf->sched_index = 0; - nufa_buf->array = GF_CALLOC (index, sizeof (struct nufa_sched_struct), - gf_nufa_mt_nufa_sched_struct); - ERR_ABORT (nufa_buf->array); - nufa_buf->local_array = GF_CALLOC (index, sizeof (int32_t), - gf_nufa_mt_int32_t); - ERR_ABORT (nufa_buf->array); - trav_xl = xl->children; - - local_name = dict_get (xl->options, "scheduler.local-volume-name"); - if (!local_name) { - /* Error */ - gf_log ("nufa", GF_LOG_ERROR, - "No 'local-volume-name' option given in volume file"); - GF_FREE (nufa_buf->array); - GF_FREE (nufa_buf->local_array); - GF_FREE (nufa_buf); - return -1; - } - - /* Get the array properly */ - index = 0; - trav_xl = xl->children; - while (trav_xl) { - nufa_buf->array[index].xl = trav_xl->xlator; - nufa_buf->array[index].eligible = 1; - nufa_buf->array[index].free_disk = nufa_buf->min_free_disk; - nufa_buf->array[index].refresh_interval = - nufa_buf->refresh_interval; - - trav_xl = trav_xl->next; - index++; - } - - { - int32_t array_index = 0; - char *child = NULL; - char *tmp = NULL; - char *childs_data = gf_strdup (local_name->data); - - child = strtok_r (childs_data, ",", &tmp); - while (child) { - /* Check if the local_volume specified is proper - subvolume of unify */ - trav_xl = xl->children; - index=0; - while (trav_xl) { - if (strcmp (child, trav_xl->xlator->name) == 0) - break; - trav_xl = trav_xl->next; - index++; - } - - if (!trav_xl) { - /* entry for 'local-volume-name' is wrong, - not present in subvolumes */ - gf_log ("nufa", GF_LOG_ERROR, - "option 'scheduler.local-volume-name' " - "%s is wrong", child); - GF_FREE (nufa_buf->array); - GF_FREE (nufa_buf->local_array); - GF_FREE (nufa_buf); - return -1; - } else { - nufa_buf->local_array[array_index++] = index; - nufa_buf->local_xl_count++; - } - child = strtok_r (NULL, ",", &tmp); - } - GF_FREE (childs_data); - } - - LOCK_INIT (&nufa_buf->nufa_lock); - *((long *)xl->private) = (long)nufa_buf; // put it at the proper place - return 0; -} - -static void -nufa_fini (xlator_t *xl) -{ - struct nufa_struct *nufa_buf = - (struct nufa_struct *)*((long *)xl->private); - - LOCK_DESTROY (&nufa_buf->nufa_lock); - GF_FREE (nufa_buf->local_array); - GF_FREE (nufa_buf->array); - GF_FREE (nufa_buf); -} - -static int32_t -update_stat_array_cbk (call_frame_t *frame, - void *cookie, - xlator_t *xl, - int32_t op_ret, - int32_t op_errno, - struct xlator_stats *trav_stats) -{ - struct nufa_struct *nufa_struct = NULL; - int32_t idx = 0; - int32_t percent = 0; - - nufa_struct = (struct nufa_struct *)*((long *)xl->private); - LOCK (&nufa_struct->nufa_lock); - for (idx = 0; idx < nufa_struct->child_count; idx++) { - if (nufa_struct->array[idx].xl->name == (char *)cookie) - break; - } - UNLOCK (&nufa_struct->nufa_lock); - - if (op_ret == 0) { - percent = ((trav_stats->free_disk * 100) / - trav_stats->total_disk_size); - if (nufa_struct->array[idx].free_disk > percent) { - if (nufa_struct->array[idx].eligible) - gf_log ("nufa", GF_LOG_CRITICAL, - "node \"%s\" is _almost_ (%d %%) full", - nufa_struct->array[idx].xl->name, - 100 - percent); - nufa_struct->array[idx].eligible = 0; - } else { - nufa_struct->array[idx].eligible = 1; - } - } else { - nufa_struct->array[idx].eligible = 0; - } - - STACK_DESTROY (frame->root); - return 0; -} - -static void -update_stat_array (xlator_t *xl) -{ - /* This function schedules the file in one of the child nodes */ - int32_t idx; - struct nufa_struct *nufa_buf = - (struct nufa_struct *)*((long *)xl->private); - call_frame_t *frame = NULL; - call_pool_t *pool = xl->ctx->pool; - - for (idx = 0; idx < nufa_buf->child_count; idx++) { - frame = create_frame (xl, pool); - - STACK_WIND_COOKIE (frame, - update_stat_array_cbk, - nufa_buf->array[idx].xl->name, - nufa_buf->array[idx].xl, - (nufa_buf->array[idx].xl)->mops->stats, - 0); //flag - } - - return; -} - -static void -nufa_update (xlator_t *xl) -{ - struct nufa_struct *nufa_buf = - (struct nufa_struct *)*((long *)xl->private); - struct timeval tv; - gettimeofday (&tv, NULL); - if (tv.tv_sec > (nufa_buf->refresh_interval - + nufa_buf->last_stat_fetch.tv_sec)) { - /* Update the stats from all the server */ - update_stat_array (xl); - nufa_buf->last_stat_fetch.tv_sec = tv.tv_sec; - } -} - -static xlator_t * -nufa_schedule (xlator_t *xl, const void *path) -{ - struct nufa_struct *nufa_buf = - (struct nufa_struct *)*((long *)xl->private); - int32_t nufa_orig = nufa_buf->local_xl_index; - int32_t rr; - - nufa_update (xl); - - while (1) { - LOCK (&nufa_buf->nufa_lock); - rr = nufa_buf->local_xl_index++; - nufa_buf->local_xl_index %= nufa_buf->local_xl_count; - UNLOCK (&nufa_buf->nufa_lock); - - /* if 'eligible' or there are _no_ eligible nodes */ - if (nufa_buf->array[nufa_buf->local_array[rr]].eligible) { - /* Return the local node */ - return nufa_buf->array[nufa_buf->local_array[rr]].xl; - } - if ((rr + 1) % nufa_buf->local_xl_count == nufa_orig) { - gf_log ("nufa", GF_LOG_CRITICAL, - "No free space available on any local " - "volumes, using RR scheduler"); - LOCK (&nufa_buf->nufa_lock); - nufa_buf->local_xl_index++; - nufa_buf->local_xl_index %= nufa_buf->local_xl_count; - UNLOCK (&nufa_buf->nufa_lock); - break; - } - } - - nufa_orig = nufa_buf->sched_index; - while (1) { - LOCK (&nufa_buf->nufa_lock); - rr = nufa_buf->sched_index++; - nufa_buf->sched_index = (nufa_buf->sched_index % - nufa_buf->child_count); - UNLOCK (&nufa_buf->nufa_lock); - - /* if 'eligible' or there are _no_ eligible nodes */ - if (nufa_buf->array[rr].eligible) { - break; - } - if ((rr + 1) % nufa_buf->child_count == nufa_orig) { - gf_log ("nufa", GF_LOG_CRITICAL, - "No free space available on any server, " - "using RR scheduler."); - LOCK (&nufa_buf->nufa_lock); - nufa_buf->sched_index++; - nufa_buf->sched_index = (nufa_buf->sched_index % - nufa_buf->child_count); - UNLOCK (&nufa_buf->nufa_lock); - break; - } - } - return nufa_buf->array[rr].xl; -} - - -/** - * notify - */ -void -nufa_notify (xlator_t *xl, int32_t event, void *data) -{ - struct nufa_struct *nufa_buf = - (struct nufa_struct *)*((long *)xl->private); - int32_t idx = 0; - - if (!nufa_buf) - return; - - for (idx = 0; idx < nufa_buf->child_count; idx++) { - if (strcmp (nufa_buf->array[idx].xl->name, - ((xlator_t *)data)->name) == 0) - break; - } - - switch (event) - { - case GF_EVENT_CHILD_UP: - { - //nufa_buf->array[idx].eligible = 1; - } - break; - case GF_EVENT_CHILD_DOWN: - { - nufa_buf->array[idx].eligible = 0; - } - break; - default: - { - ; - } - break; - } - -} - -int32_t -nufa_mem_acct_init (xlator_t *this) -{ - int ret = -1; - - if (!this) - return ret; - - ret = xlator_mem_acct_init (this, gf_nufa_mt_end + 1); - - if (ret != 0) { - gf_log (this->name, GF_LOG_ERROR, "Memory accounting init" - "failed"); - return ret; - } - - return ret; -} - -struct sched_ops sched = { - .init = nufa_init, - .fini = nufa_fini, - .update = nufa_update, - .schedule = nufa_schedule, - .notify = nufa_notify, - .mem_acct_init = nufa_mem_acct_init, -}; - -struct volume_options options[] = { - { .key = { "scheduler.refresh-interval", - "nufa.refresh-interval" }, - .type = GF_OPTION_TYPE_TIME - }, - { .key = { "scheduler.limits.min-free-disk", - "nufa.limits.min-free-disk" }, - .type = GF_OPTION_TYPE_PERCENT - }, - { .key = { "scheduler.local-volume-name", - "nufa.local-volume-name" }, - .type = GF_OPTION_TYPE_XLATOR - }, - { .key = {NULL} } -}; - diff --git a/scheduler/random/Makefile.am b/scheduler/random/Makefile.am deleted file mode 100644 index d471a3f9243..00000000000 --- a/scheduler/random/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -SUBDIRS = src - -CLEANFILES = diff --git a/scheduler/random/src/Makefile.am b/scheduler/random/src/Makefile.am deleted file mode 100644 index 572181336c2..00000000000 --- a/scheduler/random/src/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -sched_LTLIBRARIES = random.la -scheddir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/scheduler - -random_la_LDFLAGS = -module -avoidversion - -random_la_SOURCES = random.c -random_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la - -noinst_HEADERS = random.h - -AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS)\ - -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS) - -CLEANFILES = diff --git a/scheduler/random/src/random-mem-types.h b/scheduler/random/src/random-mem-types.h deleted file mode 100644 index ff30d9244fc..00000000000 --- a/scheduler/random/src/random-mem-types.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.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 __RANDOM_MEM_TYPES_H__ -#define __RANDOM_MEM_TYPES_H__ - -#include "mem-types.h" - -enum gf_random_mem_types_ { - gf_random_mt_random_struct = gf_common_mt_end + 1, - gf_random_mt_random_sched_struct, - gf_random_mt_end -}; -#endif - diff --git a/scheduler/random/src/random.c b/scheduler/random/src/random.c deleted file mode 100644 index 03a284b66bd..00000000000 --- a/scheduler/random/src/random.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.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 <stdlib.h> -#include <sys/time.h> - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include "random.h" -#include "random-mem-types.h" - -#define RANDOM_LIMITS_MIN_FREE_DISK_DEFAULT 15 -#define RANDOM_REFRESH_INTERVAL_DEFAULT 10 - - -static int32_t -random_init (xlator_t *xl) -{ - struct random_struct *random_buf = NULL; - xlator_list_t *trav_xl = xl->children; - data_t *limit = NULL; - int32_t index = 0; - - random_buf = GF_CALLOC (1, sizeof (struct random_struct), - gf_random_mt_random_struct); - ERR_ABORT (random_buf); - - /* Set the seed for the 'random' function */ - srandom ((uint32_t) time (NULL)); - - limit = dict_get (xl->options, "scheduler.limits.min-free-disk"); - if (limit) { - if (gf_string2percent (data_to_str (limit), - &random_buf->min_free_disk) != 0) { - gf_log ("random", GF_LOG_ERROR, - "invalid number format \"%s\" of \"option " - "scheduler.limits.min-free-disk\"", - limit->data); - return -1; - } - if (random_buf->min_free_disk >= 100) { - gf_log ("random", GF_LOG_ERROR, - "check the \"option random.limits.min-free" - "-disk\", it should be percentage value"); - return -1; - } - - } else { - gf_log ("random", GF_LOG_WARNING, - "No option for limit min-free-disk given, " - "defaulting it to 5%%"); - random_buf->min_free_disk = - RANDOM_LIMITS_MIN_FREE_DISK_DEFAULT; - } - - limit = dict_get (xl->options, "scheduler.refresh-interval"); - if (limit) { - if (gf_string2time (data_to_str (limit), - &random_buf->refresh_interval) != 0) { - gf_log ("random", GF_LOG_ERROR, - "invalid number format \"%s\" of " - "\"option random.refresh-interval\"", - limit->data); - return -1; - } - } else { - random_buf->refresh_interval = RANDOM_REFRESH_INTERVAL_DEFAULT; - } - - while (trav_xl) { - index++; - trav_xl = trav_xl->next; - } - random_buf->child_count = index; - random_buf->array = GF_CALLOC (index, - sizeof (struct random_sched_struct), - gf_random_mt_random_sched_struct); - ERR_ABORT (random_buf->array); - trav_xl = xl->children; - index = 0; - - while (trav_xl) { - random_buf->array[index].xl = trav_xl->xlator; - random_buf->array[index].eligible = 1; - trav_xl = trav_xl->next; - index++; - } - pthread_mutex_init (&random_buf->random_mutex, NULL); - - // put it at the proper place - *((long *)xl->private) = (long)random_buf; - return 0; -} - -static void -random_fini (xlator_t *xl) -{ - struct random_struct *random_buf = NULL; - - random_buf = (struct random_struct *)*((long *)xl->private); - pthread_mutex_destroy (&random_buf->random_mutex); - GF_FREE (random_buf->array); - GF_FREE (random_buf); -} - - -static int32_t -update_stat_array_cbk (call_frame_t *frame, - void *cookie, - xlator_t *xl, - int32_t op_ret, - int32_t op_errno, - struct xlator_stats *trav_stats) -{ - int32_t idx = 0; - int32_t percent = 0; - struct random_struct *random_buf = NULL; - - random_buf = (struct random_struct *)*((long *)xl->private); - - pthread_mutex_lock (&random_buf->random_mutex); - for (idx = 0; idx < random_buf->child_count; idx++) { - if (strcmp (random_buf->array[idx].xl->name, - (char *)cookie) == 0) - break; - } - pthread_mutex_unlock (&random_buf->random_mutex); - - if (op_ret == 0) { - percent = ((trav_stats->free_disk *100) / - trav_stats->total_disk_size); - if (random_buf->min_free_disk > percent) { - random_buf->array[idx].eligible = 0; - } else { - random_buf->array[idx].eligible = 1; - } - } else { - random_buf->array[idx].eligible = 0; - } - - STACK_DESTROY (frame->root); - return 0; -} - -static void -update_stat_array (xlator_t *xl) -{ - int32_t idx; - struct random_struct *random_buf = NULL; - call_frame_t *frame = NULL; - call_pool_t *pool = xl->ctx->pool; - - random_buf = (struct random_struct *)*((long *)xl->private); - for (idx = 0; idx < random_buf->child_count; idx++) { - frame = create_frame (xl, pool); - - STACK_WIND_COOKIE (frame, - update_stat_array_cbk, - random_buf->array[idx].xl->name, - random_buf->array[idx].xl, - (random_buf->array[idx].xl)->mops->stats, - 0); - } - return ; -} - -static void -random_update (xlator_t *xl) -{ - struct timeval tv; - struct random_struct *random_buf = NULL; - - random_buf = (struct random_struct *)*((long *)xl->private); - - gettimeofday(&tv, NULL); - if (tv.tv_sec > (random_buf->refresh_interval + - random_buf->last_stat_entry.tv_sec)) { - update_stat_array (xl); - random_buf->last_stat_entry.tv_sec = tv.tv_sec; - } -} - -static xlator_t * -random_schedule (xlator_t *xl, const void *path) -{ - struct random_struct *random_buf = NULL; - int32_t rand = 0; - int32_t try = 0; - - random_buf = (struct random_struct *)*((long *)xl->private); - - rand = (int32_t) (1.0*random_buf->child_count * - (random() / (RAND_MAX + 1.0))); - - random_update (xl); - - while (!random_buf->array[rand].eligible) { - if (try++ > 100) { - /* there is a chance of this becoming a - infinite loop otherwise. */ - break; - } - rand = (int32_t) (1.0*random_buf->child_count * - (random() / (RAND_MAX + 1.0))); - } - return random_buf->array[rand].xl; -} - -int32_t -random_mem_acct_init (xlator_t *this) -{ - int ret = -1; - - if (!this) - return ret; - - ret = xlator_mem_acct_init (this, gf_random_mt_end + 1); - - if (ret != 0) { - gf_log (this->name, GF_LOG_ERROR, "Memory accounting init" - " failed"); - return ret; - } - - return ret; -} - -/** - * notify - */ -void -random_notify (xlator_t *xl, int32_t event, void *data) -{ - struct random_struct *random_buf = NULL; - int32_t idx = 0; - - random_buf = (struct random_struct *)*((long *)xl->private); - if (!random_buf) - return; - - for (idx = 0; idx < random_buf->child_count; idx++) { - if (random_buf->array[idx].xl == (xlator_t *)data) - break; - } - - switch (event) - { - case GF_EVENT_CHILD_UP: - { - //random_buf->array[idx].eligible = 1; - } - break; - case GF_EVENT_CHILD_DOWN: - { - random_buf->array[idx].eligible = 0; - } - break; - default: - { - ; - } - break; - } - -} - -struct sched_ops sched = { - .init = random_init, - .fini = random_fini, - .update = random_update, - .schedule = random_schedule, - .notify = random_notify, - .mem_acct_init = random_mem_acct_init, -}; - -struct volume_options options[] = { - { .key = { "scheduler.refresh-interval", - "random.refresh-interval" }, - .type = GF_OPTION_TYPE_TIME - }, - { .key = { "scheduler.limits.min-free-disk", - "random.limits.min-free-disk" }, - .type = GF_OPTION_TYPE_PERCENT - }, - { .key = {NULL} } -}; diff --git a/scheduler/random/src/random.h b/scheduler/random/src/random.h deleted file mode 100644 index 154b1bdfb24..00000000000 --- a/scheduler/random/src/random.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.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 _RANDOM_H -#define _RANDOM_H - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - - -#include <sys/time.h> -#include "scheduler.h" - -struct random_sched_struct { - xlator_t *xl; - unsigned char eligible; -}; - -struct random_struct { - int32_t child_count; - uint32_t refresh_interval; - uint32_t min_free_disk; - struct timeval last_stat_entry; - struct random_sched_struct *array; - pthread_mutex_t random_mutex; -}; - -#endif /* _RANDOM_H */ diff --git a/scheduler/rr/Makefile.am b/scheduler/rr/Makefile.am deleted file mode 100644 index d471a3f9243..00000000000 --- a/scheduler/rr/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -SUBDIRS = src - -CLEANFILES = diff --git a/scheduler/rr/src/Makefile.am b/scheduler/rr/src/Makefile.am deleted file mode 100644 index 7e911c0eda8..00000000000 --- a/scheduler/rr/src/Makefile.am +++ /dev/null @@ -1,13 +0,0 @@ -sched_LTLIBRARIES = rr.la -scheddir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/scheduler - -rr_la_LDFLAGS = -module -avoidversion - -rr_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la -rr_la_SOURCES = rr.c rr-options.c -noinst_HEADERS = rr.h rr-options.h - -AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS) \ - -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS) - -CLEANFILES = diff --git a/scheduler/rr/src/rr-mem-types.h b/scheduler/rr/src/rr-mem-types.h deleted file mode 100644 index cb05323cd77..00000000000 --- a/scheduler/rr/src/rr-mem-types.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.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 __RR_MEM_TYPES_H__ -#define __RR_MEM_TYPES_H__ - -#include "mem-types.h" - -enum gf_rr_mem_types_ { - gf_rr_mt_rr_t = gf_common_mt_end + 1, - gf_rr_mt_rr_subvolume_t, - gf_rr_mt_end -}; -#endif - diff --git a/scheduler/rr/src/rr-options.c b/scheduler/rr/src/rr-options.c deleted file mode 100644 index 505b1713e33..00000000000 --- a/scheduler/rr/src/rr-options.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.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 "scheduler.h" -#include "rr-options.h" - -#define RR_LIMITS_MIN_FREE_DISK_OPTION_STRING "scheduler.limits.min-free-disk" -#define RR_LIMITS_MIN_FREE_DISK_VALUE_DEFAULT 15 -#define RR_LIMITS_MIN_FREE_DISK_VALUE_MIN 0 -#define RR_LIMITS_MIN_FREE_DISK_VALUE_MAX 100 - -#define RR_REFRESH_INTERVAL_OPTION_STRING "scheduler.refresh-interval" -#define RR_REFRESH_INTERVAL_VALUE_DEFAULT 10 - -#define RR_READ_ONLY_SUBVOLUMES_OPTION_STRING "scheduler.read-only-subvolumes" - -#define LOG_ERROR(args...) gf_log ("rr-options", GF_LOG_ERROR, ##args) -#define LOG_WARNING(args...) gf_log ("rr-options", GF_LOG_WARNING, ##args) - -static int -_rr_options_min_free_disk_validate (const char *value_string, uint32_t *n) -{ - uint32_t value = 0; - - if (value_string == NULL) - { - return -1; - } - - if (gf_string2percent (value_string, &value) != 0) - { - gf_log ("rr", - GF_LOG_ERROR, - "invalid number format [%s] of option [%s]", - value_string, - RR_LIMITS_MIN_FREE_DISK_OPTION_STRING); - return -1; - } - - if ((value <= RR_LIMITS_MIN_FREE_DISK_VALUE_MIN) || - (value >= RR_LIMITS_MIN_FREE_DISK_VALUE_MAX)) - { - gf_log ("rr", - GF_LOG_ERROR, - "out of range [%d] of option [%s]. Allowed range is 0 to 100.", - value, - RR_LIMITS_MIN_FREE_DISK_OPTION_STRING); - return -1; - } - - *n = value; - - return 0; -} - -static int -_rr_options_refresh_interval_validate (const char *value_string, uint32_t *n) -{ - uint32_t value = 0; - - if (value_string == NULL) - { - return -1; - } - - if (gf_string2time (value_string, &value) != 0) - { - gf_log ("rr", - GF_LOG_ERROR, - "invalid number format [%s] of option [%s]", - value_string, - RR_REFRESH_INTERVAL_OPTION_STRING); - return -1; - } - - *n = value; - - return 0; -} - -static int -_rr_options_read_only_subvolumes_validate (const char *value_string, - char ***volume_list, - uint64_t *volume_count) -{ - char **vlist = NULL; - int vcount = 0; - int i = 0; - - if (value_string == NULL || volume_list == NULL || volume_count) - { - return -1; - } - - if (gf_strsplit (value_string, - ", ", - &vlist, - &vcount) != 0) - { - gf_log ("rr", - GF_LOG_ERROR, - "invalid subvolume list [%s] of option [%s]", - value_string, - RR_READ_ONLY_SUBVOLUMES_OPTION_STRING); - return -1; - } - - for (i = 0; i < vcount; i++) - { - if (gf_volume_name_validate (vlist[i]) != 0) - { - gf_log ("rr", - GF_LOG_ERROR, - "invalid subvolume name [%s] in [%s] of option [%s]", - vlist[i], - value_string, - RR_READ_ONLY_SUBVOLUMES_OPTION_STRING); - goto free_exit; - } - } - - *volume_list = vlist; - *volume_count = vcount; - - return 0; - - free_exit: - for (i = 0; i < vcount; i++) - { - GF_FREE (vlist[i]); - } - GF_FREE (vlist); - - return -1; -} - -int -rr_options_validate (dict_t *options, rr_options_t *rr_options) -{ - char *value_string = NULL; - - if (options == NULL || rr_options == NULL) - { - return -1; - } - - if (dict_get (options, RR_LIMITS_MIN_FREE_DISK_OPTION_STRING)) - if (data_to_str (dict_get (options, RR_LIMITS_MIN_FREE_DISK_OPTION_STRING))) - value_string = data_to_str (dict_get (options, - RR_LIMITS_MIN_FREE_DISK_OPTION_STRING)); - if (value_string != NULL) - { - if (_rr_options_min_free_disk_validate (value_string, - &rr_options->min_free_disk) != 0) - { - return -1; - } - - gf_log ("rr", - GF_LOG_WARNING, - "using %s = %d", - RR_LIMITS_MIN_FREE_DISK_OPTION_STRING, - rr_options->min_free_disk); - } - else - { - rr_options->min_free_disk = RR_LIMITS_MIN_FREE_DISK_VALUE_DEFAULT; - - gf_log ("rr", GF_LOG_DEBUG, - "using %s = %d [default]", - RR_LIMITS_MIN_FREE_DISK_OPTION_STRING, - rr_options->min_free_disk); - } - - value_string = NULL; - if (dict_get (options, RR_REFRESH_INTERVAL_OPTION_STRING)) - value_string = data_to_str (dict_get (options, - RR_REFRESH_INTERVAL_OPTION_STRING)); - if (value_string != NULL) - { - if (_rr_options_refresh_interval_validate (value_string, - &rr_options->refresh_interval) != 0) - { - return -1; - } - - gf_log ("rr", - GF_LOG_WARNING, - "using %s = %d", - RR_REFRESH_INTERVAL_OPTION_STRING, - rr_options->refresh_interval); - } - else - { - rr_options->refresh_interval = RR_REFRESH_INTERVAL_VALUE_DEFAULT; - - gf_log ("rr", GF_LOG_DEBUG, - "using %s = %d [default]", - RR_REFRESH_INTERVAL_OPTION_STRING, - rr_options->refresh_interval); - } - - value_string = NULL; - if (dict_get (options, RR_READ_ONLY_SUBVOLUMES_OPTION_STRING)) - value_string = data_to_str (dict_get (options, - RR_READ_ONLY_SUBVOLUMES_OPTION_STRING)); - if (value_string != NULL) - { - if (_rr_options_read_only_subvolumes_validate (value_string, - &rr_options->read_only_subvolume_list, - &rr_options->read_only_subvolume_count) != 0) - { - return -1; - } - - gf_log ("rr", - GF_LOG_WARNING, - "using %s = [%s]", - RR_READ_ONLY_SUBVOLUMES_OPTION_STRING, - value_string); - } - - return 0; -} - -struct volume_options options[] = { - { .key = { "scheduler.refresh-interval", - "rr.refresh-interval" }, - .type = GF_OPTION_TYPE_TIME - }, - { .key = { "scheduler.limits.min-free-disk", - "rr.limits.min-free-disk" }, - .type = GF_OPTION_TYPE_PERCENT - }, - { .key = { "scheduler.read-only-subvolumes", - "rr.read-only-subvolumes" }, - .type = GF_OPTION_TYPE_ANY - }, - { .key = {NULL} } -}; diff --git a/scheduler/rr/src/rr-options.h b/scheduler/rr/src/rr-options.h deleted file mode 100644 index 1b0a1ef3d90..00000000000 --- a/scheduler/rr/src/rr-options.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.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 _RR_OPTIONS_H -#define _RR_OPTIONS_H - -struct rr_options -{ - uint32_t min_free_disk; - uint32_t refresh_interval; - char **read_only_subvolume_list; - uint64_t read_only_subvolume_count; -}; -typedef struct rr_options rr_options_t; - -int rr_options_validate (dict_t *options, rr_options_t *rr_options); - -#endif diff --git a/scheduler/rr/src/rr.c b/scheduler/rr/src/rr.c deleted file mode 100644 index e7b556e671b..00000000000 --- a/scheduler/rr/src/rr.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.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 _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include <sys/time.h> -#include <stdlib.h> - -#include <stdint.h> - -#include "scheduler.h" - -#include "rr-options.h" -#include "rr.h" -#include "rr-mem-types.h" - -#define RR_MIN_FREE_DISK_NOT_REACHED 0 -#define RR_MIN_FREE_DISK_REACHED 1 - -#define RR_SUBVOLUME_OFFLINE 0 -#define RR_SUBVOLUME_ONLINE 1 - -#define LOG_ERROR(args...) gf_log ("rr", GF_LOG_ERROR, ##args) -#define LOG_WARNING(args...) gf_log ("rr", GF_LOG_WARNING, ##args) -#define LOG_CRITICAL(args...) gf_log ("rr", GF_LOG_CRITICAL, ##args) - -#define ROUND_ROBIN(index, count) ((index + 1) % count) - -static int -_cleanup_rr (rr_t *rr) -{ - int i; - - if (rr == NULL) - { - return -1; - } - - if (rr->options.read_only_subvolume_list != NULL) - { - for (i = 0; i < rr->options.read_only_subvolume_count; i++) - { - GF_FREE (rr->options.read_only_subvolume_list[i]); - } - GF_FREE (rr->options.read_only_subvolume_list); - } - - GF_FREE (rr->subvolume_list); - - GF_FREE (rr); - - return 0; -} - -int -rr_init (xlator_t *this_xl) -{ - rr_t *rr = NULL; - dict_t *options = NULL; - xlator_list_t *children = NULL; - uint64_t children_count = 0; - int i = 0; - int j = 0; - - if (this_xl == NULL) - { - return -1; - } - - if ((options = this_xl->options) == NULL) - { - return -1; - } - - if ((children = this_xl->children) == NULL) - { - return -1; - } - - if ((rr = GF_CALLOC (1, sizeof (rr_t), gf_rr_mt_rr_t)) == NULL) - { - return -1; - } - - if (rr_options_validate (options, &rr->options) != 0) - { - GF_FREE (rr); - return -1; - } - - for (i = 0; i < rr->options.read_only_subvolume_count; i++) - { - char found = 0; - - for (children = this_xl->children; - children != NULL; - children = children->next) - { - if (strcmp (rr->options.read_only_subvolume_list[i], - children->xlator->name) == 0) - { - found = 1; - break; - } - } - - if (!found) - { - LOG_ERROR ("read-only subvolume [%s] not found in volume list", - rr->options.read_only_subvolume_list[i]); - _cleanup_rr (rr); - return -1; - } - } - - for (children = this_xl->children; - children != NULL; - children = children->next) - { - children_count++; - } - - /* bala: excluding read_only_subvolumes */ - if ((rr->subvolume_count = children_count - - rr->options.read_only_subvolume_count) == 0) - { - LOG_ERROR ("no writable volumes found for scheduling"); - _cleanup_rr (rr); - return -1; - } - - if ((rr->subvolume_list = GF_CALLOC (rr->subvolume_count, - sizeof (rr_subvolume_t), - gf_rr_mt_rr_subvolume_t)) == NULL) - { - _cleanup_rr (rr); - return -1; - } - - i = 0; - j = 0; - for (children = this_xl->children; - children != NULL; - children = children->next) - { - char found = 0; - - for (j = 0; j < rr->options.read_only_subvolume_count; j++) - { - if (strcmp (rr->options.read_only_subvolume_list[i], - children->xlator->name) == 0) - { - found = 1; - break; - } - } - - if (!found) - { - rr_subvolume_t *subvolume = NULL; - - subvolume = &rr->subvolume_list[i]; - - subvolume->xl = children->xlator; - subvolume->free_disk_status = RR_MIN_FREE_DISK_NOT_REACHED; - subvolume->status = RR_SUBVOLUME_ONLINE; - - i++; - } - } - - rr->schedule_index = UINT64_MAX; - rr->last_stat_fetched_time.tv_sec = 0; - rr->last_stat_fetched_time.tv_usec = 0; - pthread_mutex_init (&rr->mutex, NULL); - - *((long *)this_xl->private) = (long)rr; - - return 0; -} - -void -rr_fini (xlator_t *this_xl) -{ - rr_t *rr = NULL; - - if (this_xl == NULL) - { - return; - } - - if ((rr = (rr_t *) *((long *)this_xl->private)) != NULL) - { - pthread_mutex_destroy (&rr->mutex); - _cleanup_rr (rr); - this_xl->private = NULL; - } - - return; -} - -xlator_t * -rr_schedule (xlator_t *this_xl, const void *path) -{ - rr_t *rr = NULL; - uint64_t next_schedule_index = 0; - int i = 0; - - if (this_xl == NULL || path == NULL) - { - return NULL; - } - - rr = (rr_t *) *((long *)this_xl->private); - next_schedule_index = ROUND_ROBIN (rr->schedule_index, - rr->subvolume_count); - - rr_update (this_xl); - - for (i = next_schedule_index; i < rr->subvolume_count; i++) - { - if (rr->subvolume_list[i].status == RR_SUBVOLUME_ONLINE && - rr->subvolume_list[i].status == RR_MIN_FREE_DISK_NOT_REACHED) - { - pthread_mutex_lock (&rr->mutex); - rr->schedule_index = i; - pthread_mutex_unlock (&rr->mutex); - return rr->subvolume_list[i].xl; - } - } - - for (i = 0; i < next_schedule_index; i++) - { - if (rr->subvolume_list[i].status == RR_SUBVOLUME_ONLINE && - rr->subvolume_list[i].status == RR_MIN_FREE_DISK_NOT_REACHED) - { - pthread_mutex_lock (&rr->mutex); - rr->schedule_index = i; - pthread_mutex_unlock (&rr->mutex); - return rr->subvolume_list[i].xl; - } - } - - for (i = next_schedule_index; i < rr->subvolume_count; i++) - { - if (rr->subvolume_list[i].status == RR_SUBVOLUME_ONLINE) - { - pthread_mutex_lock (&rr->mutex); - rr->schedule_index = i; - pthread_mutex_unlock (&rr->mutex); - return rr->subvolume_list[i].xl; - } - } - - for (i = 0; i < next_schedule_index; i++) - { - if (rr->subvolume_list[i].status == RR_SUBVOLUME_ONLINE) - { - pthread_mutex_lock (&rr->mutex); - rr->schedule_index = i; - pthread_mutex_unlock (&rr->mutex); - return rr->subvolume_list[i].xl; - } - } - - return NULL; -} - -void -rr_update (xlator_t *this_xl) -{ - rr_t *rr = NULL; - struct timeval ctime = {0, 0}; - int i = 0; - - if (this_xl == NULL) - { - return ; - } - - if ((rr = (rr_t *) *((long *)this_xl->private)) == NULL) - { - return ; - } - - if (gettimeofday (&ctime, NULL) != 0) - { - return ; - } - - if (ctime.tv_sec > (rr->options.refresh_interval + - rr->last_stat_fetched_time.tv_sec)) - { - pthread_mutex_lock (&rr->mutex); - rr->last_stat_fetched_time = ctime; - pthread_mutex_unlock (&rr->mutex); - - for (i = 0; i < rr->subvolume_count; i++) - { - xlator_t *subvolume_xl = NULL; - call_frame_t *frame = NULL; - call_pool_t *pool = NULL; - - subvolume_xl = rr->subvolume_list[i].xl; - - pool = this_xl->ctx->pool; - - frame = create_frame (this_xl, pool); - - STACK_WIND_COOKIE (frame, - rr_update_cbk, - subvolume_xl->name, - subvolume_xl, - subvolume_xl->mops->stats, - 0); - } - } - - return ; -} - -int -rr_update_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this_xl, - int32_t op_ret, - int32_t op_errno, - struct xlator_stats *stats) -{ - rr_t *rr = NULL; - rr_subvolume_t *subvolume = NULL; - uint8_t free_disk_percent = 0; - int i = 0; - - if (frame == NULL) - { - return -1; - } - - if (cookie == NULL || this_xl == NULL) - { - STACK_DESTROY (frame->root); - return -1; - } - - if (op_ret == 0 && stats == NULL) - { - LOG_CRITICAL ("fatal! op_ret is 0 and stats is NULL. " - "Please report this to <gluster-devel@nongnu.org>"); - STACK_DESTROY (frame->root); - return -1; - } - - if ((rr = (rr_t *) *((long *)this_xl->private)) == NULL) - { - STACK_DESTROY (frame->root); - return -1; - } - - for (i = 0; i < rr->subvolume_count; i++) - { - if (rr->subvolume_list[i].xl->name == (char *) cookie) - { - subvolume = &rr->subvolume_list[i]; - break; - } - } - - if (subvolume == NULL) - { - LOG_ERROR ("unknown cookie [%s]", (char *) cookie); - STACK_DESTROY (frame->root); - return -1; - } - - if (op_ret == 0) - { - free_disk_percent = (stats->free_disk * 100) / stats->total_disk_size; - if (free_disk_percent > rr->options.min_free_disk) - { - if (subvolume->free_disk_status != RR_MIN_FREE_DISK_NOT_REACHED) - { - pthread_mutex_lock (&rr->mutex); - subvolume->free_disk_status = RR_MIN_FREE_DISK_NOT_REACHED; - pthread_mutex_unlock (&rr->mutex); - LOG_WARNING ("subvolume [%s] is available with free space for scheduling", - subvolume->xl->name); - } - } - else - { - if (subvolume->free_disk_status != RR_MIN_FREE_DISK_REACHED) - { - pthread_mutex_lock (&rr->mutex); - subvolume->free_disk_status = RR_MIN_FREE_DISK_REACHED; - pthread_mutex_unlock (&rr->mutex); - LOG_WARNING ("subvolume [%s] reached minimum disk space requirement", - subvolume->xl->name); - } - } - } - else - { - pthread_mutex_lock (&rr->mutex); - subvolume->status = RR_SUBVOLUME_OFFLINE; - pthread_mutex_unlock (&rr->mutex); - LOG_ERROR ("unable to get subvolume [%s] status information and " - "scheduling is disabled", - subvolume->xl->name); - } - - STACK_DESTROY (frame->root); - return 0; -} - -void -rr_notify (xlator_t *this_xl, int32_t event, void *data) -{ - rr_t *rr = NULL; - rr_subvolume_t *subvolume = NULL; - xlator_t *subvolume_xl = NULL; - int i = 0, ret = 0; - call_frame_t *frame = NULL; - call_pool_t *pool = NULL; - dict_t *xattr = get_new_dict (); - int32_t version[1] = {1}; - - if (this_xl == NULL || data == NULL) { - return ; - } - - if ((rr = (rr_t *) *((long *)this_xl->private)) == NULL) { - return ; - } - - subvolume_xl = (xlator_t *) data; - - for (i = 0; i < rr->subvolume_count; i++) { - if (rr->subvolume_list[i].xl == subvolume_xl) { - subvolume = &rr->subvolume_list[i]; - break; - } - } - - switch (event) { - case GF_EVENT_CHILD_UP: - /* Seeding, to be done only once */ - if (rr->first_time && (i == rr->subvolume_count)) { - loc_t loc = {0,}; - xlator_t *trav = NULL; - - pool = this_xl->ctx->pool; - frame = create_frame (this_xl, pool); - ret = dict_set_bin (xattr, "trusted.glusterfs.scheduler.rr", - version, sizeof (int32_t)); - if (-1 == ret) { - gf_log (this_xl->name, GF_LOG_ERROR, "rr seed setting failed"); - } - if (xattr) - dict_ref (xattr); - - loc.path = gf_strdup ("/"); - for (trav = this_xl->parents->xlator; trav; trav = trav->parents->xlator) { - if (trav->itable) { - loc.inode = trav->itable->root; - break; - } - } - STACK_WIND (frame, - rr_notify_cbk, - (xlator_t *)data, - ((xlator_t *)data)->fops->xattrop, - &loc, - GF_XATTROP_ADD_ARRAY, - xattr); - - if (xattr) - dict_unref (xattr); - - rr->first_time = 0; - } - if (subvolume) { - pthread_mutex_lock (&rr->mutex); - subvolume->status = RR_SUBVOLUME_ONLINE; - pthread_mutex_unlock (&rr->mutex); - } - break; - case GF_EVENT_CHILD_DOWN: - if (subvolume) { - pthread_mutex_lock (&rr->mutex); - subvolume->status = RR_SUBVOLUME_OFFLINE; - pthread_mutex_unlock (&rr->mutex); - } - break; - } - - return ; -} - -int -rr_notify_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this_xl, - int32_t op_ret, - int32_t op_errno, - dict_t *xattr) -{ - rr_t *rr = NULL; - int32_t *index = NULL; - int32_t ret = -1; - void *tmp_index_ptr = NULL; - - if (frame == NULL) - { - return -1; - } - - if ((this_xl == NULL) || (op_ret == -1)) - { - STACK_DESTROY (frame->root); - return -1; - } - - if ((rr = (rr_t *) *((long *)this_xl->private)) == NULL) - { - STACK_DESTROY (frame->root); - return -1; - } - - ret = dict_get_bin (xattr, "trusted.glusterfs.scheduler.rr", &tmp_index_ptr); - index = tmp_index_ptr; - if (ret == 0) - rr->schedule_index = (index[0] % rr->subvolume_count); - else - rr->schedule_index = 0; - - STACK_DESTROY (frame->root); - return 0; -} - -struct sched_ops sched = { - .init = rr_init, - .fini = rr_fini, - .update = rr_update, - .schedule = rr_schedule, - .notify = rr_notify -}; - diff --git a/scheduler/rr/src/rr.h b/scheduler/rr/src/rr.h deleted file mode 100644 index 3bd95929b61..00000000000 --- a/scheduler/rr/src/rr.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.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 _RR_H -#define _RR_H - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include "scheduler.h" -#include <stdint.h> -#include <sys/time.h> - -struct rr_subvolume -{ - xlator_t *xl; - uint8_t free_disk_status; - uint8_t status; -}; -typedef struct rr_subvolume rr_subvolume_t; - -struct rr -{ - rr_options_t options; - rr_subvolume_t *subvolume_list; - uint64_t subvolume_count; - uint64_t schedule_index; - struct timeval last_stat_fetched_time; - pthread_mutex_t mutex; - char first_time; -}; -typedef struct rr rr_t; - -int rr_init (xlator_t *this_xl); -void rr_fini (xlator_t *this_xl); -xlator_t *rr_schedule (xlator_t *this_xl, const void *path); -void rr_update (xlator_t *this_xl); -int rr_update_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this_xl, - int32_t op_ret, - int32_t op_errno, - struct xlator_stats *stats); -void rr_notify (xlator_t *this_xl, int32_t event, void *data); -int rr_notify_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this_xl, - int32_t op_ret, - int32_t op_errno, - dict_t *xattr); - -#endif /* _RR_H */ diff --git a/scheduler/switch/Makefile.am b/scheduler/switch/Makefile.am deleted file mode 100644 index d471a3f9243..00000000000 --- a/scheduler/switch/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -SUBDIRS = src - -CLEANFILES = diff --git a/scheduler/switch/src/Makefile.am b/scheduler/switch/src/Makefile.am deleted file mode 100644 index dc7d16d40d2..00000000000 --- a/scheduler/switch/src/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -sched_LTLIBRARIES = switch.la -scheddir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/scheduler - -switch_la_LDFLAGS = -module -avoidversion - -switch_la_SOURCES = switch.c -switch_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la - -AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS) \ - -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS) - -CLEANFILES = diff --git a/scheduler/switch/src/switch-mem-types.h b/scheduler/switch/src/switch-mem-types.h deleted file mode 100644 index 7039b035d0f..00000000000 --- a/scheduler/switch/src/switch-mem-types.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.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 __SWITCH_MEM_TYPES_H__ -#define __SWITCH_MEM_TYPES_H__ - -#include "mem-types.h" - -enum gf_switch_mem_types_ { - gf_switch_mt_switch_struct = gf_common_mt_end + 1, - gf_switch_mt_switch_sched_struct, - gf_switch_mt_switch_sched_array, - gf_switch_mt_end -}; -#endif - diff --git a/scheduler/switch/src/switch.c b/scheduler/switch/src/switch.c deleted file mode 100644 index 1362e5cc994..00000000000 --- a/scheduler/switch/src/switch.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.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 <sys/time.h> -#include <stdlib.h> -#include <fnmatch.h> - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include "xlator.h" -#include "scheduler.h" -#include "switch-mem-types.h" - -struct switch_sched_array { - xlator_t *xl; - int32_t eligible; - int32_t considered; -}; - -/* Select one of this struct based on the path's pattern match */ -struct switch_sched_struct { - struct switch_sched_struct *next; - struct switch_sched_array *array; - char path_pattern[256]; - int32_t node_index; /* Index of the node in - this pattern. */ - int32_t num_child; /* Total num of child nodes - with this pattern. */ -}; - -struct switch_struct { - struct switch_sched_struct *cond; - struct switch_sched_array *array; - pthread_mutex_t switch_mutex; - int32_t child_count; -}; - -/* This function should return child node as '*:subvolumes' is inserterd */ -static xlator_t * -switch_get_matching_xl (const char *path, struct switch_sched_struct *cond) -{ - struct switch_sched_struct *trav = cond; - char *pathname = gf_strdup (path); - int index = 0; - - while (trav) { - if (fnmatch (trav->path_pattern, - pathname, FNM_NOESCAPE) == 0) { - GF_FREE (pathname); - trav->node_index %= trav->num_child; - index = (trav->node_index++) % trav->num_child; - return trav->array[index].xl; - } - trav = trav->next; - } - GF_FREE (pathname); - return NULL; -} - -static int32_t -gf_unify_valid_child (const char *child, - xlator_t *xl) -{ - xlator_list_t *children = NULL, *prev = NULL; - int32_t ret = 0; - - children = xl->children; - do { - if (!strcmp (child, children->xlator->name)) { - ret = 1; - break; - } - - prev = children; - children = prev->next; - } while (children); - - return ret; -} - -static int32_t -switch_init (xlator_t *xl) -{ - int32_t index = 0; - data_t *data = NULL; - char *child = NULL; - char *tmp = NULL; - char *childs_data = NULL; - xlator_list_t *trav_xl = xl->children; - struct switch_struct *switch_buf = NULL; - - switch_buf = GF_CALLOC (1, sizeof (struct switch_struct), - gf_switch_mt_switch_struct); - ERR_ABORT (switch_buf); - - while (trav_xl) { - index++; - trav_xl = trav_xl->next; - } - switch_buf->child_count = index; - switch_buf->array = GF_CALLOC (index + 1, - sizeof (struct switch_sched_struct), - gf_switch_mt_switch_sched_struct); - ERR_ABORT (switch_buf->array); - trav_xl = xl->children; - index = 0; - - while (trav_xl) { - switch_buf->array[index].xl = trav_xl->xlator; - switch_buf->array[index].eligible = 1; - trav_xl = trav_xl->next; - index++; - } - - data = dict_get (xl->options, "scheduler.read-only-subvolumes"); - if (data) { - childs_data = gf_strdup (data->data); - child = strtok_r (childs_data, ",", &tmp); - while (child) { - for (index = 1; - index < switch_buf->child_count; index++) { - if (strcmp (switch_buf->array[index - 1].xl->name, child) == 0) { - gf_log ("switch", GF_LOG_DEBUG, - "Child '%s' is read-only", - child); - memcpy (&(switch_buf->array[index-1]), - &(switch_buf->array[switch_buf->child_count - 1]), - sizeof (struct switch_sched_array)); - switch_buf->child_count--; - break; - } - } - child = strtok_r (NULL, ",", &tmp); - } - GF_FREE (childs_data); - } - - data = dict_get (xl->options, "scheduler.local-volume-name"); - if (data) { - /* Means, give preference to that node first */ - gf_log ("switch", GF_LOG_DEBUG, - "local volume defined as %s", data->data); - - /* TODO: parse it properly, have an extra index to - specify that first */ - } - - /* *jpg:child1,child2;*mpg:child3;*:child4,child5,child6 */ - data = dict_get (xl->options, "scheduler.switch.case"); - if (data) { - char *tmp_str = NULL; - char *tmp_str1 = NULL; - char *dup_str = NULL; - char *switch_str = NULL; - char *pattern = NULL; - char *childs = NULL; - struct switch_sched_struct *switch_opt = NULL; - struct switch_sched_struct *trav = NULL; - /* Get the pattern for considering switch case. - "option block-size *avi:10MB" etc */ - switch_str = strtok_r (data->data, ";", &tmp_str); - while (switch_str) { - dup_str = gf_strdup (switch_str); - switch_opt = - GF_CALLOC (1, sizeof (struct switch_sched_struct), gf_switch_mt_switch_sched_struct); - ERR_ABORT (switch_opt); - - /* Link it to the main structure */ - if (switch_buf->cond) { - /* there are already few entries */ - trav = switch_buf->cond; - while (trav->next) - trav = trav->next; - trav->next = switch_opt; - } else { - /* First entry */ - switch_buf->cond = switch_opt; - } - pattern = strtok_r (dup_str, ":", &tmp_str1); - childs = strtok_r (NULL, ":", &tmp_str1); - if (strncmp (pattern, "*", 2) == 0) { - gf_log ("switch", GF_LOG_WARNING, - "'*' pattern will be taken by default " - "for all the unconfigured child nodes," - " hence neglecting current option"); - switch_str = strtok_r (NULL, ";", &tmp_str); - GF_FREE (dup_str); - continue; - } - memcpy (switch_opt->path_pattern, - pattern, strlen (pattern)); - if (childs) { - int32_t idx = 0; - char *tmp1 = NULL; - char *dup_childs = NULL; - /* TODO: get the list of child nodes for - the given pattern */ - dup_childs = gf_strdup (childs); - child = strtok_r (dup_childs, ",", &tmp); - while (child) { - if (gf_unify_valid_child (child, xl)) { - idx++; - child = strtok_r (NULL, ",", &tmp); - } else { - gf_log ("switch", GF_LOG_ERROR, - "%s is not a subvolume " - "of %s. pattern can " - "only be scheduled only" - " to a subvolume of %s", - child, xl->name, - xl->name); - return -1; - } - } - GF_FREE (dup_childs); - child = strtok_r (childs, ",", &tmp1); - switch_opt->num_child = idx; - switch_opt->array = - GF_CALLOC (1, idx * sizeof (struct switch_sched_array), gf_switch_mt_switch_sched_array); - ERR_ABORT (switch_opt->array); - idx = 0; - child = strtok_r (childs, ",", &tmp); - while (child) { - for (index = 1; - index < switch_buf->child_count; - index++) { - if (strcmp (switch_buf->array[index - 1].xl->name, - child) == 0) { - gf_log ("switch", - GF_LOG_DEBUG, - "'%s' pattern will be scheduled to \"%s\"", - switch_opt->path_pattern, child); - /* - if (switch_buf->array[index-1].considered) { - gf_log ("switch", GF_LOG_DEBUG, - "ambiguity found, exiting"); - return -1; - } - */ - switch_opt->array[idx].xl = switch_buf->array[index-1].xl; - switch_buf->array[index-1].considered = 1; - idx++; - break; - } - } - child = strtok_r (NULL, ",", &tmp1); - } - } else { - /* error */ - gf_log ("switch", GF_LOG_ERROR, - "Check \"scheduler.switch.case\" " - "option in unify volume. Exiting"); - GF_FREE (switch_buf->array); - GF_FREE (switch_buf); - return -1; - } - GF_FREE (dup_str); - switch_str = strtok_r (NULL, ";", &tmp_str); - } - } - /* Now, all the pattern based considerations done, so for all the - * remaining pattern, '*' to all the remaining child nodes - */ - { - struct switch_sched_struct *switch_opt = NULL; - int32_t flag = 0; - int32_t index = 0; - for (index=0; index < switch_buf->child_count; index++) { - /* check for considered flag */ - if (switch_buf->array[index].considered) - continue; - flag++; - } - if (!flag) { - gf_log ("switch", GF_LOG_ERROR, - "No nodes left for pattern '*'. Exiting."); - return -1; - } - switch_opt = GF_CALLOC (1, sizeof (struct switch_sched_struct), gf_switch_mt_switch_sched_struct); - ERR_ABORT (switch_opt); - if (switch_buf->cond) { - /* there are already few entries */ - struct switch_sched_struct *trav = switch_buf->cond; - while (trav->next) - trav = trav->next; - trav->next = switch_opt; - } else { - /* First entry */ - switch_buf->cond = switch_opt; - } - /* Add the '*' pattern to the array */ - memcpy (switch_opt->path_pattern, "*", 2); - switch_opt->num_child = flag; - switch_opt->array = - GF_CALLOC (1, flag * sizeof (struct switch_sched_array), gf_switch_mt_switch_sched_array); - ERR_ABORT (switch_opt->array); - flag = 0; - for (index=0; index < switch_buf->child_count; index++) { - /* check for considered flag */ - if (switch_buf->array[index].considered) - continue; - gf_log ("switch", GF_LOG_DEBUG, - "'%s' pattern will be scheduled to \"%s\"", - switch_opt->path_pattern, - switch_buf->array[index].xl->name); - switch_opt->array[flag].xl = - switch_buf->array[index].xl; - switch_buf->array[index].considered = 1; - flag++; - } - } - - pthread_mutex_init (&switch_buf->switch_mutex, NULL); - - // put it at the proper place - *((long *)xl->private) = (long)switch_buf; - - return 0; -} - -static void -switch_fini (xlator_t *xl) -{ - /* TODO: free all the allocated entries */ - struct switch_struct *switch_buf = NULL; - switch_buf = (struct switch_struct *)*((long *)xl->private); - - pthread_mutex_destroy (&switch_buf->switch_mutex); - GF_FREE (switch_buf->array); - GF_FREE (switch_buf); -} - -static xlator_t * -switch_schedule (xlator_t *xl, const void *path) -{ - struct switch_struct *switch_buf = NULL; - switch_buf = (struct switch_struct *)*((long *)xl->private); - - return switch_get_matching_xl (path, switch_buf->cond); -} - - -/** - * notify - */ -void -switch_notify (xlator_t *xl, int32_t event, void *data) -{ - /* TODO: This should be checking in switch_sched_struct */ -#if 0 - struct switch_struct *switch_buf = NULL; - int32_t idx = 0; - - switch_buf = (struct switch_struct *)*((long *)xl->private); - if (!switch_buf) - return; - - for (idx = 0; idx < switch_buf->child_count; idx++) { - if (switch_buf->array[idx].xl == (xlator_t *)data) - break; - } - - switch (event) - { - case GF_EVENT_CHILD_UP: - { - switch_buf->array[idx].eligible = 1; - } - break; - case GF_EVENT_CHILD_DOWN: - { - switch_buf->array[idx].eligible = 0; - } - break; - default: - { - ; - } - break; - } -#endif -} - -static void -switch_update (xlator_t *xl) -{ - return; -} - -int32_t -switch_mem_acct_init (xlator_t *this) -{ - int ret = -1; - - if (!this) - return ret; - - ret = xlator_mem_acct_init (this, gf_switch_mt_end + 1); - - if (ret != 0) { - gf_log (this->name, GF_LOG_ERROR, "Memory accounting init" - " failed"); - return ret; - } - - return ret; -} - -struct sched_ops sched = { - .init = switch_init, - .fini = switch_fini, - .update = switch_update, - .schedule = switch_schedule, - .notify = switch_notify, - .mem_acct_init = switch_mem_acct_init, -}; - -struct volume_options options[] = { - { .key = { "scheduler.read-only-subvolumes" , - "switch.read-only-subvolumes"}, - .type = GF_OPTION_TYPE_ANY - }, - { .key = { "scheduler.local-volume-name", - "switch.nufa.local-volume-name" }, - .type = GF_OPTION_TYPE_XLATOR - }, - { .key = { "scheduler.switch.case", - "switch.case" }, - .type = GF_OPTION_TYPE_ANY - }, - { .key = {NULL} } -}; diff --git a/xlators/cluster/unify/Makefile.am b/xlators/cluster/unify/Makefile.am deleted file mode 100644 index d471a3f9243..00000000000 --- a/xlators/cluster/unify/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -SUBDIRS = src - -CLEANFILES = diff --git a/xlators/cluster/unify/src/Makefile.am b/xlators/cluster/unify/src/Makefile.am deleted file mode 100644 index 2a1fe837263..00000000000 --- a/xlators/cluster/unify/src/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ - -xlator_LTLIBRARIES = unify.la -xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/legacy/cluster - -unify_la_LDFLAGS = -module -avoidversion - -unify_la_SOURCES = unify.c unify-self-heal.c -unify_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la - -noinst_HEADERS = unify.h - -AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS) \ - -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS) - -CLEANFILES = - diff --git a/xlators/cluster/unify/src/unify-mem-types.h b/xlators/cluster/unify/src/unify-mem-types.h deleted file mode 100644 index 13c9cc1f7b3..00000000000 --- a/xlators/cluster/unify/src/unify-mem-types.h +++ /dev/null @@ -1,41 +0,0 @@ - -/* - Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.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 __UNIFY_MEM_TYPES_H__ -#define __UNIFY_MEM_TYPES_H__ - -#include "mem-types.h" - -enum gf_unify_mem_types_ { - gf_unify_mt_char = gf_common_mt_end + 1, - gf_unify_mt_int16_t, - gf_unify_mt_xlator_t, - gf_unify_mt_unify_private_t, - gf_unify_mt_xlator_list_t, - gf_unify_mt_dir_entry_t, - gf_unify_mt_off_t, - gf_unify_mt_int, - gf_unify_mt_unify_self_heal_struct, - gf_unify_mt_unify_local_t, - gf_unify_mt_end -}; -#endif - diff --git a/xlators/cluster/unify/src/unify-self-heal.c b/xlators/cluster/unify/src/unify-self-heal.c deleted file mode 100644 index f99e4c7c360..00000000000 --- a/xlators/cluster/unify/src/unify-self-heal.c +++ /dev/null @@ -1,1239 +0,0 @@ -/* - Copyright (c) 2007-2011 Gluster, Inc. <http://www.gluster.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/>. -*/ - -/** - * unify-self-heal.c : - * This file implements few functions which enables 'unify' translator - * to be consistent in its behaviour when - * > a node fails, - * > a node gets added, - * > a failed node comes back - * > a new namespace server is added (ie, an fresh namespace server). - * - * This functionality of 'unify' will enable glusterfs to support storage - * system failure, and maintain consistancy. This works both ways, ie, when - * an entry (either file or directory) is found on namespace server, and not - * on storage nodes, its created in storage nodes and vica-versa. - * - * The two fops, where it can be implemented are 'getdents ()' and 'lookup ()' - * - */ - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include "glusterfs.h" -#include "unify.h" -#include "dict.h" -#include "xlator.h" -#include "hashfn.h" -#include "logging.h" -#include "stack.h" -#include "common-utils.h" - -int32_t -unify_sh_getdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dir_entry_t *entry, - int32_t count); - -int32_t -unify_sh_ns_getdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dir_entry_t *entry, - int32_t count); - -int32_t -unify_bgsh_getdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dir_entry_t *entry, - int32_t count); - -int32_t -unify_bgsh_ns_getdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dir_entry_t *entry, - int32_t count); - -/** - * unify_local_wipe - free all the extra allocation of local->* here. - */ -static void -unify_local_wipe (unify_local_t *local) -{ - /* Free the strdup'd variables in the local structure */ - if (local->name) { - GF_FREE (local->name); - } - - if (local->sh_struct) { - if (local->sh_struct->offset_list) - GF_FREE (local->sh_struct->offset_list); - - if (local->sh_struct->entry_list) - GF_FREE (local->sh_struct->entry_list); - - if (local->sh_struct->count_list) - GF_FREE (local->sh_struct->count_list); - - GF_FREE (local->sh_struct); - } - - loc_wipe (&local->loc1); - loc_wipe (&local->loc2); -} - -int32_t -unify_sh_setdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - int32_t callcnt = -1; - unify_local_t *local = frame->local; - inode_t *inode = NULL; - dict_t *tmp_dict = NULL; - dir_entry_t *prev, *entry, *trav; - - LOCK (&frame->lock); - { - /* if local->call_count == 0, that means, setdents on - * storagenodes is still pending. - */ - if (local->call_count) - callcnt = --local->call_count; - } - UNLOCK (&frame->lock); - - if (callcnt == 0) { - if (local->sh_struct->entry_list[0]) { - prev = entry = local->sh_struct->entry_list[0]; - if (!entry) - return 0; - trav = entry->next; - while (trav) { - prev->next = trav->next; - GF_FREE (trav->name); - if (IA_ISLNK (trav->buf.ia_type)) - GF_FREE (trav->link); - GF_FREE (trav); - trav = prev->next; - } - GF_FREE (entry); - } - - if (!local->flags) { - if (local->sh_struct->count_list[0] >= - UNIFY_SELF_HEAL_GETDENTS_COUNT) { - /* count == size, that means, there are more entries - to read from */ - //local->call_count = 0; - local->sh_struct->offset_list[0] += - UNIFY_SELF_HEAL_GETDENTS_COUNT; - STACK_WIND (frame, - unify_sh_ns_getdents_cbk, - NS(this), - NS(this)->fops->getdents, - local->fd, - UNIFY_SELF_HEAL_GETDENTS_COUNT, - local->sh_struct->offset_list[0], - GF_GET_DIR_ONLY); - } - } else { - inode = local->loc1.inode; - fd_unref (local->fd); - tmp_dict = local->dict; - - unify_local_wipe (local); - - STACK_UNWIND (frame, local->op_ret, local->op_errno, - inode, &local->stbuf, local->dict, - &local->oldpostparent); - if (tmp_dict) - dict_unref (tmp_dict); - } - } - - return 0; -} - - -int32_t -unify_sh_ns_getdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dir_entry_t *entry, - int32_t count) -{ - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - long index = 0; - unsigned long final = 0; - dir_entry_t *tmp = GF_CALLOC (1, sizeof (dir_entry_t), - gf_unify_mt_dir_entry_t); - - local->sh_struct->entry_list[0] = tmp; - local->sh_struct->count_list[0] = count; - if (entry) { - tmp->next = entry->next; - entry->next = NULL; - } - - if ((count < UNIFY_SELF_HEAL_GETDENTS_COUNT) || !entry) { - final = 1; - } - - LOCK (&frame->lock); - { - /* local->call_count will be '0' till now. make it 1 so, it - can be UNWIND'ed for the last call. */ - local->call_count = priv->child_count; - if (final) - local->flags = 1; - } - UNLOCK (&frame->lock); - - for (index = 0; index < priv->child_count; index++) - { - STACK_WIND_COOKIE (frame, - unify_sh_setdents_cbk, - (void *)index, - priv->xl_array[index], - priv->xl_array[index]->fops->setdents, - local->fd, GF_SET_DIR_ONLY, - local->sh_struct->entry_list[0], count); - } - - return 0; -} - -int32_t -unify_sh_ns_setdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - int32_t callcnt = -1; - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - long index = (long)cookie; - dir_entry_t *prev, *entry, *trav; - - LOCK (&frame->lock); - { - if (local->sh_struct->entry_list[index]) { - prev = entry = local->sh_struct->entry_list[index]; - trav = entry->next; - while (trav) { - prev->next = trav->next; - GF_FREE (trav->name); - if (IA_ISLNK (trav->buf.ia_type)) - GF_FREE (trav->link); - GF_FREE (trav); - trav = prev->next; - } - GF_FREE (entry); - } - } - UNLOCK (&frame->lock); - - if (local->sh_struct->count_list[index] < - UNIFY_SELF_HEAL_GETDENTS_COUNT) { - LOCK (&frame->lock); - { - callcnt = --local->call_count; - } - UNLOCK (&frame->lock); - } else { - /* count == size, that means, there are more entries - to read from */ - local->sh_struct->offset_list[index] += - UNIFY_SELF_HEAL_GETDENTS_COUNT; - STACK_WIND_COOKIE (frame, - unify_sh_getdents_cbk, - cookie, - priv->xl_array[index], - priv->xl_array[index]->fops->getdents, - local->fd, - UNIFY_SELF_HEAL_GETDENTS_COUNT, - local->sh_struct->offset_list[index], - GF_GET_ALL); - - gf_log (this->name, GF_LOG_DEBUG, - "readdir on (%s) with offset %"PRId64"", - priv->xl_array[index]->name, - local->sh_struct->offset_list[index]); - } - - if (!callcnt) { - /* All storage nodes have done unified setdents on NS node. - * Now, do getdents from NS and do setdents on storage nodes. - */ - - /* sh_struct->offset_list is no longer required for - storage nodes now */ - local->sh_struct->offset_list[0] = 0; /* reset */ - - STACK_WIND (frame, - unify_sh_ns_getdents_cbk, - NS(this), - NS(this)->fops->getdents, - local->fd, - UNIFY_SELF_HEAL_GETDENTS_COUNT, - 0, /* In this call, do send '0' as offset */ - GF_GET_DIR_ONLY); - } - - return 0; -} - - -/** - * unify_sh_getdents_cbk - - */ -int32_t -unify_sh_getdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dir_entry_t *entry, - int32_t count) -{ - int32_t callcnt = -1; - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - long index = (long)cookie; - dir_entry_t *tmp = NULL; - - if (op_ret >= 0 && count > 0) { - /* There is some dentry found, just send the dentry to NS */ - tmp = GF_CALLOC (1, sizeof (dir_entry_t), - gf_unify_mt_dir_entry_t); - local->sh_struct->entry_list[index] = tmp; - local->sh_struct->count_list[index] = count; - if (entry) { - tmp->next = entry->next; - entry->next = NULL; - } - STACK_WIND_COOKIE (frame, - unify_sh_ns_setdents_cbk, - cookie, - NS(this), - NS(this)->fops->setdents, - local->fd, - GF_SET_IF_NOT_PRESENT, - local->sh_struct->entry_list[index], - count); - return 0; - } - - if (count < UNIFY_SELF_HEAL_GETDENTS_COUNT) { - LOCK (&frame->lock); - { - callcnt = --local->call_count; - } - UNLOCK (&frame->lock); - } else { - /* count == size, that means, there are more entries - to read from */ - local->sh_struct->offset_list[index] += - UNIFY_SELF_HEAL_GETDENTS_COUNT; - STACK_WIND_COOKIE (frame, - unify_sh_getdents_cbk, - cookie, - priv->xl_array[index], - priv->xl_array[index]->fops->getdents, - local->fd, - UNIFY_SELF_HEAL_GETDENTS_COUNT, - local->sh_struct->offset_list[index], - GF_GET_ALL); - - gf_log (this->name, GF_LOG_DEBUG, - "readdir on (%s) with offset %"PRId64"", - priv->xl_array[index]->name, - local->sh_struct->offset_list[index]); - } - - if (!callcnt) { - /* All storage nodes have done unified setdents on NS node. - * Now, do getdents from NS and do setdents on storage nodes. - */ - - /* sh_struct->offset_list is no longer required for - storage nodes now */ - local->sh_struct->offset_list[0] = 0; /* reset */ - - STACK_WIND (frame, - unify_sh_ns_getdents_cbk, - NS(this), - NS(this)->fops->getdents, - local->fd, - UNIFY_SELF_HEAL_GETDENTS_COUNT, - 0, /* In this call, do send '0' as offset */ - GF_GET_DIR_ONLY); - } - - return 0; -} - -/** - * unify_sh_opendir_cbk - - * - * @cookie: - */ -int32_t -unify_sh_opendir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd) -{ - int32_t callcnt = 0; - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - int16_t index = 0; - inode_t *inode = NULL; - dict_t *tmp_dict = NULL; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - - if (op_ret >= 0) { - local->op_ret = op_ret; - } else { - gf_log (this->name, GF_LOG_WARNING, "failed"); - local->failed = 1; - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - local->call_count = priv->child_count + 1; - - if (!local->failed) { - /* send getdents() namespace after finishing - storage nodes */ - local->call_count--; - - fd_bind (fd); - - if (local->call_count) { - /* Used as the offset index. This list keeps - * track of offset sent to each node during - * STACK_WIND. - */ - local->sh_struct->offset_list = - GF_CALLOC (priv->child_count, - sizeof (off_t), - gf_unify_mt_off_t); - ERR_ABORT (local->sh_struct->offset_list); - - local->sh_struct->entry_list = - GF_CALLOC (priv->child_count, - sizeof (dir_entry_t *), - gf_unify_mt_dir_entry_t); - ERR_ABORT (local->sh_struct->entry_list); - - local->sh_struct->count_list = - GF_CALLOC (priv->child_count, - sizeof (int), - gf_unify_mt_int); - ERR_ABORT (local->sh_struct->count_list); - - /* Send getdents on all the fds */ - for (index = 0; - index < priv->child_count; index++) { - STACK_WIND_COOKIE (frame, - unify_sh_getdents_cbk, - (void *)(long)index, - priv->xl_array[index], - priv->xl_array[index]->fops->getdents, - local->fd, - UNIFY_SELF_HEAL_GETDENTS_COUNT, - 0, /* In this call, do send '0' as offset */ - GF_GET_ALL); - } - - /* did stack wind, so no need to unwind here */ - return 0; - } /* (local->call_count) */ - } /* (!local->failed) */ - - /* Opendir failed on one node. */ - inode = local->loc1.inode; - fd_unref (local->fd); - tmp_dict = local->dict; - - unify_local_wipe (local); - /* Only 'self-heal' failed, lookup() was successful. */ - local->op_ret = 0; - - /* This is lookup_cbk ()'s UNWIND. */ - STACK_UNWIND (frame, local->op_ret, local->op_errno, inode, - &local->stbuf, local->dict, &local->oldpostparent); - if (tmp_dict) - dict_unref (tmp_dict); - } - - return 0; -} - -/** - * gf_sh_checksum_cbk - - * - * @frame: frame used in lookup. get a copy of it, and use that copy. - * @this: pointer to unify xlator. - * @inode: pointer to inode, for which the consistency check is required. - * - */ -int32_t -unify_sh_checksum_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - uint8_t *file_checksum, - uint8_t *dir_checksum) -{ - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - int16_t index = 0; - int32_t callcnt = 0; - inode_t *inode = NULL; - dict_t *tmp_dict = NULL; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - if (op_ret >= 0) { - if (NS(this) == (xlator_t *)cookie) { - memcpy (local->sh_struct->ns_file_checksum, - file_checksum, NAME_MAX); - memcpy (local->sh_struct->ns_dir_checksum, - dir_checksum, NAME_MAX); - } else { - if (local->entry_count == 0) { - /* Initialize the dir_checksum to be - * used for comparision with other - * storage nodes. Should be done for - * the first successful call *only*. - */ - /* Using 'entry_count' as a flag */ - local->entry_count = 1; - memcpy (local->sh_struct->dir_checksum, - dir_checksum, NAME_MAX); - } - - /* Reply from the storage nodes */ - for (index = 0; - index < NAME_MAX; index++) { - /* Files should be present in - only one node */ - local->sh_struct->file_checksum[index] ^= file_checksum[index]; - - /* directory structure should be - same accross */ - if (local->sh_struct->dir_checksum[index] != dir_checksum[index]) - local->failed = 1; - } - } - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - for (index = 0; index < NAME_MAX ; index++) { - if (local->sh_struct->file_checksum[index] != - local->sh_struct->ns_file_checksum[index]) { - local->failed = 1; - break; - } - if (local->sh_struct->dir_checksum[index] != - local->sh_struct->ns_dir_checksum[index]) { - local->failed = 1; - break; - } - } - - if (local->failed) { - /* Log it, it should be a rare event */ - gf_log (this->name, GF_LOG_WARNING, - "Self-heal triggered on directory %s", - local->loc1.path); - - /* Any self heal will be done at directory level */ - local->call_count = 0; - local->op_ret = -1; - local->failed = 0; - - local->fd = fd_create (local->loc1.inode, - frame->root->pid); - - local->call_count = priv->child_count + 1; - - for (index = 0; - index < (priv->child_count + 1); index++) { - STACK_WIND_COOKIE (frame, - unify_sh_opendir_cbk, - priv->xl_array[index]->name, - priv->xl_array[index], - priv->xl_array[index]->fops->opendir, - &local->loc1, - local->fd); - } - /* opendir can be done on the directory */ - return 0; - } - - /* no mismatch */ - inode = local->loc1.inode; - tmp_dict = local->dict; - - unify_local_wipe (local); - - /* This is lookup_cbk ()'s UNWIND. */ - STACK_UNWIND (frame, - local->op_ret, - local->op_errno, - inode, - &local->stbuf, - local->dict, &local->oldpostparent); - if (tmp_dict) - dict_unref (tmp_dict); - } - - return 0; -} - -/* Foreground self-heal part over */ - -/* Background self-heal part */ - -int32_t -unify_bgsh_setdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - int32_t callcnt = -1; - unify_local_t *local = frame->local; - dir_entry_t *prev, *entry, *trav; - - LOCK (&frame->lock); - { - /* if local->call_count == 0, that means, setdents - on storagenodes is still pending. */ - if (local->call_count) - callcnt = --local->call_count; - } - UNLOCK (&frame->lock); - - - if (callcnt == 0) { - if (local->sh_struct->entry_list[0]) { - prev = entry = local->sh_struct->entry_list[0]; - trav = entry->next; - while (trav) { - prev->next = trav->next; - GF_FREE (trav->name); - if (IA_ISLNK (trav->buf.ia_type)) - GF_FREE (trav->link); - GF_FREE (trav); - trav = prev->next; - } - GF_FREE (entry); - } - - if (!local->flags) { - if (local->sh_struct->count_list[0] >= - UNIFY_SELF_HEAL_GETDENTS_COUNT) { - /* count == size, that means, there are more - entries to read from */ - //local->call_count = 0; - local->sh_struct->offset_list[0] += - UNIFY_SELF_HEAL_GETDENTS_COUNT; - STACK_WIND (frame, - unify_bgsh_ns_getdents_cbk, - NS(this), - NS(this)->fops->getdents, - local->fd, - UNIFY_SELF_HEAL_GETDENTS_COUNT, - local->sh_struct->offset_list[0], - GF_GET_DIR_ONLY); - } - } else { - fd_unref (local->fd); - unify_local_wipe (local); - STACK_DESTROY (frame->root); - } - } - - return 0; -} - - -int32_t -unify_bgsh_ns_getdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dir_entry_t *entry, - int32_t count) -{ - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - long index = 0; - unsigned long final = 0; - dir_entry_t *tmp = GF_CALLOC (1, sizeof (dir_entry_t), - gf_unify_mt_dir_entry_t); - - local->sh_struct->entry_list[0] = tmp; - local->sh_struct->count_list[0] = count; - if (entry) { - tmp->next = entry->next; - entry->next = NULL; - } - - if ((count < UNIFY_SELF_HEAL_GETDENTS_COUNT) || !entry) { - final = 1; - } - - LOCK (&frame->lock); - { - /* local->call_count will be '0' till now. make it 1 so, - it can be UNWIND'ed for the last call. */ - local->call_count = priv->child_count; - if (final) - local->flags = 1; - } - UNLOCK (&frame->lock); - - for (index = 0; index < priv->child_count; index++) - { - STACK_WIND_COOKIE (frame, - unify_bgsh_setdents_cbk, - (void *)index, - priv->xl_array[index], - priv->xl_array[index]->fops->setdents, - local->fd, GF_SET_DIR_ONLY, - local->sh_struct->entry_list[0], count); - } - - return 0; -} - -int32_t -unify_bgsh_ns_setdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - int32_t callcnt = -1; - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - long index = (long)cookie; - dir_entry_t *prev, *entry, *trav; - - if (local->sh_struct->entry_list[index]) { - prev = entry = local->sh_struct->entry_list[index]; - if (!entry) - return 0; - trav = entry->next; - while (trav) { - prev->next = trav->next; - GF_FREE (trav->name); - if (IA_ISLNK (trav->buf.ia_type)) - GF_FREE (trav->link); - GF_FREE (trav); - trav = prev->next; - } - GF_FREE (entry); - } - - if (local->sh_struct->count_list[index] < - UNIFY_SELF_HEAL_GETDENTS_COUNT) { - LOCK (&frame->lock); - { - callcnt = --local->call_count; - } - UNLOCK (&frame->lock); - } else { - /* count == size, that means, there are more entries - to read from */ - local->sh_struct->offset_list[index] += - UNIFY_SELF_HEAL_GETDENTS_COUNT; - STACK_WIND_COOKIE (frame, - unify_bgsh_getdents_cbk, - cookie, - priv->xl_array[index], - priv->xl_array[index]->fops->getdents, - local->fd, - UNIFY_SELF_HEAL_GETDENTS_COUNT, - local->sh_struct->offset_list[index], - GF_GET_ALL); - - gf_log (this->name, GF_LOG_DEBUG, - "readdir on (%s) with offset %"PRId64"", - priv->xl_array[index]->name, - local->sh_struct->offset_list[index]); - } - - if (!callcnt) { - /* All storage nodes have done unified setdents on NS node. - * Now, do getdents from NS and do setdents on storage nodes. - */ - - /* sh_struct->offset_list is no longer required for - storage nodes now */ - local->sh_struct->offset_list[0] = 0; /* reset */ - - STACK_WIND (frame, - unify_bgsh_ns_getdents_cbk, - NS(this), - NS(this)->fops->getdents, - local->fd, - UNIFY_SELF_HEAL_GETDENTS_COUNT, - 0, /* In this call, do send '0' as offset */ - GF_GET_DIR_ONLY); - } - - return 0; -} - - -/** - * unify_bgsh_getdents_cbk - - */ -int32_t -unify_bgsh_getdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dir_entry_t *entry, - int32_t count) -{ - int32_t callcnt = -1; - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - long index = (long)cookie; - dir_entry_t *tmp = NULL; - - if (op_ret >= 0 && count > 0) { - /* There is some dentry found, just send the dentry to NS */ - tmp = GF_CALLOC (1, sizeof (dir_entry_t), - gf_unify_mt_dir_entry_t); - local->sh_struct->entry_list[index] = tmp; - local->sh_struct->count_list[index] = count; - if (entry) { - tmp->next = entry->next; - entry->next = NULL; - } - STACK_WIND_COOKIE (frame, - unify_bgsh_ns_setdents_cbk, - cookie, - NS(this), - NS(this)->fops->setdents, - local->fd, - GF_SET_IF_NOT_PRESENT, - local->sh_struct->entry_list[index], - count); - return 0; - } - - if (count < UNIFY_SELF_HEAL_GETDENTS_COUNT) { - LOCK (&frame->lock); - { - callcnt = --local->call_count; - } - UNLOCK (&frame->lock); - } else { - /* count == size, that means, there are more entries to read from */ - local->sh_struct->offset_list[index] += - UNIFY_SELF_HEAL_GETDENTS_COUNT; - - STACK_WIND_COOKIE (frame, - unify_bgsh_getdents_cbk, - cookie, - priv->xl_array[index], - priv->xl_array[index]->fops->getdents, - local->fd, - UNIFY_SELF_HEAL_GETDENTS_COUNT, - local->sh_struct->offset_list[index], - GF_GET_ALL); - - gf_log (this->name, GF_LOG_DEBUG, - "readdir on (%s) with offset %"PRId64"", - priv->xl_array[index]->name, - local->sh_struct->offset_list[index]); - } - - if (!callcnt) { - /* All storage nodes have done unified setdents on NS node. - * Now, do getdents from NS and do setdents on storage nodes. - */ - - /* sh_struct->offset_list is no longer required for - storage nodes now */ - local->sh_struct->offset_list[0] = 0; /* reset */ - - STACK_WIND (frame, - unify_bgsh_ns_getdents_cbk, - NS(this), - NS(this)->fops->getdents, - local->fd, - UNIFY_SELF_HEAL_GETDENTS_COUNT, - 0, /* In this call, do send '0' as offset */ - GF_GET_DIR_ONLY); - } - - return 0; -} - -/** - * unify_bgsh_opendir_cbk - - * - * @cookie: - */ -int32_t -unify_bgsh_opendir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd) -{ - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - int32_t callcnt = 0; - int16_t index = 0; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - - if (op_ret >= 0) { - local->op_ret = op_ret; - } else { - local->failed = 1; - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - local->call_count = priv->child_count + 1; - - if (!local->failed) { - /* send getdents() namespace after finishing - storage nodes */ - local->call_count--; - callcnt = local->call_count; - - fd_bind (fd); - - if (local->call_count) { - /* Used as the offset index. This list keeps - track of offset sent to each node during - STACK_WIND. */ - local->sh_struct->offset_list = - GF_CALLOC (priv->child_count, - sizeof (off_t), - gf_unify_mt_off_t); - ERR_ABORT (local->sh_struct->offset_list); - - local->sh_struct->entry_list = - GF_CALLOC (priv->child_count, - sizeof (dir_entry_t *), - gf_unify_mt_dir_entry_t); - ERR_ABORT (local->sh_struct->entry_list); - - local->sh_struct->count_list = - GF_CALLOC (priv->child_count, - sizeof (int), - gf_unify_mt_int); - ERR_ABORT (local->sh_struct->count_list); - - /* Send getdents on all the fds */ - for (index = 0; - index < priv->child_count; index++) { - STACK_WIND_COOKIE (frame, - unify_bgsh_getdents_cbk, - (void *)(long)index, - priv->xl_array[index], - priv->xl_array[index]->fops->getdents, - local->fd, - UNIFY_SELF_HEAL_GETDENTS_COUNT, - 0, /* In this call, do send '0' as offset */ - GF_GET_ALL); - } - /* did a stack wind, so no need to unwind here */ - return 0; - } /* (local->call_count) */ - } /* (!local->failed) */ - - /* Opendir failed on one node. */ - fd_unref (local->fd); - - unify_local_wipe (local); - STACK_DESTROY (frame->root); - } - - return 0; -} - -/** - * gf_bgsh_checksum_cbk - - * - * @frame: frame used in lookup. get a copy of it, and use that copy. - * @this: pointer to unify xlator. - * @inode: pointer to inode, for which the consistency check is required. - * - */ -int32_t -unify_bgsh_checksum_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - uint8_t *file_checksum, - uint8_t *dir_checksum) -{ - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - int16_t index = 0; - int32_t callcnt = 0; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - if (op_ret >= 0) { - if (NS(this) == (xlator_t *)cookie) { - memcpy (local->sh_struct->ns_file_checksum, - file_checksum, NAME_MAX); - memcpy (local->sh_struct->ns_dir_checksum, - dir_checksum, NAME_MAX); - } else { - if (local->entry_count == 0) { - /* Initialize the dir_checksum to be - * used for comparision with other - * storage nodes. Should be done for - * the first successful call *only*. - */ - /* Using 'entry_count' as a flag */ - local->entry_count = 1; - memcpy (local->sh_struct->dir_checksum, - dir_checksum, NAME_MAX); - } - - /* Reply from the storage nodes */ - for (index = 0; - index < NAME_MAX; index++) { - /* Files should be present in only - one node */ - local->sh_struct->file_checksum[index] ^= file_checksum[index]; - - /* directory structure should be same - accross */ - if (local->sh_struct->dir_checksum[index] != dir_checksum[index]) - local->failed = 1; - } - } - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - for (index = 0; index < NAME_MAX ; index++) { - if (local->sh_struct->file_checksum[index] != - local->sh_struct->ns_file_checksum[index]) { - local->failed = 1; - break; - } - if (local->sh_struct->dir_checksum[index] != - local->sh_struct->ns_dir_checksum[index]) { - local->failed = 1; - break; - } - } - - if (local->failed) { - /* Log it, it should be a rare event */ - gf_log (this->name, GF_LOG_WARNING, - "Self-heal triggered on directory %s", - local->loc1.path); - - /* Any self heal will be done at the directory level */ - local->op_ret = -1; - local->failed = 0; - - local->fd = fd_create (local->loc1.inode, - frame->root->pid); - local->call_count = priv->child_count + 1; - - for (index = 0; - index < (priv->child_count + 1); index++) { - STACK_WIND_COOKIE (frame, - unify_bgsh_opendir_cbk, - priv->xl_array[index]->name, - priv->xl_array[index], - priv->xl_array[index]->fops->opendir, - &local->loc1, - local->fd); - } - - /* opendir can be done on the directory */ - return 0; - } - - /* no mismatch */ - unify_local_wipe (local); - STACK_DESTROY (frame->root); - } - - return 0; -} - -/* Background self-heal part over */ - - - - -/** - * zr_unify_self_heal - - * - * @frame: frame used in lookup. get a copy of it, and use that copy. - * @this: pointer to unify xlator. - * @inode: pointer to inode, for which the consistency check is required. - * - */ -int32_t -zr_unify_self_heal (call_frame_t *frame, - xlator_t *this, - unify_local_t *local) -{ - unify_private_t *priv = this->private; - call_frame_t *bg_frame = NULL; - unify_local_t *bg_local = NULL; - inode_t *tmp_inode = NULL; - dict_t *tmp_dict = NULL; - int16_t index = 0; - - if (local->inode_generation < priv->inode_generation) { - /* Any self heal will be done at the directory level */ - /* Update the inode's generation to the current generation - value. */ - local->inode_generation = priv->inode_generation; - inode_ctx_put (local->loc1.inode, this, - (uint64_t)(long)local->inode_generation); - - if (priv->self_heal == ZR_UNIFY_FG_SELF_HEAL) { - local->op_ret = 0; - local->failed = 0; - local->call_count = priv->child_count + 1; - local->sh_struct = - GF_CALLOC (1, sizeof (struct unify_self_heal_struct), - gf_unify_mt_unify_self_heal_struct); - - /* +1 is for NS */ - for (index = 0; - index < (priv->child_count + 1); index++) { - STACK_WIND_COOKIE (frame, - unify_sh_checksum_cbk, - priv->xl_array[index], - priv->xl_array[index], - priv->xl_array[index]->fops->checksum, - &local->loc1, - 0); - } - - /* Self-heal in foreground, hence no need - to UNWIND here */ - return 0; - } - - /* Self Heal done in background */ - bg_frame = copy_frame (frame); - INIT_LOCAL (bg_frame, bg_local); - loc_copy (&bg_local->loc1, &local->loc1); - bg_local->op_ret = 0; - bg_local->failed = 0; - bg_local->call_count = priv->child_count + 1; - bg_local->sh_struct = - GF_CALLOC (1, sizeof (struct unify_self_heal_struct), - gf_unify_mt_unify_self_heal_struct); - - /* +1 is for NS */ - for (index = 0; index < (priv->child_count + 1); index++) { - STACK_WIND_COOKIE (bg_frame, - unify_bgsh_checksum_cbk, - priv->xl_array[index], - priv->xl_array[index], - priv->xl_array[index]->fops->checksum, - &bg_local->loc1, - 0); - } - } - - /* generation number matches, self heal already done or - * self heal done in background: just do STACK_UNWIND - */ - tmp_inode = local->loc1.inode; - tmp_dict = local->dict; - - unify_local_wipe (local); - - /* This is lookup_cbk ()'s UNWIND. */ - STACK_UNWIND (frame, - local->op_ret, - local->op_errno, - tmp_inode, - &local->stbuf, - local->dict, - &local->oldpostparent); - - if (tmp_dict) - dict_unref (tmp_dict); - - return 0; -} - diff --git a/xlators/cluster/unify/src/unify.c b/xlators/cluster/unify/src/unify.c deleted file mode 100644 index f3da6d0bac7..00000000000 --- a/xlators/cluster/unify/src/unify.c +++ /dev/null @@ -1,4589 +0,0 @@ -/* - Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.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/>. -*/ - -/** - * xlators/cluster/unify: - * - This xlator is one of the main translator in GlusterFS, which - * actually does the clustering work of the file system. One need to - * understand that, unify assumes file to be existing in only one of - * the child node, and directories to be present on all the nodes. - * - * NOTE: - * Now, unify has support for global namespace, which is used to keep a - * global view of fs's namespace tree. The stat for directories are taken - * just from the namespace, where as for files, just 'ia_ino' is taken from - * Namespace node, and other stat info is taken from the actual storage node. - * Also Namespace node helps to keep consistant inode for files across - * glusterfs (re-)mounts. - */ - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include "glusterfs.h" -#include "unify.h" -#include "dict.h" -#include "xlator.h" -#include "hashfn.h" -#include "logging.h" -#include "stack.h" -#include "defaults.h" -#include "common-utils.h" -#include <signal.h> -#include <libgen.h> -#include "compat-errno.h" -#include "compat.h" - -#define UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR(_loc) do { \ - if (!(_loc && _loc->inode)) { \ - STACK_UNWIND (frame, -1, EINVAL, NULL, NULL, NULL); \ - return 0; \ - } \ -} while(0) - - -#define UNIFY_CHECK_FD_CTX_AND_UNWIND_ON_ERR(_fd) do { \ - if (!(_fd && !fd_ctx_get (_fd, this, NULL))) { \ - STACK_UNWIND (frame, -1, EBADFD, NULL, NULL); \ - return 0; \ - } \ -} while(0) - -#define UNIFY_CHECK_FD_AND_UNWIND_ON_ERR(_fd) do { \ - if (!_fd) { \ - STACK_UNWIND (frame, -1, EBADFD, NULL, NULL); \ - return 0; \ - } \ -} while(0) - -/** - * unify_local_wipe - free all the extra allocation of local->* here. - */ -static void -unify_local_wipe (unify_local_t *local) -{ - /* Free the strdup'd variables in the local structure */ - if (local->name) { - GF_FREE (local->name); - } - loc_wipe (&local->loc1); - loc_wipe (&local->loc2); -} - - - -/* - * unify_normalize_stats - - */ -void -unify_normalize_stats (struct statvfs *buf, - unsigned long bsize, - unsigned long frsize) -{ - double factor; - - if (buf->f_bsize != bsize) { - factor = ((double) buf->f_bsize) / bsize; - buf->f_bsize = bsize; - buf->f_bfree = (fsblkcnt_t) (factor * buf->f_bfree); - buf->f_bavail = (fsblkcnt_t) (factor * buf->f_bavail); - } - - if (buf->f_frsize != frsize) { - factor = ((double) buf->f_frsize) / frsize; - buf->f_frsize = frsize; - buf->f_blocks = (fsblkcnt_t) (factor * buf->f_blocks); - } -} - - -xlator_t * -unify_loc_subvol (loc_t *loc, xlator_t *this) -{ - unify_private_t *priv = NULL; - xlator_t *subvol = NULL; - int16_t *list = NULL; - long index = 0; - xlator_t *subvol_i = NULL; - int ret = 0; - uint64_t tmp_list = 0; - - priv = this->private; - subvol = NS (this); - - if (!IA_ISDIR (loc->inode->ia_type)) { - ret = inode_ctx_get (loc->inode, this, &tmp_list); - list = (int16_t *)(long)tmp_list; - if (!list) - goto out; - - for (index = 0; list[index] != -1; index++) { - subvol_i = priv->xl_array[list[index]]; - if (subvol_i != NS (this)) { - subvol = subvol_i; - break; - } - } - } -out: - return subvol; -} - - - -/** - * unify_statfs_cbk - - */ -int32_t -unify_statfs_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct statvfs *stbuf) -{ - int32_t callcnt = 0; - struct statvfs *dict_buf = NULL; - unsigned long bsize; - unsigned long frsize; - unify_local_t *local = (unify_local_t *)frame->local; - call_frame_t *prev_frame = cookie; - - LOCK (&frame->lock); - { - if (op_ret >= 0) { - /* when a call is successfull, add it to local->dict */ - dict_buf = &local->statvfs_buf; - - if (dict_buf->f_bsize != 0) { - bsize = max (dict_buf->f_bsize, - stbuf->f_bsize); - - frsize = max (dict_buf->f_frsize, - stbuf->f_frsize); - unify_normalize_stats(dict_buf, bsize, frsize); - unify_normalize_stats(stbuf, bsize, frsize); - } else { - dict_buf->f_bsize = stbuf->f_bsize; - dict_buf->f_frsize = stbuf->f_frsize; - } - - dict_buf->f_blocks += stbuf->f_blocks; - dict_buf->f_bfree += stbuf->f_bfree; - dict_buf->f_bavail += stbuf->f_bavail; - dict_buf->f_files += stbuf->f_files; - dict_buf->f_ffree += stbuf->f_ffree; - dict_buf->f_favail += stbuf->f_favail; - dict_buf->f_fsid = stbuf->f_fsid; - dict_buf->f_flag = stbuf->f_flag; - dict_buf->f_namemax = stbuf->f_namemax; - local->op_ret = op_ret; - } else { - /* fop on storage node has failed due to some error */ - if (op_errno != ENOTCONN) { - gf_log (this->name, GF_LOG_ERROR, - "child(%s): %s", - prev_frame->this->name, - strerror (op_errno)); - } - local->op_errno = op_errno; - } - callcnt = --local->call_count; - } - UNLOCK (&frame->lock); - - if (!callcnt) { - STACK_UNWIND (frame, local->op_ret, local->op_errno, - &local->statvfs_buf); - } - - return 0; -} - -/** - * unify_statfs - - */ -int32_t -unify_statfs (call_frame_t *frame, - xlator_t *this, - loc_t *loc) -{ - unify_local_t *local = NULL; - xlator_list_t *trav = this->children; - - INIT_LOCAL (frame, local); - local->call_count = ((unify_private_t *)this->private)->child_count; - - while(trav) { - STACK_WIND (frame, - unify_statfs_cbk, - trav->xlator, - trav->xlator->fops->statfs, - loc); - trav = trav->next; - } - - return 0; -} - -/** - * unify_buf_cbk - - */ -int32_t -unify_buf_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *buf) -{ - int32_t callcnt = 0; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - call_frame_t *prev_frame = cookie; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - - if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, - "%s(): child(%s): path(%s): %s", - gf_fop_list[frame->root->op], - prev_frame->this->name, - (local->loc1.path)?local->loc1.path:"", - strerror (op_errno)); - - local->op_errno = op_errno; - if ((op_errno == ENOENT) && priv->optimist) - local->op_ret = 0; - } - - if (op_ret >= 0) { - local->op_ret = 0; - - if (NS (this) == prev_frame->this) { - local->ia_ino = buf->ia_ino; - /* If the entry is directory, get the stat - from NS node */ - if (IA_ISDIR (buf->ia_type) || - !local->stbuf.ia_blksize) { - local->stbuf = *buf; - } - } - - if ((!IA_ISDIR (buf->ia_type)) && - (NS (this) != prev_frame->this)) { - /* If file, take the stat info from Storage - node. */ - local->stbuf = *buf; - } - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - /* If the inode number is not filled, operation should - fail */ - if (!local->ia_ino) - local->op_ret = -1; - - local->stbuf.ia_ino = local->ia_ino; - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, local->op_errno, - &local->stbuf); - } - - return 0; -} - -#define check_if_dht_linkfile(s) \ - ((st_mode_from_ia (s->ia_prot, s->ia_type) & ~S_IFMT) == S_ISVTX) - -/** - * unify_lookup_cbk - - */ -int32_t -unify_lookup_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - dict_t *dict, - struct iatt *postparent) -{ - int32_t callcnt = 0; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - inode_t *tmp_inode = NULL; - dict_t *local_dict = NULL; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - - if (op_ret == -1) { - if (local->revalidate && - (op_errno == ESTALE)) { - /* ESTALE takes priority */ - local->op_errno = op_errno; - local->failed = 1; - } - - if ((op_errno != ENOTCONN) - && (op_errno != ENOENT) - && (local->op_errno != ESTALE)) { - /* if local->op_errno is already ESTALE, then - * ESTALE has to propogated to the parent first. - * do not enter here. - */ - gf_log (this->name, GF_LOG_ERROR, - "child(%s): path(%s): %s", - priv->xl_array[(long)cookie]->name, - local->loc1.path, strerror (op_errno)); - local->op_errno = op_errno; - local->failed = 1; - - } else if (local->revalidate && - (local->op_errno != ESTALE) && - !(priv->optimist && (op_errno == ENOENT))) { - - gf_log (this->name, - (op_errno == ENOTCONN) ? - GF_LOG_DEBUG:GF_LOG_ERROR, - "child(%s): path(%s): %s", - priv->xl_array[(long)cookie]->name, - local->loc1.path, strerror (op_errno)); - local->op_errno = op_errno; - local->failed = 1; - } - } - - if (op_ret == 0) { - local->op_ret = 0; - - if (check_if_dht_linkfile(buf)) { - gf_log (this->name, GF_LOG_CRITICAL, - "file %s may be DHT link file on %s, " - "make sure the backend is not shared " - "between unify and DHT", - local->loc1.path, - priv->xl_array[(long)cookie]->name); - } - - if (local->stbuf.ia_type && local->stbuf.ia_blksize) { - /* make sure we already have a stbuf - stored in local->stbuf */ - if (IA_ISDIR (local->stbuf.ia_type) && - !IA_ISDIR (buf->ia_type)) { - gf_log (this->name, GF_LOG_CRITICAL, - "[CRITICAL] '%s' is directory " - "on namespace, non-directory " - "on node '%s', returning EIO", - local->loc1.path, - priv->xl_array[(long)cookie]->name); - local->return_eio = 1; - } - if (!IA_ISDIR (local->stbuf.ia_type) && - IA_ISDIR (buf->ia_type)) { - gf_log (this->name, GF_LOG_CRITICAL, - "[CRITICAL] '%s' is directory " - "on node '%s', non-directory " - "on namespace, returning EIO", - local->loc1.path, - priv->xl_array[(long)cookie]->name); - local->return_eio = 1; - } - } - - if (!local->revalidate && !IA_ISDIR (buf->ia_type)) { - /* This is the first time lookup on file*/ - if (!local->list) { - /* list is not allocated, allocate - the max possible range */ - local->list = GF_CALLOC (1, 2 * (priv->child_count + 2), - gf_unify_mt_int16_t); - if (!local->list) { - gf_log (this->name, - GF_LOG_CRITICAL, - "Not enough memory"); - STACK_UNWIND (frame, -1, - ENOMEM, inode, - NULL, NULL, NULL); - return 0; - } - } - /* update the index of the list */ - local->list [local->index++] = - (int16_t)(long)cookie; - } - - if (!local->revalidate && IA_ISDIR (buf->ia_type)) { - /* fresh lookup of a directory */ - inode_ctx_put (local->loc1.inode, this, - priv->inode_generation); - } - - if ((!local->dict) && dict && - (priv->xl_array[(long)cookie] != NS(this))) { - local->dict = dict_ref (dict); - } - - /* index of NS node is == total child count */ - if (priv->child_count == (int16_t)(long)cookie) { - /* Take the inode number from namespace */ - local->ia_ino = buf->ia_ino; - if (IA_ISDIR (buf->ia_type) || - !(local->stbuf.ia_blksize)) { - local->stbuf = *buf; - local->oldpostparent = *postparent; - } - } else if (!IA_ISDIR (buf->ia_type)) { - /* If file, then get the stat from - storage node */ - local->stbuf = *buf; - } - - if (local->ia_nlink < buf->ia_nlink) { - local->ia_nlink = buf->ia_nlink; - } - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - local_dict = local->dict; - if (local->return_eio) { - gf_log (this->name, GF_LOG_CRITICAL, - "[CRITICAL] Unable to fix the path (%s) with " - "self-heal, try manual verification. " - "returning EIO.", local->loc1.path); - unify_local_wipe (local); - STACK_UNWIND (frame, -1, EIO, inode, NULL, NULL); - if (local_dict) { - dict_unref (local_dict); - } - return 0; - } - - if (!local->stbuf.ia_blksize) { - /* Inode not present */ - local->op_ret = -1; - } else { - if (!local->revalidate && - !IA_ISDIR (local->stbuf.ia_type)) { - /* If its a file, big array is useless, - allocate the smaller one */ - int16_t *list = NULL; - list = GF_CALLOC (1, 2 * (local->index + 1), - gf_unify_mt_int16_t); - ERR_ABORT (list); - memcpy (list, local->list, 2 * local->index); - /* Make the end of the list as -1 */ - GF_FREE (local->list); - local->list = list; - local->list [local->index] = -1; - /* Update the inode's ctx with proper array */ - /* TODO: log on failure */ - inode_ctx_put (local->loc1.inode, this, - (uint64_t)(long)local->list); - } - - if (IA_ISDIR(local->loc1.inode->ia_type)) { - /* lookup is done for directory */ - if (local->failed && priv->self_heal) { - /* Triggering self-heal */ - /* means, self-heal required for this - inode */ - local->inode_generation = 0; - priv->inode_generation++; - } - } else { - local->stbuf.ia_ino = local->ia_ino; - } - - local->stbuf.ia_nlink = local->ia_nlink; - } - if (local->op_ret == -1) { - if (!local->revalidate && local->list) - GF_FREE (local->list); - } - - if ((local->op_ret >= 0) && local->failed && - local->revalidate) { - /* Done revalidate, but it failed */ - if ((op_errno != ENOTCONN) - && (local->op_errno != ESTALE)) { - gf_log (this->name, GF_LOG_ERROR, - "Revalidate failed for path(%s): %s", - local->loc1.path, strerror (op_errno)); - } - local->op_ret = -1; - } - - if ((priv->self_heal && !priv->optimist) && - (!local->revalidate && (local->op_ret == 0) && - IA_ISDIR(local->stbuf.ia_type))) { - /* Let the self heal be done here */ - zr_unify_self_heal (frame, this, local); - local_dict = NULL; - } else { - if (local->failed) { - /* NOTE: directory lookup is sent to all - * subvolumes and success from a subvolume - * might set local->op_ret to 0 (zero) */ - local->op_ret = -1; - } - - /* either no self heal, or op_ret == -1 (failure) */ - tmp_inode = local->loc1.inode; - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, local->op_errno, - tmp_inode, &local->stbuf, local->dict, - &local->oldpostparent); - } - if (local_dict) { - dict_unref (local_dict); - } - } - - return 0; -} - -/** - * unify_lookup - - */ -int32_t -unify_lookup (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - dict_t *xattr_req) -{ - unify_local_t *local = NULL; - unify_private_t *priv = this->private; - int16_t *list = NULL; - long index = 0; - - if (!(loc && loc->inode)) { - gf_log (this->name, GF_LOG_ERROR, - "%s: Argument not right", loc?loc->path:"(null)"); - STACK_UNWIND (frame, -1, EINVAL, NULL, NULL, NULL, NULL); - return 0; - } - - /* Initialization */ - INIT_LOCAL (frame, local); - loc_copy (&local->loc1, loc); - if (local->loc1.path == NULL) { - gf_log (this->name, GF_LOG_CRITICAL, "Not enough memory :O"); - STACK_UNWIND (frame, -1, ENOMEM, loc->inode, NULL, NULL, NULL); - return 0; - } - - if (inode_ctx_get (loc->inode, this, NULL) - && IA_ISDIR (loc->inode->ia_type)) { - local->revalidate = 1; - } - - if (!inode_ctx_get (loc->inode, this, NULL) && - loc->inode->ia_type && - !IA_ISDIR (loc->inode->ia_type)) { - uint64_t tmp_list = 0; - /* check if revalidate or fresh lookup */ - inode_ctx_get (loc->inode, this, &tmp_list); - local->list = (int16_t *)(long)tmp_list; - } - - if (local->list) { - list = local->list; - for (index = 0; list[index] != -1; index++); - if (index != 2) { - if (index < 2) { - gf_log (this->name, GF_LOG_ERROR, - "returning ESTALE for %s: file " - "count is %ld", loc->path, index); - /* Print where all the file is present */ - for (index = 0; - local->list[index] != -1; index++) { - gf_log (this->name, GF_LOG_ERROR, - "%s: found on %s", loc->path, - priv->xl_array[list[index]]->name); - } - unify_local_wipe (local); - STACK_UNWIND (frame, -1, ESTALE, - NULL, NULL, NULL, NULL); - return 0; - } else { - /* There are more than 2 presences */ - /* Just log and continue */ - gf_log (this->name, GF_LOG_ERROR, - "%s: file count is %ld", - loc->path, index); - /* Print where all the file is present */ - for (index = 0; - local->list[index] != -1; index++) { - gf_log (this->name, GF_LOG_ERROR, - "%s: found on %s", loc->path, - priv->xl_array[list[index]]->name); - } - } - } - - /* is revalidate */ - local->revalidate = 1; - - for (index = 0; list[index] != -1; index++) - local->call_count++; - - for (index = 0; list[index] != -1; index++) { - char need_break = (list[index+1] == -1); - STACK_WIND_COOKIE (frame, - unify_lookup_cbk, - (void *)(long)list[index], //cookie - priv->xl_array [list[index]], - priv->xl_array [list[index]]->fops->lookup, - loc, - xattr_req); - if (need_break) - break; - } - } else { - if (loc->inode->ia_type) { - if (inode_ctx_get (loc->inode, this, NULL)) { - inode_ctx_get (loc->inode, this, - &local->inode_generation); - } - } - /* This is first call, there is no list */ - /* call count should be all child + 1 namespace */ - local->call_count = priv->child_count + 1; - - for (index = 0; index <= priv->child_count; index++) { - STACK_WIND_COOKIE (frame, - unify_lookup_cbk, - (void *)index, //cookie - priv->xl_array[index], - priv->xl_array[index]->fops->lookup, - loc, - xattr_req); - } - } - - return 0; -} - -/** - * unify_stat - if directory, get the stat directly from NameSpace child. - * if file, check for a hint and send it only there (also to NS). - * if its a fresh stat, then do it on all the nodes. - * - * NOTE: for all the call, sending cookie as xlator pointer, which will be - * used in cbk. - */ -int32_t -unify_stat (call_frame_t *frame, - xlator_t *this, - loc_t *loc) -{ - unify_local_t *local = NULL; - unify_private_t *priv = this->private; - int16_t index = 0; - int16_t *list = NULL; - uint64_t tmp_list = 0; - - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (loc); - - /* Initialization */ - INIT_LOCAL (frame, local); - loc_copy (&local->loc1, loc); - if (local->loc1.path == NULL) { - gf_log (this->name, GF_LOG_CRITICAL, "Not enough memory :O"); - STACK_UNWIND (frame, -1, ENOMEM, NULL); - return 0; - } - local->ia_ino = loc->inode->ino; - if (IA_ISDIR (loc->inode->ia_type)) { - /* Directory */ - local->call_count = 1; - STACK_WIND (frame, unify_buf_cbk, NS(this), - NS(this)->fops->stat, loc); - } else { - /* File */ - inode_ctx_get (loc->inode, this, &tmp_list); - list = (int16_t *)(long)tmp_list; - - for (index = 0; list[index] != -1; index++) - local->call_count++; - - for (index = 0; list[index] != -1; index++) { - char need_break = (list[index+1] == -1); - STACK_WIND (frame, - unify_buf_cbk, - priv->xl_array[list[index]], - priv->xl_array[list[index]]->fops->stat, - loc); - if (need_break) - break; - } - } - - return 0; -} - -/** - * unify_access_cbk - - */ -int32_t -unify_access_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - STACK_UNWIND (frame, op_ret, op_errno); - return 0; -} - - -/** - * unify_access - Send request to only namespace, which has all the - * attributes set for the file. - */ -int32_t -unify_access (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t mask) -{ - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (loc); - - STACK_WIND (frame, - unify_access_cbk, - NS(this), - NS(this)->fops->access, - loc, - mask); - - return 0; -} - -int32_t -unify_mkdir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent) -{ - int32_t callcnt = 0; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - inode_t *tmp_inode = NULL; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - - if ((op_ret == -1) && !(priv->optimist && - (op_errno == ENOENT || - op_errno == EEXIST))) { - /* TODO: Decrement the inode_generation of - * this->inode's parent inode, hence the missing - * directory is created properly by self-heal. - * Currently, there is no way to get the parent - * inode directly. - */ - gf_log (this->name, GF_LOG_ERROR, - "child(%s): path(%s): %s", - priv->xl_array[(long)cookie]->name, - local->loc1.path, strerror (op_errno)); - if (op_errno != EEXIST) - local->failed = 1; - local->op_errno = op_errno; - } - - if (op_ret >= 0) - local->op_ret = 0; - - } - UNLOCK (&frame->lock); - - if (!callcnt) { - if (!local->failed) { - inode_ctx_put (local->loc1.inode, this, - priv->inode_generation); - } - - tmp_inode = local->loc1.inode; - unify_local_wipe (local); - - STACK_UNWIND (frame, local->op_ret, local->op_errno, - tmp_inode, &local->stbuf, - &local->oldpreparent, &local->oldpostparent); - } - - return 0; -} - -/** - * unify_ns_mkdir_cbk - - */ -int32_t -unify_ns_mkdir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent) -{ - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - long index = 0; - - if (op_ret == -1) { - /* No need to send mkdir request to other servers, - * as namespace action failed - */ - gf_log (this->name, GF_LOG_ERROR, - "namespace: path(%s): %s", - local->name, strerror (op_errno)); - unify_local_wipe (local); - STACK_UNWIND (frame, op_ret, op_errno, inode, NULL, - NULL, NULL); - return 0; - } - - /* Create one inode for this entry */ - local->op_ret = 0; - local->stbuf = *buf; - - local->oldpreparent = *preparent; - local->oldpostparent = *postparent; - - local->call_count = priv->child_count; - - /* Send mkdir request to all the nodes now */ - for (index = 0; index < priv->child_count; index++) { - STACK_WIND_COOKIE (frame, - unify_mkdir_cbk, - (void *)index, //cookie - priv->xl_array[index], - priv->xl_array[index]->fops->mkdir, - &local->loc1, - local->mode); - } - - return 0; -} - - -/** - * unify_mkdir - - */ -int32_t -unify_mkdir (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - mode_t mode) -{ - unify_local_t *local = NULL; - - /* Initialization */ - INIT_LOCAL (frame, local); - local->mode = mode; - - loc_copy (&local->loc1, loc); - - if (local->loc1.path == NULL) { - gf_log (this->name, GF_LOG_CRITICAL, "Not enough memory :O"); - STACK_UNWIND (frame, -1, ENOMEM, NULL, NULL); - return 0; - } - - STACK_WIND (frame, - unify_ns_mkdir_cbk, - NS(this), - NS(this)->fops->mkdir, - loc, - mode); - return 0; -} - -/** - * unify_rmdir_cbk - - */ -int32_t -unify_rmdir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *preparent, - struct iatt *postparent) -{ - int32_t callcnt = 0; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - if (op_ret == 0 || (priv->optimist && (op_errno == ENOENT))) - local->op_ret = 0; - if (op_ret == -1) - local->op_errno = op_errno; - } - UNLOCK (&frame->lock); - - if (!callcnt) { - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, local->op_errno, - &local->oldpreparent, &local->oldpostparent); - } - - return 0; -} - -/** - * unify_ns_rmdir_cbk - - */ -int32_t -unify_ns_rmdir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *preparent, - struct iatt *postparent) -{ - int16_t index = 0; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - - if (op_ret == -1) { - /* No need to send rmdir request to other servers, - * as namespace action failed - */ - gf_log (this->name, - ((op_errno != ENOTEMPTY) ? - GF_LOG_ERROR : GF_LOG_DEBUG), - "namespace: path(%s): %s", - local->loc1.path, strerror (op_errno)); - unify_local_wipe (local); - STACK_UNWIND (frame, op_ret, op_errno, NULL, NULL); - return 0; - } - - local->call_count = priv->child_count; - - local->oldpreparent = *preparent; - local->oldpostparent = *postparent; - - for (index = 0; index < priv->child_count; index++) { - STACK_WIND (frame, - unify_rmdir_cbk, - priv->xl_array[index], - priv->xl_array[index]->fops->rmdir, - &local->loc1); - } - - return 0; -} - -/** - * unify_rmdir - - */ -int32_t -unify_rmdir (call_frame_t *frame, - xlator_t *this, - loc_t *loc) -{ - unify_local_t *local = NULL; - - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (loc); - - /* Initialization */ - INIT_LOCAL (frame, local); - - loc_copy (&local->loc1, loc); - if (local->loc1.path == NULL) { - gf_log (this->name, GF_LOG_CRITICAL, "Not enough memory :O"); - STACK_UNWIND (frame, -1, ENOMEM, NULL, NULL); - return 0; - } - - STACK_WIND (frame, - unify_ns_rmdir_cbk, - NS(this), - NS(this)->fops->rmdir, - loc); - - return 0; -} - -/** - * unify_open_cbk - - */ -int32_t -unify_open_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd) -{ - int32_t callcnt = 0; - unify_local_t *local = frame->local; - - LOCK (&frame->lock); - { - if (op_ret >= 0) { - local->op_ret = op_ret; - if (NS(this) != (xlator_t *)cookie) { - /* Store child node's ptr, used in - all the f*** / FileIO calls */ - fd_ctx_set (fd, this, (uint64_t)(long)cookie); - } - } - if (op_ret == -1) { - local->op_errno = op_errno; - local->failed = 1; - } - callcnt = --local->call_count; - } - UNLOCK (&frame->lock); - - if (!callcnt) { - if ((local->failed == 1) && (local->op_ret >= 0)) { - local->call_count = 1; - /* return -1 to user */ - local->op_ret = -1; - //local->op_errno = EIO; - - if (!fd_ctx_get (local->fd, this, NULL)) { - gf_log (this->name, GF_LOG_ERROR, - "Open success on child node, " - "failed on namespace"); - } else { - gf_log (this->name, GF_LOG_ERROR, - "Open success on namespace, " - "failed on child node"); - } - } - - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, - local->op_errno, local->fd); - } - - return 0; -} - -#ifdef GF_DARWIN_HOST_OS -/** - * unify_create_lookup_cbk - - */ -int32_t -unify_open_lookup_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - dict_t *dict, - struct iatt *postparent) -{ - int32_t callcnt = 0; - int16_t index = 0; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - if ((op_ret == -1) && (op_errno != ENOENT)) { - gf_log (this->name, GF_LOG_ERROR, - "child(%s): path(%s): %s", - priv->xl_array[(long)cookie]->name, - local->loc1.path, strerror (op_errno)); - local->op_errno = op_errno; - } - - if (op_ret >= 0) { - local->op_ret = op_ret; - local->index++; - if (NS(this) == priv->xl_array[(long)cookie]) { - local->list[0] = (int16_t)(long)cookie; - } else { - local->list[1] = (int16_t)(long)cookie; - } - if (IA_ISDIR (buf->ia_type)) - local->failed = 1; - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - int16_t file_list[3] = {0,}; - local->op_ret = -1; - - file_list[0] = local->list[0]; - file_list[1] = local->list[1]; - file_list[2] = -1; - - if (local->index != 2) { - /* Lookup failed, can't do open */ - gf_log (this->name, GF_LOG_ERROR, - "%s: present on %d nodes", - local->name, local->index); - - if (local->index < 2) { - unify_local_wipe (local); - gf_log (this->name, GF_LOG_ERROR, - "returning as file found on less " - "than 2 nodes"); - STACK_UNWIND (frame, local->op_ret, - local->op_errno, local->fd); - return 0; - } - } - - if (local->failed) { - /* Open on directory, return EISDIR */ - unify_local_wipe (local); - STACK_UNWIND (frame, -1, EISDIR, local->fd); - return 0; - } - - /* Everything is perfect :) */ - local->call_count = 2; - - for (index = 0; file_list[index] != -1; index++) { - char need_break = (file_list[index+1] == -1); - STACK_WIND_COOKIE (frame, - unify_open_cbk, - priv->xl_array[file_list[index]], - priv->xl_array[file_list[index]], - priv->xl_array[file_list[index]]->fops->open, - &local->loc1, - local->flags, - local->fd, local->wbflags); - if (need_break) - break; - } - } - - return 0; -} - - -int32_t -unify_open_readlink_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - const char *path, - struct iatt *sbuf) -{ - int16_t index = 0; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - - if (op_ret == -1) { - STACK_UNWIND (frame, -1, ENOENT); - return 0; - } - - if (path[0] == '/') { - local->name = gf_strdup (path); - ERR_ABORT (local->name); - } else { - char *tmp_str = gf_strdup (local->loc1.path); - char *tmp_base = dirname (tmp_str); - local->name = GF_CALLOC (1, PATH_MAX, gf_unify_mt_char); - strcpy (local->name, tmp_base); - strncat (local->name, "/", 1); - strcat (local->name, path); - GF_FREE (tmp_str); - } - - local->list = GF_CALLOC (1, sizeof (int16_t) * 3, - gf_unify_mt_int16_t); - ERR_ABORT (local->list); - local->call_count = priv->child_count + 1; - local->op_ret = -1; - for (index = 0; index <= priv->child_count; index++) { - /* Send the lookup to all the nodes including namespace */ - STACK_WIND_COOKIE (frame, - unify_open_lookup_cbk, - (void *)(long)index, - priv->xl_array[index], - priv->xl_array[index]->fops->lookup, - &local->loc1, - NULL); - } - - return 0; -} -#endif /* GF_DARWIN_HOST_OS */ - -/** - * unify_open - - */ -int32_t -unify_open (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flags, - fd_t *fd, - int32_t wbflags) -{ - unify_private_t *priv = this->private; - unify_local_t *local = NULL; - int16_t *list = NULL; - int16_t index = 0; - int16_t file_list[3] = {0,}; - uint64_t tmp_list = 0; - - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (loc); - - /* Init */ - INIT_LOCAL (frame, local); - loc_copy (&local->loc1, loc); - local->fd = fd; - local->flags = flags; - local->wbflags = wbflags; - inode_ctx_get (loc->inode, this, &tmp_list); - list = (int16_t *)(long)tmp_list; - - local->list = list; - file_list[0] = priv->child_count; /* Thats namespace */ - file_list[2] = -1; - for (index = 0; list[index] != -1; index++) { - local->call_count++; - if (list[index] != priv->child_count) - file_list[1] = list[index]; - } - - if (local->call_count != 2) { - /* If the lookup was done for file */ - gf_log (this->name, GF_LOG_ERROR, - "%s: entry_count is %d", - loc->path, local->call_count); - for (index = 0; local->list[index] != -1; index++) - gf_log (this->name, GF_LOG_ERROR, "%s: found on %s", - loc->path, priv->xl_array[list[index]]->name); - - if (local->call_count < 2) { - gf_log (this->name, GF_LOG_ERROR, - "returning EIO as file found on onlyone node"); - STACK_UNWIND (frame, -1, EIO, fd); - return 0; - } - } - -#ifdef GF_DARWIN_HOST_OS - /* Handle symlink here */ - if (IA_ISLNK (loc->inode->ia_type)) { - /* Callcount doesn't matter here */ - STACK_WIND (frame, - unify_open_readlink_cbk, - NS(this), - NS(this)->fops->readlink, - loc, PATH_MAX); - return 0; - } -#endif /* GF_DARWIN_HOST_OS */ - - local->call_count = 2; - for (index = 0; file_list[index] != -1; index++) { - char need_break = (file_list[index+1] == -1); - STACK_WIND_COOKIE (frame, - unify_open_cbk, - priv->xl_array[file_list[index]], //cookie - priv->xl_array[file_list[index]], - priv->xl_array[file_list[index]]->fops->open, - loc, - flags, - fd, wbflags); - if (need_break) - break; - } - - return 0; -} - - -int32_t -unify_create_unlink_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *preparent, - struct iatt *postparent) -{ - unify_local_t *local = frame->local; - inode_t *inode = local->loc1.inode; - - unify_local_wipe (local); - - STACK_UNWIND (frame, local->op_ret, local->op_errno, local->fd, - inode, &local->stbuf, - &local->oldpreparent, &local->oldpostparent); - - return 0; -} - -/** - * unify_create_open_cbk - - */ -int32_t -unify_create_open_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd) -{ - int ret = 0; - int32_t callcnt = 0; - unify_local_t *local = frame->local; - inode_t *inode = NULL; - xlator_t *child = NULL; - uint64_t tmp_value = 0; - - LOCK (&frame->lock); - { - if (op_ret >= 0) { - local->op_ret = op_ret; - if (NS(this) != (xlator_t *)cookie) { - /* Store child node's ptr, used in all - the f*** / FileIO calls */ - /* TODO: log on failure */ - ret = fd_ctx_get (fd, this, &tmp_value); - cookie = (void *)(long)tmp_value; - } else { - /* NOTE: open successful on namespace. - * fd's ctx can be used to identify open - * failure on storage subvolume. cool - * ide ;) */ - local->failed = 0; - } - } else { - gf_log (this->name, GF_LOG_ERROR, - "child(%s): path(%s): %s", - ((xlator_t *)cookie)->name, - local->loc1.path, strerror (op_errno)); - local->op_errno = op_errno; - local->failed = 1; - } - callcnt = --local->call_count; - } - UNLOCK (&frame->lock); - - if (!callcnt) { - if (local->failed == 1 && (local->op_ret >= 0)) { - local->call_count = 1; - /* return -1 to user */ - local->op_ret = -1; - local->op_errno = EIO; - local->fd = fd; - local->call_count = 1; - - if (!fd_ctx_get (local->fd, this, &tmp_value)) { - child = (xlator_t *)(long)tmp_value; - - gf_log (this->name, GF_LOG_ERROR, - "Create success on child node, " - "failed on namespace"); - - STACK_WIND (frame, - unify_create_unlink_cbk, - child, - child->fops->unlink, - &local->loc1); - } else { - gf_log (this->name, GF_LOG_ERROR, - "Create success on namespace, " - "failed on child node"); - - STACK_WIND (frame, - unify_create_unlink_cbk, - NS(this), - NS(this)->fops->unlink, - &local->loc1); - } - return 0; - } - inode = local->loc1.inode; - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, local->op_errno, fd, - inode, &local->stbuf, - &local->oldpreparent, &local->oldpostparent); - } - return 0; -} - -/** - * unify_create_lookup_cbk - - */ -int32_t -unify_create_lookup_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - dict_t *dict, - struct iatt *postparent) -{ - int32_t callcnt = 0; - int16_t index = 0; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, - "child(%s): path(%s): %s", - priv->xl_array[(long)cookie]->name, - local->loc1.path, strerror (op_errno)); - local->op_errno = op_errno; - local->failed = 1; - } - - if (op_ret >= 0) { - local->op_ret = op_ret; - local->list[local->index++] = (int16_t)(long)cookie; - if (NS(this) == priv->xl_array[(long)cookie]) { - local->ia_ino = buf->ia_ino; - } else { - local->stbuf = *buf; - } - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - int16_t *list = local->list; - int16_t file_list[3] = {0,}; - local->op_ret = -1; - - local->list [local->index] = -1; - file_list[0] = list[0]; - file_list[1] = list[1]; - file_list[2] = -1; - - local->stbuf.ia_ino = local->ia_ino; - /* TODO: log on failure */ - inode_ctx_put (local->loc1.inode, this, - (uint64_t)(long)local->list); - - if (local->index != 2) { - /* Lookup failed, can't do open */ - gf_log (this->name, GF_LOG_ERROR, - "%s: present on %d nodes", - local->loc1.path, local->index); - file_list[0] = priv->child_count; - for (index = 0; list[index] != -1; index++) { - gf_log (this->name, GF_LOG_ERROR, - "%s: found on %s", local->loc1.path, - priv->xl_array[list[index]]->name); - if (list[index] != priv->child_count) - file_list[1] = list[index]; - } - - if (local->index < 2) { - unify_local_wipe (local); - gf_log (this->name, GF_LOG_ERROR, - "returning EIO as file found on " - "only one node"); - STACK_UNWIND (frame, -1, EIO, - local->fd, inode, NULL, - NULL, NULL); - return 0; - } - } - /* Everything is perfect :) */ - local->call_count = 2; - - for (index = 0; file_list[index] != -1; index++) { - char need_break = (file_list[index+1] == -1); - STACK_WIND_COOKIE (frame, - unify_create_open_cbk, - priv->xl_array[file_list[index]], - priv->xl_array[file_list[index]], - priv->xl_array[file_list[index]]->fops->open, - &local->loc1, - local->flags, - local->fd, 0); - if (need_break) - break; - } - } - - return 0; -} - - -/** - * unify_create_cbk - - */ -int32_t -unify_create_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent) -{ - int ret = 0; - unify_local_t *local = frame->local; - call_frame_t *prev_frame = cookie; - inode_t *tmp_inode = NULL; - - if (op_ret == -1) { - /* send unlink () on Namespace */ - local->op_errno = op_errno; - local->op_ret = -1; - local->call_count = 1; - gf_log (this->name, GF_LOG_ERROR, - "create failed on %s (file %s, error %s), " - "sending unlink to namespace", - prev_frame->this->name, - local->loc1.path, strerror (op_errno)); - - STACK_WIND (frame, - unify_create_unlink_cbk, - NS(this), - NS(this)->fops->unlink, - &local->loc1); - - return 0; - } - - if (op_ret >= 0) { - local->op_ret = op_ret; - local->stbuf = *buf; - /* Just inode number should be from NS node */ - local->stbuf.ia_ino = local->ia_ino; - - /* TODO: log on failure */ - ret = fd_ctx_set (fd, this, (uint64_t)(long)prev_frame->this); - } - - tmp_inode = local->loc1.inode; - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, local->op_errno, local->fd, - tmp_inode, &local->stbuf, - &local->oldpreparent, &local->oldpostparent); - - return 0; -} - -/** - * unify_ns_create_cbk - - * - */ -int32_t -unify_ns_create_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent) -{ - struct sched_ops *sched_ops = NULL; - xlator_t *sched_xl = NULL; - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - int16_t *list = NULL; - int16_t index = 0; - - if (op_ret == -1) { - /* No need to send create request to other servers, as - namespace action failed. Handle exclusive create here. */ - if ((op_errno != EEXIST) || - ((op_errno == EEXIST) && - ((local->flags & O_EXCL) == O_EXCL))) { - /* If its just a create call without O_EXCL, - don't do this */ - gf_log (this->name, GF_LOG_ERROR, - "namespace: path(%s): %s", - local->loc1.path, strerror (op_errno)); - unify_local_wipe (local); - STACK_UNWIND (frame, op_ret, op_errno, fd, inode, buf, - preparent, postparent); - return 0; - } - } - - if (op_ret >= 0) { - /* Get the inode number from the NS node */ - local->ia_ino = buf->ia_ino; - - local->oldpreparent = *preparent; - local->oldpostparent = *postparent; - - local->op_ret = -1; - - /* Start the mapping list */ - list = GF_CALLOC (1, sizeof (int16_t) * 3, - gf_unify_mt_int16_t); - ERR_ABORT (list); - inode_ctx_put (inode, this, (uint64_t)(long)list); - list[0] = priv->child_count; - list[2] = -1; - - /* This means, file doesn't exist anywhere in the Filesystem */ - sched_ops = priv->sched_ops; - - /* Send create request to the scheduled node now */ - sched_xl = sched_ops->schedule (this, local->loc1.path); - if (sched_xl == NULL) - { - /* send unlink () on Namespace */ - local->op_errno = ENOTCONN; - local->op_ret = -1; - local->call_count = 1; - gf_log (this->name, GF_LOG_ERROR, - "no node online to schedule create:(file %s) " - "sending unlink to namespace", - (local->loc1.path)?local->loc1.path:""); - - STACK_WIND (frame, - unify_create_unlink_cbk, - NS(this), - NS(this)->fops->unlink, - &local->loc1); - - return 0; - } - - for (index = 0; index < priv->child_count; index++) - if (sched_xl == priv->xl_array[index]) - break; - list[1] = index; - - STACK_WIND (frame, unify_create_cbk, - sched_xl, sched_xl->fops->create, - &local->loc1, local->flags, local->mode, fd); - } else { - /* File already exists, and there is no O_EXCL flag */ - - gf_log (this->name, GF_LOG_DEBUG, - "File(%s) already exists on namespace, sending " - "open instead", local->loc1.path); - - local->list = GF_CALLOC (1, sizeof (int16_t) * 3, - gf_unify_mt_int16_t); - ERR_ABORT (local->list); - local->call_count = priv->child_count + 1; - local->op_ret = -1; - for (index = 0; index <= priv->child_count; index++) { - /* Send lookup() to all nodes including namespace */ - STACK_WIND_COOKIE (frame, - unify_create_lookup_cbk, - (void *)(long)index, - priv->xl_array[index], - priv->xl_array[index]->fops->lookup, - &local->loc1, - NULL); - } - } - return 0; -} - -/** - * unify_create - create a file in global namespace first, so other - * clients can see them. Create the file in storage nodes in background. - */ -int32_t -unify_create (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flags, - mode_t mode, - fd_t *fd) -{ - unify_local_t *local = NULL; - - /* Initialization */ - INIT_LOCAL (frame, local); - local->mode = mode; - local->flags = flags; - local->fd = fd; - - loc_copy (&local->loc1, loc); - if (local->loc1.path == NULL) { - gf_log (this->name, GF_LOG_CRITICAL, "Not enough memory :O"); - STACK_UNWIND (frame, -1, ENOMEM, fd, loc->inode, NULL, - NULL, NULL); - return 0; - } - - STACK_WIND (frame, - unify_ns_create_cbk, - NS(this), - NS(this)->fops->create, - loc, - flags | O_EXCL, - mode, - fd); - - return 0; -} - - -/** - * unify_opendir_cbk - - */ -int32_t -unify_opendir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd) -{ - STACK_UNWIND (frame, op_ret, op_errno, fd); - - return 0; -} - -/** - * unify_opendir - - */ -int32_t -unify_opendir (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - fd_t *fd) -{ - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (loc); - - STACK_WIND (frame, unify_opendir_cbk, - NS(this), NS(this)->fops->opendir, loc, fd); - - return 0; -} - - -int32_t -unify_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *statpre, - struct iatt *statpost) -{ - int32_t callcnt = 0; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - call_frame_t *prev_frame = cookie; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - - if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, - "%s(): child(%s): path(%s): %s", - gf_fop_list[frame->root->op], - prev_frame->this->name, - (local->loc1.path)?local->loc1.path:"", - strerror (op_errno)); - - local->op_errno = op_errno; - if ((op_errno == ENOENT) && priv->optimist) - local->op_ret = 0; - } - - if (op_ret >= 0) { - local->op_ret = 0; - - if (NS (this) == prev_frame->this) { - local->ia_ino = statpost->ia_ino; - /* If the entry is directory, get the stat - from NS node */ - if (IA_ISDIR (statpost->ia_type) || - !local->stpost.ia_blksize) { - local->stpre = *statpre; - local->stpost = *statpost; - } - } - - if ((!IA_ISDIR (statpost->ia_type)) && - (NS (this) != prev_frame->this)) { - /* If file, take the stat info from Storage - node. */ - local->stpre = *statpre; - local->stpost = *statpost; - } - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - /* If the inode number is not filled, operation should - fail */ - if (!local->ia_ino) - local->op_ret = -1; - - local->stpre.ia_ino = local->ia_ino; - local->stpost.ia_ino = local->ia_ino; - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, local->op_errno, - &local->stpre, &local->stpost); - } - - return 0; -} - - -int32_t -unify_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, - struct iatt *stbuf, int32_t valid) -{ - unify_local_t *local = NULL; - unify_private_t *priv = this->private; - int32_t index = 0; - int32_t callcnt = 0; - uint64_t tmp_list = 0; - - if (!(loc && loc->inode)) { - STACK_UNWIND (frame, -1, EINVAL, NULL, NULL); - return 0; - } - - /* Initialization */ - INIT_LOCAL (frame, local); - loc_copy (&local->loc1, loc); - - if (IA_ISDIR (loc->inode->ia_type)) { - local->call_count = 1; - - STACK_WIND (frame, - unify_setattr_cbk, - NS (this), - NS (this)->fops->setattr, - loc, stbuf, valid); - } else { - inode_ctx_get (loc->inode, this, &tmp_list); - local->list = (int16_t *)(long)tmp_list; - - for (index = 0; local->list[index] != -1; index++) { - local->call_count++; - callcnt++; - } - - for (index = 0; local->list[index] != -1; index++) { - STACK_WIND (frame, - unify_setattr_cbk, - priv->xl_array[local->list[index]], - priv->xl_array[local->list[index]]->fops->setattr, - loc, stbuf, valid); - - if (!--callcnt) - break; - } - } - - return 0; -} - - -int32_t -unify_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, - struct iatt *stbuf, int32_t valid) -{ - unify_local_t *local = NULL; - xlator_t *child = NULL; - uint64_t tmp_child = 0; - - UNIFY_CHECK_FD_AND_UNWIND_ON_ERR(fd); - - /* Initialization */ - INIT_LOCAL (frame, local); - - if (!fd_ctx_get (fd, this, &tmp_child)) { - /* If its set, then its file */ - child = (xlator_t *)(long)tmp_child; - - local->call_count = 2; - - STACK_WIND (frame, unify_setattr_cbk, child, - child->fops->fsetattr, fd, stbuf, valid); - - STACK_WIND (frame, unify_setattr_cbk, NS(this), - NS(this)->fops->fsetattr, fd, stbuf, valid); - } else { - local->call_count = 1; - - STACK_WIND (frame, unify_setattr_cbk, - NS(this), NS(this)->fops->fsetattr, - fd, stbuf, valid); - } - - return 0; -} - - -/** - * unify_truncate_cbk - - */ -int32_t -unify_truncate_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *prebuf, - struct iatt *postbuf) -{ - int32_t callcnt = 0; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - call_frame_t *prev_frame = cookie; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - - if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, - "child(%s): path(%s): %s", - prev_frame->this->name, - (local->loc1.path)?local->loc1.path:"", - strerror (op_errno)); - local->op_errno = op_errno; - if (!((op_errno == ENOENT) && priv->optimist)) - local->op_ret = -1; - } - - if (op_ret >= 0) { - if (NS (this) == prev_frame->this) { - local->ia_ino = postbuf->ia_ino; - /* If the entry is directory, get the - stat from NS node */ - if (IA_ISDIR (postbuf->ia_type) || - !local->stbuf.ia_blksize) { - local->stbuf = *prebuf; - local->poststbuf = *postbuf; - } - } - - if ((!IA_ISDIR (postbuf->ia_type)) && - (NS (this) != prev_frame->this)) { - /* If file, take the stat info from - Storage node. */ - local->stbuf = *prebuf; - local->poststbuf = *postbuf; - } - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - if (local->ia_ino) { - local->stbuf.ia_ino = local->ia_ino; - local->poststbuf.ia_ino = local->ia_ino; - } else { - local->op_ret = -1; - } - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, local->op_errno, - &local->stbuf, &local->poststbuf); - } - - return 0; -} - - -/** - * unify_truncate - - */ -int32_t -unify_truncate (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - off_t offset) -{ - unify_local_t *local = NULL; - unify_private_t *priv = this->private; - int32_t index = 0; - int32_t callcnt = 0; - uint64_t tmp_list = 0; - - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (loc); - - /* Initialization */ - INIT_LOCAL (frame, local); - loc_copy (&local->loc1, loc); - local->ia_ino = loc->inode->ino; - - if (IA_ISDIR (loc->inode->ia_type)) { - local->call_count = 1; - - STACK_WIND (frame, - unify_truncate_cbk, - NS(this), - NS(this)->fops->truncate, - loc, - 0); - } else { - local->op_ret = 0; - inode_ctx_get (loc->inode, this, &tmp_list); - local->list = (int16_t *)(long)tmp_list; - - for (index = 0; local->list[index] != -1; index++) { - local->call_count++; - callcnt++; - } - - /* Don't send offset to NS truncate */ - STACK_WIND (frame, unify_truncate_cbk, NS(this), - NS(this)->fops->truncate, loc, 0); - callcnt--; - - for (index = 0; local->list[index] != -1; index++) { - if (NS(this) != priv->xl_array[local->list[index]]) { - STACK_WIND (frame, - unify_truncate_cbk, - priv->xl_array[local->list[index]], - priv->xl_array[local->list[index]]->fops->truncate, - loc, - offset); - if (!--callcnt) - break; - } - } - } - - return 0; -} - -/** - * unify_readlink_cbk - - */ -int32_t -unify_readlink_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - const char *path, - struct iatt *sbuf) -{ - STACK_UNWIND (frame, op_ret, op_errno, path, sbuf); - return 0; -} - -/** - * unify_readlink - Read the link only from the storage node. - */ -int32_t -unify_readlink (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - size_t size) -{ - unify_private_t *priv = this->private; - int32_t entry_count = 0; - int16_t *list = NULL; - int16_t index = 0; - uint64_t tmp_list = 0; - - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (loc); - - inode_ctx_get (loc->inode, this, &tmp_list); - list = (int16_t *)(long)tmp_list; - - for (index = 0; list[index] != -1; index++) - entry_count++; - - if (entry_count >= 2) { - for (index = 0; list[index] != -1; index++) { - if (priv->xl_array[list[index]] != NS(this)) { - STACK_WIND (frame, - unify_readlink_cbk, - priv->xl_array[list[index]], - priv->xl_array[list[index]]->fops->readlink, - loc, - size); - break; - } - } - } else { - gf_log (this->name, GF_LOG_ERROR, - "returning ENOENT, no softlink files found " - "on storage node"); - STACK_UNWIND (frame, -1, ENOENT, NULL); - } - - return 0; -} - - -/** - * unify_unlink_cbk - - */ -int32_t -unify_unlink_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *preparent, - struct iatt *postparent) -{ - int32_t callcnt = 0; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - if (op_ret == 0 || ((op_errno == ENOENT) && priv->optimist)) - local->op_ret = 0; - if (op_ret == -1) - local->op_errno = op_errno; - - if (((call_frame_t *)cookie)->this == NS(this)) { - local->oldpreparent = *preparent; - local->oldpostparent = *postparent; - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, local->op_errno, - &local->oldpreparent, &local->oldpostparent); - } - - return 0; -} - - -/** - * unify_unlink - - */ -int32_t -unify_unlink (call_frame_t *frame, - xlator_t *this, - loc_t *loc) -{ - unify_private_t *priv = this->private; - unify_local_t *local = NULL; - int16_t *list = NULL; - int16_t index = 0; - uint64_t tmp_list = 0; - - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (loc); - - /* Initialization */ - INIT_LOCAL (frame, local); - loc_copy (&local->loc1, loc); - - inode_ctx_get (loc->inode, this, &tmp_list); - list = (int16_t *)(long)tmp_list; - - for (index = 0; list[index] != -1; index++) - local->call_count++; - - if (local->call_count) { - for (index = 0; list[index] != -1; index++) { - char need_break = (list[index+1] == -1); - STACK_WIND (frame, - unify_unlink_cbk, - priv->xl_array[list[index]], - priv->xl_array[list[index]]->fops->unlink, - loc); - if (need_break) - break; - } - } else { - gf_log (this->name, GF_LOG_ERROR, - "%s: returning ENOENT", loc->path); - STACK_UNWIND (frame, -1, ENOENT, NULL, NULL); - } - - return 0; -} - - -/** - * unify_readv_cbk - - */ -int32_t -unify_readv_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iovec *vector, - int32_t count, - struct iatt *stbuf, - struct iobref *iobref) -{ - STACK_UNWIND (frame, op_ret, op_errno, vector, count, stbuf, iobref); - return 0; -} - -/** - * unify_readv - - */ -int32_t -unify_readv (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - size_t size, - off_t offset) -{ - UNIFY_CHECK_FD_CTX_AND_UNWIND_ON_ERR (fd); - xlator_t *child = NULL; - uint64_t tmp_child = 0; - - fd_ctx_get (fd, this, &tmp_child); - child = (xlator_t *)(long)tmp_child; - - STACK_WIND (frame, - unify_readv_cbk, - child, - child->fops->readv, - fd, - size, - offset); - - - return 0; -} - -/** - * unify_writev_cbk - - */ -int32_t -unify_writev_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *prebuf, - struct iatt *postbuf) -{ - unify_local_t *local = NULL; - - local = frame->local; - - local->stbuf = *prebuf; - local->stbuf.ia_ino = local->ia_ino; - - local->poststbuf = *postbuf; - local->poststbuf.ia_ino = local->ia_ino; - - STACK_UNWIND (frame, op_ret, op_errno, - &local->stbuf, &local->poststbuf); - return 0; -} - -/** - * unify_writev - - */ -int32_t -unify_writev (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - struct iovec *vector, - int32_t count, - off_t off, - struct iobref *iobref) -{ - UNIFY_CHECK_FD_CTX_AND_UNWIND_ON_ERR (fd); - xlator_t *child = NULL; - uint64_t tmp_child = 0; - unify_local_t *local = NULL; - - INIT_LOCAL (frame, local); - local->ia_ino = fd->inode->ino; - - fd_ctx_get (fd, this, &tmp_child); - child = (xlator_t *)(long)tmp_child; - - STACK_WIND (frame, - unify_writev_cbk, - child, - child->fops->writev, - fd, - vector, - count, - off, - iobref); - - return 0; -} - -/** - * unify_ftruncate - - */ -int32_t -unify_ftruncate (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - off_t offset) -{ - xlator_t *child = NULL; - unify_local_t *local = NULL; - uint64_t tmp_child = 0; - - UNIFY_CHECK_FD_CTX_AND_UNWIND_ON_ERR(fd); - - /* Initialization */ - INIT_LOCAL (frame, local); - local->op_ret = 0; - - fd_ctx_get (fd, this, &tmp_child); - child = (xlator_t *)(long)tmp_child; - - local->call_count = 2; - - STACK_WIND (frame, unify_truncate_cbk, - child, child->fops->ftruncate, - fd, offset); - - STACK_WIND (frame, unify_truncate_cbk, - NS(this), NS(this)->fops->ftruncate, - fd, 0); - - return 0; -} - - -/** - * unify_flush_cbk - - */ -int32_t -unify_flush_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - STACK_UNWIND (frame, op_ret, op_errno); - return 0; -} - -/** - * unify_flush - - */ -int32_t -unify_flush (call_frame_t *frame, - xlator_t *this, - fd_t *fd) -{ - UNIFY_CHECK_FD_CTX_AND_UNWIND_ON_ERR (fd); - xlator_t *child = NULL; - uint64_t tmp_child = 0; - - fd_ctx_get (fd, this, &tmp_child); - child = (xlator_t *)(long)tmp_child; - - STACK_WIND (frame, unify_flush_cbk, child, - child->fops->flush, fd); - - return 0; -} - - -/** - * unify_fsync_cbk - - */ -int32_t -unify_fsync_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *prebuf, - struct iatt *postbuf) -{ - STACK_UNWIND (frame, op_ret, op_errno, prebuf, postbuf); - return 0; -} - -/** - * unify_fsync - - */ -int32_t -unify_fsync (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - int32_t flags) -{ - UNIFY_CHECK_FD_CTX_AND_UNWIND_ON_ERR (fd); - xlator_t *child = NULL; - uint64_t tmp_child = 0; - - fd_ctx_get (fd, this, &tmp_child); - child = (xlator_t *)(long)tmp_child; - - STACK_WIND (frame, unify_fsync_cbk, child, - child->fops->fsync, fd, flags); - - return 0; -} - -/** - * unify_fstat - Send fstat FOP to Namespace only if its directory, and to - * both namespace and the storage node if its a file. - */ -int32_t -unify_fstat (call_frame_t *frame, - xlator_t *this, - fd_t *fd) -{ - unify_local_t *local = NULL; - xlator_t *child = NULL; - uint64_t tmp_child = 0; - - UNIFY_CHECK_FD_AND_UNWIND_ON_ERR(fd); - - INIT_LOCAL (frame, local); - local->ia_ino = fd->inode->ino; - - if (!fd_ctx_get (fd, this, &tmp_child)) { - /* If its set, then its file */ - child = (xlator_t *)(long)tmp_child; - local->call_count = 2; - - STACK_WIND (frame, unify_buf_cbk, child, - child->fops->fstat, fd); - - STACK_WIND (frame, unify_buf_cbk, NS(this), - NS(this)->fops->fstat, fd); - - } else { - /* this is an directory */ - local->call_count = 1; - STACK_WIND (frame, unify_buf_cbk, NS(this), - NS(this)->fops->fstat, fd); - } - - return 0; -} - -/** - * unify_getdents_cbk - - */ -int32_t -unify_getdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dir_entry_t *entry, - int32_t count) -{ - STACK_UNWIND (frame, op_ret, op_errno, entry, count); - return 0; -} - -/** - * unify_getdents - send the FOP request to all the nodes. - */ -int32_t -unify_getdents (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - size_t size, - off_t offset, - int32_t flag) -{ - UNIFY_CHECK_FD_AND_UNWIND_ON_ERR (fd); - - STACK_WIND (frame, unify_getdents_cbk, NS(this), - NS(this)->fops->getdents, fd, size, offset, flag); - - return 0; -} - - -/** - * unify_readdir_cbk - - */ -int32_t -unify_readdir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - gf_dirent_t *buf) -{ - STACK_UNWIND (frame, op_ret, op_errno, buf); - - return 0; -} - -/** - * unify_readdir - send the FOP request to all the nodes. - */ -int32_t -unify_readdir (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - size_t size, - off_t offset) -{ - UNIFY_CHECK_FD_AND_UNWIND_ON_ERR (fd); - - STACK_WIND (frame, unify_readdir_cbk, NS(this), - NS(this)->fops->readdir, fd, size, offset); - - return 0; -} - - -int32_t -unify_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, gf_dirent_t *buf) -{ - STACK_UNWIND (frame, op_ret, op_errno, buf); - - return 0; -} - - -int32_t -unify_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, - off_t offset) -{ - UNIFY_CHECK_FD_AND_UNWIND_ON_ERR (fd); - - STACK_WIND (frame, unify_readdirp_cbk, NS(this), - NS(this)->fops->readdirp, fd, size, offset); - - return 0; -} - - -/** - * unify_fsyncdir_cbk - - */ -int32_t -unify_fsyncdir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - STACK_UNWIND (frame, op_ret, op_errno); - - return 0; -} - -/** - * unify_fsyncdir - - */ -int32_t -unify_fsyncdir (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - int32_t flags) -{ - UNIFY_CHECK_FD_AND_UNWIND_ON_ERR (fd); - - STACK_WIND (frame, unify_fsyncdir_cbk, - NS(this), NS(this)->fops->fsyncdir, fd, flags); - - return 0; -} - -/** - * unify_lk_cbk - UNWIND frame with the proper return arguments. - */ -int32_t -unify_lk_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct gf_flock *lock) -{ - STACK_UNWIND (frame, op_ret, op_errno, lock); - return 0; -} - -/** - * unify_lk - Send it to all the storage nodes, (should be 1) which has file. - */ -int32_t -unify_lk (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - int32_t cmd, - struct gf_flock *lock) -{ - UNIFY_CHECK_FD_CTX_AND_UNWIND_ON_ERR (fd); - xlator_t *child = NULL; - uint64_t tmp_child = 0; - - fd_ctx_get (fd, this, &tmp_child); - child = (xlator_t *)(long)tmp_child; - - STACK_WIND (frame, unify_lk_cbk, child, - child->fops->lk, fd, cmd, lock); - - return 0; -} - - -int32_t -unify_setxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno); - -static int32_t -unify_setxattr_file_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - unify_private_t *private = this->private; - unify_local_t *local = frame->local; - xlator_t *sched_xl = NULL; - struct sched_ops *sched_ops = NULL; - - if (op_ret == -1) { - if (!ENOTSUP) - gf_log (this->name, GF_LOG_ERROR, - "setxattr with XATTR_CREATE on ns: " - "path(%s) key(%s): %s", - local->loc1.path, local->name, - strerror (op_errno)); - unify_local_wipe (local); - STACK_UNWIND (frame, op_ret, op_errno); - return 0; - } - - LOCK (&frame->lock); - { - local->failed = 0; - local->op_ret = 0; - local->op_errno = 0; - local->call_count = 1; - } - UNLOCK (&frame->lock); - - /* schedule XATTR_CREATE on one of the child node */ - sched_ops = private->sched_ops; - - /* Send create request to the scheduled node now */ - sched_xl = sched_ops->schedule (this, local->name); - if (!sched_xl) { - STACK_UNWIND (frame, -1, ENOTCONN); - return 0; - } - - STACK_WIND (frame, - unify_setxattr_cbk, - sched_xl, - sched_xl->fops->setxattr, - &local->loc1, - local->dict, - local->flags); - return 0; -} - -/** - * unify_setxattr_cbk - When all the child nodes return, UNWIND frame. - */ -int32_t -unify_setxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - int32_t callcnt = 0; - unify_local_t *local = frame->local; - call_frame_t *prev_frame = cookie; - dict_t *dict = NULL; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - - if (op_ret == -1) { - gf_log (this->name, (((op_errno == ENOENT) || - (op_errno == ENOTSUP))? - GF_LOG_DEBUG : GF_LOG_ERROR), - "child(%s): path(%s): %s", - prev_frame->this->name, - (local->loc1.path)?local->loc1.path:"", - strerror (op_errno)); - if (local->failed == -1) { - local->failed = 1; - } - local->op_errno = op_errno; - } else { - local->failed = 0; - local->op_ret = op_ret; - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - if (local->failed && local->name && - ZR_FILE_CONTENT_REQUEST(local->name)) { - dict = get_new_dict (); - dict_set (dict, local->dict->members_list->key, - data_from_dynptr(NULL, 0)); - dict_ref (dict); - - local->call_count = 1; - - STACK_WIND (frame, - unify_setxattr_file_cbk, - NS(this), - NS(this)->fops->setxattr, - &local->loc1, - dict, - XATTR_CREATE); - - dict_unref (dict); - return 0; - } - - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, local->op_errno); - } - - return 0; -} - -/** - * unify_sexattr - This function should be sent to all the storage nodes, - * which contains the file, (excluding namespace). - */ -int32_t -unify_setxattr (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - dict_t *dict, - int32_t flags) -{ - unify_private_t *priv = this->private; - unify_local_t *local = NULL; - int16_t *list = NULL; - int16_t index = 0; - int32_t call_count = 0; - uint64_t tmp_list = 0; - data_pair_t *trav = dict->members_list; - - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (loc); - - /* Initialization */ - INIT_LOCAL (frame, local); - local->failed = -1; - loc_copy (&local->loc1, loc); - - if (IA_ISDIR (loc->inode->ia_type)) { - - if (trav && trav->key && ZR_FILE_CONTENT_REQUEST(trav->key)) { - /* direct the storage xlators to change file - content only if file exists */ - local->flags = flags; - local->dict = dict; - local->name = gf_strdup (trav->key); - flags |= XATTR_REPLACE; - } - - local->call_count = priv->child_count; - for (index = 0; index < priv->child_count; index++) { - STACK_WIND (frame, - unify_setxattr_cbk, - priv->xl_array[index], - priv->xl_array[index]->fops->setxattr, - loc, dict, flags); - } - return 0; - } - - inode_ctx_get (loc->inode, this, &tmp_list); - list = (int16_t *)(long)tmp_list; - - for (index = 0; list[index] != -1; index++) { - if (NS(this) != priv->xl_array[list[index]]) { - local->call_count++; - call_count++; - } - } - - if (local->call_count) { - for (index = 0; list[index] != -1; index++) { - if (priv->xl_array[list[index]] != NS(this)) { - STACK_WIND (frame, - unify_setxattr_cbk, - priv->xl_array[list[index]], - priv->xl_array[list[index]]->fops->setxattr, - loc, - dict, - flags); - if (!--call_count) - break; - } - } - return 0; - } - - /* No entry in storage nodes */ - gf_log (this->name, GF_LOG_DEBUG, - "returning ENOENT, file not found on storage node."); - STACK_UNWIND (frame, -1, ENOENT); - - return 0; -} - - -/** - * unify_getxattr_cbk - This function is called from only one child, so, no - * need of any lock or anything else, just send it to above layer - */ -int32_t -unify_getxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *value) -{ - int32_t callcnt = 0; - dict_t *local_value = NULL; - unify_local_t *local = frame->local; - call_frame_t *prev_frame = cookie; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - - if (op_ret == -1) { - local->op_errno = op_errno; - gf_log (this->name, - (((op_errno == ENOENT) || - (op_errno == ENODATA) || - (op_errno == ENOTSUP)) ? - GF_LOG_DEBUG : GF_LOG_ERROR), - "child(%s): path(%s): %s", - prev_frame->this->name, - (local->loc1.path)?local->loc1.path:"", - strerror (op_errno)); - } else { - if (!local->dict) - local->dict = dict_ref (value); - local->op_ret = op_ret; - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - local_value = local->dict; - local->dict = NULL; - - STACK_UNWIND (frame, local->op_ret, local->op_errno, - local_value); - - if (local_value) - dict_unref (local_value); - } - - return 0; -} - - -/** - * unify_getxattr - This FOP is sent to only the storage node. - */ -int32_t -unify_getxattr (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - const char *name) -{ - unify_private_t *priv = this->private; - int16_t *list = NULL; - int16_t index = 0; - int16_t count = 0; - unify_local_t *local = NULL; - uint64_t tmp_list = 0; - - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (loc); - INIT_LOCAL (frame, local); - - if (IA_ISDIR (loc->inode->ia_type)) { - local->call_count = priv->child_count; - for (index = 0; index < priv->child_count; index++) - STACK_WIND (frame, - unify_getxattr_cbk, - priv->xl_array[index], - priv->xl_array[index]->fops->getxattr, - loc, - name); - return 0; - } - - inode_ctx_get (loc->inode, this, &tmp_list); - list = (int16_t *)(long)tmp_list; - - for (index = 0; list[index] != -1; index++) { - if (NS(this) != priv->xl_array[list[index]]) { - local->call_count++; - count++; - } - } - - if (count) { - for (index = 0; list[index] != -1; index++) { - if (priv->xl_array[list[index]] != NS(this)) { - STACK_WIND (frame, - unify_getxattr_cbk, - priv->xl_array[list[index]], - priv->xl_array[list[index]]->fops->getxattr, - loc, - name); - if (!--count) - break; - } - } - } else { - dict_t *tmp_dict = get_new_dict (); - gf_log (this->name, GF_LOG_DEBUG, - "%s: returning ENODATA, no file found on storage node", - loc->path); - STACK_UNWIND (frame, -1, ENODATA, tmp_dict); - dict_destroy (tmp_dict); - } - - return 0; -} - -/** - * unify_removexattr_cbk - Wait till all the child node returns the call - * and then UNWIND to above layer. - */ -int32_t -unify_removexattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - int32_t callcnt = 0; - unify_local_t *local = frame->local; - call_frame_t *prev_frame = cookie; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - if (op_ret == -1) { - local->op_errno = op_errno; - if (op_errno != ENOTSUP) - gf_log (this->name, GF_LOG_ERROR, - "child(%s): path(%s): %s", - prev_frame->this->name, - local->loc1.path, strerror (op_errno)); - } else { - local->op_ret = op_ret; - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - STACK_UNWIND (frame, local->op_ret, local->op_errno); - } - - return 0; -} - -/** - * unify_removexattr - Send it to all the child nodes which has the files. - */ -int32_t -unify_removexattr (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - const char *name) -{ - unify_private_t *priv = this->private; - unify_local_t *local = NULL; - int16_t *list = NULL; - int16_t index = 0; - int32_t call_count = 0; - uint64_t tmp_list = 0; - - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (loc); - - /* Initialization */ - INIT_LOCAL (frame, local); - - if (IA_ISDIR (loc->inode->ia_type)) { - local->call_count = priv->child_count; - for (index = 0; index < priv->child_count; index++) - STACK_WIND (frame, - unify_removexattr_cbk, - priv->xl_array[index], - priv->xl_array[index]->fops->removexattr, - loc, - name); - - return 0; - } - - inode_ctx_get (loc->inode, this, &tmp_list); - list = (int16_t *)(long)tmp_list; - - for (index = 0; list[index] != -1; index++) { - if (NS(this) != priv->xl_array[list[index]]) { - local->call_count++; - call_count++; - } - } - - if (local->call_count) { - for (index = 0; list[index] != -1; index++) { - if (priv->xl_array[list[index]] != NS(this)) { - STACK_WIND (frame, - unify_removexattr_cbk, - priv->xl_array[list[index]], - priv->xl_array[list[index]]->fops->removexattr, - loc, - name); - if (!--call_count) - break; - } - } - return 0; - } - - gf_log (this->name, GF_LOG_DEBUG, - "%s: returning ENOENT, not found on storage node.", loc->path); - STACK_UNWIND (frame, -1, ENOENT); - - return 0; -} - - -int32_t -unify_mknod_unlink_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *preparent, - struct iatt *postparent) -{ - unify_local_t *local = frame->local; - - if (op_ret == -1) - gf_log (this->name, GF_LOG_ERROR, - "%s: %s", local->loc1.path, strerror (op_errno)); - - unify_local_wipe (local); - /* No log required here as this -1 is for mknod call */ - STACK_UNWIND (frame, -1, local->op_errno, NULL, NULL); - return 0; -} - -/** - * unify_mknod_cbk - - */ -int32_t -unify_mknod_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent) -{ - unify_local_t *local = frame->local; - - if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, - "mknod failed on storage node, sending unlink to " - "namespace"); - local->op_errno = op_errno; - STACK_WIND (frame, - unify_mknod_unlink_cbk, - NS(this), - NS(this)->fops->unlink, - &local->loc1); - return 0; - } - - local->stbuf = *buf; - local->stbuf.ia_ino = local->ia_ino; - unify_local_wipe (local); - STACK_UNWIND (frame, op_ret, op_errno, inode, &local->stbuf, - &local->oldpreparent, &local->oldpostparent); - return 0; -} - -/** - * unify_ns_mknod_cbk - - */ -int32_t -unify_ns_mknod_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent) -{ - struct sched_ops *sched_ops = NULL; - xlator_t *sched_xl = NULL; - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - int16_t *list = NULL; - int16_t index = 0; - call_frame_t *prev_frame = cookie; - - if (op_ret == -1) { - /* No need to send mknod request to other servers, - * as namespace action failed - */ - gf_log (this->name, GF_LOG_ERROR, - "child(%s): path(%s): %s", - prev_frame->this->name, local->loc1.path, - strerror (op_errno)); - unify_local_wipe (local); - STACK_UNWIND (frame, op_ret, op_errno, inode, buf, - preparent, postparent); - return 0; - } - - /* Create one inode for this entry */ - local->op_ret = 0; - local->stbuf = *buf; - local->ia_ino = buf->ia_ino; - - local->oldpreparent = *preparent; - local->oldpostparent = *postparent; - - list = GF_CALLOC (1, sizeof (int16_t) * 3, gf_unify_mt_int16_t); - ERR_ABORT (list); - list[0] = priv->child_count; - list[2] = -1; - inode_ctx_put (inode, this, (uint64_t)(long)list); - - sched_ops = priv->sched_ops; - - /* Send mknod request to scheduled node now */ - sched_xl = sched_ops->schedule (this, local->loc1.path); - if (!sched_xl) { - gf_log (this->name, GF_LOG_ERROR, - "mknod failed on storage node, no node online " - "at the moment, sending unlink to NS"); - local->op_errno = ENOTCONN; - STACK_WIND (frame, - unify_mknod_unlink_cbk, - NS(this), - NS(this)->fops->unlink, - &local->loc1); - - return 0; - } - - for (index = 0; index < priv->child_count; index++) - if (sched_xl == priv->xl_array[index]) - break; - list[1] = index; - - STACK_WIND (frame, unify_mknod_cbk, - sched_xl, sched_xl->fops->mknod, - &local->loc1, local->mode, local->dev); - - return 0; -} - -/** - * unify_mknod - Create a device on namespace first, and later create on - * the storage node. - */ -int32_t -unify_mknod (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - mode_t mode, - dev_t rdev) -{ - unify_local_t *local = NULL; - - /* Initialization */ - INIT_LOCAL (frame, local); - local->mode = mode; - local->dev = rdev; - loc_copy (&local->loc1, loc); - if (local->loc1.path == NULL) { - gf_log (this->name, GF_LOG_CRITICAL, "Not enough memory :O"); - STACK_UNWIND (frame, -1, ENOMEM, loc->inode, NULL); - return 0; - } - - STACK_WIND (frame, - unify_ns_mknod_cbk, - NS(this), - NS(this)->fops->mknod, - loc, - mode, - rdev); - - return 0; -} - -int32_t -unify_symlink_unlink_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *preparent, - struct iatt *postparent) -{ - unify_local_t *local = frame->local; - if (op_ret == -1) - gf_log (this->name, GF_LOG_ERROR, - "%s: %s", local->loc1.path, strerror (op_errno)); - - unify_local_wipe (local); - STACK_UNWIND (frame, -1, local->op_errno, NULL, NULL); - return 0; -} - -/** - * unify_symlink_cbk - - */ -int32_t -unify_symlink_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent) -{ - unify_local_t *local = frame->local; - - if (op_ret == -1) { - /* Symlink on storage node failed, hence send unlink - to the NS node */ - local->op_errno = op_errno; - gf_log (this->name, GF_LOG_ERROR, - "symlink on storage node failed, sending unlink " - "to namespace"); - - STACK_WIND (frame, - unify_symlink_unlink_cbk, - NS(this), - NS(this)->fops->unlink, - &local->loc1); - - return 0; - } - - local->stbuf = *buf; - local->stbuf.ia_ino = local->ia_ino; - unify_local_wipe (local); - STACK_UNWIND (frame, op_ret, op_errno, inode, &local->stbuf, - &local->oldpreparent, &local->oldpostparent); - - return 0; -} - -/** - * unify_ns_symlink_cbk - - */ -int32_t -unify_ns_symlink_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent) -{ - - struct sched_ops *sched_ops = NULL; - xlator_t *sched_xl = NULL; - int16_t *list = NULL; - unify_local_t *local = frame->local; - unify_private_t *priv = this->private; - int16_t index = 0; - - if (op_ret == -1) { - /* No need to send symlink request to other servers, - * as namespace action failed - */ - gf_log (this->name, GF_LOG_ERROR, - "namespace: path(%s): %s", - local->loc1.path, strerror (op_errno)); - unify_local_wipe (local); - STACK_UNWIND (frame, op_ret, op_errno, NULL, buf, - preparent, postparent); - return 0; - } - - /* Create one inode for this entry */ - local->op_ret = 0; - local->ia_ino = buf->ia_ino; - - local->oldpreparent = *preparent; - local->oldpostparent = *postparent; - - /* Start the mapping list */ - - list = GF_CALLOC (1, sizeof (int16_t) * 3, gf_unify_mt_int16_t); - ERR_ABORT (list); - list[0] = priv->child_count; //namespace's index - list[2] = -1; - inode_ctx_put (inode, this, (uint64_t)(long)list); - - sched_ops = priv->sched_ops; - - /* Send symlink request to all the nodes now */ - sched_xl = sched_ops->schedule (this, local->loc1.path); - if (!sched_xl) { - /* Symlink on storage node failed, hence send unlink - to the NS node */ - local->op_errno = ENOTCONN; - gf_log (this->name, GF_LOG_ERROR, - "symlink on storage node failed, no node online, " - "sending unlink to namespace"); - - STACK_WIND (frame, - unify_symlink_unlink_cbk, - NS(this), - NS(this)->fops->unlink, - &local->loc1); - - return 0; - } - - for (index = 0; index < priv->child_count; index++) - if (sched_xl == priv->xl_array[index]) - break; - list[1] = index; - - STACK_WIND (frame, - unify_symlink_cbk, - sched_xl, - sched_xl->fops->symlink, - local->name, - &local->loc1); - - return 0; -} - -/** - * unify_symlink - - */ -int32_t -unify_symlink (call_frame_t *frame, - xlator_t *this, - const char *linkpath, - loc_t *loc) -{ - unify_local_t *local = NULL; - - /* Initialization */ - INIT_LOCAL (frame, local); - loc_copy (&local->loc1, loc); - local->name = gf_strdup (linkpath); - - if ((local->name == NULL) || - (local->loc1.path == NULL)) { - gf_log (this->name, GF_LOG_CRITICAL, "Not enough memory :O"); - STACK_UNWIND (frame, -1, ENOMEM, loc->inode, NULL); - return 0; - } - - STACK_WIND (frame, - unify_ns_symlink_cbk, - NS(this), - NS(this)->fops->symlink, - linkpath, - loc); - - return 0; -} - - -int32_t -unify_rename_unlink_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *preparent, - struct iatt *postparent) -{ - int32_t callcnt = 0; - unify_local_t *local = frame->local; - call_frame_t *prev_frame = cookie; - - if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, - "child(%s): path(%s -> %s): %s", - prev_frame->this->name, - local->loc1.path, local->loc2.path, - strerror (op_errno)); - - } - LOCK (&frame->lock); - { - callcnt = --local->call_count; - } - UNLOCK (&frame->lock); - - if (!callcnt) { - local->stbuf.ia_ino = local->ia_ino; - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, local->op_errno, - &local->stbuf); - } - return 0; -} - -int32_t -unify_ns_rename_undo_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *buf, - struct iatt *preoldparent, - struct iatt *postoldparent, - struct iatt *prenewparent, - struct iatt *postnewparent) -{ - unify_local_t *local = frame->local; - - if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, - "namespace: path(%s -> %s): %s", - local->loc1.path, local->loc2.path, - strerror (op_errno)); - } - - local->stbuf.ia_ino = local->ia_ino; - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, local->op_errno, &local->stbuf); - return 0; -} - -int32_t -unify_rename_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *buf, - struct iatt *preoldparent, - struct iatt *postoldparent, - struct iatt *prenewparent, - struct iatt *postnewparent) -{ - int32_t index = 0; - int32_t callcnt = 0; - int16_t *list = NULL; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - call_frame_t *prev_frame = cookie; - - LOCK (&frame->lock); - { - callcnt = --local->call_count; - if (op_ret >= 0) { - if (!IA_ISDIR (buf->ia_type)) - local->stbuf = *buf; - local->op_ret = op_ret; - } else { - gf_log (this->name, GF_LOG_ERROR, - "child(%s): path(%s -> %s): %s", - prev_frame->this->name, - local->loc1.path, local->loc2.path, - strerror (op_errno)); - local->op_errno = op_errno; - } - } - UNLOCK (&frame->lock); - - if (!callcnt) { - local->stbuf.ia_ino = local->ia_ino; - if (IA_ISDIR (local->loc1.inode->ia_type)) { - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, local->op_errno, - &local->stbuf, &local->oldpreparent, - &local->oldpostparent, &local->newpreparent, - &local->newpostparent); - return 0; - } - - if (local->op_ret == -1) { - /* TODO: check this logic */ - - /* Rename failed in storage node, successful on NS, - * hence, rename back the entries in NS */ - /* NOTE: this will be done only if the destination - * doesn't exists, if the destination exists, the - * job of correcting NS is left to self-heal - */ - if (!local->index) { - loc_t tmp_oldloc = { - /* its actual 'newloc->path' */ - .path = local->loc2.path, - .inode = local->loc1.inode, - .parent = local->loc2.parent - }; - - loc_t tmp_newloc = { - /* Actual 'oldloc->path' */ - .path = local->loc1.path, - .parent = local->loc1.parent - }; - - gf_log (this->name, GF_LOG_ERROR, - "rename succussful on namespace, on " - "stroage node failed, reverting back"); - - STACK_WIND (frame, - unify_ns_rename_undo_cbk, - NS(this), - NS(this)->fops->rename, - &tmp_oldloc, - &tmp_newloc); - return 0; - } - } else { - /* Rename successful on storage nodes */ - - int32_t idx = 0; - int16_t *tmp_list = NULL; - uint64_t tmp_list_int64 = 0; - if (local->loc2.inode) { - inode_ctx_get (local->loc2.inode, - this, &tmp_list_int64); - list = (int16_t *)(long)tmp_list_int64; - - } - - if (list) { - for (index = 0; list[index] != -1; index++); - tmp_list = GF_CALLOC (1, index * 2, - gf_unify_mt_int16_t); - memcpy (tmp_list, list, index * 2); - - for (index = 0; list[index] != -1; index++) { - /* TODO: Check this logic. */ - /* If the destination file exists in - * the same storage node where we sent - * 'rename' call, no need to send - * unlink - */ - for (idx = 0; - local->list[idx] != -1; idx++) { - if (tmp_list[index] == local->list[idx]) { - tmp_list[index] = priv->child_count; - continue; - } - } - - if (NS(this) != priv->xl_array[tmp_list[index]]) { - local->call_count++; - callcnt++; - } - } - - if (local->call_count) { - if (callcnt > 1) - gf_log (this->name, - GF_LOG_ERROR, - "%s->%s: more (%d) " - "subvolumes have the " - "newloc entry", - local->loc1.path, - local->loc2.path, - callcnt); - - for (index=0; - tmp_list[index] != -1; index++) { - if (NS(this) != priv->xl_array[tmp_list[index]]) { - STACK_WIND (frame, - unify_rename_unlink_cbk, - priv->xl_array[tmp_list[index]], - priv->xl_array[tmp_list[index]]->fops->unlink, - &local->loc2); - if (!--callcnt) - break; - } - } - - GF_FREE (tmp_list); - return 0; - } - if (tmp_list) - GF_FREE (tmp_list); - } - } - - /* Need not send 'unlink' to storage node */ - unify_local_wipe (local); - STACK_UNWIND (frame, local->op_ret, - local->op_errno, &local->stbuf, - &local->oldpreparent, &local->oldpostparent, - &local->newpreparent, &local->newpostparent); - } - - return 0; -} - -int32_t -unify_ns_rename_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *buf, - struct iatt *preoldparent, - struct iatt *postoldparent, - struct iatt *prenewparent, - struct iatt *postnewparent) -{ - int32_t index = 0; - int32_t callcnt = 0; - int16_t *list = NULL; - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - - if (op_ret == -1) { - /* Free local->new_inode */ - gf_log (this->name, GF_LOG_ERROR, - "namespace: path(%s -> %s): %s", - local->loc1.path, local->loc2.path, - strerror (op_errno)); - - unify_local_wipe (local); - STACK_UNWIND (frame, op_ret, op_errno, buf, - preoldparent, postoldparent, - prenewparent, postnewparent); - return 0; - } - - local->stbuf = *buf; - local->ia_ino = buf->ia_ino; - - local->oldpreparent = *preoldparent; - local->oldpostparent = *postoldparent; - local->newpreparent = *prenewparent; - local->newpostparent = *postnewparent; - - /* Everything is fine. */ - if (IA_ISDIR (buf->ia_type)) { - local->call_count = priv->child_count; - for (index=0; index < priv->child_count; index++) { - STACK_WIND (frame, - unify_rename_cbk, - priv->xl_array[index], - priv->xl_array[index]->fops->rename, - &local->loc1, - &local->loc2); - } - - return 0; - } - - local->call_count = 0; - /* send rename */ - list = local->list; - for (index=0; list[index] != -1; index++) { - if (NS(this) != priv->xl_array[list[index]]) { - local->call_count++; - callcnt++; - } - } - - if (local->call_count) { - for (index=0; list[index] != -1; index++) { - if (NS(this) != priv->xl_array[list[index]]) { - STACK_WIND (frame, - unify_rename_cbk, - priv->xl_array[list[index]], - priv->xl_array[list[index]]->fops->rename, - &local->loc1, - &local->loc2); - if (!--callcnt) - break; - } - } - } else { - /* file doesn't seem to be present in storage nodes */ - gf_log (this->name, GF_LOG_CRITICAL, - "CRITICAL: source file not in storage node, " - "rename successful on namespace :O"); - unify_local_wipe (local); - STACK_UNWIND (frame, -1, EIO, NULL, - NULL, NULL, /* preoldparent, postoldparent */ - NULL, NULL); /* prenewparent, postnewparent */ - } - return 0; -} - - -/** - * unify_rename - One of the tricky function. The deadliest of all :O - */ -int32_t -unify_rename (call_frame_t *frame, - xlator_t *this, - loc_t *oldloc, - loc_t *newloc) -{ - unify_local_t *local = NULL; - uint64_t tmp_list = 0; - - /* Initialization */ - INIT_LOCAL (frame, local); - loc_copy (&local->loc1, oldloc); - loc_copy (&local->loc2, newloc); - - if ((local->loc1.path == NULL) || - (local->loc2.path == NULL)) { - gf_log (this->name, GF_LOG_CRITICAL, "Not enough memory :O"); - STACK_UNWIND (frame, -1, ENOMEM, NULL, - NULL, NULL, /* preoldparent, postoldparent */ - NULL, NULL); /* prenewparent, postnewparent */ - return 0; - } - - inode_ctx_get (oldloc->inode, this, &tmp_list); - local->list = (int16_t *)(long)tmp_list; - - STACK_WIND (frame, - unify_ns_rename_cbk, - NS(this), - NS(this)->fops->rename, - oldloc, - newloc); - return 0; -} - -/** - * unify_link_cbk - - */ -int32_t -unify_link_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent) -{ - unify_local_t *local = frame->local; - - if (op_ret >= 0) - local->stbuf = *buf; - local->stbuf.ia_ino = local->ia_ino; - - unify_local_wipe (local); - STACK_UNWIND (frame, op_ret, op_errno, inode, &local->stbuf, - &local->oldpreparent, &local->oldpostparent); - - return 0; -} - -/** - * unify_ns_link_cbk - - */ -int32_t -unify_ns_link_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent) -{ - unify_private_t *priv = this->private; - unify_local_t *local = frame->local; - int16_t *list = local->list; - int16_t index = 0; - - if (op_ret == -1) { - /* No need to send link request to other servers, - * as namespace action failed - */ - gf_log (this->name, GF_LOG_ERROR, - "namespace: path(%s -> %s): %s", - local->loc1.path, local->loc2.path, - strerror (op_errno)); - unify_local_wipe (local); - STACK_UNWIND (frame, op_ret, op_errno, inode, buf, - preparent, postparent); - return 0; - } - - /* Update inode for this entry */ - local->op_ret = 0; - local->ia_ino = buf->ia_ino; - - local->oldpreparent = *preparent; - local->oldpostparent = *postparent; - - /* Send link request to the node now */ - for (index = 0; list[index] != -1; index++) { - char need_break = (list[index+1] == -1); - if (priv->xl_array[list[index]] != NS (this)) { - STACK_WIND (frame, - unify_link_cbk, - priv->xl_array[list[index]], - priv->xl_array[list[index]]->fops->link, - &local->loc1, - &local->loc2); - break; - } - if (need_break) - break; - } - - return 0; -} - -/** - * unify_link - - */ -int32_t -unify_link (call_frame_t *frame, - xlator_t *this, - loc_t *oldloc, - loc_t *newloc) -{ - unify_local_t *local = NULL; - uint64_t tmp_list = 0; - - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (oldloc); - UNIFY_CHECK_INODE_CTX_AND_UNWIND_ON_ERR (newloc); - - /* Initialization */ - INIT_LOCAL (frame, local); - - loc_copy (&local->loc1, oldloc); - loc_copy (&local->loc2, newloc); - - inode_ctx_get (oldloc->inode, this, &tmp_list); - local->list = (int16_t *)(long)tmp_list; - - STACK_WIND (frame, - unify_ns_link_cbk, - NS(this), - NS(this)->fops->link, - oldloc, - newloc); - - return 0; -} - - -/** - * unify_checksum_cbk - - */ -int32_t -unify_checksum_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - uint8_t *fchecksum, - uint8_t *dchecksum) -{ - STACK_UNWIND (frame, op_ret, op_errno, fchecksum, dchecksum); - - return 0; -} - -/** - * unify_checksum - - */ -int32_t -unify_checksum (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flag) -{ - STACK_WIND (frame, - unify_checksum_cbk, - NS(this), - NS(this)->fops->checksum, - loc, - flag); - - return 0; -} - - -/** - * unify_finodelk_cbk - - */ -int -unify_finodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - STACK_UNWIND (frame, op_ret, op_errno); - return 0; -} - -/** - * unify_finodelk - */ -int -unify_finodelk (call_frame_t *frame, xlator_t *this, - const char *volume, fd_t *fd, int cmd, struct gf_flock *flock) -{ - UNIFY_CHECK_FD_CTX_AND_UNWIND_ON_ERR (fd); - xlator_t *child = NULL; - uint64_t tmp_child = 0; - - fd_ctx_get (fd, this, &tmp_child); - child = (xlator_t *)(long)tmp_child; - - STACK_WIND (frame, unify_finodelk_cbk, - child, child->fops->finodelk, - volume, fd, cmd, flock); - - return 0; -} - - - -/** - * unify_fentrylk_cbk - - */ -int -unify_fentrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - STACK_UNWIND (frame, op_ret, op_errno); - return 0; -} - -/** - * unify_fentrylk - */ -int -unify_fentrylk (call_frame_t *frame, xlator_t *this, - const char *volume, fd_t *fd, const char *basename, - entrylk_cmd cmd, entrylk_type type) - -{ - UNIFY_CHECK_FD_CTX_AND_UNWIND_ON_ERR (fd); - xlator_t *child = NULL; - uint64_t tmp_child = 0; - - fd_ctx_get (fd, this, &tmp_child); - child = (xlator_t *)(long)tmp_child; - - STACK_WIND (frame, unify_fentrylk_cbk, - child, child->fops->fentrylk, - volume, fd, basename, cmd, type); - - return 0; -} - - - -/** - * unify_fxattrop_cbk - - */ -int -unify_fxattrop_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xattr) -{ - STACK_UNWIND (frame, op_ret, op_errno, xattr); - return 0; -} - -/** - * unify_fxattrop - */ -int -unify_fxattrop (call_frame_t *frame, xlator_t *this, - fd_t *fd, gf_xattrop_flags_t optype, dict_t *xattr) -{ - UNIFY_CHECK_FD_CTX_AND_UNWIND_ON_ERR (fd); - xlator_t *child = NULL; - uint64_t tmp_child = 0; - - fd_ctx_get (fd, this, &tmp_child); - child = (xlator_t *)(long)tmp_child; - - STACK_WIND (frame, unify_fxattrop_cbk, - child, child->fops->fxattrop, - fd, optype, xattr); - - return 0; -} - - -/** - * unify_inodelk_cbk - - */ -int -unify_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - STACK_UNWIND (frame, op_ret, op_errno); - return 0; -} - - -/** - * unify_inodelk - */ -int -unify_inodelk (call_frame_t *frame, xlator_t *this, - const char *volume, loc_t *loc, int cmd, struct gf_flock *flock) -{ - xlator_t *child = NULL; - - child = unify_loc_subvol (loc, this); - - STACK_WIND (frame, unify_inodelk_cbk, - child, child->fops->inodelk, - volume, loc, cmd, flock); - - return 0; -} - - - -/** - * unify_entrylk_cbk - - */ -int -unify_entrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - STACK_UNWIND (frame, op_ret, op_errno); - return 0; -} - -/** - * unify_entrylk - */ -int -unify_entrylk (call_frame_t *frame, xlator_t *this, - const char *volume, loc_t *loc, const char *basename, - entrylk_cmd cmd, entrylk_type type) - -{ - xlator_t *child = NULL; - - child = unify_loc_subvol (loc, this); - - STACK_WIND (frame, unify_entrylk_cbk, - child, child->fops->entrylk, - volume, loc, basename, cmd, type); - - return 0; -} - - - -/** - * unify_xattrop_cbk - - */ -int -unify_xattrop_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xattr) -{ - STACK_UNWIND (frame, op_ret, op_errno, xattr); - return 0; -} - -/** - * unify_xattrop - */ -int -unify_xattrop (call_frame_t *frame, xlator_t *this, - loc_t *loc, gf_xattrop_flags_t optype, dict_t *xattr) -{ - xlator_t *child = NULL; - - child = unify_loc_subvol (loc, this); - - STACK_WIND (frame, unify_xattrop_cbk, - child, child->fops->xattrop, - loc, optype, xattr); - - return 0; -} - -int -unify_forget (xlator_t *this, - inode_t *inode) -{ - int16_t *list = NULL; - uint64_t tmp_list = 0; - - if (inode->ia_type && (!IA_ISDIR(inode->ia_type))) { - inode_ctx_get (inode, this, &tmp_list); - if (tmp_list) { - list = (int16_t *)(long)tmp_list; - GF_FREE (list); - } - } - - return 0; -} - -/** - * notify - */ -int32_t -notify (xlator_t *this, - int32_t event, - void *data, - ...) -{ - unify_private_t *priv = this->private; - struct sched_ops *sched = NULL; - - if (!priv) { - return 0; - } - - sched = priv->sched_ops; - if (!sched) { - gf_log (this->name, GF_LOG_CRITICAL, "No scheduler :O"); - raise (SIGTERM); - return 0; - } - if (priv->namespace == data) { - if (event == GF_EVENT_CHILD_UP) { - sched->notify (this, event, data); - } - return 0; - } - - switch (event) - { - case GF_EVENT_CHILD_UP: - { - /* Call scheduler's update () to enable it for scheduling */ - sched->notify (this, event, data); - - LOCK (&priv->lock); - { - /* Increment the inode's generation, which is - used for self_heal */ - ++priv->inode_generation; - ++priv->num_child_up; - } - UNLOCK (&priv->lock); - - if (!priv->is_up) { - default_notify (this, event, data); - priv->is_up = 1; - } - } - break; - case GF_EVENT_CHILD_DOWN: - { - /* Call scheduler's update () to disable the child node - * for scheduling - */ - sched->notify (this, event, data); - LOCK (&priv->lock); - { - --priv->num_child_up; - } - UNLOCK (&priv->lock); - - if (priv->num_child_up == 0) { - /* Send CHILD_DOWN to upper layer */ - default_notify (this, event, data); - priv->is_up = 0; - } - } - break; - - default: - { - default_notify (this, event, data); - } - break; - } - - return 0; -} - -int32_t -mem_acct_init (xlator_t *this) -{ - int ret = -1; - - if (!this) - return ret; - - ret = xlator_mem_acct_init (this, gf_unify_mt_end + 1); - - if (ret != 0) { - gf_log (this->name, GF_LOG_ERROR, "Memory accounting init" - "failed"); - return ret; - } - - return ret; -} - -/** - * init - This function is called first in the xlator, while initializing. - * All the config file options are checked and appropriate flags are set. - * - * @this - - */ -int32_t -init (xlator_t *this) -{ - int32_t ret = 0; - int32_t count = 0; - data_t *scheduler = NULL; - data_t *data = NULL; - xlator_t *ns_xl = NULL; - xlator_list_t *trav = NULL; - xlator_list_t *xlparent = NULL; - xlator_list_t *parent = NULL; - unify_private_t *_private = NULL; - - - /* Check for number of child nodes, if there is no child nodes, exit */ - if (!this->children) { - gf_log (this->name, GF_LOG_ERROR, - "No child nodes specified. check \"subvolumes \" " - "option in volfile"); - return -1; - } - - if (!this->parents) { - gf_log (this->name, GF_LOG_WARNING, - "dangling volume. check volfile "); - } - - /* Check for 'scheduler' in volume */ - scheduler = dict_get (this->options, "scheduler"); - if (!scheduler) { - gf_log (this->name, GF_LOG_ERROR, - "\"option scheduler <x>\" is missing in volfile"); - return -1; - } - - /* Setting "option namespace <node>" */ - data = dict_get (this->options, "namespace"); - if(!data) { - gf_log (this->name, GF_LOG_CRITICAL, - "namespace option not specified, Exiting"); - return -1; - } - /* Search namespace in the child node, if found, exit */ - trav = this->children; - while (trav) { - if (strcmp (trav->xlator->name, data->data) == 0) - break; - trav = trav->next; - } - if (trav) { - gf_log (this->name, GF_LOG_CRITICAL, - "namespace node used as a subvolume, Exiting"); - return -1; - } - - /* Search for the namespace node, if found, continue */ - ns_xl = this->next; - while (ns_xl) { - if (strcmp (ns_xl->name, data->data) == 0) - break; - ns_xl = ns_xl->next; - } - if (!ns_xl) { - gf_log (this->name, GF_LOG_CRITICAL, - "namespace node not found in volfile, Exiting"); - return -1; - } - - gf_log (this->name, GF_LOG_DEBUG, - "namespace node specified as %s", data->data); - - _private = GF_CALLOC (1, sizeof (*_private), - gf_unify_mt_unify_private_t); - ERR_ABORT (_private); - _private->sched_ops = get_scheduler (this, scheduler->data); - if (!_private->sched_ops) { - gf_log (this->name, GF_LOG_CRITICAL, - "Error while loading scheduler. Exiting"); - GF_FREE (_private); - return -1; - } - - if (ns_xl->parents) { - gf_log (this->name, GF_LOG_CRITICAL, - "Namespace node should not be a child of any other node. Exiting"); - GF_FREE (_private); - return -1; - } - - _private->namespace = ns_xl; - - /* update _private structure */ - { - count = 0; - trav = this->children; - /* Get the number of child count */ - while (trav) { - count++; - trav = trav->next; - } - - gf_log (this->name, GF_LOG_DEBUG, - "Child node count is %d", count); - - _private->child_count = count; - if (count == 1) { - /* TODO: Should I error out here? */ - gf_log (this->name, GF_LOG_CRITICAL, - "WARNING: You have defined only one " - "\"subvolumes\" for unify volume. It may not " - "be the desired config, review your volume " - "volfile. If this is how you are testing it," - " you may hit some performance penalty"); - } - - _private->xl_array = GF_CALLOC (1, - sizeof (xlator_t) * (count + 1), - gf_unify_mt_xlator_t); - ERR_ABORT (_private->xl_array); - - count = 0; - trav = this->children; - while (trav) { - _private->xl_array[count++] = trav->xlator; - trav = trav->next; - } - _private->xl_array[count] = _private->namespace; - - /* self-heal part, start with generation '1' */ - _private->inode_generation = 1; - /* Because, Foreground part is tested well */ - _private->self_heal = ZR_UNIFY_FG_SELF_HEAL; - data = dict_get (this->options, "self-heal"); - if (data) { - if (strcasecmp (data->data, "off") == 0) - _private->self_heal = ZR_UNIFY_SELF_HEAL_OFF; - - if (strcasecmp (data->data, "foreground") == 0) - _private->self_heal = ZR_UNIFY_FG_SELF_HEAL; - - if (strcasecmp (data->data, "background") == 0) - _private->self_heal = ZR_UNIFY_BG_SELF_HEAL; - } - - /* optimist - ask bulde for more about it */ - data = dict_get (this->options, "optimist"); - if (data) { - if (gf_string2boolean (data->data, - &_private->optimist) == -1) { - gf_log (this->name, GF_LOG_ERROR, - "optimist excepts only boolean " - "options"); - } - } - - LOCK_INIT (&_private->lock); - } - - /* Now that everything is fine. */ - this->private = (void *)_private; - { - ret = _private->sched_ops->mem_acct_init (this); - - if (ret == -1) { - return -1; - } - - /* Initialize scheduler, if everything else is successful */ - ret = _private->sched_ops->init (this); - if (ret == -1) { - gf_log (this->name, GF_LOG_CRITICAL, - "Initializing scheduler failed, Exiting"); - GF_FREE (_private); - return -1; - } - - - ret = 0; - - /* This section is required because some fops may look - * for 'xl->parent' variable - */ - xlparent = GF_CALLOC (1, sizeof (*xlparent), - gf_unify_mt_xlator_list_t); - xlparent->xlator = this; - if (!ns_xl->parents) { - ns_xl->parents = xlparent; - } else { - parent = ns_xl->parents; - while (parent->next) - parent = parent->next; - parent->next = xlparent; - } - } - - /* Tell namespace node that init is done */ - xlator_notify (ns_xl, GF_EVENT_PARENT_UP, this); - - return 0; -} - -/** - * fini - Free all the allocated memory - */ -void -fini (xlator_t *this) -{ - unify_private_t *priv = this->private; - priv->sched_ops->fini (this); - this->private = NULL; - LOCK_DESTROY (&priv->lock); - GF_FREE (priv->xl_array); - GF_FREE (priv); - return; -} - - -struct xlator_fops fops = { - .stat = unify_stat, - .readlink = unify_readlink, - .mknod = unify_mknod, - .mkdir = unify_mkdir, - .unlink = unify_unlink, - .rmdir = unify_rmdir, - .symlink = unify_symlink, - .rename = unify_rename, - .link = unify_link, - .truncate = unify_truncate, - .create = unify_create, - .open = unify_open, - .readv = unify_readv, - .writev = unify_writev, - .statfs = unify_statfs, - .flush = unify_flush, - .fsync = unify_fsync, - .setxattr = unify_setxattr, - .getxattr = unify_getxattr, - .removexattr = unify_removexattr, - .opendir = unify_opendir, - .readdir = unify_readdir, - .readdirp = unify_readdirp, - .fsyncdir = unify_fsyncdir, - .access = unify_access, - .ftruncate = unify_ftruncate, - .fstat = unify_fstat, - .lk = unify_lk, - .lookup = unify_lookup, - .getdents = unify_getdents, - .checksum = unify_checksum, - .inodelk = unify_inodelk, - .finodelk = unify_finodelk, - .entrylk = unify_entrylk, - .fentrylk = unify_fentrylk, - .xattrop = unify_xattrop, - .fxattrop = unify_fxattrop, - .setattr = unify_setattr, - .fsetattr = unify_fsetattr, -}; - - -struct xlator_cbks cbks = { - .forget = unify_forget, -}; - -struct volume_options options[] = { - { .key = { "namespace" }, - .type = GF_OPTION_TYPE_XLATOR - }, - { .key = { "scheduler" }, - .value = { "alu", "rr", "random", "nufa", "switch" }, - .type = GF_OPTION_TYPE_STR - }, - { .key = {"self-heal"}, - .value = { "foreground", "background", "off" }, - .type = GF_OPTION_TYPE_STR - }, - /* TODO: remove it some time later */ - { .key = {"optimist"}, - .type = GF_OPTION_TYPE_BOOL - }, - - { .key = {NULL} }, -}; diff --git a/xlators/cluster/unify/src/unify.h b/xlators/cluster/unify/src/unify.h deleted file mode 100644 index dbd5e44a2f1..00000000000 --- a/xlators/cluster/unify/src/unify.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.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 _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#ifndef _UNIFY_H -#define _UNIFY_H - -#include "scheduler.h" -#include "list.h" -#include "unify-mem-types.h" - -#define MAX_DIR_ENTRY_STRING (32 * 1024) - -#define ZR_UNIFY_SELF_HEAL_OFF 0 -#define ZR_UNIFY_FG_SELF_HEAL 1 -#define ZR_UNIFY_BG_SELF_HEAL 2 - -/* Sometimes one should use completely random numbers.. its good :p */ -#define UNIFY_SELF_HEAL_GETDENTS_COUNT 512 - -#define NS(xl) (((unify_private_t *)xl->private)->namespace) - -/* This is used to allocate memory for local structure */ -#define INIT_LOCAL(fr, loc) \ -do { \ - loc = GF_CALLOC (1, sizeof (unify_local_t), gf_unify_mt_unify_local_t); \ - ERR_ABORT (loc); \ - if (!loc) { \ - STACK_UNWIND (fr, -1, ENOMEM); \ - return 0; \ - } \ - fr->local = loc; \ - loc->op_ret = -1; \ - loc->op_errno = ENOENT; \ -} while (0) - - - -struct unify_private { - /* Update this structure depending on requirement */ - void *scheduler; /* THIS SHOULD BE THE FIRST VARIABLE, - if xlator is using scheduler */ - struct sched_ops *sched_ops; /* Scheduler options */ - xlator_t *namespace; /* ptr to namespace xlator */ - xlator_t **xl_array; - gf_boolean_t optimist; - int16_t child_count; - int16_t num_child_up; - uint8_t self_heal; - uint8_t is_up; - uint64_t inode_generation; - gf_lock_t lock; -}; -typedef struct unify_private unify_private_t; - -struct unify_self_heal_struct { - uint8_t dir_checksum[NAME_MAX]; - uint8_t ns_dir_checksum[NAME_MAX]; - uint8_t file_checksum[NAME_MAX]; - uint8_t ns_file_checksum[NAME_MAX]; - off_t *offset_list; - int *count_list; - dir_entry_t **entry_list; -}; - - -struct _unify_local_t { - int32_t call_count; - int32_t op_ret; - int32_t op_errno; - mode_t mode; - off_t offset; - dev_t dev; - uid_t uid; - gid_t gid; - int32_t flags; - int32_t entry_count; - int32_t count; // dir_entry_t count; - fd_t *fd; - struct iatt stbuf; - struct iatt stpre; - struct iatt stpost; - struct statvfs statvfs_buf; - struct timespec tv[2]; - char *name; - int32_t revalidate; - - ino_t ia_ino; - nlink_t ia_nlink; - - dict_t *dict; - - int16_t *list; - int16_t *new_list; /* Used only in case of rename */ - int16_t index; - - int32_t failed; - int32_t return_eio; /* Used in case of different st-mode - present for a given path */ - - uint64_t inode_generation; /* used to store the per directory - * inode_generation. Got from inode's ctx - * of directory inodes - */ - - struct unify_self_heal_struct *sh_struct; - loc_t loc1, loc2; - - struct iatt poststbuf; - /* When not used for rename, old* - * are used as the attrs for the current - * parent directory. - */ - struct iatt oldpreparent; - struct iatt oldpostparent; - struct iatt newpreparent; - struct iatt newpostparent; - int32_t wbflags; -}; -typedef struct _unify_local_t unify_local_t; - -int32_t zr_unify_self_heal (call_frame_t *frame, - xlator_t *this, - unify_local_t *local); - -#endif /* _UNIFY_H */ |