diff options
Diffstat (limited to 'xlators/protocol/server')
| -rw-r--r-- | xlators/protocol/server/Makefile.am | 2 | ||||
| -rw-r--r-- | xlators/protocol/server/src/Makefile.am | 28 | ||||
| -rw-r--r-- | xlators/protocol/server/src/authenticate.c | 253 | ||||
| -rw-r--r-- | xlators/protocol/server/src/authenticate.h | 51 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-dentry.c | 413 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-handshake.c | 781 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-helpers.c | 1837 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-helpers.h | 101 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-mem-types.h | 30 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-protocol.c | 8339 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-protocol.h | 157 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-resolve.c | 598 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-rpc-fops.c | 6179 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server.c | 1214 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server.h | 196 |
15 files changed, 10518 insertions, 9661 deletions
diff --git a/xlators/protocol/server/Makefile.am b/xlators/protocol/server/Makefile.am index d471a3f92..af437a64d 100644 --- a/xlators/protocol/server/Makefile.am +++ b/xlators/protocol/server/Makefile.am @@ -1,3 +1 @@ SUBDIRS = src - -CLEANFILES = diff --git a/xlators/protocol/server/src/Makefile.am b/xlators/protocol/server/src/Makefile.am index dcd92aeed..6a18bf025 100644 --- a/xlators/protocol/server/src/Makefile.am +++ b/xlators/protocol/server/src/Makefile.am @@ -1,18 +1,26 @@ - xlator_LTLIBRARIES = server.la xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/protocol -server_la_LDFLAGS = -module -avoidversion +server_la_LDFLAGS = -module -avoid-version + +server_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \ + $(top_builddir)/rpc/rpc-lib/src/libgfrpc.la \ + $(top_builddir)/rpc/xdr/src/libgfxdr.la -server_la_SOURCES = server-protocol.c server-dentry.c server-helpers.c -server_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la +server_la_SOURCES = server.c server-resolve.c server-helpers.c \ + server-rpc-fops.c server-handshake.c authenticate.c -noinst_HEADERS = server-protocol.h server-helpers.h +noinst_HEADERS = server.h server-helpers.h server-mem-types.h authenticate.h -AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS) \ - -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles \ - -DDATADIR=\"$(localstatedir)\" -DCONFDIR=\"$(sysconfdir)/glusterfs\" \ - $(GF_CFLAGS) +AM_CPPFLAGS = $(GF_CPPFLAGS) \ + -I$(top_srcdir)/libglusterfs/src \ + -DCONFDIR=\"$(sysconfdir)/glusterfs\" \ + -DLIBDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/auth\" \ + -I$(top_srcdir)/xlators/protocol/lib/src \ + -I$(top_srcdir)/rpc/rpc-lib/src \ + -I$(top_srcdir)/rpc/xdr/src -CLEANFILES = +AM_CFLAGS = -Wall $(GF_CFLAGS) \ + -DDATADIR=\"$(localstatedir)\" +CLEANFILES = *~ diff --git a/xlators/protocol/server/src/authenticate.c b/xlators/protocol/server/src/authenticate.c new file mode 100644 index 000000000..d8d138a84 --- /dev/null +++ b/xlators/protocol/server/src/authenticate.c @@ -0,0 +1,253 @@ +/* + Copyright (c) 2007-2013 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 _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <stdio.h> +#include <dlfcn.h> +#include <errno.h> +#include "authenticate.h" + +static int +init (dict_t *this, char *key, data_t *value, void *data) +{ + void *handle = NULL; + char *auth_file = NULL; + auth_handle_t *auth_handle = NULL; + auth_fn_t authenticate = NULL; + int *error = NULL; + int ret = 0; + + /* It gets over written */ + error = data; + + if (!strncasecmp (key, "ip", strlen ("ip"))) { + gf_log ("authenticate", GF_LOG_ERROR, + "AUTHENTICATION MODULE \"IP\" HAS BEEN REPLACED " + "BY \"ADDR\""); + dict_set (this, key, data_from_dynptr (NULL, 0)); + /* TODO: 1.3.x backword compatibility */ + // *error = -1; + // return; + key = "addr"; + } + + ret = gf_asprintf (&auth_file, "%s/%s.so", LIBDIR, key); + if (-1 == ret) { + dict_set (this, key, data_from_dynptr (NULL, 0)); + *error = -1; + return -1; + } + + handle = dlopen (auth_file, RTLD_LAZY); + if (!handle) { + gf_log ("authenticate", GF_LOG_ERROR, "dlopen(%s): %s\n", + auth_file, dlerror ()); + dict_set (this, key, data_from_dynptr (NULL, 0)); + GF_FREE (auth_file); + *error = -1; + return -1; + } + GF_FREE (auth_file); + + authenticate = dlsym (handle, "gf_auth"); + if (!authenticate) { + gf_log ("authenticate", GF_LOG_ERROR, + "dlsym(gf_auth) on %s\n", dlerror ()); + dict_set (this, key, data_from_dynptr (NULL, 0)); + dlclose (handle); + *error = -1; + return -1; + } + + auth_handle = GF_CALLOC (1, sizeof (*auth_handle), + gf_common_mt_auth_handle_t); + if (!auth_handle) { + dict_set (this, key, data_from_dynptr (NULL, 0)); + *error = -1; + dlclose (handle); + return -1; + } + auth_handle->vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t), + gf_common_mt_volume_opt_list_t); + if (!auth_handle->vol_opt) { + dict_set (this, key, data_from_dynptr (NULL, 0)); + *error = -1; + GF_FREE (auth_handle); + dlclose (handle); + return -1; + } + auth_handle->vol_opt->given_opt = dlsym (handle, "options"); + if (auth_handle->vol_opt->given_opt == NULL) { + gf_log ("authenticate", GF_LOG_DEBUG, + "volume option validation not specified"); + } + + auth_handle->authenticate = authenticate; + auth_handle->handle = handle; + + dict_set (this, key, + data_from_dynptr (auth_handle, sizeof (*auth_handle))); + return 0; +} + +static int +fini (dict_t *this, char *key, data_t *value, void *data) +{ + auth_handle_t *handle = data_to_ptr (value); + if (handle) { + dlclose (handle->handle); + } + return 0; +} + +static int +_gf_auth_option_validate (dict_t *d, char *k, data_t *v, void *tmp) +{ + auth_handle_t *handle = NULL; + xlator_t *xl = NULL; + int ret = 0; + + xl = tmp; + + handle = data_to_ptr (v); + if (!handle) + return 0; + + list_add_tail (&(handle->vol_opt->list), &(xl->volume_options)); + + ret = xlator_options_validate_list (xl, xl->options, + handle->vol_opt, NULL); + if (ret) { + gf_log ("authenticate", GF_LOG_ERROR, + "volume option validation failed"); + return -1; + } + return 0; +} + +int32_t +gf_auth_init (xlator_t *xl, dict_t *auth_modules) +{ + int ret = 0; + + dict_foreach (auth_modules, init, &ret); + if (ret) + goto out; + + ret = dict_foreach (auth_modules, _gf_auth_option_validate, xl); + +out: + if (ret) { + gf_log (xl->name, GF_LOG_ERROR, "authentication init failed"); + dict_foreach (auth_modules, fini, &ret); + ret = -1; + } + return ret; +} + +static dict_t *__input_params; +static dict_t *__config_params; + +int +map (dict_t *this, char *key, data_t *value, void *data) +{ + dict_t *res = data; + auth_fn_t authenticate; + auth_handle_t *handle = NULL; + + if (value && (handle = data_to_ptr (value)) && + (authenticate = handle->authenticate)) { + dict_set (res, key, + int_to_data (authenticate (__input_params, + __config_params))); + } else { + dict_set (res, key, int_to_data (AUTH_DONT_CARE)); + } + return 0; +} + +int +reduce (dict_t *this, char *key, data_t *value, void *data) +{ + int64_t val = 0; + int64_t *res = data; + if (!data) + return 0; + + val = data_to_int64 (value); + switch (val) + { + case AUTH_ACCEPT: + if (AUTH_DONT_CARE == *res) + *res = AUTH_ACCEPT; + break; + + case AUTH_REJECT: + *res = AUTH_REJECT; + break; + + case AUTH_DONT_CARE: + break; + } + return 0; +} + + +auth_result_t +gf_authenticate (dict_t *input_params, + dict_t *config_params, + dict_t *auth_modules) +{ + char *name = NULL; + dict_t *results = NULL; + int64_t result = AUTH_DONT_CARE; + data_t *peerinfo_data = NULL; + + results = get_new_dict (); + __input_params = input_params; + __config_params = config_params; + + dict_foreach (auth_modules, map, results); + + dict_foreach (results, reduce, &result); + if (AUTH_DONT_CARE == result) { + peerinfo_data = dict_get (input_params, "peer-info-name"); + + if (peerinfo_data) { + name = peerinfo_data->data; + } + + gf_log ("auth", GF_LOG_ERROR, + "no authentication module is interested in " + "accepting remote-client %s", name); + result = AUTH_REJECT; + } + + dict_destroy (results); + return result; +} + +void +gf_auth_fini (dict_t *auth_modules) +{ + int32_t dummy; + + dict_foreach (auth_modules, fini, &dummy); +} diff --git a/xlators/protocol/server/src/authenticate.h b/xlators/protocol/server/src/authenticate.h new file mode 100644 index 000000000..d4d43e498 --- /dev/null +++ b/xlators/protocol/server/src/authenticate.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2007-2013 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 _AUTHENTICATE_H +#define _AUTHENTICATE_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <stdio.h> +#include <fnmatch.h> +#include "dict.h" +#include "compat.h" +#include "list.h" +#include "xlator.h" + +typedef enum { + AUTH_ACCEPT, + AUTH_REJECT, + AUTH_DONT_CARE +} auth_result_t; + +typedef auth_result_t (*auth_fn_t) (dict_t *input_params, + dict_t *config_params); + +typedef struct { + void *handle; + auth_fn_t authenticate; + volume_opt_list_t *vol_opt; +} auth_handle_t; + +auth_result_t gf_authenticate (dict_t *input_params, + dict_t *config_params, + dict_t *auth_modules); +int32_t gf_auth_init (xlator_t *xl, dict_t *auth_modules); +void gf_auth_fini (dict_t *auth_modules); + +#endif /* _AUTHENTICATE_H */ diff --git a/xlators/protocol/server/src/server-dentry.c b/xlators/protocol/server/src/server-dentry.c deleted file mode 100644 index d3a69a393..000000000 --- a/xlators/protocol/server/src/server-dentry.c +++ /dev/null @@ -1,413 +0,0 @@ -#include "glusterfs.h" -#include "xlator.h" -#include "server-protocol.h" -#include "server-helpers.h" -#include <libgen.h> - -/* SERVER_DENTRY_STATE_PREPARE - prepare a fresh state for use - * - * @state - an empty state - * @loc - loc_t which needs to resolved - * @parent - most immediate parent of @loc available in dentry cache - * @resolved - component of @loc->path which has been resolved - * through dentry cache - */ -#define SERVER_DENTRY_STATE_PREPARE(_state,_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); \ - _state->loc.parent = inode_ref (_parent); \ - _state->loc.inode = inode_new (_state->itable); \ - if (_resolved) { \ - resolvedlen = strlen (_resolved); \ - strncpy (path, _resolved, resolvedlen); \ - _state->resolved = memdup (path, pathlen); \ - if (resolvedlen == 1) /* only root resolved */ \ - pad = 0; \ - else { \ - pad = 1; \ - path[resolvedlen] = '/'; \ - } \ - strcpy_till (path + resolvedlen + pad, loc->path + resolvedlen + pad, '/'); \ - } else { \ - strncpy (path, _loc->path, pathlen); \ - } \ - _state->loc.path = path; \ - _state->loc.name = strrchr (path, '/'); \ - if (_state->loc.name) \ - _state->loc.name++; \ - _state->path = strdup (_loc->path); \ - }while (0); - -/* SERVER_DENTRY_UPDATE_STATE - update a server_state_t, to prepare state - * for new lookup - * - * @state - state to be updated. - */ -#define SERVER_DENTRY_UPDATE_STATE(_state) do { \ - char *path = NULL; \ - size_t pathlen = 0; \ - strcpy (_state->resolved, _state->loc.path); \ - pathlen = strlen (_state->loc.path); \ - if (!strcmp (_state->resolved, _state->path)) { \ - free (_state->resolved); \ - _state->resolved = NULL; \ - goto resume; \ - } \ - \ - path = (char *)(_state->loc.path + pathlen); \ - path[0] = '/'; \ - strcpy_till (path + 1, \ - _state->path + pathlen + 1, '/'); \ - _state->loc.name = strrchr (_state->loc.path, '/'); \ - if (_state->loc.name) \ - _state->loc.name++; \ - inode_unref (_state->loc.parent); \ - _state->loc.parent = inode_ref (_state->loc.inode); \ - inode_unref (_state->loc.inode); \ - _state->loc.inode = inode_new (_state->itable); \ - }while (0); - -/* NOTE: should be used only for a state which was created by __do_path_resolve - * using any other state will result in double free corruption. - */ -#define SERVER_STATE_CLEANUP(_state) do { \ - if (_state->resolved) \ - free (_state->resolved); \ - if (_state->path) \ - free (_state->path); \ - server_loc_wipe (&_state->loc); \ - free_state (_state); \ - } 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; -} - -/* __server_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 * -__server_path_to_parenti (inode_table_t *itable, - const char *path, - char **reslv) -{ - char *resolved_till = NULL; - char *strtokptr = NULL; - char *component = NULL; - char *next_component = NULL; - char *pathdup = NULL; - inode_t *curr = NULL; - inode_t *parent = NULL; - size_t pathlen = 0; - - - pathlen = STRLEN_0 (path); - resolved_till = CALLOC (1, pathlen); - - GF_VALIDATE_OR_GOTO("server-dentry", resolved_till, out); - pathdup = strdup (path); - GF_VALIDATE_OR_GOTO("server-dentry", pathdup, out); - - parent = inode_ref (itable->root); - curr = NULL; - - component = strtok_r (pathdup, "/", &strtokptr); - - while (component) { - curr = inode_search (itable, parent->ino, component); - if (!curr) { - /* if current component was the last component - set it to NULL - */ - component = strtok_r (NULL, "/", &strtokptr); - 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; - } - - free (pathdup); - - if (component) { - *reslv = resolved_till; - } else { - free (resolved_till); - } -out: - return parent; -} - - -/* __do_path_resolve_cbk - - * - * @frame - - * @cookie - - * @this - - * @op_ret - - * @op_errno - - * @inode - - * @stbuf - - * @dict - - * - */ -static int32_t -__do_path_resolve_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct stat *stbuf, - dict_t *dict) -{ - server_state_t *state = NULL; - call_stub_t *stub = NULL; - inode_t *parent = NULL; - - stub = frame->local; - state = CALL_STATE(frame); - - parent = state->loc.parent; - - if (op_ret == -1) { - if (strcmp (state->path, state->loc.path)) - parent = NULL; - - server_stub_resume (stub, op_ret, op_errno, NULL, parent); - goto cleanup; - } else { - if (inode->ino == 0) { - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "looked up for %s (%"PRId64"/%s)", - state->loc.path, state->loc.parent->ino, state->loc.name); - inode_link (inode, state->loc.parent, state->loc.name, stbuf); - inode_lookup (inode); - } - - if (state->resolved) { - SERVER_DENTRY_UPDATE_STATE(state); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "looking up for %s (%"PRId64"/%s)", - state->loc.path, state->loc.parent->ino, state->loc.name); - - STACK_WIND (frame, - __do_path_resolve_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->lookup, - &(state->loc), - 0); - - goto out; - } - resume: - /* we are done, call stub_resume() to do rest of the job */ - server_stub_resume (stub, op_ret, op_errno, inode, parent); - cleanup: - SERVER_STATE_CLEANUP(state); - /* stub will be freed by stub_resume, leave no traces */ - frame->local = NULL; - STACK_DESTROY (frame->root); - } -out: - return 0; -} - -/* __do_path_resolve - resolve @loc->path into @loc->inode and @loc->parent. also - * update the dentry cache - * - * @stub - call stub to resume after resolving @loc->path - * @loc - loc to resolve before resuming @stub. - * - * return - return value of __do_path_resolve doesn't matter to the caller, if @stub - * is not NULL. - */ -static int32_t -__do_path_resolve (call_stub_t *stub, - const loc_t *loc) -{ - int32_t ret = -1; - char *resolved = NULL; - call_frame_t *new_frame = NULL; - server_state_t *state = NULL, *new_state = NULL; - inode_t *parent = NULL; - - state = CALL_STATE(stub->frame); - parent = loc->parent; - if (parent) { - inode_ref (parent); - gf_log (BOUND_XL(stub->frame)->name, GF_LOG_DEBUG, - "loc->parent(%"PRId64") already present. sending lookup " - "for %"PRId64"/%s", parent->ino, parent->ino, loc->name); - resolved = strdup (loc->path); - resolved = dirname (resolved); - } else { - parent = __server_path_to_parenti (state->itable, loc->path, &resolved); - } - - if (parent == NULL) { - /* fire in the bush.. run! run!! run!!! */ - gf_log ("server", - GF_LOG_CRITICAL, - "failed to get parent inode number"); - goto panic; - } - - if (resolved) { - gf_log (BOUND_XL(stub->frame)->name, - GF_LOG_DEBUG, - "resolved path(%s) till %"PRId64"(%s). " - "sending lookup for remaining path", - loc->path, parent->ino, resolved); - } - - { - new_frame = server_copy_frame (stub->frame); - new_state = CALL_STATE(new_frame); - - SERVER_DENTRY_STATE_PREPARE(new_state, loc, parent, resolved); - - if (parent) - inode_unref (parent); /* __server_path_to_parenti()'s inode_ref */ - free (resolved); - /* now interpret state as: - * state->path - compelete pathname to resolve - * state->resolved - pathname resolved from dentry cache - */ - new_frame->local = stub; - STACK_WIND (new_frame, - __do_path_resolve_cbk, - BOUND_XL(new_frame), - BOUND_XL(new_frame)->fops->lookup, - &(new_state->loc), - 0); - goto out; - } -panic: - server_stub_resume (stub, -1, ENOENT, NULL, NULL); -out: - return ret; -} - - -/* - * do_path_lookup - transform a pathname into inode, with the compelete - * dentry tree upto inode built. - * - * @stub - call stub to resume after completing pathname to inode transform - * @loc - location. valid fields that do_path_lookup() uses in @loc are - * @loc->path - pathname - * @loc->ino - inode number - * - * return - do_path_lookup returns only after complete dentry tree is built - * upto @loc->path. - */ -int32_t -do_path_lookup (call_stub_t *stub, - const loc_t *loc) -{ - char *pathname = NULL; - char *directory = NULL; - inode_t *inode = NULL; - inode_t *parent = NULL; - server_state_t *state = NULL; - - state = CALL_STATE(stub->frame); - - inode = inode_from_path (state->itable, loc->path); - pathname = strdup (loc->path); - directory = dirname (pathname); - parent = inode_from_path (state->itable, directory); - - if (inode && parent) { - gf_log (BOUND_XL(stub->frame)->name, - GF_LOG_DEBUG, - "resolved path(%s) to %"PRId64"/%"PRId64"(%s)", - loc->path, parent->ino, inode->ino, loc->name); - server_stub_resume (stub, 0, 0, inode, parent); - inode_unref (inode); - inode_unref (parent); - } else { - gf_log (BOUND_XL(stub->frame)->name, - GF_LOG_DEBUG, - "resolved path(%s) to %p(%"PRId64")/%p(%"PRId64")", - loc->path, parent, (parent ? parent->ino : 0), - inode, (inode ? inode->ino : 0)); - if (parent) { - inode_unref (parent); - } else if (inode) { - inode_unref (inode); - gf_log (BOUND_XL(stub->frame)->name, - GF_LOG_ERROR, - "undesired behaviour. inode(%"PRId64") for %s " - "exists without parent (%s)", - inode->ino, loc->path, directory); - } - __do_path_resolve (stub, loc); - } - - if (pathname) - free (pathname); - - return 0; -} diff --git a/xlators/protocol/server/src/server-handshake.c b/xlators/protocol/server/src/server-handshake.c new file mode 100644 index 000000000..d4941011d --- /dev/null +++ b/xlators/protocol/server/src/server-handshake.c @@ -0,0 +1,781 @@ +/* + Copyright (c) 2010-2013 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 _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "server.h" +#include "server-helpers.h" +#include "glusterfs3-xdr.h" +#include "compat-errno.h" +#include "glusterfs3.h" +#include "authenticate.h" + +struct __get_xl_struct { + const char *name; + xlator_t *reply; +}; +int +gf_compare_client_version (rpcsvc_request_t *req, int fop_prognum, + int mgmt_prognum) +{ + int ret = -1; + /* TODO: think.. */ + if (glusterfs3_3_fop_prog.prognum == fop_prognum) + ret = 0; + + return ret; +} + +void __check_and_set (xlator_t *each, void *data) +{ + if (!strcmp (each->name, + ((struct __get_xl_struct *) data)->name)) + ((struct __get_xl_struct *) data)->reply = each; +} + +static xlator_t * +get_xlator_by_name (xlator_t *some_xl, const char *name) +{ + struct __get_xl_struct get = { + .name = name, + .reply = NULL + }; + + xlator_foreach (some_xl, __check_and_set, &get); + + return get.reply; +} + + +int +_volfile_update_checksum (xlator_t *this, char *key, uint32_t checksum) +{ + server_conf_t *conf = NULL; + struct _volfile_ctx *temp_volfile = NULL; + + conf = this->private; + temp_volfile = conf->volfile; + + while (temp_volfile) { + if ((NULL == key) && (NULL == temp_volfile->key)) + break; + if ((NULL == key) || (NULL == temp_volfile->key)) { + temp_volfile = temp_volfile->next; + continue; + } + if (strcmp (temp_volfile->key, key) == 0) + break; + temp_volfile = temp_volfile->next; + } + + if (!temp_volfile) { + temp_volfile = GF_CALLOC (1, sizeof (struct _volfile_ctx), + gf_server_mt_volfile_ctx_t); + if (!temp_volfile) + goto out; + temp_volfile->next = conf->volfile; + temp_volfile->key = (key)? gf_strdup (key): NULL; + temp_volfile->checksum = checksum; + + conf->volfile = temp_volfile; + goto out; + } + + if (temp_volfile->checksum != checksum) { + gf_log (this->name, GF_LOG_INFO, + "the volume file was modified between a prior access " + "and now. This may lead to inconsistency between " + "clients, you are advised to remount client"); + temp_volfile->checksum = checksum; + } + +out: + return 0; +} + + +static size_t +getspec_build_volfile_path (xlator_t *this, const char *key, char *path, + size_t path_len) +{ + char *filename = NULL; + server_conf_t *conf = NULL; + int ret = -1; + int free_filename = 0; + char data_key[256] = {0,}; + + conf = this->private; + + /* Inform users that this option is changed now */ + ret = dict_get_str (this->options, "client-volume-filename", + &filename); + if (ret == 0) { + gf_log (this->name, GF_LOG_WARNING, + "option 'client-volume-filename' is changed to " + "'volume-filename.<key>' which now takes 'key' as an " + "option to choose/fetch different files from server. " + "Refer documentation or contact developers for more " + "info. Currently defaulting to given file '%s'", + filename); + } + + if (key && !filename) { + sprintf (data_key, "volume-filename.%s", key); + ret = dict_get_str (this->options, data_key, &filename); + if (ret < 0) { + /* Make sure that key doesn't contain "../" in path */ + if ((gf_strstr (key, "/", "..")) == -1) { + gf_log (this->name, GF_LOG_ERROR, + "%s: invalid key", key); + goto out; + } + } + } + + if (!filename) { + ret = dict_get_str (this->options, + "volume-filename.default", &filename); + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "no default volume filename given, " + "defaulting to %s", DEFAULT_VOLUME_FILE_PATH); + } + } + + if (!filename && key) { + ret = gf_asprintf (&filename, "%s/%s.vol", conf->conf_dir, key); + if (-1 == ret) + goto out; + + free_filename = 1; + } + if (!filename) + filename = DEFAULT_VOLUME_FILE_PATH; + + ret = -1; + + if ((filename) && (path_len > strlen (filename))) { + strcpy (path, filename); + ret = strlen (filename); + } + +out: + if (free_filename) + GF_FREE (filename); + + return ret; +} + +int +_validate_volfile_checksum (xlator_t *this, char *key, + uint32_t checksum) +{ + char filename[PATH_MAX] = {0,}; + server_conf_t *conf = NULL; + struct _volfile_ctx *temp_volfile = NULL; + int ret = 0; + int fd = 0; + uint32_t local_checksum = 0; + + conf = this->private; + temp_volfile = conf->volfile; + + if (!checksum) + goto out; + + if (!temp_volfile) { + ret = getspec_build_volfile_path (this, key, filename, + sizeof (filename)); + if (ret <= 0) + goto out; + fd = open (filename, O_RDONLY); + if (-1 == fd) { + ret = 0; + gf_log (this->name, GF_LOG_INFO, + "failed to open volume file (%s) : %s", + filename, strerror (errno)); + goto out; + } + get_checksum_for_file (fd, &local_checksum); + _volfile_update_checksum (this, key, local_checksum); + close (fd); + } + + temp_volfile = conf->volfile; + while (temp_volfile) { + if ((NULL == key) && (NULL == temp_volfile->key)) + break; + if ((NULL == key) || (NULL == temp_volfile->key)) { + temp_volfile = temp_volfile->next; + continue; + } + if (strcmp (temp_volfile->key, key) == 0) + break; + temp_volfile = temp_volfile->next; + } + + if (!temp_volfile) + goto out; + + if ((temp_volfile->checksum) && + (checksum != temp_volfile->checksum)) + ret = -1; + +out: + return ret; +} + + +int +server_getspec (rpcsvc_request_t *req) +{ + int32_t ret = -1; + int32_t op_errno = ENOENT; + int32_t spec_fd = -1; + size_t file_len = 0; + char filename[PATH_MAX] = {0,}; + struct stat stbuf = {0,}; + uint32_t checksum = 0; + char *key = NULL; + server_conf_t *conf = NULL; + xlator_t *this = NULL; + gf_getspec_req args = {0,}; + gf_getspec_rsp rsp = {0,}; + + this = req->svc->mydata; + conf = this->private; + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gf_getspec_req); + if (ret < 0) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + op_errno = EINVAL; + goto fail; + } + + ret = getspec_build_volfile_path (this, args.key, + filename, sizeof (filename)); + if (ret > 0) { + /* to allocate the proper buffer to hold the file data */ + ret = stat (filename, &stbuf); + if (ret < 0){ + gf_log (this->name, GF_LOG_ERROR, + "Unable to stat %s (%s)", + filename, strerror (errno)); + op_errno = errno; + goto fail; + } + + spec_fd = open (filename, O_RDONLY); + if (spec_fd < 0) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to open %s (%s)", + filename, strerror (errno)); + op_errno = errno; + goto fail; + } + ret = file_len = stbuf.st_size; + + if (conf->verify_volfile) { + get_checksum_for_file (spec_fd, &checksum); + _volfile_update_checksum (this, key, checksum); + } + } else { + op_errno = ENOENT; + } + + if (file_len) { + rsp.spec = GF_CALLOC (file_len, sizeof (char), + gf_server_mt_rsp_buf_t); + if (!rsp.spec) { + ret = -1; + op_errno = ENOMEM; + goto fail; + } + ret = read (spec_fd, rsp.spec, file_len); + } + + /* convert to XDR */ + op_errno = errno; +fail: + if (!rsp.spec) + rsp.spec = ""; + rsp.op_errno = gf_errno_to_error (op_errno); + rsp.op_ret = ret; + + if (spec_fd != -1) + close (spec_fd); + + server_submit_reply (NULL, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_getspec_rsp); + + return 0; +} + + +int +server_setvolume (rpcsvc_request_t *req) +{ + gf_setvolume_req args = {{0,},}; + gf_setvolume_rsp rsp = {0,}; + client_t *client = NULL; + server_ctx_t *serv_ctx = NULL; + server_conf_t *conf = NULL; + peer_info_t *peerinfo = NULL; + dict_t *reply = NULL; + dict_t *config_params = NULL; + dict_t *params = NULL; + char *name = NULL; + char *client_uid = NULL; + char *clnt_version = NULL; + xlator_t *xl = NULL; + char *msg = NULL; + char *volfile_key = NULL; + xlator_t *this = NULL; + uint32_t checksum = 0; + int32_t ret = -1; + int32_t op_ret = -1; + int32_t op_errno = EINVAL; + int32_t fop_version = 0; + int32_t mgmt_version = 0; + uint32_t lk_version = 0; + char *buf = NULL; + gf_boolean_t cancelled = _gf_false; + + params = dict_new (); + reply = dict_new (); + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gf_setvolume_req); + if (ret < 0) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto fail; + } + + this = req->svc->mydata; + + config_params = dict_copy_with_ref (this->options, NULL); + conf = this->private; + + buf = memdup (args.dict.dict_val, args.dict.dict_len); + if (buf == NULL) { + op_ret = -1; + op_errno = ENOMEM; + goto fail; + } + + ret = dict_unserialize (buf, args.dict.dict_len, ¶ms); + if (ret < 0) { + ret = dict_set_str (reply, "ERROR", + "Internal error: failed to unserialize " + "request dictionary"); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg \"%s\"", + "Internal error: failed to unserialize " + "request dictionary"); + + op_ret = -1; + op_errno = EINVAL; + goto fail; + } + + params->extra_free = buf; + buf = NULL; + + ret = dict_get_str (params, "process-uuid", &client_uid); + if (ret < 0) { + ret = dict_set_str (reply, "ERROR", + "UUID not specified"); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg"); + + op_ret = -1; + op_errno = EINVAL; + goto fail; + } + + /*lk_verion :: [1..2^31-1]*/ + ret = dict_get_uint32 (params, "clnt-lk-version", &lk_version); + if (ret < 0) { + ret = dict_set_str (reply, "ERROR", + "lock state version not supplied"); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg"); + + op_ret = -1; + op_errno = EINVAL; + goto fail; + } + + client = gf_client_get (this, &req->cred, client_uid); + if (client == NULL) { + op_ret = -1; + op_errno = ENOMEM; + goto fail; + } + + gf_log (this->name, GF_LOG_DEBUG, "Connected to %s", client->client_uid); + cancelled = server_cancel_grace_timer (this, client); + if (cancelled)//Do gf_client_put on behalf of grace-timer-handler. + gf_client_put (client, NULL); + + serv_ctx = server_ctx_get (client, client->this); + if (serv_ctx == NULL) { + gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed"); + goto fail; + } + + if (serv_ctx->lk_version != 0 && + serv_ctx->lk_version != lk_version) { + (void) server_connection_cleanup (this, client, + INTERNAL_LOCKS | POSIX_LOCKS); + } + + if (req->trans->xl_private != client) + req->trans->xl_private = client; + + ret = dict_get_int32 (params, "fops-version", &fop_version); + if (ret < 0) { + ret = dict_set_str (reply, "ERROR", + "No FOP version number specified"); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg"); + } + + ret = dict_get_int32 (params, "mgmt-version", &mgmt_version); + if (ret < 0) { + ret = dict_set_str (reply, "ERROR", + "No MGMT version number specified"); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg"); + } + + ret = gf_compare_client_version (req, fop_version, mgmt_version); + if (ret != 0) { + ret = gf_asprintf (&msg, "version mismatch: client(%d)" + " - client-mgmt(%d)", + fop_version, mgmt_version); + /* get_supported_version (req)); */ + if (-1 == ret) { + gf_log (this->name, GF_LOG_ERROR, + "asprintf failed while setting up error msg"); + goto fail; + } + ret = dict_set_dynstr (reply, "ERROR", msg); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg"); + + op_ret = -1; + op_errno = EINVAL; + goto fail; + } + + ret = dict_get_str (params, "remote-subvolume", &name); + if (ret < 0) { + ret = dict_set_str (reply, "ERROR", + "No remote-subvolume option specified"); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg"); + + op_ret = -1; + op_errno = EINVAL; + goto fail; + } + + xl = get_xlator_by_name (this, name); + if (xl == NULL) { + ret = gf_asprintf (&msg, "remote-subvolume \"%s\" is not found", + name); + if (-1 == ret) { + gf_log (this->name, GF_LOG_ERROR, + "asprintf failed while setting error msg"); + goto fail; + } + ret = dict_set_dynstr (reply, "ERROR", msg); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg"); + + op_ret = -1; + op_errno = ENOENT; + goto fail; + } + + if (conf->verify_volfile) { + ret = dict_get_uint32 (params, "volfile-checksum", &checksum); + if (ret == 0) { + ret = dict_get_str (params, "volfile-key", + &volfile_key); + if (ret) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set 'volfile-key'"); + + ret = _validate_volfile_checksum (this, volfile_key, + checksum); + if (-1 == ret) { + ret = dict_set_str (reply, "ERROR", + "volume-file checksum " + "varies from earlier " + "access"); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg"); + + op_ret = -1; + op_errno = ESTALE; + goto fail; + } + } + } + + + peerinfo = &req->trans->peerinfo; + if (peerinfo) { + ret = dict_set_static_ptr (params, "peer-info", peerinfo); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set peer-info"); + } + if (conf->auth_modules == NULL) { + gf_log (this->name, GF_LOG_ERROR, + "Authentication module not initialized"); + } + + ret = dict_get_str (params, "client-version", &clnt_version); + if (ret) + gf_log (this->name, GF_LOG_INFO, "client-version not set, " + "may be of older version"); + + ret = gf_authenticate (params, config_params, + conf->auth_modules); + + if (ret == AUTH_ACCEPT) { + + gf_log (this->name, GF_LOG_INFO, + "accepted client from %s (version: %s)", + client->client_uid, + (clnt_version) ? clnt_version : "old"); + op_ret = 0; + client->bound_xl = xl; + ret = dict_set_str (reply, "ERROR", "Success"); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg"); + } else { + gf_log (this->name, GF_LOG_ERROR, + "Cannot authenticate client from %s %s", + client->client_uid, + (clnt_version) ? clnt_version : "old"); + + op_ret = -1; + op_errno = EACCES; + ret = dict_set_str (reply, "ERROR", "Authentication failed"); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg"); + goto fail; + } + + if (client->bound_xl == NULL) { + ret = dict_set_str (reply, "ERROR", + "Check volfile and handshake " + "options in protocol/client"); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg"); + + op_ret = -1; + op_errno = EACCES; + goto fail; + } + + if ((client->bound_xl != NULL) && + (ret >= 0) && + (client->bound_xl->itable == NULL)) { + /* create inode table for this bound_xl, if one doesn't + already exist */ + + gf_log (this->name, GF_LOG_TRACE, + "creating inode table with lru_limit=%"PRId32", " + "xlator=%s", conf->inode_lru_limit, + client->bound_xl->name); + + /* TODO: what is this ? */ + client->bound_xl->itable = + inode_table_new (conf->inode_lru_limit, + client->bound_xl); + } + + ret = dict_set_str (reply, "process-uuid", + this->ctx->process_uuid); + if (ret) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set 'process-uuid'"); + + ret = dict_set_uint32 (reply, "clnt-lk-version", serv_ctx->lk_version); + if (ret) + gf_log (this->name, GF_LOG_WARNING, + "failed to set 'clnt-lk-version'"); + + ret = dict_set_uint64 (reply, "transport-ptr", + ((uint64_t) (long) req->trans)); + if (ret) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set 'transport-ptr'"); + +fail: + rsp.dict.dict_len = dict_serialized_length (reply); + if (rsp.dict.dict_len < 0) { + gf_log ("server-handshake", GF_LOG_DEBUG, + "failed to get serialized length of reply dict"); + op_ret = -1; + op_errno = EINVAL; + rsp.dict.dict_len = 0; + } + + if (rsp.dict.dict_len) { + rsp.dict.dict_val = GF_CALLOC (1, rsp.dict.dict_len, + gf_server_mt_rsp_buf_t); + if (rsp.dict.dict_val) { + ret = dict_serialize (reply, rsp.dict.dict_val); + if (ret < 0) { + gf_log ("server-handshake", GF_LOG_DEBUG, + "failed to serialize reply dict"); + op_ret = -1; + op_errno = -ret; + } + } + } + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + /* if bound_xl is NULL or something fails, then put the connection + * back. Otherwise the connection would have been added to the + * list of connections the server is maintaining and might segfault + * during statedump when bound_xl of the connection is accessed. + */ + if (op_ret && !xl) { + /* We would have set the xl_private of the transport to the + * @conn. But if we have put the connection i.e shutting down + * the connection, then we should set xl_private to NULL as it + * would be pointing to a freed memory and would segfault when + * accessed upon getting DISCONNECT. + */ + gf_client_put (client, NULL); + req->trans->xl_private = NULL; + } + server_submit_reply (NULL, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_setvolume_rsp); + + + free (args.dict.dict_val); + + GF_FREE (rsp.dict.dict_val); + + dict_unref (params); + dict_unref (reply); + dict_unref (config_params); + + GF_FREE (buf); + + return 0; +} + + +int +server_ping (rpcsvc_request_t *req) +{ + gf_common_rsp rsp = {0,}; + + /* Accepted */ + rsp.op_ret = 0; + + server_submit_reply (NULL, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + return 0; +} + +int +server_set_lk_version (rpcsvc_request_t *req) +{ + int op_ret = -1; + int op_errno = EINVAL; + gf_set_lk_ver_req args = {0,}; + gf_set_lk_ver_rsp rsp = {0,}; + client_t *client = NULL; + server_ctx_t *serv_ctx = NULL; + xlator_t *this = NULL; + + this = req->svc->mydata; + //TODO: Decide on an appropriate errno for the error-path + //below + if (!this) + goto fail; + + op_ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gf_set_lk_ver_req); + if (op_ret < 0) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto fail; + } + + client = gf_client_get (this, &req->cred, args.uid); + serv_ctx = server_ctx_get (client, client->this); + if (serv_ctx == NULL) { + gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed"); + goto fail; + } + + serv_ctx->lk_version = args.lk_ver; + gf_client_put (client, NULL); + + rsp.lk_ver = args.lk_ver; + + op_ret = 0; +fail: + rsp.op_ret = op_ret; + rsp.op_errno = op_errno; + server_submit_reply (NULL, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_set_lk_ver_rsp); + + free (args.uid); + + return 0; +} + +rpcsvc_actor_t gluster_handshake_actors[] = { + [GF_HNDSK_NULL] = {"NULL", GF_HNDSK_NULL, server_null, NULL, 0, DRC_NA}, + [GF_HNDSK_SETVOLUME] = {"SETVOLUME", GF_HNDSK_SETVOLUME, server_setvolume, NULL, 0, DRC_NA}, + [GF_HNDSK_GETSPEC] = {"GETSPEC", GF_HNDSK_GETSPEC, server_getspec, NULL, 0, DRC_NA}, + [GF_HNDSK_PING] = {"PING", GF_HNDSK_PING, server_ping, NULL, 0, DRC_NA}, + [GF_HNDSK_SET_LK_VER] = {"SET_LK_VER", GF_HNDSK_SET_LK_VER, server_set_lk_version, NULL, 0, DRC_NA}, +}; + + +struct rpcsvc_program gluster_handshake_prog = { + .progname = "GlusterFS Handshake", + .prognum = GLUSTER_HNDSK_PROGRAM, + .progver = GLUSTER_HNDSK_VERSION, + .actors = gluster_handshake_actors, + .numactors = GF_HNDSK_MAXVALUE, +}; diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c index a4e0b2081..f0b040c74 100644 --- a/xlators/protocol/server/src/server-helpers.c +++ b/xlators/protocol/server/src/server-helpers.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2010-2013 Red Hat, Inc. <http://www.redhat.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/>. + 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 _CONFIG_H @@ -22,779 +13,1249 @@ #include "config.h" #endif -#include "server-protocol.h" +#include "server.h" #include "server-helpers.h" +#include <fnmatch.h> -/* server_loc_fill - derive a loc_t for a given inode number - * - * NOTE: make sure that @loc is empty, because any pointers it holds with reference will - * be leaked after returning from here. - */ int -server_loc_fill (loc_t *loc, server_state_t *state, - ino_t ino, ino_t par, - const char *name, const char *path) -{ - inode_t *inode = NULL; - inode_t *parent = NULL; - int32_t ret = -1; - char *dentry_path = NULL; - - - GF_VALIDATE_OR_GOTO ("server", loc, out); - GF_VALIDATE_OR_GOTO ("server", state, out); - GF_VALIDATE_OR_GOTO ("server", path, out); - - /* anything beyond this point is success */ - ret = 0; - loc->ino = ino; - inode = loc->inode; - if (inode == NULL) { - if (ino) - inode = inode_search (state->itable, ino, NULL); - - if ((inode == NULL) && - (par && name)) - inode = inode_search (state->itable, par, name); - - loc->inode = inode; - if (inode) - loc->ino = inode->ino; - } - - parent = loc->parent; - if (parent == NULL) { - if (inode) - parent = inode_parent (inode, par, name); - else - parent = inode_search (state->itable, par, NULL); - loc->parent = parent; - } - - if (name && parent) { - ret = inode_path (parent, name, &dentry_path); - if (ret < 0) { - gf_log (state->bound_xl->name, GF_LOG_DEBUG, - "failed to build path for %"PRId64"/%s: %s", - parent->ino, name, strerror (-ret)); - } - } else if (inode) { - ret = inode_path (inode, NULL, &dentry_path); - if (ret < 0) { - gf_log (state->bound_xl->name, GF_LOG_DEBUG, - "failed to build path for %"PRId64": %s", - inode->ino, strerror (-ret)); - - inode_unref (loc->inode); - loc->inode = NULL; - } - } - - if (dentry_path) { - if (strcmp (dentry_path, path)) { - gf_log (state->bound_xl->name, GF_LOG_DEBUG, - "paths differ for inode(%"PRId64"): " - "client path = %s. dentry path = %s", - ino, path, dentry_path); - } - - loc->path = dentry_path; - loc->name = strrchr (loc->path, '/'); - if (loc->name) - loc->name++; - } else { - loc->path = strdup (path); - loc->name = strrchr (loc->path, '/'); - if (loc->name) - loc->name++; - } +server_decode_groups (call_frame_t *frame, rpcsvc_request_t *req) +{ + int i = 0; + + GF_VALIDATE_OR_GOTO ("server", frame, out); + GF_VALIDATE_OR_GOTO ("server", req, out); + + if (call_stack_alloc_groups (frame->root, req->auxgidcount) != 0) + return -1; + + frame->root->ngrps = req->auxgidcount; + if (frame->root->ngrps == 0) + return 0; + if (frame->root->ngrps > GF_MAX_AUX_GROUPS) + return -1; + + for (; i < frame->root->ngrps; ++i) + frame->root->groups[i] = req->auxgids[i]; out: - return ret; + return 0; } -/* - * stat_to_str - convert struct stat to a ASCII string - * @stbuf: struct stat pointer - * - * not for external reference - */ -char * -stat_to_str (struct stat *stbuf) -{ - char *tmp_buf = NULL; - - uint64_t dev = stbuf->st_dev; - uint64_t ino = stbuf->st_ino; - uint32_t mode = stbuf->st_mode; - uint32_t nlink = stbuf->st_nlink; - uint32_t uid = stbuf->st_uid; - uint32_t gid = stbuf->st_gid; - uint64_t rdev = stbuf->st_rdev; - uint64_t size = stbuf->st_size; - uint32_t blksize = stbuf->st_blksize; - uint64_t blocks = stbuf->st_blocks; - uint32_t atime = stbuf->st_atime; - uint32_t mtime = stbuf->st_mtime; - uint32_t ctime = stbuf->st_ctime; - - uint32_t atime_nsec = ST_ATIM_NSEC(stbuf); - uint32_t mtime_nsec = ST_MTIM_NSEC(stbuf); - uint32_t ctime_nsec = ST_CTIM_NSEC(stbuf); - - - asprintf (&tmp_buf, - GF_STAT_PRINT_FMT_STR, - dev, - ino, - mode, - nlink, - uid, - gid, - rdev, - size, - blksize, - blocks, - atime, - atime_nsec, - mtime, - mtime_nsec, - ctime, - ctime_nsec); - - return tmp_buf; + +void +server_loc_wipe (loc_t *loc) +{ + if (loc->parent) { + inode_unref (loc->parent); + loc->parent = NULL; + } + + if (loc->inode) { + inode_unref (loc->inode); + loc->inode = NULL; + } + + GF_FREE ((void *)loc->path); } void -server_loc_wipe (loc_t *loc) +server_resolve_wipe (server_resolve_t *resolve) { - if (loc->parent) - inode_unref (loc->parent); - if (loc->inode) - inode_unref (loc->inode); - if (loc->path) - free ((char *)loc->path); + GF_FREE ((void *)resolve->path); + + GF_FREE ((void *)resolve->bname); + + loc_wipe (&resolve->resolve_loc); } + void free_state (server_state_t *state) { - transport_t *trans = NULL; + if (state->xprt) { + rpc_transport_unref (state->xprt); + state->xprt = NULL; + } + if (state->fd) { + fd_unref (state->fd); + state->fd = NULL; + } - trans = state->trans; + if (state->params) { + dict_unref (state->params); + state->params = NULL; + } - if (state->fd) - fd_unref (state->fd); + if (state->iobref) { + iobref_unref (state->iobref); + state->iobref = NULL; + } - transport_unref (trans); - - if (state->xattr_req) - dict_unref (state->xattr_req); + if (state->iobuf) { + iobuf_unref (state->iobuf); + state->iobuf = NULL; + } - if (state->volume) - FREE (state->volume); + if (state->dict) { + dict_unref (state->dict); + state->dict = NULL; + } + + if (state->xdata) { + dict_unref (state->xdata); + state->xdata = NULL; + } + + GF_FREE ((void *)state->volume); + + GF_FREE ((void *)state->name); + + server_loc_wipe (&state->loc); + server_loc_wipe (&state->loc2); + + server_resolve_wipe (&state->resolve); + server_resolve_wipe (&state->resolve2); + + GF_FREE (state); +} + + +static int +server_connection_cleanup_flush_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata) +{ + int32_t ret = -1; + fd_t *fd = NULL; + client_t *client = NULL; + + GF_VALIDATE_OR_GOTO ("server", this, out); + GF_VALIDATE_OR_GOTO ("server", cookie, out); + GF_VALIDATE_OR_GOTO ("server", frame, out); + + fd = frame->local; + client = frame->root->client; + + fd_unref (fd); + frame->local = NULL; + + gf_client_unref (client); + STACK_DESTROY (frame->root); + + ret = 0; +out: + return ret; +} + + +static int +do_fd_cleanup (xlator_t *this, client_t* client, fdentry_t *fdentries, int fd_count) +{ + fd_t *fd = NULL; + int i = 0, ret = -1; + call_frame_t *tmp_frame = NULL; + xlator_t *bound_xl = NULL; + char *path = NULL; + + GF_VALIDATE_OR_GOTO ("server", this, out); + GF_VALIDATE_OR_GOTO ("server", fdentries, out); + + bound_xl = client->bound_xl; + for (i = 0;i < fd_count; i++) { + fd = fdentries[i].fd; + + if (fd != NULL) { + tmp_frame = create_frame (this, this->ctx->pool); + if (tmp_frame == NULL) { + goto out; + } + + GF_ASSERT (fd->inode); + + ret = inode_path (fd->inode, NULL, &path); + + if (ret > 0) { + gf_log (this->name, GF_LOG_INFO, + "fd cleanup on %s", path); + GF_FREE (path); + } else { + + gf_log (this->name, GF_LOG_INFO, + "fd cleanup on inode with gfid %s", + uuid_utoa (fd->inode->gfid)); + } + + tmp_frame->local = fd; + + tmp_frame->root->pid = 0; + gf_client_ref (client); + memset (&tmp_frame->root->lk_owner, 0, + sizeof (gf_lkowner_t)); + + STACK_WIND (tmp_frame, + server_connection_cleanup_flush_cbk, + bound_xl, bound_xl->fops->flush, fd, NULL); + } + } + + GF_FREE (fdentries); + ret = 0; + +out: + return ret; +} + + +int +server_connection_cleanup (xlator_t *this, client_t *client, + int32_t flags) +{ + server_ctx_t *serv_ctx = NULL; + fdentry_t *fdentries = NULL; + uint32_t fd_count = 0; + int cd_ret = 0; + int ret = 0; + + GF_VALIDATE_OR_GOTO (this->name, this, out); + GF_VALIDATE_OR_GOTO (this->name, client, out); + GF_VALIDATE_OR_GOTO (this->name, flags, out); + + serv_ctx = server_ctx_get (client, client->this); + + if (serv_ctx == NULL) { + gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed"); + goto out; + } + + LOCK (&serv_ctx->fdtable_lock); + { + if (serv_ctx->fdtable && (flags & POSIX_LOCKS)) + fdentries = gf_fd_fdtable_get_all_fds (serv_ctx->fdtable, + &fd_count); + } + UNLOCK (&serv_ctx->fdtable_lock); + + if (client->bound_xl == NULL) + goto out; + + if (flags & INTERNAL_LOCKS) { + cd_ret = gf_client_disconnect (client); + } + + if (fdentries != NULL) + ret = do_fd_cleanup (this, client, fdentries, fd_count); + else + gf_log (this->name, GF_LOG_INFO, "no fdentries to clean"); + + if (cd_ret || ret) + ret = -1; + +out: + return ret; +} + + +static call_frame_t * +server_alloc_frame (rpcsvc_request_t *req) +{ + call_frame_t *frame = NULL; + server_state_t *state = NULL; + client_t *client = NULL; + + GF_VALIDATE_OR_GOTO ("server", req, out); + GF_VALIDATE_OR_GOTO ("server", req->trans, out); + GF_VALIDATE_OR_GOTO ("server", req->svc, out); + GF_VALIDATE_OR_GOTO ("server", req->svc->ctx, out); + + client = req->trans->xl_private; + GF_VALIDATE_OR_GOTO ("server", client, out); + + frame = create_frame (client->this, req->svc->ctx->pool); + if (!frame) + goto out; + + state = GF_CALLOC (1, sizeof (*state), gf_server_mt_state_t); + if (!state) + goto out; - FREE (state); + if (client->bound_xl) + state->itable = client->bound_xl->itable; + + state->xprt = rpc_transport_ref (req->trans); + state->resolve.fd_no = -1; + state->resolve2.fd_no = -1; + + frame->root->client = client; + frame->root->state = state; /* which socket */ + frame->root->unique = 0; /* which call */ + + frame->this = client->this; +out: + return frame; } call_frame_t * -server_copy_frame (call_frame_t *frame) +get_frame_from_request (rpcsvc_request_t *req) { - call_frame_t *new_frame = NULL; - server_state_t *state = NULL, *new_state = NULL; + call_frame_t *frame = NULL; + client_t *client = NULL; + + GF_VALIDATE_OR_GOTO ("server", req, out); - state = frame->root->state; + client = req->trans->xl_private; - new_frame = copy_frame (frame); + frame = server_alloc_frame (req); + if (!frame) + goto out; - new_state = CALLOC (1, sizeof (server_state_t)); + frame->root->op = req->procnum; - new_frame->root->op = frame->root->op; - new_frame->root->type = frame->root->type; - new_frame->root->trans = state->trans; - new_frame->root->state = new_state; + frame->root->unique = req->xid; - new_state->bound_xl = state->bound_xl; - new_state->trans = transport_ref (state->trans); - new_state->itable = state->itable; + frame->root->uid = req->uid; + frame->root->gid = req->gid; + frame->root->pid = req->pid; + gf_client_ref (client); + frame->root->client = client; + frame->root->lk_owner = req->lk_owner; - return new_frame; + server_decode_groups (frame, req); + + frame->local = req; +out: + return frame; } -int32_t -gf_add_locker (struct _lock_table *table, - const char *volume, - loc_t *loc, - fd_t *fd, - pid_t pid) -{ - int32_t ret = -1; - struct _locker *new = NULL; - uint8_t dir = 0; - - new = CALLOC (1, sizeof (struct _locker)); - if (new == NULL) { - gf_log ("server", GF_LOG_ERROR, - "failed to allocate memory for \'struct _locker\'"); - goto out; - } - INIT_LIST_HEAD (&new->lockers); - - new->volume = strdup (volume); - - if (fd == NULL) { - loc_copy (&new->loc, loc); - dir = S_ISDIR (new->loc.inode->st_mode); - } else { - new->fd = fd_ref (fd); - dir = S_ISDIR (fd->inode->st_mode); - } - - new->pid = pid; - - LOCK (&table->lock); - { - if (dir) - list_add_tail (&new->lockers, &table->dir_lockers); - else - list_add_tail (&new->lockers, &table->file_lockers); - } - UNLOCK (&table->lock); + +int +server_build_config (xlator_t *this, server_conf_t *conf) +{ + data_t *data = NULL; + int ret = -1; + struct stat buf = {0,}; + + GF_VALIDATE_OR_GOTO ("server", this, out); + GF_VALIDATE_OR_GOTO ("server", conf, out); + + ret = dict_get_int32 (this->options, "inode-lru-limit", + &conf->inode_lru_limit); + if (ret < 0) { + conf->inode_lru_limit = 16384; + } + + conf->verify_volfile = 1; + data = dict_get (this->options, "verify-volfile-checksum"); + if (data) { + ret = gf_string2boolean(data->data, &conf->verify_volfile); + if (ret != 0) { + gf_log (this->name, GF_LOG_WARNING, + "wrong value for 'verify-volfile-checksum', " + "Neglecting option"); + } + } + + data = dict_get (this->options, "trace"); + if (data) { + ret = gf_string2boolean (data->data, &conf->trace); + if (ret != 0) { + gf_log (this->name, GF_LOG_WARNING, + "'trace' takes on only boolean values. " + "Neglecting option"); + } + } + + /* TODO: build_rpc_config (); */ + ret = dict_get_int32 (this->options, "limits.transaction-size", + &conf->rpc_conf.max_block_size); + if (ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "defaulting limits.transaction-size to %d", + DEFAULT_BLOCK_SIZE); + conf->rpc_conf.max_block_size = DEFAULT_BLOCK_SIZE; + } + + data = dict_get (this->options, "config-directory"); + if (data) { + /* Check whether the specified directory exists, + or directory specified is non standard */ + ret = stat (data->data, &buf); + if ((ret != 0) || !S_ISDIR (buf.st_mode)) { + gf_log (this->name, GF_LOG_ERROR, + "Directory '%s' doesn't exist, exiting.", + data->data); + ret = -1; + goto out; + } + /* Make sure that conf-dir doesn't contain ".." in path */ + if ((gf_strstr (data->data, "/", "..")) == -1) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, + "%s: invalid conf_dir", data->data); + goto out; + } + + conf->conf_dir = gf_strdup (data->data); + } + ret = 0; out: - return ret; + return ret; } -int32_t -gf_del_locker (struct _lock_table *table, - const char *volume, - loc_t *loc, - fd_t *fd, - pid_t pid) -{ - struct _locker *locker = NULL, *tmp = NULL; - int32_t ret = 0; - uint8_t dir = 0; - struct list_head *head = NULL; - struct list_head del; - - INIT_LIST_HEAD (&del); - - if (fd) { - dir = S_ISDIR (fd->inode->st_mode); - } else { - dir = S_ISDIR (loc->inode->st_mode); - } - - LOCK (&table->lock); - { - if (dir) { - head = &table->dir_lockers; - } else { - head = &table->file_lockers; - } - - list_for_each_entry_safe (locker, tmp, head, lockers) { - if (locker->fd && - fd && - (locker->fd == fd) && (locker->pid == pid) - && !strcmp (locker->volume, volume)) { - list_move_tail (&locker->lockers, &del); - } else if (locker->loc.inode && - loc && - (locker->loc.inode == loc->inode) && - (locker->pid == pid) - && !strcmp (locker->volume, volume)) { - list_move_tail (&locker->lockers, &del); - } - } - } - UNLOCK (&table->lock); - - tmp = NULL; - locker = NULL; - - list_for_each_entry_safe (locker, tmp, &del, lockers) { - list_del_init (&locker->lockers); - if (locker->fd) - fd_unref (locker->fd); - else - loc_wipe (&locker->loc); - - free (locker->volume); - free (locker); - } - - return ret; + +void +print_caller (char *str, int size, call_frame_t *frame) +{ + server_state_t *state = NULL; + + GF_VALIDATE_OR_GOTO ("server", str, out); + GF_VALIDATE_OR_GOTO ("server", frame, out); + + state = CALL_STATE (frame); + + snprintf (str, size, + " Callid=%"PRId64", Client=%s", + frame->root->unique, + state->xprt->peerinfo.identifier); + +out: + return; } -int32_t -gf_direntry_to_bin (dir_entry_t *head, - char *buffer) -{ - dir_entry_t *trav = NULL; - uint32_t len = 0; - uint32_t this_len = 0; - size_t buflen = -1; - char *ptr = NULL; - char *tmp_buf = NULL; - - trav = head->next; - while (trav) { - len += strlen (trav->name); - len += 1; - len += strlen (trav->link); - len += 1; /* for '\n' */ - len += 256; // max possible for statbuf; - trav = trav->next; - } - - ptr = buffer; - trav = head->next; - while (trav) { - tmp_buf = stat_to_str (&trav->buf); - /* tmp_buf will have \n before \0 */ - - this_len = sprintf (ptr, "%s/%s%s\n", - trav->name, tmp_buf, - trav->link); - - FREE (tmp_buf); - trav = trav->next; - ptr += this_len; - } - - buflen = strlen (buffer); - - return buflen; -} - - -static struct _lock_table * -gf_lock_table_new (void) -{ - struct _lock_table *new = NULL; - - new = CALLOC (1, sizeof (struct _lock_table)); - if (new == NULL) { - gf_log ("server-protocol", GF_LOG_CRITICAL, - "failed to allocate memory for new lock table"); - goto out; - } - INIT_LIST_HEAD (&new->dir_lockers); - INIT_LIST_HEAD (&new->file_lockers); - LOCK_INIT (&new->lock); + +void +server_print_resolve (char *str, int size, server_resolve_t *resolve) +{ + int filled = 0; + + GF_VALIDATE_OR_GOTO ("server", str, out); + + if (!resolve) { + snprintf (str, size, "<nul>"); + return; + } + + filled += snprintf (str + filled, size - filled, + " Resolve={"); + if (resolve->fd_no != -1) + filled += snprintf (str + filled, size - filled, + "fd=%"PRId64",", (uint64_t) resolve->fd_no); + if (resolve->bname) + filled += snprintf (str + filled, size - filled, + "bname=%s,", resolve->bname); + if (resolve->path) + filled += snprintf (str + filled, size - filled, + "path=%s", resolve->path); + + snprintf (str + filled, size - filled, "}"); out: - return new; + return; } -static int32_t -server_connection_cleanup_flush_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) +void +server_print_loc (char *str, int size, loc_t *loc) { - fd_t *fd = NULL; - fd = frame->local; + int filled = 0; - fd_unref (fd); - frame->local = NULL; + GF_VALIDATE_OR_GOTO ("server", str, out); - STACK_DESTROY (frame->root); - return 0; + if (!loc) { + snprintf (str, size, "<nul>"); + return; + } + + filled += snprintf (str + filled, size - filled, + " Loc={"); + + if (loc->path) + filled += snprintf (str + filled, size - filled, + "path=%s,", loc->path); + if (loc->inode) + filled += snprintf (str + filled, size - filled, + "inode=%p,", loc->inode); + if (loc->parent) + filled += snprintf (str + filled, size - filled, + "parent=%p", loc->parent); + + snprintf (str + filled, size - filled, "}"); +out: + return; +} + + +void +server_print_params (char *str, int size, server_state_t *state) +{ + int filled = 0; + + GF_VALIDATE_OR_GOTO ("server", str, out); + + filled += snprintf (str + filled, size - filled, + " Params={"); + + if (state->fd) + filled += snprintf (str + filled, size - filled, + "fd=%p,", state->fd); + if (state->valid) + filled += snprintf (str + filled, size - filled, + "valid=%d,", state->valid); + if (state->flags) + filled += snprintf (str + filled, size - filled, + "flags=%d,", state->flags); + if (state->wbflags) + filled += snprintf (str + filled, size - filled, + "wbflags=%d,", state->wbflags); + if (state->size) + filled += snprintf (str + filled, size - filled, + "size=%zu,", state->size); + if (state->offset) + filled += snprintf (str + filled, size - filled, + "offset=%"PRId64",", state->offset); + if (state->cmd) + filled += snprintf (str + filled, size - filled, + "cmd=%d,", state->cmd); + if (state->type) + filled += snprintf (str + filled, size - filled, + "type=%d,", state->type); + if (state->name) + filled += snprintf (str + filled, size - filled, + "name=%s,", state->name); + if (state->mask) + filled += snprintf (str + filled, size - filled, + "mask=%d,", state->mask); + if (state->volume) + filled += snprintf (str + filled, size - filled, + "volume=%s,", state->volume); + +/* FIXME + snprintf (str + filled, size - filled, + "bound_xl=%s}", state->client->bound_xl->name); +*/ +out: + return; } int -server_connection_cleanup (xlator_t *this, server_connection_t *conn) -{ - call_frame_t *frame = NULL, *tmp_frame = NULL; - xlator_t *bound_xl = NULL; - server_state_t *state = NULL; - struct list_head file_lockers; - struct list_head dir_lockers; - struct _lock_table *ltable = NULL; - struct _locker *locker = NULL, *tmp = NULL; - struct flock flock = {0,}; - fd_t *fd = NULL; - uint32_t fd_count = 0; - fd_t **fds = NULL; - int32_t i = 0; +server_resolve_is_empty (server_resolve_t *resolve) +{ + if (resolve->fd_no != -1) + return 0; + + if (resolve->path != 0) + return 0; + + if (resolve->bname != 0) + return 0; + + return 1; +} + + +void +server_print_reply (call_frame_t *frame, int op_ret, int op_errno) +{ + server_conf_t *conf = NULL; + server_state_t *state = NULL; + xlator_t *this = NULL; + char caller[512]; + char fdstr[32]; + char *op = "UNKNOWN"; + + GF_VALIDATE_OR_GOTO ("server", frame, out); - if (conn == NULL) { + this = frame->this; + conf = this->private; + + GF_VALIDATE_OR_GOTO ("server", conf, out); + GF_VALIDATE_OR_GOTO ("server", conf->trace, out); + + state = CALL_STATE (frame); + + print_caller (caller, 256, frame); + + switch (frame->root->type) { + case GF_OP_TYPE_FOP: + op = (char *)gf_fop_list[frame->root->op]; + break; + default: + op = ""; + } + + fdstr[0] = '\0'; + if (state->fd) + snprintf (fdstr, 32, " fd=%p", state->fd); + + gf_log (this->name, GF_LOG_INFO, + "%s%s => (%d, %d)%s", + op, caller, op_ret, op_errno, fdstr); +out: + return; +} + + +void +server_print_request (call_frame_t *frame) +{ + server_conf_t *conf = NULL; + xlator_t *this = NULL; + server_state_t *state = NULL; + char *op = "UNKNOWN"; + char resolve_vars[256]; + char resolve2_vars[256]; + char loc_vars[256]; + char loc2_vars[256]; + char other_vars[512]; + char caller[512]; + + GF_VALIDATE_OR_GOTO ("server", frame, out); + + this = frame->this; + conf = this->private; + + GF_VALIDATE_OR_GOTO ("server", conf, out); + + if (!conf->trace) goto out; + + state = CALL_STATE (frame); + + memset (resolve_vars, '\0', 256); + memset (resolve2_vars, '\0', 256); + memset (loc_vars, '\0', 256); + memset (loc2_vars, '\0', 256); + memset (other_vars, '\0', 256); + + print_caller (caller, 256, frame); + + if (!server_resolve_is_empty (&state->resolve)) { + server_print_resolve (resolve_vars, 256, &state->resolve); + server_print_loc (loc_vars, 256, &state->loc); } - bound_xl = (xlator_t *) (conn->bound_xl); - - if (bound_xl) { - /* trans will have ref_count = 1 after this call, but its - ok since this function is called in - GF_EVENT_TRANSPORT_CLEANUP */ - frame = create_frame (this, this->ctx->pool); - - pthread_mutex_lock (&(conn->lock)); - { - if (conn->ltable) { - ltable = conn->ltable; - conn->ltable = gf_lock_table_new (); - } - } - pthread_mutex_unlock (&conn->lock); - - INIT_LIST_HEAD (&file_lockers); - INIT_LIST_HEAD (&dir_lockers); - - LOCK (<able->lock); - { - list_splice_init (<able->file_lockers, - &file_lockers); - - list_splice_init (<able->dir_lockers, &dir_lockers); - } - UNLOCK (<able->lock); - free (ltable); - - flock.l_type = F_UNLCK; - flock.l_start = 0; - flock.l_len = 0; - list_for_each_entry_safe (locker, - tmp, &file_lockers, lockers) { - tmp_frame = copy_frame (frame); - /* - pid = 0 is a special case that tells posix-locks - to release all locks from this transport - */ - tmp_frame->root->pid = 0; - tmp_frame->root->trans = conn; - - if (locker->fd) { - STACK_WIND (tmp_frame, server_nop_cbk, - bound_xl, - bound_xl->fops->finodelk, - locker->volume, - locker->fd, F_SETLK, &flock); - fd_unref (locker->fd); - } else { - STACK_WIND (tmp_frame, server_nop_cbk, - bound_xl, - bound_xl->fops->inodelk, - locker->volume, - &(locker->loc), F_SETLK, &flock); - loc_wipe (&locker->loc); - } - - free (locker->volume); - - list_del_init (&locker->lockers); - free (locker); - } - - tmp = NULL; - locker = NULL; - list_for_each_entry_safe (locker, tmp, &dir_lockers, lockers) { - tmp_frame = copy_frame (frame); - - tmp_frame->root->pid = 0; - tmp_frame->root->trans = conn; - - if (locker->fd) { - STACK_WIND (tmp_frame, server_nop_cbk, - bound_xl, - bound_xl->fops->fentrylk, - locker->volume, - locker->fd, NULL, - ENTRYLK_UNLOCK, ENTRYLK_WRLCK); - fd_unref (locker->fd); - } else { - STACK_WIND (tmp_frame, server_nop_cbk, - bound_xl, - bound_xl->fops->entrylk, - locker->volume, - &(locker->loc), NULL, - ENTRYLK_UNLOCK, ENTRYLK_WRLCK); - loc_wipe (&locker->loc); - } - - free (locker->volume); - - list_del_init (&locker->lockers); - free (locker); - } - - pthread_mutex_lock (&conn->lock); - { - if (conn->fdtable) { - fds = gf_fd_fdtable_get_all_fds (conn->fdtable, - &fd_count); + if (!server_resolve_is_empty (&state->resolve2)) { + server_print_resolve (resolve2_vars, 256, &state->resolve2); + server_print_loc (loc2_vars, 256, &state->loc2); + } + + server_print_params (other_vars, 512, state); + + switch (frame->root->type) { + case GF_OP_TYPE_FOP: + op = (char *)gf_fop_list[frame->root->op]; + break; + default: + op = ""; + break; + } + + gf_log (this->name, GF_LOG_INFO, + "%s%s%s%s%s%s%s", + op, caller, + resolve_vars, loc_vars, resolve2_vars, loc2_vars, other_vars); +out: + return; +} + + +int +serialize_rsp_direntp (gf_dirent_t *entries, gfs3_readdirp_rsp *rsp) +{ + gf_dirent_t *entry = NULL; + gfs3_dirplist *trav = NULL; + gfs3_dirplist *prev = NULL; + int ret = -1; + + GF_VALIDATE_OR_GOTO ("server", entries, out); + GF_VALIDATE_OR_GOTO ("server", rsp, out); + + list_for_each_entry (entry, &entries->list, list) { + trav = GF_CALLOC (1, sizeof (*trav), gf_server_mt_dirent_rsp_t); + if (!trav) + goto out; + + trav->d_ino = entry->d_ino; + trav->d_off = entry->d_off; + trav->d_len = entry->d_len; + trav->d_type = entry->d_type; + trav->name = entry->d_name; + + gf_stat_from_iatt (&trav->stat, &entry->d_stat); + + /* if 'dict' is present, pack it */ + if (entry->dict) { + trav->dict.dict_len = dict_serialized_length (entry->dict); + if (trav->dict.dict_len < 0) { + gf_log (THIS->name, GF_LOG_ERROR, + "failed to get serialized length " + "of reply dict"); + errno = EINVAL; + trav->dict.dict_len = 0; + goto out; } - } - pthread_mutex_unlock (&conn->lock); - - if (fds != NULL) { - for (i = 0;i < fd_count; i++) { - fd = fds[i]; - - if (fd != NULL) { - tmp_frame = copy_frame (frame); - tmp_frame->local = fd; - - tmp_frame->root->pid = 0; - tmp_frame->root->trans = conn; - STACK_WIND (tmp_frame, - server_connection_cleanup_flush_cbk, - bound_xl, - bound_xl->fops->flush, - fd); - } + + trav->dict.dict_val = GF_CALLOC (1, trav->dict.dict_len, + gf_server_mt_rsp_buf_t); + if (!trav->dict.dict_val) { + errno = ENOMEM; + trav->dict.dict_len = 0; + goto out; + } + + ret = dict_serialize (entry->dict, trav->dict.dict_val); + if (ret < 0) { + gf_log (THIS->name, GF_LOG_ERROR, + "failed to serialize reply dict"); + errno = -ret; + trav->dict.dict_len = 0; + goto out; } - FREE (fds); } - state = CALL_STATE (frame); - if (state) - free (state); - STACK_DESTROY (frame->root); + if (prev) + prev->nextentry = trav; + else + rsp->reply = trav; + + prev = trav; + trav = NULL; } + ret = 0; out: + GF_FREE (trav); + + return ret; +} + + +int +serialize_rsp_dirent (gf_dirent_t *entries, gfs3_readdir_rsp *rsp) +{ + gf_dirent_t *entry = NULL; + gfs3_dirlist *trav = NULL; + gfs3_dirlist *prev = NULL; + int ret = -1; + + GF_VALIDATE_OR_GOTO ("server", entries, out); + GF_VALIDATE_OR_GOTO ("server", rsp, out); + + list_for_each_entry (entry, &entries->list, list) { + trav = GF_CALLOC (1, sizeof (*trav), gf_server_mt_dirent_rsp_t); + if (!trav) + goto out; + trav->d_ino = entry->d_ino; + trav->d_off = entry->d_off; + trav->d_len = entry->d_len; + trav->d_type = entry->d_type; + trav->name = entry->d_name; + if (prev) + prev->nextentry = trav; + else + rsp->reply = trav; + + prev = trav; + } + + ret = 0; +out: + return ret; +} + + +int +readdir_rsp_cleanup (gfs3_readdir_rsp *rsp) +{ + gfs3_dirlist *prev = NULL; + gfs3_dirlist *trav = NULL; + + trav = rsp->reply; + prev = trav; + while (trav) { + trav = trav->nextentry; + GF_FREE (prev); + prev = trav; + } + return 0; } int -server_connection_destroy (xlator_t *this, server_connection_t *conn) -{ - call_frame_t *frame = NULL, *tmp_frame = NULL; - xlator_t *bound_xl = NULL; - int32_t ret = -1; - server_state_t *state = NULL; - struct list_head file_lockers; - struct list_head dir_lockers; - struct _lock_table *ltable = NULL; - struct _locker *locker = NULL, *tmp = NULL; - struct flock flock = {0,}; - fd_t *fd = NULL; - int32_t i = 0; - fd_t **fds = NULL; - uint32_t fd_count = 0; - - if (conn == NULL) { - ret = 0; - goto out; +readdirp_rsp_cleanup (gfs3_readdirp_rsp *rsp) +{ + gfs3_dirplist *prev = NULL; + gfs3_dirplist *trav = NULL; + + trav = rsp->reply; + prev = trav; + while (trav) { + trav = trav->nextentry; + GF_FREE (prev->dict.dict_val); + GF_FREE (prev); + prev = trav; } - bound_xl = (xlator_t *) (conn->bound_xl); - - if (bound_xl) { - /* trans will have ref_count = 1 after this call, but its - ok since this function is called in - GF_EVENT_TRANSPORT_CLEANUP */ - frame = create_frame (this, this->ctx->pool); - - pthread_mutex_lock (&(conn->lock)); - { - if (conn->ltable) { - ltable = conn->ltable; - conn->ltable = NULL; - } - } - pthread_mutex_unlock (&conn->lock); - - INIT_LIST_HEAD (&file_lockers); - INIT_LIST_HEAD (&dir_lockers); - - LOCK (<able->lock); - { - list_splice_init (<able->file_lockers, - &file_lockers); - - list_splice_init (<able->dir_lockers, &dir_lockers); - } - UNLOCK (<able->lock); - free (ltable); - - flock.l_type = F_UNLCK; - flock.l_start = 0; - flock.l_len = 0; - list_for_each_entry_safe (locker, - tmp, &file_lockers, lockers) { - tmp_frame = copy_frame (frame); - /* - pid = 0 is a special case that tells posix-locks - to release all locks from this transport - */ - tmp_frame->root->pid = 0; - tmp_frame->root->trans = conn; - - if (locker->fd) { - STACK_WIND (tmp_frame, server_nop_cbk, - bound_xl, - bound_xl->fops->finodelk, - locker->volume, - locker->fd, F_SETLK, &flock); - fd_unref (locker->fd); - } else { - STACK_WIND (tmp_frame, server_nop_cbk, - bound_xl, - bound_xl->fops->inodelk, - locker->volume, - &(locker->loc), F_SETLK, &flock); - loc_wipe (&locker->loc); - } - - free (locker->volume); - - list_del_init (&locker->lockers); - free (locker); - } - - tmp = NULL; - locker = NULL; - list_for_each_entry_safe (locker, tmp, &dir_lockers, lockers) { - tmp_frame = copy_frame (frame); - - tmp_frame->root->pid = 0; - tmp_frame->root->trans = conn; - - if (locker->fd) { - STACK_WIND (tmp_frame, server_nop_cbk, - bound_xl, - bound_xl->fops->fentrylk, - locker->volume, - locker->fd, NULL, - ENTRYLK_UNLOCK, ENTRYLK_WRLCK); - fd_unref (locker->fd); - } else { - STACK_WIND (tmp_frame, server_nop_cbk, - bound_xl, - bound_xl->fops->entrylk, - locker->volume, - &(locker->loc), NULL, - ENTRYLK_UNLOCK, ENTRYLK_WRLCK); - loc_wipe (&locker->loc); - } - - free (locker->volume); - - list_del_init (&locker->lockers); - free (locker); - } - - state = CALL_STATE (frame); - if (state) - free (state); - STACK_DESTROY (frame->root); - - pthread_mutex_lock (&(conn->lock)); - { - if (conn->fdtable) { - fds = gf_fd_fdtable_get_all_fds (conn->fdtable, - &fd_count); - gf_fd_fdtable_destroy (conn->fdtable); - conn->fdtable = NULL; - } - } - pthread_mutex_unlock (&conn->lock); - - if (fds != NULL) { - for (i = 0; i < fd_count; i++) { - fd = fds[i]; - if (fd != NULL) { - tmp_frame = copy_frame (frame); - tmp_frame->local = fd; - - STACK_WIND (tmp_frame, - server_connection_cleanup_flush_cbk, - bound_xl, - bound_xl->fops->flush, - fd); - } + return 0; +} + + +int +gf_server_check_getxattr_cmd (call_frame_t *frame, const char *key) +{ + + server_conf_t *conf = NULL; + rpc_transport_t *xprt = NULL; + + conf = frame->this->private; + if (!conf) + return 0; + + if (fnmatch ("*list*mount*point*", key, 0) == 0) { + /* list all the client protocol connecting to this process */ + pthread_mutex_lock (&conf->mutex); + { + list_for_each_entry (xprt, &conf->xprt_list, list) { + gf_log ("mount-point-list", GF_LOG_INFO, + "%s", xprt->peerinfo.identifier); } - FREE (fds); } - } + pthread_mutex_unlock (&conf->mutex); + } - gf_log (this->name, GF_LOG_INFO, "destroyed connection of %s", - conn->id); + /* Add more options/keys here */ - FREE (conn->id); - FREE (conn); + return 0; +} -out: - return ret; + +int +gf_server_check_setxattr_cmd (call_frame_t *frame, dict_t *dict) +{ + + server_conf_t *conf = NULL; + rpc_transport_t *xprt = NULL; + uint64_t total_read = 0; + uint64_t total_write = 0; + + conf = frame->this->private; + if (!conf || !dict) + return 0; + + if (dict_foreach_fnmatch (dict, "*io*stat*dump", + dict_null_foreach_fn, NULL ) > 0) { + list_for_each_entry (xprt, &conf->xprt_list, list) { + total_read += xprt->total_bytes_read; + total_write += xprt->total_bytes_write; + } + gf_log ("stats", GF_LOG_INFO, + "total-read %"PRIu64", total-write %"PRIu64, + total_read, total_write); + } + + return 0; } -server_connection_t * -server_connection_get (xlator_t *this, const char *id) +gf_boolean_t +server_cancel_grace_timer (xlator_t *this, client_t *client) +{ + server_ctx_t *serv_ctx = NULL; + gf_timer_t *timer = NULL; + gf_boolean_t cancelled = _gf_false; + + if (!this || !client) { + gf_log (THIS->name, GF_LOG_ERROR, + "Invalid arguments to cancel connection timer"); + return cancelled; + } + + serv_ctx = server_ctx_get (client, client->this); + + if (serv_ctx == NULL) { + gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed"); + goto out; + } + + LOCK (&serv_ctx->fdtable_lock); + { + if (serv_ctx->grace_timer) { + timer = serv_ctx->grace_timer; + serv_ctx->grace_timer = NULL; + } + } + UNLOCK (&serv_ctx->fdtable_lock); + + if (timer) { + gf_timer_call_cancel (this->ctx, timer); + cancelled = _gf_true; + } +out: + return cancelled; +} + +server_ctx_t* +server_ctx_get (client_t *client, xlator_t *xlator) { - server_connection_t *conn = NULL; - server_connection_t *trav = NULL; - server_conf_t *conf = NULL; + void *tmp = NULL; + server_ctx_t *ctx = NULL; + + client_ctx_get (client, xlator, &tmp); + + ctx = tmp; + + if (ctx != NULL) + goto out; + + ctx = GF_CALLOC (1, sizeof (server_ctx_t), gf_server_mt_server_conf_t); + + if (ctx == NULL) + goto out; + + /* ctx->lk_version = 0; redundant */ + ctx->fdtable = gf_fd_fdtable_alloc (); + + if (ctx->fdtable == NULL) { + GF_FREE (ctx); + ctx = NULL; + goto out; + } + + LOCK_INIT (&ctx->fdtable_lock); + + if (client_ctx_set (client, xlator, ctx) != 0) { + LOCK_DESTROY (&ctx->fdtable_lock); + GF_FREE (ctx); + ctx = NULL; + } - conf = this->private; +out: + return ctx; +} - pthread_mutex_lock (&conf->mutex); - { - list_for_each_entry (trav, &conf->conns, list) { - if (!strcmp (id, trav->id)) { - conn = trav; - break; - } - } +int32_t +gf_barrier_transmit (server_conf_t *conf, gf_barrier_payload_t *payload) +{ + gf_barrier_t *barrier = NULL; + int32_t ret = -1; + client_t *client = NULL; + gf_boolean_t lk_heal = _gf_false; + call_frame_t *frame = NULL; + server_state_t *state = NULL; + + GF_VALIDATE_OR_GOTO ("barrier", conf, out); + GF_VALIDATE_OR_GOTO ("barrier", conf->barrier, out); + GF_VALIDATE_OR_GOTO ("barrier", payload, out); + + barrier = conf->barrier; + + frame = payload->frame; + if (frame) { + state = CALL_STATE (frame); + frame->local = NULL; + client = frame->root->client; + } + /* currently lk fops are not barrier'ed. This is reflecting code in + * server_submit_reply */ + if (client) + lk_heal = ((server_conf_t *) client->this->private)->lk_heal; + + ret = rpcsvc_submit_generic (payload->req, &payload->rsp, 1, + payload->payload, payload->payload_count, + payload->iobref); + iobuf_unref (payload->iob); + if (ret == -1) { + gf_log_callingfn ("", GF_LOG_ERROR, "Reply submission failed"); + if (frame && client && !lk_heal) { + server_connection_cleanup (frame->this, client, + INTERNAL_LOCKS | POSIX_LOCKS); + } else { + /* TODO: Failure of open(dir), create, inodelk, entrylk + or lk fops send failure must be handled specially. */ + } + goto ret; + } - if (!conn) { - conn = (void *) CALLOC (1, sizeof (*conn)); + ret = 0; +ret: + if (state) { + free_state (state); + } + + if (frame) { + gf_client_unref (client); + STACK_DESTROY (frame->root); + } - conn->id = strdup (id); - conn->fdtable = gf_fd_fdtable_alloc (); - conn->ltable = gf_lock_table_new (); + if (payload->free_iobref) { + iobref_unref (payload->iobref); + } +out: + return ret; +} - pthread_mutex_init (&conn->lock, NULL); +gf_barrier_payload_t * +gf_barrier_dequeue (gf_barrier_t *barrier) +{ + gf_barrier_payload_t *payload = NULL; - list_add (&conn->list, &conf->conns); - } + if (!barrier || list_empty (&barrier->queue)) + return NULL; - conn->ref++; - } - pthread_mutex_unlock (&conf->mutex); + payload = list_entry (barrier->queue.next, + gf_barrier_payload_t, list); + if (payload) { + list_del_init (&payload->list); + barrier->cur_size--; + } - return conn; + return payload; } +void* +gf_barrier_dequeue_start (void *data) +{ + server_conf_t *conf = NULL; + gf_barrier_t *barrier = NULL; + gf_barrier_payload_t *payload = NULL; + + conf = (server_conf_t *)data; + if (!conf || !conf->barrier) + return NULL; + barrier = conf->barrier; + + LOCK (&barrier->lock); + { + while (barrier->cur_size) { + payload = gf_barrier_dequeue (barrier); + if (payload) { + if (gf_barrier_transmit (conf, payload)) { + gf_log ("server", GF_LOG_WARNING, + "Failed to transmit"); + } + GF_FREE (payload); + } + } + } + UNLOCK (&barrier->lock); + return NULL; +} + void -server_connection_put (xlator_t *this, server_connection_t *conn) +gf_barrier_timeout (void *data) { - server_conf_t *conf = NULL; - server_connection_t *todel = NULL; + server_conf_t *conf = NULL; + gf_barrier_t *barrier = NULL; + gf_boolean_t need_dequeue = _gf_false; - if (conn == NULL) { + conf = (server_conf_t *)data; + if (!conf || !conf->barrier) goto out; + barrier = conf->barrier; + + gf_log ("", GF_LOG_INFO, "barrier timed-out"); + LOCK (&barrier->lock); + { + need_dequeue = barrier->on; + barrier->on = _gf_false; + } + UNLOCK (&barrier->lock); + + if (need_dequeue == _gf_true) + gf_barrier_dequeue_start (data); +out: + return; +} + + +int32_t +gf_barrier_start (xlator_t *this) +{ + server_conf_t *conf = NULL; + gf_barrier_t *barrier = NULL; + int32_t ret = -1; + struct timespec time = {0,}; + + conf = this->private; + + GF_VALIDATE_OR_GOTO ("server", this, out); + GF_VALIDATE_OR_GOTO (this->name, conf, out); + GF_VALIDATE_OR_GOTO (this->name, conf->barrier, out); + + barrier = conf->barrier; + + gf_log (this->name, GF_LOG_INFO, "barrier start called"); + LOCK (&barrier->lock); + { + /* if barrier is on, reset timer */ + if (barrier->on == _gf_true) { + ret = gf_timer_call_cancel (this->ctx, barrier->timer); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to " + "unset timer, failing barrier start"); + goto unlock; + } + } + + barrier->on = _gf_true; + time.tv_sec = barrier->time_out; + time.tv_nsec = 0; + + barrier->timer = gf_timer_call_after (this->ctx, time, + gf_barrier_timeout, + (void *)conf); + if (!barrier->timer) { + gf_log (this->name, GF_LOG_ERROR, "Failed to set " + "timer, failing barrier start"); + barrier->on = _gf_false; + } } +unlock: + UNLOCK (&barrier->lock); - conf = this->private; + ret = 0; +out: + return ret; +} - pthread_mutex_lock (&conf->mutex); - { - conn->ref--; +int32_t +gf_barrier_stop (xlator_t *this) +{ + server_conf_t *conf = NULL; + gf_barrier_t *barrier = NULL; + int32_t ret = -1; + gf_boolean_t need_dequeue = _gf_false; + + conf = this->private; - if (!conn->ref) { - list_del_init (&conn->list); - todel = conn; - } - } - pthread_mutex_unlock (&conf->mutex); + GF_VALIDATE_OR_GOTO ("server", this, out); + GF_VALIDATE_OR_GOTO (this->name, conf, out); + GF_VALIDATE_OR_GOTO (this->name, conf->barrier, out); - if (todel) { - server_connection_destroy (this, todel); - } + barrier = conf->barrier; + gf_log (this->name, GF_LOG_INFO, "barrier stop called"); + LOCK (&barrier->lock); + { + need_dequeue = barrier->on; + barrier->on = _gf_false; + } + UNLOCK (&barrier->lock); + + if (need_dequeue == _gf_true) { + gf_timer_call_cancel (this->ctx, barrier->timer); + ret = gf_thread_create (&conf->barrier_th, NULL, + gf_barrier_dequeue_start, + conf); + if (ret) { + gf_log (this->name, GF_LOG_CRITICAL, + "Failed to start un-barriering"); + goto out; + } + } + ret = 0; out: - return; + return ret; +} + +int32_t +gf_barrier_fops_configure (xlator_t *this, gf_barrier_t *barrier, char *str) +{ + int32_t ret = -1; + char *dup_str = NULL; + char *str_tok = NULL; + char *save_ptr = NULL; + uint64_t fops = 0; + + /* by defaul fsync & flush needs to be barriered */ + + fops |= 1 << GFS3_OP_FSYNC; + fops |= 1 << GFS3_OP_FLUSH; + + if (!str) + goto done; + + dup_str = gf_strdup (str); + if (!dup_str) + goto done; + + str_tok = strtok_r (dup_str, ",", &save_ptr); + if (!str_tok) + goto done; + + fops = 0; + while (str_tok) { + if (!strcmp(str_tok, "writev")) { + fops |= ((uint64_t)1 << GFS3_OP_WRITE); + } else if (!strcmp(str_tok, "fsync")) { + fops |= ((uint64_t)1 << GFS3_OP_FSYNC); + } else if (!strcmp(str_tok, "read")) { + fops |= ((uint64_t)1 << GFS3_OP_READ); + } else if (!strcmp(str_tok, "rename")) { + fops |= ((uint64_t)1 << GFS3_OP_RENAME); + } else if (!strcmp(str_tok, "flush")) { + fops |= ((uint64_t)1 << GFS3_OP_FLUSH); + } else if (!strcmp(str_tok, "ftruncate")) { + fops |= ((uint64_t)1 << GFS3_OP_FTRUNCATE); + } else if (!strcmp(str_tok, "fallocate")) { + fops |= ((uint64_t)1 << GFS3_OP_FALLOCATE); + } else if (!strcmp(str_tok, "rmdir")) { + fops |= ((uint64_t)1 << GFS3_OP_RMDIR); + } else { + gf_log ("barrier", GF_LOG_ERROR, + "Invalid barrier fop %s", str_tok); + } + + str_tok = strtok_r (NULL, ",", &save_ptr); + } +done: + LOCK (&barrier->lock); + { + barrier->fops = fops; + } + UNLOCK (&barrier->lock); + ret = 0; + + GF_FREE (dup_str); + return ret; +} + +void +gf_barrier_enqueue (gf_barrier_t *barrier, gf_barrier_payload_t *payload) +{ + list_add_tail (&payload->list, &barrier->queue); + barrier->cur_size++; +} + +gf_barrier_payload_t * +gf_barrier_payload (rpcsvc_request_t *req, struct iovec *rsp, + call_frame_t *frame, struct iovec *payload_orig, + int payloadcount, struct iobref *iobref, + struct iobuf *iob, gf_boolean_t free_iobref) +{ + gf_barrier_payload_t *payload = NULL; + + if (!rsp) + return NULL; + + payload = GF_CALLOC (1, sizeof (*payload),1); + if (!payload) + return NULL; + + INIT_LIST_HEAD (&payload->list); + + payload->req = req; + memcpy (&payload->rsp, rsp, sizeof (struct iovec)); + payload->frame = frame; + payload->payload = payload_orig; + payload->payload_count = payloadcount; + payload->iobref = iobref; + payload->iob = iob; + payload->free_iobref = free_iobref; + + return payload; } diff --git a/xlators/protocol/server/src/server-helpers.h b/xlators/protocol/server/src/server-helpers.h index 48f5f4a6d..b455aa6df 100644 --- a/xlators/protocol/server/src/server-helpers.h +++ b/xlators/protocol/server/src/server-helpers.h @@ -1,77 +1,74 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2010-2013 Red Hat, Inc. <http://www.redhat.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/>. + 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 __SERVER_HELPERS_H__ -#define __SERVER_HELPERS_H__ - -#define CALL_STATE(frame) ((server_state_t *)frame->root->state) +#ifndef _SERVER_HELPERS_H +#define _SERVER_HELPERS_H -#define BOUND_XL(frame) ((xlator_t *) CALL_STATE(frame)->bound_xl) +#include "server.h" -#define TRANSPORT_FROM_FRAME(frame) ((transport_t *) CALL_STATE(frame)->trans) +#define CALL_STATE(frame) ((server_state_t *)frame->root->state) -#define SERVER_CONNECTION(frame) \ - ((server_connection_t *) TRANSPORT_FROM_FRAME(frame)->xl_private) +#define XPRT_FROM_FRAME(frame) ((rpc_transport_t *) CALL_STATE(frame)->xprt) -#define SERVER_CONF(frame) \ - ((server_conf_t *)TRANSPORT_FROM_FRAME(frame)->xl->private) +#define SERVER_CONF(frame) \ + ((server_conf_t *)XPRT_FROM_FRAME(frame)->this->private) -#define TRANSPORT_FROM_XLATOR(this) ((((server_conf_t *)this->private))->trans) +#define XPRT_FROM_XLATOR(this) ((((server_conf_t *)this->private))->listen) -#define INODE_LRU_LIMIT(this) \ - (((server_conf_t *)(this->private))->inode_lru_limit) +#define INODE_LRU_LIMIT(this) \ + (((server_conf_t *)(this->private))->config.inode_lru_limit) #define IS_ROOT_INODE(inode) (inode == inode->table->root) #define IS_NOT_ROOT(pathlen) ((pathlen > 2)? 1 : 0) -int32_t -server_loc_fill (loc_t *loc, - server_state_t *state, - ino_t ino, - ino_t par, - const char *name, - const char *path); - -char * -stat_to_str (struct stat *stbuf); +#define is_fop_barriered(fops, procnum) (fops & ((uint64_t)1 << procnum)) -call_frame_t * -server_copy_frame (call_frame_t *frame); +#define barrier_add_to_queue(barrier) (barrier->on || barrier->cur_size) void free_state (server_state_t *state); void server_loc_wipe (loc_t *loc); -int32_t -gf_add_locker (struct _lock_table *table, const char *volume, - loc_t *loc, - fd_t *fd, - pid_t pid); +void +server_print_request (call_frame_t *frame); + +call_frame_t * +get_frame_from_request (rpcsvc_request_t *req); + +int +server_connection_cleanup (xlator_t *this, struct _client_t *client, + int32_t flags); + +gf_boolean_t +server_cancel_grace_timer (xlator_t *this, struct _client_t *client); + +int +server_build_config (xlator_t *this, server_conf_t *conf); + +int serialize_rsp_dirent (gf_dirent_t *entries, gfs3_readdir_rsp *rsp); +int serialize_rsp_direntp (gf_dirent_t *entries, gfs3_readdirp_rsp *rsp); +int readdirp_rsp_cleanup (gfs3_readdirp_rsp *rsp); +int readdir_rsp_cleanup (gfs3_readdir_rsp *rsp); -int32_t -gf_del_locker (struct _lock_table *table, const char *volume, - loc_t *loc, - fd_t *fd, - pid_t pid); +server_ctx_t *server_ctx_get (client_t *client, xlator_t *xlator); -int32_t -gf_direntry_to_bin (dir_entry_t *head, char *bufferp); +int32_t gf_barrier_start (xlator_t *this); +int32_t gf_barrier_stop (xlator_t *this); +int32_t gf_barrier_fops_configure (xlator_t *this, gf_barrier_t *barrier, + char *str); +void gf_barrier_enqueue (gf_barrier_t *barrier, gf_barrier_payload_t *stub); +gf_barrier_payload_t * +gf_barrier_payload (rpcsvc_request_t *req, struct iovec *rsp, + call_frame_t *frame, struct iovec *payload, + int payloadcount, struct iobref *iobref, + struct iobuf *iob, gf_boolean_t free_iobref); -#endif /* __SERVER_HELPERS_H__ */ +#endif /* !_SERVER_HELPERS_H */ diff --git a/xlators/protocol/server/src/server-mem-types.h b/xlators/protocol/server/src/server-mem-types.h new file mode 100644 index 000000000..19c3466d3 --- /dev/null +++ b/xlators/protocol/server/src/server-mem-types.h @@ -0,0 +1,30 @@ +/* + Copyright (c) 2010-2013 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 __SERVER_MEM_TYPES_H__ +#define __SERVER_MEM_TYPES_H__ + +#include "mem-types.h" + +enum gf_server_mem_types_ { + gf_server_mt_server_conf_t = gf_common_mt_end + 1, + gf_server_mt_resolv_comp_t, + gf_server_mt_state_t, + gf_server_mt_locker_t, + gf_server_mt_lock_table_t, + gf_server_mt_conn_t, + gf_server_mt_dirent_rsp_t, + gf_server_mt_rsp_buf_t, + gf_server_mt_volfile_ctx_t, + gf_server_mt_timer_data_t, + gf_server_mt_end, +}; +#endif /* __SERVER_MEM_TYPES_H__ */ diff --git a/xlators/protocol/server/src/server-protocol.c b/xlators/protocol/server/src/server-protocol.c deleted file mode 100644 index 78ca63523..000000000 --- a/xlators/protocol/server/src/server-protocol.c +++ /dev/null @@ -1,8339 +0,0 @@ -/* - Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> - This file is part of GlusterFS. - - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. -*/ - - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif -#include <time.h> -#include <sys/uio.h> -#include <sys/resource.h> - -#include <libgen.h> - -#include "transport.h" -#include "fnmatch.h" -#include "xlator.h" -#include "protocol.h" -#include "server-protocol.h" -#include "server-helpers.h" -#include "call-stub.h" -#include "defaults.h" -#include "list.h" -#include "dict.h" -#include "compat.h" -#include "compat-errno.h" - - -static void -protocol_server_reply (call_frame_t *frame, - int type, int op, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iovec *vector, int count, - struct iobref *iobref) -{ - server_state_t *state = NULL; - xlator_t *bound_xl = NULL; - transport_t *trans = NULL; - - bound_xl = BOUND_XL(frame); - state = CALL_STATE(frame); - trans = state->trans; - - hdr->callid = hton64 (frame->root->unique); - hdr->type = hton32 (type); - hdr->op = hton32 (op); - - transport_submit (trans, (char *)hdr, hdrlen, vector, count, iobref); - /* TODO: If transport submit fails, there is no reply sent to client, - * its bailed out as of now.. loggically, only this frame should fail. - */ - - STACK_DESTROY (frame->root); - - if (state) - free_state (state); - -} - - -/* - * server_fchmod_cbk - */ -int32_t -server_fchmod_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_fchmod_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - server_state_t *state = NULL; - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret == 0) { - gf_stat_from_stat (&rsp->stat, stbuf); - } else { - state = CALL_STATE(frame); - - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": FCHMOD %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FCHMOD, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_fchmod - * - */ -int32_t -server_fchmod (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - server_connection_t *conn = NULL; - gf_fop_fchmod_req_t *req = NULL; - server_state_t *state = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->mode = ntoh32 (req->mode); - } - - GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail); - - STACK_WIND (frame, - server_fchmod_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->fchmod, - state->fd, - state->mode); - - return 0; -fail: - server_fchmod_cbk (frame, NULL, frame->this, - -1, EINVAL, NULL); - return 0; -} - - -/* - * server_fchown_cbk - */ -int32_t -server_fchown_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_fchown_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - server_state_t *state = NULL; - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret == 0) { - gf_stat_from_stat (&rsp->stat, stbuf); - } else { - state = CALL_STATE(frame); - - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": FCHOWN %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FCHOWN, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_fchown - * - */ -int32_t -server_fchown (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - server_connection_t *conn = NULL; - gf_fop_fchown_req_t *req = NULL; - server_state_t *state = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->uid = ntoh32 (req->uid); - state->gid = ntoh32 (req->gid); - } - - GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail); - - STACK_WIND (frame, - server_fchown_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->fchown, - state->fd, - state->uid, - state->gid); - - return 0; -fail: - server_fchown_cbk (frame, NULL, frame->this, - -1, EINVAL, NULL); - return 0; -} - -/* - * server_setdents_cbk - writedir callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * - * not for external reference - */ -int32_t -server_setdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_setdents_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_SETDENTS, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_lk_cbk - lk callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @lock: - * - * not for external reference - */ -int32_t -server_lk_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct flock *lock) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_lk_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - server_state_t *state = NULL; - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret == 0) { - gf_flock_from_flock (&rsp->flock, lock); - } else if (op_errno != ENOSYS) { - state = CALL_STATE(frame); - - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": LK %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_LK, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -int32_t -server_inodelk_cbk (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno) -{ - server_connection_t *conn = NULL; - gf_hdr_common_t *hdr = NULL; - gf_fop_inodelk_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - conn = SERVER_CONNECTION(frame); - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret >= 0) { - if (state->flock.l_type == F_UNLCK) - gf_del_locker (conn->ltable, state->volume, - &state->loc, NULL, frame->root->pid); - else - gf_add_locker (conn->ltable, state->volume, - &state->loc, NULL, frame->root->pid); - } else if (op_errno != ENOSYS) { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": INODELK %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, op_ret, - strerror (op_errno)); - } - - server_loc_wipe (&state->loc); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_INODELK, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -int32_t -server_finodelk_cbk (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno) -{ - server_connection_t *conn = NULL; - gf_hdr_common_t *hdr = NULL; - gf_fop_finodelk_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - conn = SERVER_CONNECTION(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - state = CALL_STATE(frame); - - if (op_ret >= 0) { - if (state->flock.l_type == F_UNLCK) - gf_del_locker (conn->ltable, state->volume, - NULL, state->fd, - frame->root->pid); - else - gf_add_locker (conn->ltable, state->volume, - NULL, state->fd, - frame->root->pid); - } else if (op_errno != ENOSYS) { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": FINODELK %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FINODELK, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_entrylk_cbk - - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @lock: - * - * not for external reference - */ -int32_t -server_entrylk_cbk (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno) -{ - server_connection_t *conn = NULL; - gf_hdr_common_t *hdr = NULL; - gf_fop_entrylk_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - conn = SERVER_CONNECTION(frame); - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret >= 0) { - if (state->cmd == ENTRYLK_UNLOCK) - gf_del_locker (conn->ltable, state->volume, - &state->loc, NULL, frame->root->pid); - else - gf_add_locker (conn->ltable, state->volume, - &state->loc, NULL, frame->root->pid); - } else if (op_errno != ENOSYS) { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": INODELK %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, op_ret, - strerror (op_errno)); - } - - server_loc_wipe (&state->loc); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_ENTRYLK, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -int32_t -server_fentrylk_cbk (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno) -{ - server_connection_t *conn = NULL; - gf_hdr_common_t *hdr = NULL; - gf_fop_fentrylk_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - conn = SERVER_CONNECTION(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret >= 0) { - state = CALL_STATE(frame); - if (state->cmd == ENTRYLK_UNLOCK) - gf_del_locker (conn->ltable, state->volume, - NULL, state->fd, frame->root->pid); - else - gf_add_locker (conn->ltable, state->volume, - NULL, state->fd, frame->root->pid); - } else if (op_errno != ENOSYS) { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": FENTRYLK %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FENTRYLK, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_access_cbk - access callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * - * not for external reference - */ -int32_t -server_access_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_access_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_ACCESS, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_utimens_cbk - utimens callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @stbuf: - * - * not for external reference - */ -int32_t -server_utimens_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_utimens_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret == 0) - gf_stat_from_stat (&rsp->stat, stbuf); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_UTIMENS, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_chmod_cbk - chmod callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @stbuf: - * - * not for external reference - */ -int32_t -server_chmod_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_chmod_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret == 0) - gf_stat_from_stat (&rsp->stat, stbuf); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_CHMOD, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_chown_cbk - chown callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @stbuf: - * - * not for external reference - */ -int32_t -server_chown_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_chown_rsp_t *rsp = NULL; - server_state_t *state = NULL; - int32_t gf_errno = 0; - size_t hdrlen = 0; - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret == 0) - gf_stat_from_stat (&rsp->stat, stbuf); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_CHOWN, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_rmdir_cbk - rmdir callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * - * not for external reference - */ -int32_t -server_rmdir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_rmdir_rsp_t *rsp = NULL; - server_state_t *state = NULL; - int32_t gf_errno = 0; - size_t hdrlen = 0; - - state = CALL_STATE(frame); - - if (op_ret == 0) { - inode_unlink (state->loc.inode, state->loc.parent, - state->loc.name); - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": RMDIR %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - } - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_RMDIR, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_mkdir_cbk - mkdir callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @stbuf: - * - * not for external reference - */ -int32_t -server_mkdir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_mkdir_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret >= 0) { - gf_stat_from_stat (&rsp->stat, stbuf); - inode_link (inode, state->loc.parent, state->loc.name, stbuf); - inode_lookup (inode); - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": MKDIR %s ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - op_ret, strerror (op_errno)); - } - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_MKDIR, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_mknod_cbk - mknod callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @stbuf: - * - * not for external reference - */ -int32_t -server_mknod_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_mknod_rsp_t *rsp = NULL; - server_state_t *state = NULL; - int32_t gf_errno = 0; - size_t hdrlen = 0; - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret >= 0) { - gf_stat_from_stat (&rsp->stat, stbuf); - inode_link (inode, state->loc.parent, state->loc.name, stbuf); - inode_lookup (inode); - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": MKNOD %s ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - op_ret, strerror (op_errno)); - } - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_MKNOD, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_fsyncdir_cbk - fsyncdir callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * - * not for external reference - */ -int32_t -server_fsyncdir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_fsyncdir_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - server_state_t *state = NULL; - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - if (op_ret < 0) { - state = CALL_STATE(frame); - - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": FSYNCDIR %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FSYNCDIR, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_getdents_cbk - readdir callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * @entries: - * @count: - * - * not for external reference - */ -int32_t -server_getdents_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dir_entry_t *entries, - int32_t count) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_getdents_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t vec_count = 0; - int32_t gf_errno = 0; - struct iobref *iobref = NULL; - struct iobuf *iobuf = NULL; - size_t buflen = 0; - struct iovec vector[1]; - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - if (op_ret >= 0) { - iobuf = iobuf_get (this->ctx->iobuf_pool); - if (!iobuf) { - op_ret = -1; - op_errno = ENOMEM; - goto out; - } - - buflen = gf_direntry_to_bin (entries, iobuf->ptr); - if (buflen < 0) { - gf_log (this->name, GF_LOG_ERROR, - "fd - %"PRId64" (%"PRId64"): failed to convert " - "entries list to string buffer", - state->fd_no, state->fd->inode->ino); - op_ret = -1; - op_errno = EINVAL; - goto out; - } - - iobref = iobref_new (); - if (iobref == NULL) { - gf_log (this->name, GF_LOG_ERROR, - "fd - %"PRId64" (%"PRId64"): failed to get iobref", - state->fd_no, state->fd->inode->ino); - op_ret = -1; - op_errno = ENOMEM; - goto out; - } - - iobref_add (iobref, iobuf); - - vector[0].iov_base = iobuf->ptr; - vector[0].iov_len = buflen; - vec_count = 1; - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": GETDENTS %"PRId64" (%"PRId64"): %"PRId32" (%s)", - frame->root->unique, - state->fd_no, - state->fd ? state->fd->inode->ino : 0, - op_ret, strerror (op_errno)); - vector[0].iov_base = NULL; - vector[0].iov_len = 0; - } - -out: - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - rsp->count = hton32 (count); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_GETDENTS, - hdr, hdrlen, vector, vec_count, iobref); - - if (iobref) - iobref_unref (iobref); - if (iobuf) - iobuf_unref (iobuf); - - return 0; -} - - -/* - * server_readdir_cbk - getdents callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * - * not for external reference - */ -int32_t -server_readdir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - gf_dirent_t *entries) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_readdir_rsp_t *rsp = NULL; - size_t hdrlen = 0; - size_t buf_size = 0; - int32_t gf_errno = 0; - server_state_t *state = NULL; - - if (op_ret > 0) - buf_size = gf_dirent_serialize (entries, NULL, 0); - - hdrlen = gf_hdr_len (rsp, buf_size); - hdr = gf_hdr_new (rsp, buf_size); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret > 0) { - rsp->size = hton32 (buf_size); - gf_dirent_serialize (entries, rsp->buf, buf_size); - } else { - state = CALL_STATE(frame); - - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": READDIR %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_READDIR, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_releasedir_cbk - releasedir callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * - * not for external reference - */ -int32_t -server_releasedir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_cbk_releasedir_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - protocol_server_reply (frame, GF_OP_TYPE_CBK_REPLY, GF_CBK_RELEASEDIR, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_opendir_cbk - opendir callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * @fd: file descriptor structure of opened directory - * - * not for external reference - */ -int32_t -server_opendir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd) -{ - server_connection_t *conn = NULL; - gf_hdr_common_t *hdr = NULL; - gf_fop_opendir_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - conn = SERVER_CONNECTION(frame); - - state = CALL_STATE(frame); - - if (op_ret >= 0) { - fd_bind (fd); - - state->fd_no = gf_fd_unused_get (conn->fdtable, fd); - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": OPENDIR %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - - /* NOTE: corresponding to fd_create()'s ref */ - if (state->fd) - fd_unref (state->fd); - } - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - rsp->fd = hton64 (state->fd_no); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_OPENDIR, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_statfs_cbk - statfs callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * @buf: - * - * not for external reference - */ -int32_t -server_statfs_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct statvfs *buf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_statfs_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret >= 0) { - gf_statfs_from_statfs (&rsp->statfs, buf); - } - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_STATFS, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_removexattr_cbk - removexattr callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * - * not for external reference - */ -int32_t -server_removexattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_removexattr_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_REMOVEXATTR, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_getxattr_cbk - getxattr callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * @value: - * - * not for external reference - */ -int32_t -server_getxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_getxattr_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t len = 0; - int32_t gf_errno = 0; - int32_t ret = -1; - - state = CALL_STATE(frame); - - if (op_ret >= 0) { - len = dict_serialized_length (dict); - if (len < 0) { - gf_log (this->name, GF_LOG_ERROR, - "%s (%"PRId64"): failed to get serialized length of " - "reply dict", - state->loc.path, state->ino); - op_ret = -1; - op_errno = EINVAL; - len = 0; - } - } - - hdrlen = gf_hdr_len (rsp, len + 1); - hdr = gf_hdr_new (rsp, len + 1); - rsp = gf_param (hdr); - - if (op_ret >= 0) { - ret = dict_serialize (dict, rsp->dict); - if (len < 0) { - gf_log (this->name, GF_LOG_ERROR, - "%s (%"PRId64"): failed to serialize reply dict", - state->loc.path, state->ino); - op_ret = -1; - op_errno = -ret; - } - } - rsp->dict_len = hton32 (len); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_GETXATTR, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -int32_t -server_fgetxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_fgetxattr_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t len = 0; - int32_t gf_errno = 0; - int32_t ret = -1; - - state = CALL_STATE(frame); - - if (op_ret >= 0) { - len = dict_serialized_length (dict); - if (len < 0) { - gf_log (this->name, GF_LOG_ERROR, - "%s (%"PRId64"): failed to get serialized length of " - "reply dict", - state->loc.path, state->ino); - op_ret = -1; - op_errno = EINVAL; - len = 0; - } - } - - hdrlen = gf_hdr_len (rsp, len + 1); - hdr = gf_hdr_new (rsp, len + 1); - rsp = gf_param (hdr); - - if (op_ret >= 0) { - ret = dict_serialize (dict, rsp->dict); - if (len < 0) { - gf_log (this->name, GF_LOG_ERROR, - "%s (%"PRId64"): failed to serialize reply dict", - state->loc.path, state->ino); - op_ret = -1; - op_errno = -ret; - } - } - rsp->dict_len = hton32 (len); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - fd_unref (state->fd); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FGETXATTR, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_setxattr_cbk - setxattr callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * - * not for external reference - */ -int32_t -server_setxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_setxattr_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_SETXATTR, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -int32_t -server_fsetxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_fsetxattr_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FSETXATTR, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_rename_cbk - rename callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * - * not for external reference - */ -int32_t -server_rename_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_rename_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret == 0) { - stbuf->st_ino = state->loc.inode->ino; - stbuf->st_mode = state->loc.inode->st_mode; - - gf_log (state->bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": RENAME_CBK (%"PRId64") %"PRId64"/%s " - "==> %"PRId64"/%s", - frame->root->unique, state->loc.inode->ino, - state->loc.parent->ino, state->loc.name, - state->loc2.parent->ino, state->loc2.name); - - inode_rename (state->itable, - state->loc.parent, state->loc.name, - state->loc2.parent, state->loc2.name, - state->loc.inode, stbuf); - gf_stat_from_stat (&rsp->stat, stbuf); - } - - server_loc_wipe (&(state->loc)); - server_loc_wipe (&(state->loc2)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_RENAME, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_unlink_cbk - unlink callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * - * not for external reference - */ -int32_t -server_unlink_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_unlink_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - state = CALL_STATE(frame); - - if (op_ret == 0) { - gf_log (state->bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": UNLINK_CBK %"PRId64"/%s (%"PRId64")", - frame->root->unique, state->loc.parent->ino, - state->loc.name, state->loc.inode->ino); - - inode_unlink (state->loc.inode, state->loc.parent, - state->loc.name); - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": UNLINK %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - } - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_UNLINK, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_symlink_cbk - symlink callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * - * not for external reference - */ -int32_t -server_symlink_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_symlink_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno_to_error (op_errno)); - - if (op_ret >= 0) { - gf_stat_from_stat (&rsp->stat, stbuf); - inode_link (inode, state->loc.parent, state->loc.name, stbuf); - inode_lookup (inode); - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": SYMLINK %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - } - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_SYMLINK, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_link_cbk - link callback for server protocol - * @frame: call frame - * @this: - * @op_ret: - * @op_errno: - * @stbuf: - * - * not for external reference - */ -int32_t -server_link_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_link_rsp_t *rsp = NULL; - server_state_t *state = NULL; - int32_t gf_errno = 0; - size_t hdrlen = 0; - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret == 0) { - stbuf->st_ino = state->loc.inode->ino; - gf_stat_from_stat (&rsp->stat, stbuf); - gf_log (state->bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": LINK (%"PRId64") %"PRId64"/%s ==> %"PRId64"/%s", - frame->root->unique, inode->ino, state->loc2.parent->ino, - state->loc2.name, state->loc.parent->ino, state->loc.name); - - inode_link (inode, state->loc2.parent, - state->loc2.name, stbuf); - } else { - gf_log (state->bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": LINK (%"PRId64") %"PRId64"/%s ==> %"PRId64"/%s " - " ==> %"PRId32" (%s)", - frame->root->unique, inode->ino, state->loc2.parent->ino, - state->loc2.name, state->loc.parent->ino, state->loc.name, - op_ret, strerror (op_errno)); - } - - server_loc_wipe (&(state->loc)); - server_loc_wipe (&(state->loc2)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_LINK, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_truncate_cbk - truncate callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @stbuf: - * - * not for external reference - */ -int32_t -server_truncate_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_truncate_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret == 0) { - gf_stat_from_stat (&rsp->stat, stbuf); - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": TRUNCATE %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - } - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_TRUNCATE, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_fstat_cbk - fstat callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @stbuf: - * - * not for external reference - */ -int32_t -server_fstat_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_fstat_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - server_state_t *state = NULL; - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret == 0) { - gf_stat_from_stat (&rsp->stat, stbuf); - } else { - state = CALL_STATE(frame); - - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": FSTAT %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FSTAT, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_ftruncate_cbk - ftruncate callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @stbuf: - * - * not for external reference - */ -int32_t -server_ftruncate_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_ftruncate_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - server_state_t *state = NULL; - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret == 0) { - gf_stat_from_stat (&rsp->stat, stbuf); - } else { - state = CALL_STATE(frame); - - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": FTRUNCATE %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FTRUNCATE, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_flush_cbk - flush callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * - * not for external reference - */ -int32_t -server_flush_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_flush_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - server_state_t *state = NULL; - - if (op_ret < 0) { - state = CALL_STATE(frame); - - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": FLUSH %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FLUSH, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_fsync_cbk - fsync callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * - * not for external reference - */ -int32_t -server_fsync_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_fsync_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - server_state_t *state = NULL; - - if (op_ret < 0) { - state = CALL_STATE(frame); - - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": FSYNC %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FSYNC, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_release_cbk - rleease callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * - * not for external reference - */ -int32_t -server_release_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_cbk_release_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - protocol_server_reply (frame, GF_OP_TYPE_CBK_REPLY, GF_CBK_RELEASE, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_writev_cbk - writev callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * - * not for external reference - */ - -int32_t -server_writev_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_write_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - server_state_t *state = NULL; - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno_to_error (op_errno)); - - if (op_ret >= 0) { - gf_stat_from_stat (&rsp->stat, stbuf); - } else { - state = CALL_STATE(frame); - - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": WRITEV %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - protocol_server_reply (frame, - GF_OP_TYPE_FOP_REPLY, GF_FOP_WRITE, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_readv_cbk - readv callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @vector: - * @count: - * - * not for external reference - */ -int32_t -server_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 stat *stbuf, - struct iobref *iobref) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_read_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - server_state_t *state = NULL; - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret >= 0) { - gf_stat_from_stat (&rsp->stat, stbuf); - } else { - state = CALL_STATE(frame); - - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": READV %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_READ, - hdr, hdrlen, vector, count, iobref); - - return 0; -} - - -/* - * server_open_cbk - open callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @fd: - * - * not for external reference - */ -int32_t -server_open_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd) -{ - server_connection_t *conn = NULL; - gf_hdr_common_t *hdr = NULL; - gf_fop_open_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - conn = SERVER_CONNECTION(frame); - - state = CALL_STATE(frame); - - if (op_ret >= 0) { - fd_bind (fd); - - state->fd_no = gf_fd_unused_get (conn->fdtable, fd); - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": OPEN %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - - /* NOTE: corresponding to fd_create()'s ref */ - if (state->fd) - fd_unref (state->fd); - } - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - rsp->fd = hton64 (state->fd_no); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_OPEN, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_create_cbk - create callback for server - * @frame: call frame - * @cookie: - * @this: translator structure - * @op_ret: - * @op_errno: - * @fd: file descriptor - * @inode: inode structure - * @stbuf: struct stat of created file - * - * not for external reference - */ -int32_t -server_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 stat *stbuf) -{ - server_connection_t *conn = NULL; - gf_hdr_common_t *hdr = NULL; - gf_fop_create_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - conn = SERVER_CONNECTION(frame); - - state = CALL_STATE(frame); - - if (op_ret >= 0) { - gf_log (state->bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": CREATE %"PRId64"/%s (%"PRId64")", - frame->root->unique, state->loc.parent->ino, - state->loc.name, stbuf->st_ino); - - inode_link (inode, state->loc.parent, state->loc.name, stbuf); - inode_lookup (inode); - - fd_bind (fd); - - state->fd_no = gf_fd_unused_get (conn->fdtable, fd); - - if ((state->fd_no < 0) || (fd == 0)) { - op_ret = state->fd_no; - op_errno = errno; - } - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": CREATE %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - - /* NOTE: corresponding to fd_create()'s ref */ - if (state->fd) - fd_unref (state->fd); - - } - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - rsp->fd = hton64 (state->fd_no); - - if (op_ret >= 0) - gf_stat_from_stat (&rsp->stat, stbuf); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_CREATE, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_readlink_cbk - readlink callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @buf: - * - * not for external reference - */ -int32_t -server_readlink_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - const char *buf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_readlink_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - size_t linklen = 0; - int32_t gf_errno = 0; - - state = CALL_STATE(frame); - - if (op_ret >= 0) { - linklen = strlen (buf) + 1; - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": READLINK %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - } - - hdrlen = gf_hdr_len (rsp, linklen); - hdr = gf_hdr_new (rsp, linklen); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno_to_error (op_errno)); - - if (op_ret >= 0) - strcpy (rsp->path, buf); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_READLINK, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_stat_cbk - stat callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @stbuf: - * - * not for external reference - */ -int32_t -server_stat_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *stbuf) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_stat_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - state = CALL_STATE(frame); - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno_to_error (op_errno)); - - if (op_ret == 0) { - gf_stat_from_stat (&rsp->stat, stbuf); - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": STAT %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - } - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_STAT, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_forget_cbk - forget callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * - * not for external reference - */ -int32_t -server_forget_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - gf_hdr_common_t *hdr = NULL; - gf_cbk_forget_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - protocol_server_reply (frame, GF_OP_TYPE_CBK_REPLY, GF_CBK_FORGET, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * server_lookup_cbk - lookup callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: - * @op_errno: - * @inode: - * @stbuf: - * - * not for external reference - */ -int32_t -server_lookup_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct stat *stbuf, - dict_t *dict) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_lookup_rsp_t *rsp = NULL; - server_state_t *state = NULL; - inode_t *root_inode = NULL; - int32_t dict_len = 0; - size_t hdrlen = 0; - int32_t gf_errno = 0; - int32_t ret = -1; - - state = CALL_STATE(frame); - if ((op_errno == ESTALE) && (op_ret == -1)) { - /* Send lookup again with new ctx dictionary */ - loc_t loc = {0,}; - - root_inode = BOUND_XL(frame)->itable->root; - if (state->loc.inode != root_inode) { - if (state->loc.inode) - inode_unref (state->loc.inode); - state->loc.inode = inode_new (BOUND_XL(frame)->itable); - } - loc.inode = state->loc.inode; - loc.path = state->path; - state->is_revalidate = 2; - STACK_WIND (frame, server_lookup_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->lookup, - &loc, - state->xattr_req); - return 0; - } - - if (dict) { - dict_len = dict_serialized_length (dict); - if (dict_len < 0) { - gf_log (this->name, GF_LOG_ERROR, - "%s (%"PRId64"): failed to get serialized " - "length of reply dict", - state->loc.path, state->loc.inode->ino); - op_ret = -1; - op_errno = EINVAL; - dict_len = 0; - } - } - - hdrlen = gf_hdr_len (rsp, dict_len); - hdr = gf_hdr_new (rsp, dict_len); - rsp = gf_param (hdr); - - if ((op_ret >= 0) && dict) { - ret = dict_serialize (dict, rsp->dict); - if (ret < 0) { - gf_log (this->name, GF_LOG_ERROR, - "%s (%"PRId64"): failed to serialize reply dict", - state->loc.path, state->loc.inode->ino); - op_ret = -1; - op_errno = -ret; - dict_len = 0; - } - } - rsp->dict_len = hton32 (dict_len); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret == 0) { - root_inode = BOUND_XL(frame)->itable->root; - if (inode == root_inode) { - /* we just looked up root ("/") */ - stbuf->st_ino = 1; - if (inode->st_mode == 0) - inode->st_mode = stbuf->st_mode; - } - - gf_stat_from_stat (&rsp->stat, stbuf); - - if (inode->ino == 0) { - inode_link (inode, state->loc.parent, - state->loc.name, stbuf); - inode_lookup (inode); - } - } else { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": LOOKUP %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - } - - server_loc_wipe (&state->loc); - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_LOOKUP, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -int32_t -server_xattrop_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_xattrop_rsp_t *rsp = NULL; - server_state_t *state = NULL; - size_t hdrlen = 0; - int32_t len = 0; - int32_t gf_errno = 0; - int32_t ret = -1; - - state = CALL_STATE(frame); - - if (op_ret < 0) { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": XATTROP %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - } - - if ((op_ret >= 0) && dict) { - len = dict_serialized_length (dict); - if (len < 0) { - gf_log (this->name, GF_LOG_ERROR, - "%s (%"PRId64"): failed to get serialized length" - " for reply dict", - state->loc.path, state->loc.inode->ino); - op_ret = -1; - op_errno = EINVAL; - len = 0; - } - } - - hdrlen = gf_hdr_len (rsp, len + 1); - hdr = gf_hdr_new (rsp, len + 1); - rsp = gf_param (hdr); - - if ((op_ret >= 0) && dict) { - ret = dict_serialize (dict, rsp->dict); - if (ret < 0) { - gf_log (this->name, GF_LOG_ERROR, - "%s (%"PRId64"): failed to serialize reply dict", - state->loc.path, state->loc.inode->ino); - op_ret = -1; - op_errno = -ret; - len = 0; - } - } - rsp->dict_len = hton32 (len); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - server_loc_wipe (&(state->loc)); - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_XATTROP, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -int32_t -server_fxattrop_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_xattrop_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t len = 0; - int32_t gf_errno = 0; - int32_t ret = -1; - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - if (op_ret < 0) { - gf_log (this->name, GF_LOG_DEBUG, - "%"PRId64": FXATTROP %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - if ((op_ret >= 0) && dict) { - len = dict_serialized_length (dict); - if (len < 0) { - gf_log (this->name, GF_LOG_ERROR, - "fd - %"PRId64" (%"PRId64"): failed to get " - "serialized length for reply dict", - state->fd_no, state->fd->inode->ino); - op_ret = -1; - op_errno = EINVAL; - len = 0; - } - } - - hdrlen = gf_hdr_len (rsp, len + 1); - hdr = gf_hdr_new (rsp, len + 1); - rsp = gf_param (hdr); - - if ((op_ret >= 0) && dict) { - ret = dict_serialize (dict, rsp->dict); - if (ret < 0) { - gf_log (this->name, GF_LOG_ERROR, - "fd - %"PRId64" (%"PRId64"): failed to " - "serialize reply dict", - state->fd_no, state->fd->inode->ino); - op_ret = -1; - op_errno = -ret; - len = 0; - } - } - rsp->dict_len = hton32 (len); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FXATTROP, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * server_stub_resume - this is callback function used whenever an fop does - * STACK_WIND to fops->lookup in order to lookup the inode - * for a pathname. this case of doing fops->lookup arises - * when fop searches in inode table for pathname and search - * fails. - * - * @stub: call stub - * @op_ret: - * @op_errno: - * @inode: - * @parent: - * - * not for external reference - */ -int32_t -server_stub_resume (call_stub_t *stub, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - inode_t *parent) -{ - inode_t *server_inode = inode; - - if (!stub) { - return 0; - } - switch (stub->fop) - { - case GF_FOP_RENAME: - if (stub->args.rename.old.inode == NULL) { - loc_t *newloc = NULL; - /* now we are called by lookup of oldpath. */ - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": RENAME (%s -> %s) on %s " - "returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.rename.old.path, - stub->args.rename.new.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - /* lookup of oldpath failed, UNWIND to - * server_rename_cbk with ret=-1 and - * errno=ENOENT - */ - server_rename_cbk (stub->frame, - NULL, - stub->frame->this, - -1, - ENOENT, - NULL); - server_loc_wipe (&stub->args.rename.old); - server_loc_wipe (&stub->args.rename.new); - FREE (stub); - return 0; - } - - if (stub->args.rename.old.parent == NULL) - stub->args.rename.old.parent = - inode_ref (parent); - - /* store inode information of oldpath in our stub - * and search for newpath in inode table. - */ - if (server_inode) { - stub->args.rename.old.inode = - inode_ref (server_inode); - - stub->args.rename.old.ino = - server_inode->ino; - } - - /* now lookup for newpath */ - newloc = &stub->args.rename.new; - - if (newloc->parent == NULL) { - /* lookup for newpath */ - do_path_lookup (stub, newloc); - break; - } else { - /* found newpath in inode cache */ - call_resume (stub); - break; - } - } else { - /* we are called by the lookup of newpath */ - if (stub->args.rename.new.parent == NULL) - stub->args.rename.new.parent = - inode_ref (parent); - } - - /* after looking up for oldpath as well as newpath, - * we are ready to resume */ - { - call_resume (stub); - } - break; - - case GF_FOP_OPEN: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": OPEN (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.open.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_open_cbk (stub->frame, - NULL, - stub->frame->this, - -1, - ENOENT, - NULL); - FREE (stub->args.open.loc.path); - FREE (stub); - return 0; - } - if (stub->args.open.loc.parent == NULL) - stub->args.open.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.open.loc.inode == NULL)) { - stub->args.open.loc.inode = inode_ref (server_inode); - stub->args.open.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_LOOKUP: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, - GF_LOG_DEBUG, - "%"PRId64": LOOKUP (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.lookup.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_lookup_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL, NULL, - NULL); - server_loc_wipe (&stub->args.lookup.loc); - FREE (stub); - return 0; - } - - if (stub->args.lookup.loc.parent == NULL) - stub->args.lookup.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.lookup.loc.inode == NULL)) { - stub->args.lookup.loc.inode = inode_ref (server_inode); - stub->args.lookup.loc.ino = server_inode->ino; - } - - call_resume (stub); - - break; - } - - case GF_FOP_STAT: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": STAT (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.stat.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - server_stat_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL); - server_loc_wipe (&stub->args.stat.loc); - FREE (stub); - return 0; - } - - /* TODO:reply from here only, we already have stat structure */ - if (stub->args.stat.loc.parent == NULL) - stub->args.stat.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.stat.loc.inode == NULL)) { - stub->args.stat.loc.inode = inode_ref (server_inode); - stub->args.stat.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_XATTROP: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": XATTROP (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.xattrop.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - server_xattrop_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL); - server_loc_wipe (&stub->args.xattrop.loc); - FREE (stub); - return 0; - } - - if (stub->args.xattrop.loc.parent == NULL) - stub->args.xattrop.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.xattrop.loc.inode == NULL)) { - stub->args.xattrop.loc.inode = - inode_ref (server_inode); - - stub->args.xattrop.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_UNLINK: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": UNLINK (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.unlink.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - server_unlink_cbk (stub->frame, NULL, - stub->frame->this, - -1, ENOENT); - server_loc_wipe (&stub->args.unlink.loc); - FREE (stub); - return 0; - } - - if (stub->args.unlink.loc.parent == NULL) - stub->args.unlink.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.unlink.loc.inode == NULL)) { - stub->args.unlink.loc.inode = inode_ref (server_inode); - stub->args.unlink.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_SYMLINK: - { - if ((op_ret < 0) && (parent == NULL)) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": SYMLINK (%s -> %s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.symlink.loc.path, - stub->args.symlink.linkname, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - server_symlink_cbk (stub->frame, NULL, - stub->frame->this, - -1, ENOENT, - NULL, NULL); - server_loc_wipe (&stub->args.symlink.loc); - FREE (stub); - return 0; - } - - if (stub->args.symlink.loc.parent == NULL) - stub->args.symlink.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.symlink.loc.inode == NULL)) { - stub->args.symlink.loc.inode = - inode_ref (server_inode); - stub->args.symlink.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_RMDIR: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": RMDIR (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.rmdir.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - server_rmdir_cbk (stub->frame, - NULL, - stub->frame->this, - -1, - ENOENT); - server_loc_wipe (&stub->args.rmdir.loc); - FREE (stub); - return 0; - } - - if (stub->args.rmdir.loc.parent == NULL) - stub->args.rmdir.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.rmdir.loc.inode == NULL)) { - stub->args.rmdir.loc.inode = inode_ref (server_inode); - stub->args.rmdir.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_CHMOD: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": CHMOD (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.chmod.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - server_chmod_cbk (stub->frame, - NULL, - stub->frame->this, - -1, - ENOENT, - NULL); - server_loc_wipe (&stub->args.chmod.loc); - FREE (stub); - return 0; - } - - if (stub->args.chmod.loc.parent == NULL) - stub->args.chmod.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.chmod.loc.inode == NULL)) { - stub->args.chmod.loc.inode = inode_ref (server_inode); - stub->args.chmod.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_CHOWN: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": CHOWN (%s) on %s returning ENOENT: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.chown.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - server_chown_cbk (stub->frame, - NULL, - stub->frame->this, - -1, - ENOENT, - NULL); - server_loc_wipe (&stub->args.chown.loc); - FREE (stub); - return 0; - } - - if (stub->args.chown.loc.parent == NULL) - stub->args.chown.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.chown.loc.inode == NULL)) { - stub->args.chown.loc.inode = inode_ref (server_inode); - stub->args.chown.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_LINK: - { - if (stub->args.link.oldloc.inode == NULL) { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": LINK (%s -> %s) on %s returning " - "error for oldloc: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.link.oldloc.path, - stub->args.link.newloc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_link_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL, NULL); - server_loc_wipe (&stub->args.link.oldloc); - server_loc_wipe (&stub->args.link.newloc); - FREE (stub); - return 0; - } - - if (stub->args.link.oldloc.parent == NULL) - stub->args.link.oldloc.parent = - inode_ref (parent); - - if (server_inode && - (stub->args.link.oldloc.inode == NULL)) { - stub->args.link.oldloc.inode = - inode_ref (server_inode); - stub->args.link.oldloc.ino = server_inode->ino; - } - - if (stub->args.link.newloc.parent == NULL) { - do_path_lookup (stub, - &(stub->args.link.newloc)); - break; - } - } else { - /* we are called by the lookup of newpath */ - if ((op_ret < 0) && (parent == NULL)) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": LINK (%s -> %s) on %s returning " - "error for newloc: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.link.oldloc.path, - stub->args.link.newloc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_link_cbk (stub->frame, NULL, - stub->frame->this, - -1, ENOENT, - NULL, NULL); - - server_loc_wipe (&stub->args.link.oldloc); - server_loc_wipe (&stub->args.link.newloc); - FREE (stub); - break; - } - - if (stub->args.link.newloc.parent == NULL) { - stub->args.link.newloc.parent = - inode_ref (parent); - } - - if (server_inode && - (stub->args.link.newloc.inode == NULL)) { - /* as new.inode doesn't get forget, it - * needs to be unref'd here */ - stub->args.link.newloc.inode = - inode_ref (server_inode); - stub->args.link.newloc.ino = server_inode->ino; - } - } - call_resume (stub); - break; - } - - case GF_FOP_TRUNCATE: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": TRUNCATE (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.truncate.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_truncate_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL); - server_loc_wipe (&stub->args.truncate.loc); - FREE (stub); - return 0; - } - - if (stub->args.truncate.loc.parent == NULL) - stub->args.truncate.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.truncate.loc.inode == NULL)) { - stub->args.truncate.loc.inode = - inode_ref (server_inode); - stub->args.truncate.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_STATFS: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": STATFS (%s) on %s returning ENOENT: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.statfs.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_statfs_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL); - server_loc_wipe (&stub->args.statfs.loc); - FREE (stub); - return 0; - } - - if (stub->args.statfs.loc.parent == NULL) - stub->args.statfs.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.statfs.loc.inode == NULL)) { - stub->args.statfs.loc.inode = inode_ref (server_inode); - stub->args.statfs.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_SETXATTR: - { - dict_t *dict = stub->args.setxattr.dict; - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": SETXATTR (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.setxattr.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_setxattr_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT); - - server_loc_wipe (&stub->args.setxattr.loc); - dict_unref (dict); - FREE (stub); - return 0; - } - - if (stub->args.setxattr.loc.parent == NULL) - stub->args.setxattr.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.setxattr.loc.inode == NULL)) { - stub->args.setxattr.loc.inode = - inode_ref (server_inode); - stub->args.setxattr.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_GETXATTR: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": GETXATTR (%s) on %s for key %s " - "returning error: %"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.getxattr.loc.path, - BOUND_XL(stub->frame)->name, - stub->args.getxattr.name ? - stub->args.getxattr.name : "<nul>", - op_ret, op_errno); - - server_getxattr_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL); - server_loc_wipe (&stub->args.getxattr.loc); - FREE (stub); - return 0; - } - - if (stub->args.getxattr.loc.parent == NULL) - stub->args.getxattr.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.getxattr.loc.inode == NULL)) { - stub->args.getxattr.loc.inode = - inode_ref (server_inode); - stub->args.getxattr.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_REMOVEXATTR: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": REMOVEXATTR (%s) on %s for key %s " - "returning error: %"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.removexattr.loc.path, - BOUND_XL(stub->frame)->name, - stub->args.removexattr.name, - op_ret, op_errno); - - server_removexattr_cbk (stub->frame, - NULL, - stub->frame->this, - -1, - ENOENT); - server_loc_wipe (&stub->args.removexattr.loc); - FREE (stub); - return 0; - } - - if (stub->args.removexattr.loc.parent == NULL) - stub->args.removexattr.loc.parent = inode_ref (parent); - - if (server_inode && - (stub->args.removexattr.loc.inode == NULL)) { - stub->args.removexattr.loc.inode = - inode_ref (server_inode); - stub->args.removexattr.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_OPENDIR: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": OPENDIR (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.opendir.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_opendir_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL); - server_loc_wipe (&stub->args.opendir.loc); - FREE (stub); - return 0; - } - - if (stub->args.opendir.loc.parent == NULL) - stub->args.opendir.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.opendir.loc.inode == NULL)) { - stub->args.opendir.loc.inode = - inode_ref (server_inode); - stub->args.opendir.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_ACCESS: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": ACCESS (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.access.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_access_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT); - server_loc_wipe (&stub->args.access.loc); - FREE (stub); - return 0; - } - - if (stub->args.access.loc.parent == NULL) - stub->args.access.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.access.loc.inode == NULL)) { - stub->args.access.loc.inode = inode_ref (server_inode); - stub->args.access.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - - case GF_FOP_UTIMENS: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": UTIMENS (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.utimens.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_utimens_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL); - server_loc_wipe (&stub->args.utimens.loc); - FREE (stub); - return 0; - } - - if (stub->args.utimens.loc.parent == NULL) - stub->args.utimens.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.utimens.loc.inode == NULL)) { - stub->args.utimens.loc.inode = - inode_ref (server_inode); - stub->args.utimens.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - - case GF_FOP_READLINK: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": READLINK (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.readlink.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_readlink_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL); - server_loc_wipe (&stub->args.readlink.loc); - FREE (stub); - return 0; - } - - if (stub->args.readlink.loc.parent == NULL) - stub->args.readlink.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.readlink.loc.inode == NULL)) { - stub->args.readlink.loc.inode = - inode_ref (server_inode); - stub->args.readlink.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - case GF_FOP_MKDIR: - { - if ((op_ret < 0) && (parent == NULL)) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": MKDIR (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.mkdir.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_mkdir_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL, NULL); - server_loc_wipe (&stub->args.mkdir.loc); - FREE (stub); - break; - } - - if (stub->args.mkdir.loc.parent == NULL) - stub->args.mkdir.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.mkdir.loc.inode == NULL)) { - stub->args.mkdir.loc.inode = inode_ref (server_inode); - stub->args.mkdir.loc.ino = server_inode->ino; - } - - call_resume (stub); - break; - } - - case GF_FOP_CREATE: - { - if ((op_ret < 0) && (parent == NULL)) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": CREATE (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.create.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_create_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL, NULL, - NULL); - if (stub->args.create.fd) - fd_unref (stub->args.create.fd); - server_loc_wipe (&stub->args.create.loc); - FREE (stub); - break; - } - - if (stub->args.create.loc.parent == NULL) - stub->args.create.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.create.loc.inode == NULL)) { - stub->args.create.loc.inode = inode_ref (server_inode); - stub->args.create.loc.ino = server_inode->ino; - } - - call_resume (stub); - break; - } - - case GF_FOP_MKNOD: - { - if ((op_ret < 0) && (parent == NULL)) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": MKNOD (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.mknod.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_mknod_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT, - NULL, NULL); - server_loc_wipe (&stub->args.mknod.loc); - FREE (stub); - break; - } - - if (stub->args.mknod.loc.parent == NULL) - stub->args.mknod.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.mknod.loc.inode == NULL)) { - stub->args.mknod.loc.inode = inode_ref (server_inode); - stub->args.mknod.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - case GF_FOP_ENTRYLK: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": ENTRYLK (%s) on %s for key %s returning " - "error: %"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.entrylk.loc.path, - BOUND_XL(stub->frame)->name, - stub->args.entrylk.name ? - stub->args.entrylk.name : "<nul>", - op_ret, op_errno); - - server_entrylk_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT); - server_loc_wipe (&stub->args.entrylk.loc); - FREE (stub); - break; - } - - if (stub->args.entrylk.loc.parent == NULL) - stub->args.entrylk.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.entrylk.loc.inode == NULL)) { - stub->args.entrylk.loc.inode = inode_ref (server_inode); - stub->args.entrylk.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - case GF_FOP_INODELK: - { - if (op_ret < 0) { - gf_log (stub->frame->this->name, GF_LOG_ERROR, - "%"PRId64": INODELK (%s) on %s returning error: " - "%"PRId32" (%"PRId32")", - stub->frame->root->unique, - stub->args.inodelk.loc.path, - BOUND_XL(stub->frame)->name, - op_ret, op_errno); - - server_inodelk_cbk (stub->frame, - NULL, - stub->frame->this, - -1, ENOENT); - server_loc_wipe (&stub->args.inodelk.loc); - FREE (stub); - break; - } - - if (stub->args.inodelk.loc.parent == NULL) - stub->args.inodelk.loc.parent = inode_ref (parent); - - if (server_inode && (stub->args.inodelk.loc.inode == NULL)) { - stub->args.inodelk.loc.inode = - inode_ref (server_inode); - stub->args.inodelk.loc.ino = server_inode->ino; - } - call_resume (stub); - break; - } - default: - call_resume (stub); - } - - return 0; -} - -static int -server_lookup_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - dict_t *xattr_req) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - if ((state->loc.parent == NULL) && - (loc->parent)) - state->loc.parent = inode_ref (loc->parent); - - if (state->loc.inode == NULL) { - if (loc->inode == NULL) - state->loc.inode = inode_new (state->itable); - else - /* FIXME: why another lookup? */ - state->loc.inode = inode_ref (loc->inode); - } else { - if (loc->inode && (state->loc.inode != loc->inode)) { - if (state->loc.inode) - inode_unref (state->loc.inode); - state->loc.inode = inode_ref (loc->inode); - } - } - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": LOOKUP \'%"PRId64"/%s\'", - frame->root->unique, state->par, state->bname); - - STACK_WIND (frame, - server_lookup_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->lookup, - &(state->loc), - xattr_req); - return 0; -} - -/* - * server_lookup - lookup function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int -server_lookup (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_lookup_req_t *req = NULL; - server_state_t *state = NULL; - call_stub_t *lookup_stub = NULL; - int32_t ret = -1; - size_t pathlen = 0, baselen = 0; - size_t dictlen = 0; - dict_t *xattr_req = NULL; - char *req_dictbuf = NULL; - - req = gf_param (hdr); - - state = CALL_STATE(frame); - { - - pathlen = STRLEN_0 (req->path); - dictlen = ntoh32 (req->dictlen); - - /* NOTE: lookup() uses req->ino only to identify if a lookup() - * is requested for 'root' or not - */ - state->ino = ntoh64 (req->ino); - if (state->ino != 1) - state->ino = 0; - - state->par = ntoh64 (req->par); - state->path = req->path; - if (IS_NOT_ROOT(pathlen)) { - state->bname = req->bname + pathlen; - baselen = STRLEN_0 (state->bname); - } - - if (dictlen) { - /* Unserialize the dictionary */ - req_dictbuf = memdup (req->dict + pathlen + baselen, dictlen); - GF_VALIDATE_OR_GOTO(bound_xl->name, req_dictbuf, fail); - - xattr_req = dict_new (); - GF_VALIDATE_OR_GOTO(bound_xl->name, xattr_req, fail); - - ret = dict_unserialize (req_dictbuf, dictlen, &xattr_req); - if (ret < 0) { - gf_log (bound_xl->name, GF_LOG_ERROR, - "%"PRId64": %s (%"PRId64"): failed to " - "unserialize request buffer to dictionary", - frame->root->unique, state->loc.path, - state->ino); - free (req_dictbuf); - goto fail; - } else{ - xattr_req->extra_free = req_dictbuf; - state->xattr_req = xattr_req; - xattr_req = NULL; - } - } - } - - ret = server_loc_fill (&state->loc, state, - state->ino, state->par, state->bname, - state->path); - - if (state->loc.inode) { - /* revalidate */ - state->is_revalidate = 1; - } else { - /* fresh lookup or inode was previously pruned out */ - state->is_revalidate = -1; - } - - lookup_stub = fop_lookup_stub (frame, server_lookup_resume, - &(state->loc), state->xattr_req); - GF_VALIDATE_OR_GOTO(bound_xl->name, lookup_stub, fail); - - if ((state->loc.parent == NULL) && - IS_NOT_ROOT(pathlen)) - do_path_lookup (lookup_stub, &(state->loc)); - else - call_resume (lookup_stub); - - return 0; -fail: - server_lookup_cbk (frame, NULL, frame->this, - -1,EINVAL, - NULL, NULL, NULL); - if (xattr_req) - dict_unref (xattr_req); - - return 0; -} - - -/* - * server_forget - forget function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_forget (call_frame_t *frame, xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - int index = 0; - ino_t ino = 0; - int32_t count = 0; - inode_t *inode = NULL; - gf_cbk_forget_req_t *req = NULL; - - req = gf_param (hdr); - count = ntoh32 (req->count); - - for (index = 0; index < count; index++) { - - ino = ntoh64 (req->ino_array[index]); - - if (!ino) - continue; - - inode = inode_search (bound_xl->itable, ino, NULL); - - if (inode) { - inode_forget (inode, 0); - inode_unref (inode); - } else { - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": FORGET %"PRId64" not found " - "in inode table", - frame->root->unique, ino); - } - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": FORGET \'%"PRId64"\'", - frame->root->unique, ino); - } - - server_forget_cbk (frame, NULL, bound_xl, 0, 0); - - return 0; -} - - - -int32_t -server_stat_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": STAT \'%s (%"PRId64")\'", - frame->root->unique, state->loc.path, state->loc.ino); - - STACK_WIND (frame, - server_stat_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->stat, - loc); - return 0; -} - -/* - * server_stat - stat function for server - * @frame: call frame - * @bound_xl: translator this server is bound to - * @params: parameters dictionary - * - * not for external reference - */ -int32_t -server_stat (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *stat_stub = NULL; - gf_fop_stat_req_t *req = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - - state->ino = ntoh64 (req->ino); - state->path = req->path; - pathlen = STRLEN_0(state->path); - - ret = server_loc_fill (&(state->loc), state, - state->ino, state->par, state->bname, - state->path); - - stat_stub = fop_stat_stub (frame, - server_stat_resume, - &(state->loc)); - GF_VALIDATE_OR_GOTO(bound_xl->name, stat_stub, fail); - - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { - do_path_lookup (stat_stub, &(state->loc)); - } else { - call_resume (stat_stub); - } - return 0; -fail: - server_stat_cbk (frame, NULL, frame->this, - -1, EINVAL, - NULL); - return 0; -} - - -int32_t -server_readlink_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - size_t size) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": READLINK \'%s (%"PRId64")\'", - frame->root->unique, state->loc.path, state->loc.ino); - - STACK_WIND (frame, - server_readlink_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->readlink, - loc, - size); - return 0; -} - -/* - * server_readlink - readlink function for server - * @frame: call frame - * @bound_xl: translator this server is bound to - * @params: parameters dictionary - * - * not for external reference - */ -int32_t -server_readlink (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *readlink_stub = NULL; - gf_fop_readlink_req_t *req = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - - req = gf_param (hdr); - state = CALL_STATE(frame); - - state->size = ntoh32 (req->size); - - state->ino = ntoh64 (req->ino); - state->path = req->path; - - ret = server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - readlink_stub = fop_readlink_stub (frame, - server_readlink_resume, - &(state->loc), - state->size); - GF_VALIDATE_OR_GOTO(bound_xl->name, readlink_stub, fail); - - if ((state->loc.parent == NULL) || - (state->loc.inode == NULL)) { - do_path_lookup (readlink_stub, &(state->loc)); - } else { - call_resume (readlink_stub); - } - return 0; -fail: - server_readlink_cbk (frame, NULL,frame->this, - -1, EINVAL, - NULL); - return 0; -} - -int32_t -server_create_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flags, - mode_t mode, - fd_t *fd) -{ - server_state_t *state = CALL_STATE(frame); - - if (state->loc.parent == NULL) - state->loc.parent = inode_ref (loc->parent); - - state->loc.inode = inode_new (state->itable); - GF_VALIDATE_OR_GOTO(BOUND_XL(frame)->name, state->loc.inode, fail); - - state->fd = fd_create (state->loc.inode, frame->root->pid); - GF_VALIDATE_OR_GOTO(BOUND_XL(frame)->name, state->fd, fail); - - state->fd->flags = flags; - state->fd = fd_ref (state->fd); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": CREATE \'%"PRId64"/%s\'", - frame->root->unique, state->par, state->bname); - - STACK_WIND (frame, - server_create_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->create, - &(state->loc), - flags, - mode, - state->fd); - - return 0; -fail: - server_create_cbk (frame, NULL, frame->this, - -1, EINVAL, - NULL, NULL, NULL); - return 0; -} - - -/* - * server_create - create function for server - * @frame: call frame - * @bound_xl: translator this server is bound to - * @params: parameters dictionary - * - * not for external reference - */ -int32_t -server_create (call_frame_t *frame, xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_create_req_t *req = NULL; - server_state_t *state = NULL; - call_stub_t *create_stub = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - pathlen = STRLEN_0(req->path); - - state->par = ntoh64 (req->par); - state->path = req->path; - if (IS_NOT_ROOT(pathlen)) - state->bname = req->bname + pathlen; - - state->mode = ntoh32 (req->mode); - state->flags = ntoh32 (req->flags); - } - - ret = server_loc_fill (&(state->loc), state, - 0, state->par, state->bname, - state->path); - - create_stub = fop_create_stub (frame, server_create_resume, - &(state->loc), state->flags, - state->mode, state->fd); - GF_VALIDATE_OR_GOTO(bound_xl->name, create_stub, fail); - - if (state->loc.parent == NULL) { - do_path_lookup (create_stub, &state->loc); - } else { - call_resume (create_stub); - } - return 0; -fail: - server_create_cbk (frame, NULL, frame->this, - -1, EINVAL, - NULL, NULL, NULL); - return 0; -} - - -int32_t -server_open_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flags, - fd_t *fd) -{ - server_state_t *state = CALL_STATE(frame); - fd_t *new_fd = NULL; - - new_fd = fd_create (loc->inode, frame->root->pid); - GF_VALIDATE_OR_GOTO(BOUND_XL(frame)->name, new_fd, fail); - - new_fd->flags = flags; - - state->fd = fd_ref (new_fd); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": OPEN \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_open_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->open, - loc, - flags, - state->fd); - - return 0; -fail: - server_open_cbk (frame, NULL, frame->this, - -1, EINVAL, - NULL); - return 0; -} - -/* - * server_open - open function for server protocol - * @frame: call frame - * @bound_xl: translator this server protocol is bound to - * @params: parameters dictionary - * - * not for external reference - */ -int32_t -server_open (call_frame_t *frame, xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *open_stub = NULL; - gf_fop_open_req_t *req = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->ino = ntoh64 (req->ino); - state->path = req->path; - pathlen = STRLEN_0(state->path); - state->flags = ntoh32 (req->flags); - } - ret = server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - open_stub = fop_open_stub (frame, - server_open_resume, - &(state->loc), state->flags, NULL); - GF_VALIDATE_OR_GOTO(bound_xl->name, open_stub, fail); - - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { - do_path_lookup (open_stub, &state->loc); - } else { - call_resume (open_stub); - } - return 0; -fail: - server_open_cbk (frame, NULL, frame->this, - -1, EINVAL, - NULL); - return 0; -} - - -/* - * server_readv - readv function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_readv (call_frame_t *frame, xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_read_req_t *req = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->size = ntoh32 (req->size); - state->offset = ntoh64 (req->offset); - } - - GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail); - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": READV \'fd=%"PRId64" (%"PRId64"); " - "offset=%"PRId64"; size=%"PRId64, - frame->root->unique, state->fd_no, state->fd->inode->ino, - state->offset, (int64_t)state->size); - - STACK_WIND (frame, - server_readv_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->readv, - state->fd, state->size, state->offset); - return 0; -fail: - server_readv_cbk (frame, NULL, frame->this, - -1, EINVAL, NULL, 0, NULL, NULL); - return 0; -} - - -/* - * server_writev - writev function for server - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_writev (call_frame_t *frame, xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - server_connection_t *conn = NULL; - gf_fop_write_req_t *req = NULL; - struct iovec iov = {0, }; - struct iobref *iobref = NULL; - server_state_t *state = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->offset = ntoh64 (req->offset); - state->size = ntoh32 (req->size); - } - - GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail); - - if (iobuf) - iov.iov_base = iobuf->ptr; - iov.iov_len = state->size; - - iobref = iobref_new (); - GF_VALIDATE_OR_GOTO(bound_xl->name, iobref, fail); - - iobref_add (iobref, iobuf); - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": WRITEV \'fd=%"PRId64" (%"PRId64"); " - "offset=%"PRId64"; size=%"PRId32, - frame->root->unique, state->fd_no, state->fd->inode->ino, - state->offset, (int32_t)state->size); - - STACK_WIND (frame, - server_writev_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->writev, - state->fd, &iov, 1, state->offset, iobref); - - if (iobref) - iobref_unref (iobref); - if (iobuf) - iobuf_unref (iobuf); - - return 0; -fail: - server_writev_cbk (frame, NULL, frame->this, - -1, EINVAL, NULL); - - if (iobref) - iobref_unref (iobref); - if (iobuf) - iobuf_unref (iobuf); - - return 0; -} - - - -/* - * server_release - release function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_release (call_frame_t *frame, xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_cbk_release_req_t *req = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - - state->fd_no = ntoh64 (req->fd); - - gf_fd_put (conn->fdtable, - state->fd_no); - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": RELEASE \'fd=%"PRId64"\'", - frame->root->unique, state->fd_no); - - server_release_cbk (frame, NULL, frame->this, 0, 0); - return 0; -} - - -/* - * server_fsync - fsync function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameters dictionary - * - * not for external reference - */ -int32_t -server_fsync (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_fsync_req_t *req = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->flags = ntoh32 (req->data); - } - - GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail); - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": FSYNC \'fd=%"PRId64" (%"PRId64")\'", - frame->root->unique, state->fd_no, state->fd->inode->ino); - - STACK_WIND (frame, - server_fsync_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->fsync, - state->fd, state->flags); - return 0; -fail: - server_fsync_cbk (frame, NULL, frame->this, - -1, EINVAL); - - return 0; -} - - -/* - * server_flush - flush function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_flush (call_frame_t *frame, xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_flush_req_t *req = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - } - - GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail); - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": FLUSH \'fd=%"PRId64" (%"PRId64")\'", - frame->root->unique, state->fd_no, state->fd->inode->ino); - - STACK_WIND (frame, - server_flush_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->flush, - state->fd); - return 0; - -fail: - server_flush_cbk (frame, NULL, frame->this, - -1, EINVAL); - - return 0; -} - - -/* - * server_ftruncate - ftruncate function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameters dictionary - * - * not for external reference - */ -int32_t -server_ftruncate (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_ftruncate_req_t *req = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->offset = ntoh64 (req->offset); - } - - GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail); - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": FTRUNCATE \'fd=%"PRId64" (%"PRId64"); " - "offset=%"PRId64"\'", - frame->root->unique, state->fd_no, state->fd->inode->ino, - state->offset); - - STACK_WIND (frame, - server_ftruncate_cbk, - bound_xl, - bound_xl->fops->ftruncate, - state->fd, - state->offset); - return 0; -fail: - server_ftruncate_cbk (frame, NULL, frame->this, - -1, EINVAL, NULL); - - return 0; -} - - -/* - * server_fstat - fstat function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_fstat (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_fstat_req_t *req = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - } - - - if (state->fd == NULL) { - gf_log (frame->this->name, GF_LOG_ERROR, - "fd - %"PRId64": unresolved fd", - state->fd_no); - - server_fstat_cbk (frame, NULL, frame->this, - -1, EINVAL, NULL); - - goto out; - } - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": FSTAT \'fd=%"PRId64" (%"PRId64")\'", - frame->root->unique, state->fd_no, state->fd->inode->ino); - - STACK_WIND (frame, - server_fstat_cbk, - bound_xl, - bound_xl->fops->fstat, - state->fd); -out: - return 0; -} - - -int32_t -server_truncate_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - off_t offset) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": TRUNCATE \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_truncate_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->truncate, - loc, - offset); - return 0; -} - - -/* - * server_truncate - truncate function for server protocol - * @frame: call frame - * @bound_xl: - * @params: - * - * not for external reference - */ -int32_t -server_truncate (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *truncate_stub = NULL; - gf_fop_truncate_req_t *req = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - pathlen = STRLEN_0(req->path); - state->offset = ntoh64 (req->offset); - - state->path = req->path; - state->ino = ntoh64 (req->ino); - } - - - ret = server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - truncate_stub = fop_truncate_stub (frame, - server_truncate_resume, - &(state->loc), - state->offset); - if ((state->loc.parent == NULL) || - (state->loc.inode == NULL)) { - do_path_lookup (truncate_stub, &(state->loc)); - } else { - call_resume (truncate_stub); - } - - return 0; -} - - - - - -int32_t -server_unlink_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - if (state->loc.parent == NULL) - state->loc.parent = inode_ref (loc->parent); - - if (state->loc.inode == NULL) - state->loc.inode = inode_ref (loc->inode); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": UNLINK \'%"PRId64"/%s (%"PRId64")\'", - frame->root->unique, state->par, state->path, - state->loc.inode->ino); - - STACK_WIND (frame, - server_unlink_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->unlink, - loc); - return 0; -} - -/* - * server_unlink - unlink function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_unlink (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *unlink_stub = NULL; - gf_fop_unlink_req_t *req = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - - pathlen = STRLEN_0(req->path); - - state->par = ntoh64 (req->par); - state->path = req->path; - if (IS_NOT_ROOT(pathlen)) - state->bname = req->bname + pathlen; - - ret = server_loc_fill (&(state->loc), state, - 0, state->par, state->bname, - state->path); - - unlink_stub = fop_unlink_stub (frame, - server_unlink_resume, - &(state->loc)); - - if ((state->loc.parent == NULL) || - (state->loc.inode == NULL)) { - do_path_lookup (unlink_stub, &state->loc); - } else { - call_resume (unlink_stub); - } - - return 0; -} - - - - - -int32_t -server_setxattr_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - dict_t *dict, - int32_t flags) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": SETXATTR \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_setxattr_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->setxattr, - loc, - dict, - flags); - return 0; -} - -/* - * server_setxattr - setxattr function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ - -int32_t -server_setxattr (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *setxattr_stub = NULL; - gf_fop_setxattr_req_t *req = NULL; - dict_t *dict = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - size_t dict_len = 0; - char *req_dictbuf = NULL; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - dict_len = ntoh32 (req->dict_len); - - state->path = req->path + dict_len; - - pathlen = STRLEN_0(state->path); - state->ino = ntoh64 (req->ino); - - state->flags = ntoh32 (req->flags); - } - ret = server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - { - /* Unserialize the dictionary */ - req_dictbuf = memdup (req->dict, dict_len); - GF_VALIDATE_OR_GOTO(bound_xl->name, req_dictbuf, fail); - - dict = dict_new (); - GF_VALIDATE_OR_GOTO(bound_xl->name, dict, fail); - - ret = dict_unserialize (req_dictbuf, dict_len, &dict); - if (ret < 0) { - gf_log (bound_xl->name, GF_LOG_ERROR, - "%"PRId64": %s (%"PRId64"): failed to " - "unserialize request buffer to dictionary", - frame->root->unique, state->loc.path, - state->ino); - free (req_dictbuf); - goto fail; - } else{ - dict->extra_free = req_dictbuf; - } - } - - setxattr_stub = fop_setxattr_stub (frame, - server_setxattr_resume, - &(state->loc), - dict, - state->flags); - GF_VALIDATE_OR_GOTO(bound_xl->name, setxattr_stub, fail); - - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { - do_path_lookup (setxattr_stub, &(state->loc)); - } else { - call_resume (setxattr_stub); - } - - if (dict) - dict_unref (dict); - - return 0; -fail: - if (dict) - dict_unref (dict); - - server_setxattr_cbk (frame, NULL, frame->this, - -1, ENOENT); - return 0; - -} - - -int32_t -server_fsetxattr (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - server_connection_t *conn = NULL; - gf_fop_fsetxattr_req_t *req = NULL; - - dict_t *dict = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - size_t dict_len = 0; - char *req_dictbuf = NULL; - - conn = SERVER_CONNECTION (frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - dict_len = ntoh32 (req->dict_len); - - pathlen = STRLEN_0(state->path); - state->ino = ntoh64 (req->ino); - - state->flags = ntoh32 (req->flags); - } - - /* Unserialize the dictionary */ - req_dictbuf = memdup (req->dict, dict_len); - GF_VALIDATE_OR_GOTO(bound_xl->name, req_dictbuf, fail); - - dict = dict_new (); - GF_VALIDATE_OR_GOTO(bound_xl->name, dict, fail); - - ret = dict_unserialize (req_dictbuf, dict_len, &dict); - if (ret < 0) { - gf_log (bound_xl->name, GF_LOG_ERROR, - "%"PRId64": %s (%"PRId64"): failed to " - "unserialize request buffer to dictionary", - frame->root->unique, state->loc.path, - state->ino); - free (req_dictbuf); - goto fail; - } else{ - dict->extra_free = req_dictbuf; - } - - STACK_WIND (frame, - server_setxattr_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->fsetxattr, - state->fd, dict, state->flags); - - if (dict) - dict_unref (dict); - - return 0; -fail: - if (dict) - dict_unref (dict); - - server_fsetxattr_cbk (frame, NULL, frame->this, - -1, ENOENT); - return 0; -} - - -int32_t -server_fxattrop (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - server_connection_t *conn = NULL; - gf_fop_fxattrop_req_t *req = NULL; - dict_t *dict = NULL; - server_state_t *state = NULL; - size_t dict_len = 0; - char *req_dictbuf = NULL; - int32_t ret = -1; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - dict_len = ntoh32 (req->dict_len); - state->ino = ntoh64 (req->ino); - state->flags = ntoh32 (req->flags); - } - - if (dict_len) { - /* Unserialize the dictionary */ - req_dictbuf = memdup (req->dict, dict_len); - GF_VALIDATE_OR_GOTO(bound_xl->name, req_dictbuf, fail); - - dict = dict_new (); - GF_VALIDATE_OR_GOTO(bound_xl->name, dict, fail); - - ret = dict_unserialize (req_dictbuf, dict_len, &dict); - if (ret < 0) { - gf_log (bound_xl->name, GF_LOG_ERROR, - "fd - %"PRId64" (%"PRId64"): failed to unserialize " - "request buffer to dictionary", - state->fd_no, state->fd->inode->ino); - free (req_dictbuf); - goto fail; - } else { - dict->extra_free = req_dictbuf; - } - } - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": FXATTROP \'fd=%"PRId64" (%"PRId64")\'", - frame->root->unique, state->fd_no, state->fd->inode->ino); - - STACK_WIND (frame, - server_fxattrop_cbk, - bound_xl, - bound_xl->fops->fxattrop, - state->fd, - state->flags, - dict); - if (dict) - dict_unref (dict); - return 0; -fail: - if (dict) - dict_unref (dict); - - server_fxattrop_cbk (frame, NULL, frame->this, - -1, EINVAL, NULL); - return 0; -} - -int32_t -server_xattrop_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - gf_xattrop_flags_t flags, - dict_t *dict) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": XATTROP \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_xattrop_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->xattrop, - loc, - flags, - dict); - return 0; -} - -int32_t -server_xattrop (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_xattrop_req_t *req = NULL; - dict_t *dict = NULL; - server_state_t *state = NULL; - call_stub_t *xattrop_stub = NULL; - int32_t ret = -1; - size_t pathlen = 0; - size_t dict_len = 0; - char *req_dictbuf = NULL; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - dict_len = ntoh32 (req->dict_len); - state->ino = ntoh64 (req->ino); - state->path = req->path + dict_len; - pathlen = STRLEN_0(state->path); - state->flags = ntoh32 (req->flags); - } - - ret = server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - if (dict_len) { - /* Unserialize the dictionary */ - req_dictbuf = memdup (req->dict, dict_len); - GF_VALIDATE_OR_GOTO(bound_xl->name, req_dictbuf, fail); - - dict = dict_new (); - GF_VALIDATE_OR_GOTO(bound_xl->name, dict, fail); - - ret = dict_unserialize (req_dictbuf, dict_len, &dict); - if (ret < 0) { - gf_log (bound_xl->name, GF_LOG_ERROR, - "%s (%"PRId64"): failed to unserialize " - "request buffer to dictionary", - state->loc.path, state->ino); - goto fail; - } else { - dict->extra_free = req_dictbuf; - } - } - xattrop_stub = fop_xattrop_stub (frame, - server_xattrop_resume, - &(state->loc), - state->flags, - dict); - GF_VALIDATE_OR_GOTO(bound_xl->name, xattrop_stub, fail); - - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { - do_path_lookup (xattrop_stub, &(state->loc)); - } else { - call_resume (xattrop_stub); - } - - if (dict) - dict_unref (dict); - return 0; -fail: - if (dict) - dict_unref (dict); - - server_xattrop_cbk (frame, NULL, frame->this, - -1, EINVAL, - NULL); - return 0; -} - - -int32_t -server_getxattr_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - const char *name) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": GETXATTR \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_getxattr_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->getxattr, - loc, - name); - return 0; -} - -/* - * server_getxattr - getxattr function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_getxattr (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_getxattr_req_t *req = NULL; - call_stub_t *getxattr_stub = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t namelen = 0; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - pathlen = STRLEN_0(req->path); - - state->path = req->path; - state->ino = ntoh64 (req->ino); - - namelen = ntoh32 (req->namelen); - if (namelen) - state->name = (req->name + pathlen); - } - - ret = server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - getxattr_stub = fop_getxattr_stub (frame, - server_getxattr_resume, - &(state->loc), - state->name); - - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { - do_path_lookup (getxattr_stub, &(state->loc)); - } else { - call_resume (getxattr_stub); - } - - return 0; -} - - -int32_t -server_fgetxattr (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - server_connection_t *conn = NULL; - gf_fop_fgetxattr_req_t *req = NULL; - server_state_t *state = NULL; - - size_t namelen = 0; - - conn = SERVER_CONNECTION (frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->ino = ntoh64 (req->ino); - - namelen = ntoh32 (req->namelen); - if (namelen) - state->name = (req->name); - } - - STACK_WIND (frame, - server_fgetxattr_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->fgetxattr, - state->fd, - state->name); - return 0; -} - - -int32_t -server_removexattr_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - const char *name) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": REMOVEXATTR \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_removexattr_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->removexattr, - loc, - name); - return 0; -} - -/* - * server_removexattr - removexattr function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_removexattr (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_removexattr_req_t *req = NULL; - call_stub_t *removexattr_stub = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - pathlen = STRLEN_0(req->path); - - state->path = req->path; - state->ino = ntoh64 (req->ino); - - state->name = (req->name + pathlen); - } - - ret = server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - removexattr_stub = fop_removexattr_stub (frame, - server_removexattr_resume, - &(state->loc), - state->name); - - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { - do_path_lookup (removexattr_stub, &(state->loc)); - } else { - call_resume (removexattr_stub); - } - - return 0; -} - - -/* - * server_statfs - statfs function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_statfs (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_statfs_req_t *req = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - - req = gf_param (hdr); - - state = CALL_STATE(frame); - state->ino = ntoh64 (req->ino); - state->path = req->path; - - ret = server_loc_fill (&state->loc, state, - state->ino, 0, NULL, state->path); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": STATFS \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_statfs_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->statfs, - &(state->loc)); - - return 0; -} - - - -int32_t -server_opendir_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - fd_t *fd) -{ - server_state_t *state = CALL_STATE(frame); - fd_t *new_fd = NULL; - - new_fd = fd_create (loc->inode, frame->root->pid); - state->fd = fd_ref (new_fd); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": OPENDIR \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_opendir_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->opendir, - loc, - state->fd); - return 0; -} - - -/* - * server_opendir - opendir function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_opendir (call_frame_t *frame, xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *opendir_stub = NULL; - gf_fop_opendir_req_t *req = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->path = req->path; - pathlen = STRLEN_0(state->path); - state->ino = ntoh64 (req->ino); - } - - ret = server_loc_fill (&state->loc, state, - state->ino, 0, NULL, state->path); - - opendir_stub = fop_opendir_stub (frame, - server_opendir_resume, - &(state->loc), - NULL); - - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { - do_path_lookup (opendir_stub, &(state->loc)); - } else { - call_resume (opendir_stub); - } - - return 0; -} - - -/* - * server_releasedir - releasedir function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_releasedir (call_frame_t *frame, xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_cbk_releasedir_req_t *req = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - - state->fd_no = ntoh64 (req->fd); - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - if (state->fd == NULL) { - gf_log (frame->this->name, GF_LOG_ERROR, - "fd - %"PRId64": unresolved fd", - state->fd_no); - - server_releasedir_cbk (frame, NULL, frame->this, - -1, EINVAL); - goto out; - } - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": RELEASEDIR \'fd=%"PRId64" (%"PRId64")\'", - frame->root->unique, state->fd_no, state->fd->inode->ino); - - gf_fd_put (conn->fdtable, state->fd_no); - - server_releasedir_cbk (frame, NULL, frame->this, - 0, 0); -out: - return 0; -} - - -/* - * server_readdir - readdir function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_getdents (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_getdents_req_t *req = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->size = ntoh32 (req->size); - state->offset = ntoh64 (req->offset); - state->flags = ntoh32 (req->flags); - } - - - if (state->fd == NULL) { - gf_log (frame->this->name, GF_LOG_ERROR, - "fd - %"PRId64": unresolved fd", - state->fd_no); - - server_getdents_cbk (frame, NULL, frame->this, - -1, EINVAL, NULL, 0); - - goto out; - } - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": GETDENTS \'fd=%"PRId64" (%"PRId64"); " - "offset=%"PRId64"; size=%"PRId64, - frame->root->unique, state->fd_no, state->fd->inode->ino, - state->offset, (int64_t)state->size); - - STACK_WIND (frame, - server_getdents_cbk, - bound_xl, - bound_xl->fops->getdents, - state->fd, - state->size, - state->offset, - state->flags); -out: - return 0; -} - - -/* - * server_readdir - readdir function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_readdir (call_frame_t *frame, xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_readdir_req_t *req = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->size = ntoh32 (req->size); - state->offset = ntoh64 (req->offset); - } - - - if (state->fd == NULL) { - gf_log (frame->this->name, GF_LOG_ERROR, - "fd - %"PRId64": unresolved fd", - state->fd_no); - - server_readdir_cbk (frame, NULL, frame->this, - -1, EINVAL, NULL); - - goto out; - } - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": READDIR \'fd=%"PRId64" (%"PRId64"); " - "offset=%"PRId64"; size=%"PRId64, - frame->root->unique, state->fd_no, state->fd->inode->ino, - state->offset, (int64_t)state->size); - - STACK_WIND (frame, - server_readdir_cbk, - bound_xl, - bound_xl->fops->readdir, - state->fd, state->size, state->offset); -out: - return 0; -} - - - -/* - * server_fsyncdir - fsyncdir function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_fsyncdir (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_fsyncdir_req_t *req = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->flags = ntoh32 (req->data); - } - - if (state->fd == NULL) { - gf_log (frame->this->name, GF_LOG_ERROR, - "fd - %"PRId64": unresolved fd", - state->fd_no); - - server_fsyncdir_cbk (frame, NULL, frame->this, - -1, EINVAL); - goto out; - } - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": FSYNCDIR \'fd=%"PRId64" (%"PRId64")\'", - frame->root->unique, state->fd_no, state->fd->inode->ino); - - STACK_WIND (frame, - server_fsyncdir_cbk, - bound_xl, - bound_xl->fops->fsyncdir, - state->fd, state->flags); -out: - return 0; -} - - -int32_t -server_mknod_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - mode_t mode, - dev_t dev) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - if (state->loc.parent == NULL) - state->loc.parent = inode_ref (loc->parent); - - state->loc.inode = inode_new (state->itable); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": MKNOD \'%"PRId64"/%s\'", - frame->root->unique, state->par, state->bname); - - STACK_WIND (frame, - server_mknod_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->mknod, - &(state->loc), mode, dev); - - return 0; -} -/* - * server_mknod - mknod function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_mknod (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_mknod_req_t *req = NULL; - server_state_t *state = NULL; - call_stub_t *mknod_stub = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - pathlen = STRLEN_0(req->path); - - state->par = ntoh64 (req->par); - state->path = req->path; - if (IS_NOT_ROOT(pathlen)) - state->bname = req->bname + pathlen; - - state->mode = ntoh32 (req->mode); - state->dev = ntoh64 (req->dev); - } - ret = server_loc_fill (&(state->loc), state, - 0, state->par, state->bname, - state->path); - - mknod_stub = fop_mknod_stub (frame, server_mknod_resume, - &(state->loc), state->mode, state->dev); - - if (state->loc.parent == NULL) { - do_path_lookup (mknod_stub, &(state->loc)); - } else { - call_resume (mknod_stub); - } - - return 0; -} - -int32_t -server_mkdir_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - mode_t mode) - -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - if (state->loc.parent == NULL) - state->loc.parent = inode_ref (loc->parent); - - state->loc.inode = inode_new (state->itable); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": MKDIR \'%"PRId64"/%s\'", - frame->root->unique, state->par, state->bname); - - STACK_WIND (frame, - server_mkdir_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->mkdir, - &(state->loc), - state->mode); - - return 0; -} - -/* - * server_mkdir - mkdir function for server protocol - * @frame: call frame - * @bound_xl: - * @params: - * - * not for external reference - */ -int32_t -server_mkdir (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_mkdir_req_t *req = NULL; - server_state_t *state = NULL; - call_stub_t *mkdir_stub = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - pathlen = STRLEN_0(req->path); - state->mode = ntoh32 (req->mode); - - state->path = req->path; - state->bname = req->bname + pathlen; - state->par = ntoh64 (req->par); - } - - - ret = server_loc_fill (&(state->loc), state, - 0, state->par, state->bname, - state->path); - - mkdir_stub = fop_mkdir_stub (frame, server_mkdir_resume, - &(state->loc), state->mode); - - if (state->loc.parent == NULL) { - do_path_lookup (mkdir_stub, &(state->loc)); - } else { - call_resume (mkdir_stub); - } - - return 0; -} - - -int32_t -server_rmdir_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - if (state->loc.parent == NULL) - state->loc.parent = inode_ref (loc->parent); - - if (state->loc.inode == NULL) - state->loc.inode = inode_ref (loc->inode); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": RMDIR \'%"PRId64"/%s\'", - frame->root->unique, state->par, state->bname); - - STACK_WIND (frame, - server_rmdir_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->rmdir, - loc); - return 0; -} - -/* - * server_rmdir - rmdir function for server protocol - * @frame: call frame - * @bound_xl: - * @params: - * - * not for external reference - */ -int32_t -server_rmdir (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *rmdir_stub = NULL; - gf_fop_rmdir_req_t *req = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - pathlen = STRLEN_0(req->path); - state->path = req->path; - state->par = ntoh64 (req->par); - state->bname = req->bname + pathlen; - } - - - ret = server_loc_fill (&(state->loc), state, - state->ino, state->par, state->bname, - state->path); - - rmdir_stub = fop_rmdir_stub (frame, - server_rmdir_resume, - &(state->loc)); - - if ((state->loc.parent == NULL) || - (state->loc.inode == NULL)) { - do_path_lookup (rmdir_stub, &(state->loc)); - } else { - call_resume (rmdir_stub); - } - - return 0; -} - - - -int32_t -server_chown_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - uid_t uid, - gid_t gid) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": CHOWN \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, server_chown_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->chown, - loc, uid, gid); - return 0; -} - - -/* - * server_chown - chown function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_chown (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *chown_stub = NULL; - gf_fop_chown_req_t *req = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->ino = ntoh64 (req->ino); - state->path = req->path; - pathlen = STRLEN_0(state->path); - state->uid = ntoh32 (req->uid); - state->gid = ntoh32 (req->gid); - } - - - ret = server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - chown_stub = fop_chown_stub (frame, - server_chown_resume, - &(state->loc), - state->uid, - state->gid); - - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { - do_path_lookup (chown_stub, &(state->loc)); - } else { - call_resume (chown_stub); - } - - return 0; -} - - -int32_t -server_chmod_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - mode_t mode) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": CHMOD \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_chmod_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->chmod, - loc, - mode); - return 0; - -} - -/* - * server_chmod - chmod function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_chmod (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *chmod_stub = NULL; - gf_fop_chmod_req_t *req = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - - state = CALL_STATE(frame); - { - state->ino = ntoh64 (req->ino); - state->path = req->path; - pathlen = STRLEN_0(state->path); - - state->mode = ntoh32 (req->mode); - } - - ret = server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - chmod_stub = fop_chmod_stub (frame, - server_chmod_resume, - &(state->loc), - state->mode); - - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { - do_path_lookup (chmod_stub, &(state->loc)); - } else { - call_resume (chmod_stub); - } - - return 0; -} - - -int32_t -server_utimens_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - struct timespec *tv) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": UTIMENS \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_utimens_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->utimens, - loc, - tv); - return 0; -} - -/* - * server_utimens - utimens function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_utimens (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *utimens_stub = NULL; - gf_fop_utimens_req_t *req = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->ino = ntoh64 (req->ino); - state->path = req->path; - pathlen = STRLEN_0(state->path); - - gf_timespec_to_timespec (req->tv, state->tv); - } - - - ret = server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - utimens_stub = fop_utimens_stub (frame, - server_utimens_resume, - &(state->loc), - state->tv); - - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { - do_path_lookup (utimens_stub, &(state->loc)); - } else { - call_resume (utimens_stub); - } - - return 0; -} - - - -int32_t -server_inodelk_resume (call_frame_t *frame, - xlator_t *this, - const char *volume, loc_t *loc, int32_t cmd, - struct flock *flock) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - if (state->loc.inode == NULL) { - state->loc.inode = inode_ref (loc->inode); - } - - if (state->loc.parent == NULL) { - state->loc.parent = inode_ref (loc->parent); - } - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": INODELK \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_inodelk_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->inodelk, - volume, loc, cmd, flock); - return 0; - -} - - -int32_t -server_inodelk (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *inodelk_stub = NULL; - gf_fop_inodelk_req_t *req = NULL; - server_state_t *state = NULL; - size_t pathlen = 0; - size_t vollen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->cmd = ntoh32 (req->cmd); - switch (state->cmd) { - case GF_LK_GETLK: - state->cmd = F_GETLK; - break; - case GF_LK_SETLK: - state->cmd = F_SETLK; - break; - case GF_LK_SETLKW: - state->cmd = F_SETLKW; - break; - } - - state->type = ntoh32 (req->type); - - pathlen = STRLEN_0(req->path); - vollen = STRLEN_0(req->volume + vollen); - - state->path = req->path; - state->volume = strdup (req->volume + vollen); - state->ino = ntoh64 (req->ino); - - gf_flock_to_flock (&req->flock, &state->flock); - - switch (state->type) { - case GF_LK_F_RDLCK: - state->flock.l_type = F_RDLCK; - break; - case GF_LK_F_WRLCK: - state->flock.l_type = F_WRLCK; - break; - case GF_LK_F_UNLCK: - state->flock.l_type = F_UNLCK; - break; - } - - } - - server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - inodelk_stub = fop_inodelk_stub (frame, - server_inodelk_resume, - state->volume, &state->loc, - state->cmd, &state->flock); - - if ((state->loc.parent == NULL) || - (state->loc.inode == NULL)) { - do_path_lookup (inodelk_stub, &(state->loc)); - } else { - call_resume (inodelk_stub); - } - - return 0; -} - - -int32_t -server_finodelk (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_finodelk_req_t *req = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->volume = strdup (req->volume); - - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->cmd = ntoh32 (req->cmd); - switch (state->cmd) { - case GF_LK_GETLK: - state->cmd = F_GETLK; - break; - case GF_LK_SETLK: - state->cmd = F_SETLK; - break; - case GF_LK_SETLKW: - state->cmd = F_SETLKW; - break; - } - - state->type = ntoh32 (req->type); - - gf_flock_to_flock (&req->flock, &state->flock); - - switch (state->type) { - case GF_LK_F_RDLCK: - state->flock.l_type = F_RDLCK; - break; - case GF_LK_F_WRLCK: - state->flock.l_type = F_WRLCK; - break; - case GF_LK_F_UNLCK: - state->flock.l_type = F_UNLCK; - break; - } - - } - - if (state->fd == NULL) { - gf_log (frame->this->name, GF_LOG_ERROR, - "fd - %"PRId64": unresolved fd", - state->fd_no); - - server_finodelk_cbk (frame, NULL, frame->this, - -1, EINVAL); - return -1; - } - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": FINODELK \'fd=%"PRId64" (%"PRId64")\'", - frame->root->unique, state->fd_no, state->fd->inode->ino); - - STACK_WIND (frame, server_finodelk_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->finodelk, - state->volume, state->fd, state->cmd, &state->flock); - return 0; -} - - -int32_t -server_entrylk_resume (call_frame_t *frame, - xlator_t *this, - const char *volume, loc_t *loc, const char *name, - entrylk_cmd cmd, entrylk_type type) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - if (state->loc.inode == NULL) - state->loc.inode = inode_ref (loc->inode); - - if ((state->loc.parent == NULL) && - (loc->parent)) - state->loc.parent = inode_ref (loc->parent); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": ENTRYLK \'%s (%"PRId64") \'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_entrylk_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->entrylk, - volume, loc, name, cmd, type); - return 0; - -} - -/* - * server_entrylk - entrylk function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_entrylk (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_entrylk_req_t *req = NULL; - server_state_t *state = NULL; - call_stub_t *entrylk_stub = NULL; - size_t pathlen = 0; - size_t namelen = 0; - size_t vollen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - pathlen = STRLEN_0(req->path); - - state->path = req->path; - state->ino = ntoh64 (req->ino); - namelen = ntoh64 (req->namelen); - if (namelen) - state->name = req->name + pathlen; - - vollen = STRLEN_0(req->volume + pathlen + namelen); - state->volume = strdup (req->volume + pathlen + namelen); - - state->cmd = ntoh32 (req->cmd); - state->type = ntoh32 (req->type); - } - - - server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - entrylk_stub = fop_entrylk_stub (frame, - server_entrylk_resume, - state->volume, - &state->loc, state->name, state->cmd, - state->type); - - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { - do_path_lookup (entrylk_stub, &(state->loc)); - } else { - call_resume (entrylk_stub); - } - - return 0; -} - - -int32_t -server_fentrylk (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_fentrylk_req_t *req = NULL; - server_state_t *state = NULL; - size_t namelen = 0; - size_t vollen = 0; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->cmd = ntoh32 (req->cmd); - state->type = ntoh32 (req->type); - namelen = ntoh64 (req->namelen); - - if (namelen) - state->name = req->name; - - vollen = STRLEN_0(req->volume + namelen); - state->volume = strdup (req->volume + namelen); - } - - if (state->fd == NULL) { - gf_log (frame->this->name, GF_LOG_ERROR, - "fd - %"PRId64": unresolved fd", - state->fd_no); - - server_fentrylk_cbk (frame, NULL, frame->this, - -1, EINVAL); - return -1; - } - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": FENTRYLK \'fd=%"PRId64" (%"PRId64")\'", - frame->root->unique, state->fd_no, state->fd->inode->ino); - - STACK_WIND (frame, server_fentrylk_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->fentrylk, - state->volume, state->fd, state->name, - state->cmd, state->type); - return 0; -} - - -int32_t -server_access_resume (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t mask) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": ACCESS \'%s (%"PRId64")\'", - frame->root->unique, state->path, state->ino); - - STACK_WIND (frame, - server_access_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->access, - loc, - mask); - return 0; -} - -/* - * server_access - access function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_access (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - call_stub_t *access_stub = NULL; - gf_fop_access_req_t *req = NULL; - server_state_t *state = NULL; - int32_t ret = -1; - size_t pathlen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - - state->mask = ntoh32 (req->mask); - - state->ino = ntoh64 (req->ino); - state->path = req->path; - pathlen = STRLEN_0(state->path); - - ret = server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, state->path); - - access_stub = fop_access_stub (frame, - server_access_resume, - &(state->loc), - state->mask); - - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { - do_path_lookup (access_stub, &(state->loc)); - } else { - call_resume (access_stub); - } - - return 0; -} - - -int32_t -server_symlink_resume (call_frame_t *frame, - xlator_t *this, - const char *linkname, - loc_t *loc) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - if (state->loc.parent == NULL) - state->loc.parent = inode_ref (loc->parent); - - state->loc.inode = inode_new (BOUND_XL(frame)->itable); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": SYMLINK \'%"PRId64"/%s \'", - frame->root->unique, state->par, state->bname); - - STACK_WIND (frame, - server_symlink_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->symlink, - linkname, - &(state->loc)); - - return 0; -} - -/* - * server_symlink- symlink function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ - -int32_t -server_symlink (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - server_state_t *state = NULL; - gf_fop_symlink_req_t *req = NULL; - call_stub_t *symlink_stub = NULL; - int32_t ret = -1; - size_t pathlen = 0; - size_t baselen = 0; - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - pathlen = STRLEN_0(req->path); - baselen = STRLEN_0(req->bname + pathlen); - - state->par = ntoh64 (req->par); - state->path = req->path; - state->bname = req->bname + pathlen; - - state->name = (req->linkname + pathlen + baselen); - } - - ret = server_loc_fill (&(state->loc), state, - 0, state->par, state->bname, - state->path); - - symlink_stub = fop_symlink_stub (frame, server_symlink_resume, - state->name, &(state->loc)); - - if (state->loc.parent == NULL) { - do_path_lookup (symlink_stub, &(state->loc)); - } else { - call_resume (symlink_stub); - } - - return 0; -} - -int32_t -server_link_resume (call_frame_t *frame, - xlator_t *this, - loc_t *oldloc, - loc_t *newloc) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - if (state->loc.parent == NULL) - state->loc.parent = inode_ref (oldloc->parent); - - if (state->loc.inode == NULL) { - state->loc.inode = inode_ref (oldloc->inode); - } else if (state->loc.inode != oldloc->inode) { - if (state->loc.inode) - inode_unref (state->loc.inode); - state->loc.inode = inode_ref (oldloc->inode); - } - - if (state->loc2.parent == NULL) - state->loc2.parent = inode_ref (newloc->parent); - - state->loc2.inode = inode_ref (state->loc.inode); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": LINK \'%"PRId64"/%s ==> %s (%"PRId64")\'", - frame->root->unique, state->par2, state->bname2, - state->path, state->ino); - - STACK_WIND (frame, - server_link_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->link, - &(state->loc), - &(state->loc2)); - return 0; -} - -/* - * server_link - link function for server protocol - * @frame: call frame - * @bound_xl: - * @params: - * - * not for external reference - */ -int32_t -server_link (call_frame_t *frame, - xlator_t *this, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_link_req_t *req = NULL; - server_state_t *state = NULL; - call_stub_t *link_stub = NULL; - int32_t ret = -1; - size_t oldpathlen = 0; - size_t newpathlen = 0; - size_t newbaselen = 0; - - req = gf_param (hdr); - - state = CALL_STATE(frame); - { - oldpathlen = STRLEN_0(req->oldpath); - newpathlen = STRLEN_0(req->newpath + oldpathlen); - newbaselen = STRLEN_0(req->newbname + oldpathlen + newpathlen); - - state->path = req->oldpath; - state->path2 = req->newpath + oldpathlen; - state->bname2 = req->newbname + oldpathlen + newpathlen; - state->ino = ntoh64 (req->oldino); - state->par2 = ntoh64 (req->newpar); - } - - ret = server_loc_fill (&(state->loc), state, - state->ino, 0, NULL, - state->path); - ret = server_loc_fill (&(state->loc2), state, - 0, state->par2, state->bname2, - state->path2); - - link_stub = fop_link_stub (frame, server_link_resume, - &(state->loc), &(state->loc2)); - - if ((state->loc.parent == NULL) || - (state->loc.inode == NULL)) { - do_path_lookup (link_stub, &(state->loc)); - } else if (state->loc2.parent == NULL) { - do_path_lookup (link_stub, &(state->loc2)); - } else { - call_resume (link_stub); - } - - return 0; -} - - -int32_t -server_rename_resume (call_frame_t *frame, - xlator_t *this, - loc_t *oldloc, - loc_t *newloc) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - if (state->loc.parent == NULL) - state->loc.parent = inode_ref (oldloc->parent); - - if (state->loc.inode == NULL) { - state->loc.inode = inode_ref (oldloc->inode); - } - - if (state->loc2.parent == NULL) - state->loc2.parent = inode_ref (newloc->parent); - - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": RENAME %s (%"PRId64"/%s) ==> %s (%"PRId64"/%s)", - frame->root->unique, state->path, state->par, state->bname, - state->path2, state->par2, state->bname2); - - STACK_WIND (frame, - server_rename_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->rename, - &(state->loc), - &(state->loc2)); - return 0; -} - -/* - * server_rename - rename function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ -int32_t -server_rename (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_fop_rename_req_t *req = NULL; - server_state_t *state = NULL; - call_stub_t *rename_stub = NULL; - int32_t ret = -1; - size_t oldpathlen = 0; - size_t oldbaselen = 0; - size_t newpathlen = 0; - size_t newbaselen = 0; - - req = gf_param (hdr); - - state = CALL_STATE(frame); - { - oldpathlen = STRLEN_0(req->oldpath); - oldbaselen = STRLEN_0(req->oldbname + oldpathlen); - newpathlen = STRLEN_0(req->newpath + oldpathlen + oldbaselen); - newbaselen = STRLEN_0(req->newbname + oldpathlen + - oldbaselen + newpathlen); - - state->path = req->oldpath; - state->bname = req->oldbname + oldpathlen; - state->path2 = req->newpath + oldpathlen + oldbaselen; - state->bname2 = (req->newbname + oldpathlen + oldbaselen + - newpathlen); - - state->par = ntoh64 (req->oldpar); - state->par2 = ntoh64 (req->newpar); - } - - ret = server_loc_fill (&(state->loc), state, - 0, state->par, state->bname, - state->path); - ret = server_loc_fill (&(state->loc2), state, - 0, state->par2, state->bname2, - state->path2); - - rename_stub = fop_rename_stub (frame, - server_rename_resume, - &(state->loc), - &(state->loc2)); - - if ((state->loc.parent == NULL) || - (state->loc.inode == NULL)){ - do_path_lookup (rename_stub, &(state->loc)); - } else if ((state->loc2.parent == NULL)){ - do_path_lookup (rename_stub, &(state->loc2)); - } else { - /* we have found inode for both oldpath and newpath in - * inode cache. lets continue with fops->rename() */ - call_resume (rename_stub); - } - - return 0; -} - - -/* - * server_lk - lk function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - * not for external reference - */ - -int32_t -server_lk (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - struct flock lock = {0, }; - gf_fop_lk_req_t *req = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - { - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->cmd = ntoh32 (req->cmd); - state->type = ntoh32 (req->type); - } - - - if (state->fd == NULL) { - gf_log (frame->this->name, GF_LOG_ERROR, - "fd - %"PRId64": unresolved fd", - state->fd_no); - - server_lk_cbk (frame, NULL, frame->this, - -1, EINVAL, NULL); - - goto out; - } - - switch (state->cmd) { - case GF_LK_GETLK: - state->cmd = F_GETLK; - break; - case GF_LK_SETLK: - state->cmd = F_SETLK; - break; - case GF_LK_SETLKW: - state->cmd = F_SETLKW; - break; - } - - switch (state->type) { - case GF_LK_F_RDLCK: - lock.l_type = F_RDLCK; - break; - case GF_LK_F_WRLCK: - lock.l_type = F_WRLCK; - break; - case GF_LK_F_UNLCK: - lock.l_type = F_UNLCK; - break; - default: - gf_log (bound_xl->name, GF_LOG_ERROR, - "fd - %"PRId64" (%"PRId64"): Unknown lock type: %"PRId32"!", - state->fd_no, state->fd->inode->ino, state->type); - break; - } - - gf_flock_to_flock (&req->flock, &lock); - - gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG, - "%"PRId64": LK \'fd=%"PRId64" (%"PRId64")\'", - frame->root->unique, state->fd_no, state->fd->inode->ino); - - STACK_WIND (frame, server_lk_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->lk, - state->fd, state->cmd, &lock); - -out: - return 0; -} - - -/* - * server_writedir - - * - * @frame: - * @bound_xl: - * @params: - * - */ -int32_t -server_setdents (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - server_connection_t *conn = NULL; - gf_fop_setdents_req_t *req = NULL; - server_state_t *state = NULL; - dir_entry_t *entry = NULL; - dir_entry_t *trav = NULL; - dir_entry_t *prev = NULL; - int32_t count = 0; - int32_t i = 0; - int32_t bread = 0; - char *ender = NULL; - char *buffer_ptr = NULL; - char tmp_buf[512] = {0,}; - - conn = SERVER_CONNECTION(frame); - - req = gf_param (hdr); - state = CALL_STATE(frame); - - state->fd_no = ntoh64 (req->fd); - if (state->fd_no >= 0) - state->fd = gf_fd_fdptr_get (conn->fdtable, - state->fd_no); - - state->nr_count = ntoh32 (req->count); - - if (state->fd == NULL) { - gf_log (frame->this->name, GF_LOG_ERROR, - "fd - %"PRId64": unresolved fd", - state->fd_no); - - server_setdents_cbk (frame, NULL, frame->this, - -1, EINVAL); - - goto out; - } - - if (iobuf == NULL) { - gf_log (frame->this->name, GF_LOG_ERROR, - "fd - %"PRId64" (%"PRId64"): received a null buffer, " - "returning EINVAL", - state->fd_no, state->fd->inode->ino); - - server_setdents_cbk (frame, NULL, frame->this, - -1, EINVAL); - - goto out; - } - - entry = CALLOC (1, sizeof (dir_entry_t)); - ERR_ABORT (entry); - prev = entry; - buffer_ptr = iobuf->ptr; - - for (i = 0; i < state->nr_count ; i++) { - bread = 0; - trav = CALLOC (1, sizeof (dir_entry_t)); - ERR_ABORT (trav); - - ender = strchr (buffer_ptr, '/'); - if (!ender) - break; - count = ender - buffer_ptr; - trav->name = CALLOC (1, count + 2); - ERR_ABORT (trav->name); - - strncpy (trav->name, buffer_ptr, count); - bread = count + 1; - buffer_ptr += bread; - - ender = strchr (buffer_ptr, '\n'); - if (!ender) - break; - count = ender - buffer_ptr; - strncpy (tmp_buf, buffer_ptr, count); - bread = count + 1; - buffer_ptr += bread; - - /* TODO: use str_to_stat instead */ - { - uint64_t dev; - uint64_t ino; - uint32_t mode; - uint32_t nlink; - uint32_t uid; - uint32_t gid; - uint64_t rdev; - uint64_t size; - uint32_t blksize; - uint64_t blocks; - uint32_t atime; - uint32_t atime_nsec; - uint32_t mtime; - uint32_t mtime_nsec; - uint32_t ctime; - uint32_t ctime_nsec; - - sscanf (tmp_buf, GF_STAT_PRINT_FMT_STR, - &dev, - &ino, - &mode, - &nlink, - &uid, - &gid, - &rdev, - &size, - &blksize, - &blocks, - &atime, - &atime_nsec, - &mtime, - &mtime_nsec, - &ctime, - &ctime_nsec); - - trav->buf.st_dev = dev; - trav->buf.st_ino = ino; - trav->buf.st_mode = mode; - trav->buf.st_nlink = nlink; - trav->buf.st_uid = uid; - trav->buf.st_gid = gid; - trav->buf.st_rdev = rdev; - trav->buf.st_size = size; - trav->buf.st_blksize = blksize; - trav->buf.st_blocks = blocks; - - trav->buf.st_atime = atime; - trav->buf.st_mtime = mtime; - trav->buf.st_ctime = ctime; - - ST_ATIM_NSEC_SET(&trav->buf, atime_nsec); - ST_MTIM_NSEC_SET(&trav->buf, mtime_nsec); - ST_CTIM_NSEC_SET(&trav->buf, ctime_nsec); - - } - - ender = strchr (buffer_ptr, '\n'); - if (!ender) - break; - count = ender - buffer_ptr; - *ender = '\0'; - if (S_ISLNK (trav->buf.st_mode)) { - trav->link = strdup (buffer_ptr); - } else - trav->link = ""; - bread = count + 1; - buffer_ptr += bread; - - prev->next = trav; - prev = trav; - } - - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": SETDENTS \'fd=%"PRId64" (%"PRId64"); count=%"PRId64, - frame->root->unique, state->fd_no, state->fd->inode->ino, - (int64_t)state->nr_count); - - STACK_WIND (frame, - server_setdents_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->setdents, - state->fd, - state->flags, - entry, - state->nr_count); - - - /* Free the variables allocated in this fop here */ - trav = entry->next; - prev = entry; - while (trav) { - prev->next = trav->next; - FREE (trav->name); - if (S_ISLNK (trav->buf.st_mode)) - FREE (trav->link); - FREE (trav); - trav = prev->next; - } - FREE (entry); - -out: - if (iobuf) - iobuf_unref (iobuf); - return 0; -} - - - -/* xxx_MOPS */ - - -int -_volfile_update_checksum (xlator_t *this, char *key, uint32_t checksum) -{ - server_conf_t *conf = NULL; - struct _volfile_ctx *temp_volfile = NULL; - - conf = this->private; - temp_volfile = conf->volfile; - - while (temp_volfile) { - if ((NULL == key) && (NULL == temp_volfile->key)) - break; - if ((NULL == key) || (NULL == temp_volfile->key)) { - temp_volfile = temp_volfile->next; - continue; - } - if (strcmp (temp_volfile->key, key) == 0) - break; - temp_volfile = temp_volfile->next; - } - - if (!temp_volfile) { - temp_volfile = CALLOC (1, sizeof (struct _volfile_ctx)); - - temp_volfile->next = conf->volfile; - temp_volfile->key = (key)? strdup (key): NULL; - temp_volfile->checksum = checksum; - - conf->volfile = temp_volfile; - goto out; - } - - if (temp_volfile->checksum != checksum) { - gf_log (this->name, GF_LOG_CRITICAL, - "the volume file got modified between earlier access " - "and now, this may lead to inconsistency between " - "clients, advised to remount client"); - temp_volfile->checksum = checksum; - } - - out: - return 0; -} - - -char * -build_volfile_path (xlator_t *this, char *key) -{ - int ret = -1; - char *filename = NULL; - char data_key[256] = {0,}; - - /* Inform users that this option is changed now */ - ret = dict_get_str (this->options, "client-volume-filename", - &filename); - if (ret == 0) { - gf_log (this->name, GF_LOG_WARNING, - "option 'client-volume-filename' is changed to " - "'volume-filename.<key>' which now takes 'key' as an " - "option to choose/fetch different files from server. " - "Refer documentation or contact developers for more " - "info. Currently defaulting to given file '%s'", - filename); - } - - if (key && !filename) { - sprintf (data_key, "volume-filename.%s", key); - ret = dict_get_str (this->options, data_key, &filename); - if (ret < 0) { - gf_log (this->name, GF_LOG_ERROR, - "failed to get corresponding volume file " - "for the key '%s'.", key); - } - } - - if (!filename) { - ret = dict_get_str (this->options, - "volume-filename.default", &filename); - if (ret < 0) { - gf_log (this->name, GF_LOG_DEBUG, - "no default volume filename given, " - "defaulting to %s", DEFAULT_VOLUME_FILE_PATH); - - filename = DEFAULT_VOLUME_FILE_PATH; - } - } - - return filename; -} - -int -_validate_volfile_checksum (xlator_t *this, char *key, - uint32_t checksum) -{ - char *filename = NULL; - server_conf_t *conf = NULL; - struct _volfile_ctx *temp_volfile = NULL; - int ret = 0; - uint32_t local_checksum = 0; - - conf = this->private; - temp_volfile = conf->volfile; - - if (!checksum) - goto out; - - if (!temp_volfile) { - filename = build_volfile_path (this, key); - if (NULL == filename) - goto out; - ret = open (filename, O_RDONLY); - if (-1 == ret) { - ret = 0; - gf_log (this->name, GF_LOG_DEBUG, - "failed to open volume file (%s) : %s", - filename, strerror (errno)); - goto out; - } - get_checksum_for_file (ret, &local_checksum); - _volfile_update_checksum (this, key, local_checksum); - close (ret); - } - - temp_volfile = conf->volfile; - while (temp_volfile) { - if ((NULL == key) && (NULL == temp_volfile->key)) - break; - if (strcmp (temp_volfile->key, key) == 0) - break; - temp_volfile = temp_volfile->next; - } - - if (!temp_volfile) - goto out; - - if ((temp_volfile->checksum) && - (checksum != temp_volfile->checksum)) - ret = -1; - - out: - return ret; -} - -/* Management Calls */ -/* - * mop_getspec - getspec function for server protocol - * @frame: call frame - * @bound_xl: - * @params: - * - */ -int32_t -mop_getspec (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_hdr_common_t *_hdr = NULL; - gf_mop_getspec_rsp_t *rsp = NULL; - int32_t ret = -1; - int32_t op_errno = ENOENT; - int32_t gf_errno = 0; - int32_t spec_fd = -1; - size_t file_len = 0; - size_t _hdrlen = 0; - char *filename = NULL; - struct stat stbuf = {0,}; - - gf_mop_getspec_req_t *req = NULL; - uint32_t checksum = 0; - uint32_t flags = 0; - uint32_t keylen = 0; - char *key = NULL; - server_conf_t *conf = NULL; - - req = gf_param (hdr); - flags = ntoh32 (req->flags); - keylen = ntoh32 (req->keylen); - if (keylen) { - key = req->key; - } - - conf = frame->this->private; - - filename = build_volfile_path (frame->this, key); - if (filename) { - /* to allocate the proper buffer to hold the file data */ - ret = stat (filename, &stbuf); - if (ret < 0){ - gf_log (frame->this->name, GF_LOG_ERROR, - "Unable to stat %s (%s)", - filename, strerror (errno)); - goto fail; - } - - ret = open (filename, O_RDONLY); - spec_fd = ret; - if (spec_fd < 0) { - gf_log (frame->this->name, GF_LOG_ERROR, - "Unable to open %s (%s)", - filename, strerror (errno)); - goto fail; - } - ret = 0; - file_len = stbuf.st_size; - if (conf->verify_volfile_checksum) { - get_checksum_for_file (spec_fd, &checksum); - _volfile_update_checksum (frame->this, key, checksum); - } - } else { - errno = ENOENT; - } - -fail: - op_errno = errno; - - _hdrlen = gf_hdr_len (rsp, file_len + 1); - _hdr = gf_hdr_new (rsp, file_len + 1); - rsp = gf_param (_hdr); - - _hdr->rsp.op_ret = hton32 (ret); - gf_errno = gf_errno_to_error (op_errno); - _hdr->rsp.op_errno = hton32 (gf_errno); - - if (file_len) { - ret = read (spec_fd, rsp->spec, file_len); - close (spec_fd); - } - protocol_server_reply (frame, GF_OP_TYPE_MOP_REPLY, GF_MOP_GETSPEC, - _hdr, _hdrlen, NULL, 0, NULL); - - return 0; -} - -int32_t -server_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) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_checksum_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - - hdrlen = gf_hdr_len (rsp, ZR_FILENAME_MAX + 1 + ZR_FILENAME_MAX + 1); - hdr = gf_hdr_new (rsp, ZR_FILENAME_MAX + 1 + ZR_FILENAME_MAX + 1); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - if (op_ret >= 0) { - memcpy (rsp->fchecksum, fchecksum, ZR_FILENAME_MAX); - rsp->fchecksum[ZR_FILENAME_MAX] = '\0'; - memcpy (rsp->dchecksum + ZR_FILENAME_MAX, - dchecksum, ZR_FILENAME_MAX); - rsp->dchecksum[ZR_FILENAME_MAX + ZR_FILENAME_MAX] = '\0'; - } - - protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_CHECKSUM, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -int32_t -server_checksum (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - loc_t loc = {0,}; - int32_t flag = 0; - gf_fop_checksum_req_t *req = NULL; - - req = gf_param (hdr); - - loc.path = req->path; - loc.ino = ntoh64 (req->ino); - loc.inode = NULL; - flag = ntoh32 (req->flag); - - gf_log (bound_xl->name, GF_LOG_DEBUG, - "%"PRId64": CHECKSUM \'%s (%"PRId64")\'", - frame->root->unique, loc.path, loc.ino); - - STACK_WIND (frame, - server_checksum_cbk, - BOUND_XL(frame), - BOUND_XL(frame)->fops->checksum, - &loc, - flag); - - return 0; -} - - -/* - * mop_unlock - unlock management function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - */ -int32_t -mop_getvolume (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - return 0; -} - -struct __get_xl_struct { - const char *name; - xlator_t *reply; -}; - -void __check_and_set (xlator_t *each, - void *data) -{ - if (!strcmp (each->name, - ((struct __get_xl_struct *) data)->name)) - ((struct __get_xl_struct *) data)->reply = each; -} - -static xlator_t * -get_xlator_by_name (xlator_t *some_xl, - const char *name) -{ - struct __get_xl_struct get = { - .name = name, - .reply = NULL - }; - - xlator_foreach (some_xl, __check_and_set, &get); - - return get.reply; -} - - -/* - * mop_setvolume - setvolume management function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - */ -int -mop_setvolume (call_frame_t *frame, xlator_t *bound_xl, - gf_hdr_common_t *req_hdr, size_t req_hdrlen, - struct iobuf *iobuf) -{ - server_connection_t *conn = NULL; - server_conf_t *conf = NULL; - gf_hdr_common_t *rsp_hdr = NULL; - gf_mop_setvolume_req_t *req = NULL; - gf_mop_setvolume_rsp_t *rsp = NULL; - peer_info_t *peerinfo = NULL; - int32_t ret = -1; - int32_t op_ret = -1; - int32_t op_errno = EINVAL; - int32_t gf_errno = 0; - dict_t *reply = NULL; - dict_t *config_params = NULL; - dict_t *params = NULL; - char *name = NULL; - char *version = NULL; - char *process_uuid = NULL; - xlator_t *xl = NULL; - transport_t *trans = NULL; - size_t rsp_hdrlen = -1; - size_t dict_len = -1; - size_t req_dictlen = -1; - char *msg = NULL; - char *volfile_key = NULL; - uint32_t checksum = 0; - - params = dict_new (); - reply = dict_new (); - - req = gf_param (req_hdr); - req_dictlen = ntoh32 (req->dict_len); - ret = dict_unserialize (req->buf, req_dictlen, ¶ms); - - config_params = dict_copy_with_ref (frame->this->options, NULL); - trans = TRANSPORT_FROM_FRAME(frame); - conf = SERVER_CONF(frame); - - if (ret < 0) { - ret = dict_set_str (reply, "ERROR", - "Internal error: failed to unserialize " - "request dictionary"); - if (ret < 0) - gf_log (bound_xl->name, GF_LOG_ERROR, - "failed to set error msg \"%s\"", - "Internal error: failed to unserialize " - "request dictionary"); - - op_ret = -1; - op_errno = EINVAL; - goto fail; - } - - ret = dict_get_str (params, "process-uuid", &process_uuid); - if (ret < 0) { - ret = dict_set_str (reply, "ERROR", - "UUID not specified"); - if (ret < 0) - gf_log (bound_xl->name, GF_LOG_ERROR, - "failed to set error msg"); - - op_ret = -1; - op_errno = EINVAL; - goto fail; - } - - - conn = server_connection_get (frame->this, process_uuid); - if (trans->xl_private != conn) - trans->xl_private = conn; - - ret = dict_get_str (params, "version", &version); - if (ret < 0) { - ret = dict_set_str (reply, "ERROR", - "No version number specified"); - if (ret < 0) - gf_log (trans->xl->name, GF_LOG_ERROR, - "failed to set error msg"); - - op_ret = -1; - op_errno = EINVAL; - goto fail; - } - - ret = strcmp (version, PACKAGE_VERSION); - if (ret != 0) { - asprintf (&msg, - "Version mismatch: client(%s) Vs server (%s)", - version, PACKAGE_VERSION); - ret = dict_set_dynstr (reply, "ERROR", msg); - if (ret < 0) - gf_log (trans->xl->name, GF_LOG_ERROR, - "failed to set error msg"); - - op_ret = -1; - op_errno = EINVAL; - goto fail; - } - - ret = dict_get_str (params, - "remote-subvolume", &name); - if (ret < 0) { - ret = dict_set_str (reply, "ERROR", - "No remote-subvolume option specified"); - if (ret < 0) - gf_log (trans->xl->name, GF_LOG_ERROR, - "failed to set error msg"); - - op_ret = -1; - op_errno = EINVAL; - goto fail; - } - - xl = get_xlator_by_name (frame->this, name); - if (xl == NULL) { - asprintf (&msg, "remote-subvolume \"%s\" is not found", name); - ret = dict_set_dynstr (reply, "ERROR", msg); - if (ret < 0) - gf_log (trans->xl->name, GF_LOG_ERROR, - "failed to set error msg"); - - op_ret = -1; - op_errno = ENOENT; - goto fail; - } - - if (conf->verify_volfile_checksum) { - ret = dict_get_uint32 (params, "volfile-checksum", &checksum); - if (ret == 0) { - ret = dict_get_str (params, "volfile-key", - &volfile_key); - - ret = _validate_volfile_checksum (trans->xl, - volfile_key, - checksum); - if (-1 == ret) { - ret = dict_set_str (reply, "ERROR", - "volume-file checksum " - "varies from earlier " - "access"); - if (ret < 0) - gf_log (trans->xl->name, GF_LOG_ERROR, - "failed to set error msg"); - - op_ret = -1; - op_errno = ESTALE; - goto fail; - } - } - } - - - peerinfo = &trans->peerinfo; - ret = dict_set_static_ptr (params, "peer-info", peerinfo); - if (ret < 0) - gf_log (trans->xl->name, GF_LOG_ERROR, - "failed to set peer-info"); - - if (conf->auth_modules == NULL) { - gf_log (trans->xl->name, GF_LOG_ERROR, - "Authentication module not initialized"); - } - - ret = gf_authenticate (params, config_params, - conf->auth_modules); - if (ret == AUTH_ACCEPT) { - gf_log (trans->xl->name, GF_LOG_INFO, - "accepted client from %s", - peerinfo->identifier); - op_ret = 0; - conn->bound_xl = xl; - ret = dict_set_str (reply, "ERROR", "Success"); - if (ret < 0) - gf_log (trans->xl->name, GF_LOG_ERROR, - "failed to set error msg"); - } else { - gf_log (trans->xl->name, GF_LOG_ERROR, - "Cannot authenticate client from %s", - peerinfo->identifier); - op_ret = -1; - op_errno = EACCES; - ret = dict_set_str (reply, "ERROR", "Authentication failed"); - if (ret < 0) - gf_log (bound_xl->name, GF_LOG_ERROR, - "failed to set error msg"); - - goto fail; - } - - if (conn->bound_xl == NULL) { - ret = dict_set_str (reply, "ERROR", - "Check volfile and handshake " - "options in protocol/client"); - if (ret < 0) - gf_log (trans->xl->name, GF_LOG_ERROR, - "failed to set error msg"); - - op_ret = -1; - op_errno = EACCES; - goto fail; - } - - if ((conn->bound_xl != NULL) && - (ret >= 0) && - (conn->bound_xl->itable == NULL)) { - /* create inode table for this bound_xl, if one doesn't - already exist */ - int32_t lru_limit = 1024; - - lru_limit = INODE_LRU_LIMIT (frame->this); - - gf_log (trans->xl->name, GF_LOG_DEBUG, - "creating inode table with lru_limit=%"PRId32", " - "xlator=%s", lru_limit, conn->bound_xl->name); - - conn->bound_xl->itable = - inode_table_new (lru_limit, - conn->bound_xl); - } - - ret = dict_set_str (reply, "process-uuid", - xl->ctx->process_uuid); - -fail: - dict_len = dict_serialized_length (reply); - if (dict_len < 0) { - gf_log (xl->name, GF_LOG_ERROR, - "failed to get serialized length of reply dict"); - op_ret = -1; - op_errno = EINVAL; - dict_len = 0; - } - - rsp_hdr = gf_hdr_new (rsp, dict_len); - rsp_hdrlen = gf_hdr_len (rsp, dict_len); - rsp = gf_param (rsp_hdr); - - if (dict_len) { - ret = dict_serialize (reply, rsp->buf); - if (ret < 0) { - gf_log (xl->name, GF_LOG_ERROR, - "failed to serialize reply dict"); - op_ret = -1; - op_errno = -ret; - } - } - rsp->dict_len = hton32 (dict_len); - - rsp_hdr->rsp.op_ret = hton32 (op_ret); - gf_errno = gf_errno_to_error (op_errno); - rsp_hdr->rsp.op_errno = hton32 (gf_errno); - - protocol_server_reply (frame, GF_OP_TYPE_MOP_REPLY, GF_MOP_SETVOLUME, - rsp_hdr, rsp_hdrlen, NULL, 0, NULL); - - dict_unref (params); - dict_unref (reply); - dict_unref (config_params); - - return 0; -} - -/* - * server_mop_stats_cbk - stats callback for server management operation - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * @stats:err - * - * not for external reference - */ - -int32_t -server_mop_stats_cbk (call_frame_t *frame, - void *cookie, - xlator_t *xl, - int32_t ret, - int32_t op_errno, - struct xlator_stats *stats) -{ - /* TODO: get this information from somewhere else, not extern */ - gf_hdr_common_t *hdr = NULL; - gf_mop_stats_rsp_t *rsp = NULL; - char buffer[256] = {0,}; - int64_t glusterfsd_stats_nr_clients = 0; - size_t hdrlen = 0; - size_t buf_len = 0; - int32_t gf_errno = 0; - - if (ret >= 0) { - sprintf (buffer, - "%"PRIx64",%"PRIx64",%"PRIx64 - ",%"PRIx64",%"PRIx64",%"PRIx64 - ",%"PRIx64",%"PRIx64"\n", - stats->nr_files, - stats->disk_usage, - stats->free_disk, - stats->total_disk_size, - stats->read_usage, - stats->write_usage, - stats->disk_speed, - glusterfsd_stats_nr_clients); - - buf_len = strlen (buffer); - } - - hdrlen = gf_hdr_len (rsp, buf_len + 1); - hdr = gf_hdr_new (rsp, buf_len + 1); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (ret); - gf_errno = gf_errno_to_error (op_errno); - hdr->rsp.op_errno = hton32 (gf_errno); - - strcpy (rsp->buf, buffer); - - protocol_server_reply (frame, GF_OP_TYPE_MOP_REPLY, GF_MOP_STATS, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - - -/* - * mop_unlock - unlock management function for server protocol - * @frame: call frame - * @bound_xl: - * @params: parameter dictionary - * - */ -static int32_t -mop_stats (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - int32_t flag = 0; - gf_mop_stats_req_t *req = NULL; - - req = gf_param (hdr); - - flag = ntoh32 (req->flags); - - STACK_WIND (frame, - server_mop_stats_cbk, - bound_xl, - bound_xl->mops->stats, - flag); - - return 0; -} - -int32_t -mop_ping (call_frame_t *frame, - xlator_t *bound_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf) -{ - gf_hdr_common_t *rsp_hdr = NULL; - gf_mop_ping_rsp_t *rsp = NULL; - size_t rsp_hdrlen = 0; - - rsp_hdrlen = gf_hdr_len (rsp, 0); - rsp_hdr = gf_hdr_new (rsp, 0); - - hdr->rsp.op_ret = 0; - - protocol_server_reply (frame, GF_OP_TYPE_MOP_REPLY, GF_MOP_PING, - rsp_hdr, rsp_hdrlen, NULL, 0, NULL); - - return 0; -} -/* - * unknown_op_cbk - This function is called when a opcode for unknown - * type is called. Helps to keep the backward/forward - * compatiblity - * @frame: call frame - * @type: - * @opcode: - * - */ - -int32_t -unknown_op_cbk (call_frame_t *frame, - int32_t type, - int32_t opcode) -{ - gf_hdr_common_t *hdr = NULL; - gf_fop_flush_rsp_t *rsp = NULL; - size_t hdrlen = 0; - int32_t gf_errno = 0; - hdrlen = gf_hdr_len (rsp, 0); - hdr = gf_hdr_new (rsp, 0); - rsp = gf_param (hdr); - - hdr->rsp.op_ret = hton32 (-1); - gf_errno = gf_errno_to_error (ENOSYS); - hdr->rsp.op_errno = hton32 (gf_errno); - - protocol_server_reply (frame, type, opcode, - hdr, hdrlen, NULL, 0, NULL); - - return 0; -} - -/* - * get_frame_for_transport - get call frame for specified transport object - * - * @trans: transport object - * - */ -static call_frame_t * -get_frame_for_transport (transport_t *trans) -{ - call_frame_t *frame = NULL; - call_pool_t *pool = NULL; - server_connection_t *conn = NULL; - server_state_t *state = NULL;; - - GF_VALIDATE_OR_GOTO("server", trans, out); - - if (trans->xl && trans->xl->ctx) - pool = trans->xl->ctx->pool; - GF_VALIDATE_OR_GOTO("server", pool, out); - - frame = create_frame (trans->xl, pool); - GF_VALIDATE_OR_GOTO("server", frame, out); - - state = CALLOC (1, sizeof (*state)); - GF_VALIDATE_OR_GOTO("server", state, out); - - conn = trans->xl_private; - if (conn) { - if (conn->bound_xl) - state->itable = conn->bound_xl->itable; - state->bound_xl = conn->bound_xl; - } - - state->trans = transport_ref (trans); - - frame->root->trans = conn; - frame->root->state = state; /* which socket */ - frame->root->unique = 0; /* which call */ - -out: - return frame; -} - -/* - * get_frame_for_call - create a frame into the capable of - * generating and replying the reply packet by itself. - * By making a call with this frame, the last UNWIND - * function will have all needed state from its - * frame_t->root to send reply. - * @trans: - * @blk: - * @params: - * - * not for external reference - */ -static call_frame_t * -get_frame_for_call (transport_t *trans, gf_hdr_common_t *hdr) -{ - call_frame_t *frame = NULL; - - frame = get_frame_for_transport (trans); - - frame->root->op = ntoh32 (hdr->op); - frame->root->type = ntoh32 (hdr->type); - - frame->root->uid = ntoh32 (hdr->req.uid); - frame->root->unique = ntoh64 (hdr->callid); /* which call */ - frame->root->gid = ntoh32 (hdr->req.gid); - frame->root->pid = ntoh32 (hdr->req.pid); - - return frame; -} - -/* - * prototype of operations function for each of mop and - * fop at server protocol level - * - * @frame: call frame pointer - * @bound_xl: the xlator that this frame is bound to - * @params: parameters dictionary - * - * to be used by protocol interpret, _not_ for exterenal reference - */ -typedef int32_t (*gf_op_t) (call_frame_t *frame, xlator_t *bould_xl, - gf_hdr_common_t *hdr, size_t hdrlen, - struct iobuf *iobuf); - - -static gf_op_t gf_fops[] = { - [GF_FOP_STAT] = server_stat, - [GF_FOP_READLINK] = server_readlink, - [GF_FOP_MKNOD] = server_mknod, - [GF_FOP_MKDIR] = server_mkdir, - [GF_FOP_UNLINK] = server_unlink, - [GF_FOP_RMDIR] = server_rmdir, - [GF_FOP_SYMLINK] = server_symlink, - [GF_FOP_RENAME] = server_rename, - [GF_FOP_LINK] = server_link, - [GF_FOP_CHMOD] = server_chmod, - [GF_FOP_CHOWN] = server_chown, - [GF_FOP_TRUNCATE] = server_truncate, - [GF_FOP_OPEN] = server_open, - [GF_FOP_READ] = server_readv, - [GF_FOP_WRITE] = server_writev, - [GF_FOP_STATFS] = server_statfs, - [GF_FOP_FLUSH] = server_flush, - [GF_FOP_FSYNC] = server_fsync, - [GF_FOP_SETXATTR] = server_setxattr, - [GF_FOP_GETXATTR] = server_getxattr, - [GF_FOP_FGETXATTR] = server_fgetxattr, - [GF_FOP_FSETXATTR] = server_fsetxattr, - [GF_FOP_REMOVEXATTR] = server_removexattr, - [GF_FOP_OPENDIR] = server_opendir, - [GF_FOP_GETDENTS] = server_getdents, - [GF_FOP_FSYNCDIR] = server_fsyncdir, - [GF_FOP_ACCESS] = server_access, - [GF_FOP_CREATE] = server_create, - [GF_FOP_FTRUNCATE] = server_ftruncate, - [GF_FOP_FSTAT] = server_fstat, - [GF_FOP_LK] = server_lk, - [GF_FOP_UTIMENS] = server_utimens, - [GF_FOP_FCHMOD] = server_fchmod, - [GF_FOP_FCHOWN] = server_fchown, - [GF_FOP_LOOKUP] = server_lookup, - [GF_FOP_SETDENTS] = server_setdents, - [GF_FOP_READDIR] = server_readdir, - [GF_FOP_INODELK] = server_inodelk, - [GF_FOP_FINODELK] = server_finodelk, - [GF_FOP_ENTRYLK] = server_entrylk, - [GF_FOP_FENTRYLK] = server_fentrylk, - [GF_FOP_CHECKSUM] = server_checksum, - [GF_FOP_XATTROP] = server_xattrop, - [GF_FOP_FXATTROP] = server_fxattrop, -}; - - - -static gf_op_t gf_mops[] = { - [GF_MOP_SETVOLUME] = mop_setvolume, - [GF_MOP_GETVOLUME] = mop_getvolume, - [GF_MOP_STATS] = mop_stats, - [GF_MOP_GETSPEC] = mop_getspec, - [GF_MOP_PING] = mop_ping, -}; - -static gf_op_t gf_cbks[] = { - [GF_CBK_FORGET] = server_forget, - [GF_CBK_RELEASE] = server_release, - [GF_CBK_RELEASEDIR] = server_releasedir -}; - -int -protocol_server_interpret (xlator_t *this, transport_t *trans, - char *hdr_p, size_t hdrlen, struct iobuf *iobuf) -{ - server_connection_t *conn = NULL; - gf_hdr_common_t *hdr = NULL; - xlator_t *bound_xl = NULL; - call_frame_t *frame = NULL; - peer_info_t *peerinfo = NULL; - int32_t type = -1; - int32_t op = -1; - int32_t ret = -1; - - hdr = (gf_hdr_common_t *)hdr_p; - type = ntoh32 (hdr->type); - op = ntoh32 (hdr->op); - - conn = trans->xl_private; - if (conn) - bound_xl = conn->bound_xl; - - peerinfo = &trans->peerinfo; - switch (type) { - case GF_OP_TYPE_FOP_REQUEST: - if ((op < 0) || - (op > GF_FOP_MAXVALUE)) { - gf_log (this->name, GF_LOG_ERROR, - "invalid fop %"PRId32" from client %s", - op, peerinfo->identifier); - break; - } - if (bound_xl == NULL) { - gf_log (this->name, GF_LOG_ERROR, - "Received fop %"PRId32" before " - "authentication.", op); - break; - } - frame = get_frame_for_call (trans, hdr); - ret = gf_fops[op] (frame, bound_xl, hdr, hdrlen, iobuf); - break; - - case GF_OP_TYPE_MOP_REQUEST: - if (op < 0 || op > GF_MOP_MAXVALUE) { - gf_log (this->name, GF_LOG_ERROR, - "invalid mop %"PRId32" from client %s", - op, peerinfo->identifier); - break; - } - frame = get_frame_for_call (trans, hdr); - ret = gf_mops[op] (frame, bound_xl, hdr, hdrlen, iobuf); - break; - - case GF_OP_TYPE_CBK_REQUEST: - if (op < 0 || op > GF_CBK_MAXVALUE) { - gf_log (this->name, GF_LOG_ERROR, - "invalid cbk %"PRId32" from client %s", - op, peerinfo->identifier); - break; - } - if (bound_xl == NULL) { - gf_log (this->name, GF_LOG_ERROR, - "Received cbk %d before authentication.", op); - break; - } - - frame = get_frame_for_call (trans, hdr); - ret = gf_cbks[op] (frame, bound_xl, hdr, hdrlen, iobuf); - break; - - default: - break; - } - - return ret; -} - - -/* - * server_nop_cbk - nop callback for server protocol - * @frame: call frame - * @cookie: - * @this: - * @op_ret: return value - * @op_errno: errno - * - * not for external reference - */ -int -server_nop_cbk (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno) -{ - server_state_t *state = NULL; - - state = CALL_STATE(frame); - - if (state) - free_state (state); - STACK_DESTROY (frame->root); - return 0; -} - - -static void -get_auth_types (dict_t *this, - char *key, - data_t *value, - void *data) -{ - dict_t *auth_dict = data; - char *saveptr = NULL, *tmp = NULL; - char *key_cpy = NULL; - int32_t ret = -1; - - key_cpy = strdup (key); - GF_VALIDATE_OR_GOTO("server", key_cpy, out); - - tmp = strtok_r (key_cpy, ".", &saveptr); - ret = strcmp (tmp, "auth"); - if (ret == 0) { - tmp = strtok_r (NULL, ".", &saveptr); - if (strcmp (tmp, "ip") == 0) { - /* TODO: backward compatibility, remove when - newer versions are available */ - tmp = "addr"; - gf_log ("server", GF_LOG_WARNING, - "assuming 'auth.ip' to be 'auth.addr'"); - } - ret = dict_set_dynptr (auth_dict, tmp, NULL, 0); - if (ret < 0) { - gf_log ("server", GF_LOG_ERROR, - "failed to dict_set_dynptr"); - } - } - - FREE (key_cpy); -out: - return; -} - - -static int -validate_auth_options (xlator_t *this, dict_t *dict) -{ - int ret = -1; - int error = 0; - xlator_list_t *trav = NULL; - data_pair_t *pair = NULL; - char *saveptr = NULL, *tmp = NULL; - char *key_cpy = NULL; - - trav = this->children; - while (trav) { - error = -1; - for (pair = dict->members_list; pair; pair = pair->next) { - key_cpy = strdup (pair->key); - tmp = strtok_r (key_cpy, ".", &saveptr); - ret = strcmp (tmp, "auth"); - if (ret == 0) { - /* for module type */ - tmp = strtok_r (NULL, ".", &saveptr); - /* for volume name */ - tmp = strtok_r (NULL, ".", &saveptr); - } - - if (strcmp (tmp, trav->xlator->name) == 0) { - error = 0; - free (key_cpy); - break; - } - free (key_cpy); - } - if (-1 == error) { - gf_log (this->name, GF_LOG_ERROR, - "volume '%s' defined as subvolume, but no " - "authentication defined for the same", - trav->xlator->name); - break; - } - trav = trav->next; - } - - return error; -} - - -/* - * init - called during server protocol initialization - * - * @this: - * - */ -int -init (xlator_t *this) -{ - int32_t ret = -1; - transport_t *trans = NULL; - server_conf_t *conf = NULL; - data_t *data = NULL; - - if (this->children == NULL) { - gf_log (this->name, GF_LOG_ERROR, - "protocol/server should have subvolume"); - goto out; - } - - trans = transport_load (this->options, this); - if (trans == NULL) { - gf_log (this->name, GF_LOG_ERROR, - "failed to load transport"); - goto out; - } - - ret = transport_listen (trans); - if (ret == -1) { - gf_log (this->name, GF_LOG_ERROR, - "failed to bind/listen on socket"); - goto out; - } - - conf = CALLOC (1, sizeof (server_conf_t)); - GF_VALIDATE_OR_GOTO(this->name, conf, out); - - INIT_LIST_HEAD (&conf->conns); - pthread_mutex_init (&conf->mutex, NULL); - - conf->trans = trans; - - conf->auth_modules = dict_new (); - GF_VALIDATE_OR_GOTO(this->name, conf->auth_modules, out); - - dict_foreach (this->options, get_auth_types, - conf->auth_modules); - ret = validate_auth_options (this, this->options); - if (ret == -1) { - /* logging already done in validate_auth_options function. */ - goto out; - } - - ret = gf_auth_init (this, conf->auth_modules); - if (ret) { - dict_unref (conf->auth_modules); - goto out; - } - - this->private = conf; - - ret = dict_get_int32 (this->options, "inode-lru-limit", - &conf->inode_lru_limit); - if (ret < 0) { - conf->inode_lru_limit = 1024; - } - - ret = dict_get_int32 (this->options, "limits.transaction-size", - &conf->max_block_size); - if (ret < 0) { - gf_log (this->name, GF_LOG_DEBUG, - "defaulting limits.transaction-size to %d", - DEFAULT_BLOCK_SIZE); - conf->max_block_size = DEFAULT_BLOCK_SIZE; - } - - conf->verify_volfile_checksum = 1; - data = dict_get (this->options, "verify-volfile-checksum"); - if (data) { - ret = gf_string2boolean(data->data, - &conf->verify_volfile_checksum); - if (ret != 0) { - gf_log (this->name, GF_LOG_DEBUG, - "wrong value for verify-volfile-checksum"); - conf->verify_volfile_checksum = 1; - } - } - -#ifndef GF_DARWIN_HOST_OS - { - struct rlimit lim; - - lim.rlim_cur = 1048576; - lim.rlim_max = 1048576; - - if (setrlimit (RLIMIT_NOFILE, &lim) == -1) { - gf_log (this->name, GF_LOG_WARNING, - "WARNING: Failed to set 'ulimit -n 1M': %s", - strerror(errno)); - lim.rlim_cur = 65536; - lim.rlim_max = 65536; - - if (setrlimit (RLIMIT_NOFILE, &lim) == -1) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to set max open fd to 64k: %s", - strerror(errno)); - } else { - gf_log (this->name, GF_LOG_ERROR, - "max open fd set to 64k"); - } - } - } -#endif - this->ctx->top = this; - - ret = 0; -out: - return ret; -} - - - -int -protocol_server_pollin (xlator_t *this, transport_t *trans) -{ - char *hdr = NULL; - size_t hdrlen = 0; - int ret = -1; - struct iobuf *iobuf = NULL; - - - ret = transport_receive (trans, &hdr, &hdrlen, &iobuf); - - if (ret == 0) - ret = protocol_server_interpret (this, trans, hdr, - hdrlen, iobuf); - - /* TODO: use mem-pool */ - FREE (hdr); - - return ret; -} - - -/* - * fini - finish function for server protocol, called before - * unloading server protocol. - * - * @this: - * - */ -void -fini (xlator_t *this) -{ - server_conf_t *conf = this->private; - - GF_VALIDATE_OR_GOTO(this->name, conf, out); - - if (conf->auth_modules) { - dict_unref (conf->auth_modules); - } - - FREE (conf); - this->private = NULL; -out: - return; -} - -/* - * server_protocol_notify - notify function for server protocol - * @this: - * @trans: - * @event: - * - */ -int -notify (xlator_t *this, int32_t event, void *data, ...) -{ - int ret = 0; - transport_t *trans = data; - peer_info_t *peerinfo = NULL; - peer_info_t *myinfo = NULL; - - if (trans != NULL) { - peerinfo = &(trans->peerinfo); - myinfo = &(trans->myinfo); - } - - switch (event) { - case GF_EVENT_POLLIN: - ret = protocol_server_pollin (this, trans); - break; - case GF_EVENT_POLLERR: - { - gf_log (trans->xl->name, GF_LOG_INFO, "%s disconnected", - peerinfo->identifier); - - ret = -1; - transport_disconnect (trans); - if (trans->xl_private == NULL) { - gf_log (this->name, GF_LOG_DEBUG, - "POLLERR received on (%s) even before " - "handshake with (%s) is successful", - myinfo->identifier, peerinfo->identifier); - } else { - server_connection_cleanup (this, trans->xl_private); - } - } - break; - - case GF_EVENT_TRANSPORT_CLEANUP: - { - if (trans->xl_private) { - server_connection_put (this, trans->xl_private); - } else { - gf_log (this->name, GF_LOG_DEBUG, - "transport (%s) cleaned up even before " - "handshake with (%s) is successful", - myinfo->identifier, peerinfo->identifier); - } - } - break; - - default: - default_notify (this, event, data); - break; - } - - return ret; -} - - -struct xlator_mops mops = { -}; - -struct xlator_fops fops = { -}; - -struct xlator_cbks cbks = { -}; - -struct volume_options options[] = { - { .key = {"transport-type"}, - .value = {"tcp", "socket", "ib-verbs", "unix", "ib-sdp", - "tcp/server", "ib-verbs/server"}, - .type = GF_OPTION_TYPE_STR - }, - { .key = {"volume-filename.*"}, - .type = GF_OPTION_TYPE_PATH, - }, - { .key = {"inode-lru-limit"}, - .type = GF_OPTION_TYPE_INT, - .min = 0, - .max = (1 * GF_UNIT_MB) - }, - { .key = {"client-volume-filename"}, - .type = GF_OPTION_TYPE_PATH - }, - { .key = {"verify-volfile-checksum"}, - .type = GF_OPTION_TYPE_BOOL - }, - { .key = {NULL} }, -}; diff --git a/xlators/protocol/server/src/server-protocol.h b/xlators/protocol/server/src/server-protocol.h deleted file mode 100644 index 1ea30cc6f..000000000 --- a/xlators/protocol/server/src/server-protocol.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> - This file is part of GlusterFS. - - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. -*/ - -#ifndef _SERVER_PROTOCOL_H_ -#define _SERVER_PROTOCOL_H_ - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include <pthread.h> - -#include "glusterfs.h" -#include "xlator.h" -#include "logging.h" -#include "call-stub.h" -#include "authenticate.h" -#include "fd.h" -#include "byte-order.h" - -#define DEFAULT_BLOCK_SIZE 4194304 /* 4MB */ -#define DEFAULT_VOLUME_FILE_PATH CONFDIR "/glusterfs.vol" - -typedef struct _server_state server_state_t; - -struct _locker { - struct list_head lockers; - char *volume; - loc_t loc; - fd_t *fd; - pid_t pid; -}; - -struct _lock_table { - struct list_head file_lockers; - struct list_head dir_lockers; - gf_lock_t lock; - size_t count; -}; - - -/* private structure per connection (transport object) - * used as transport_t->xl_private - */ -struct _server_connection { - struct list_head list; - char *id; - int ref; - pthread_mutex_t lock; - char disconnected; - fdtable_t *fdtable; - struct _lock_table *ltable; - xlator_t *bound_xl; -}; - -typedef struct _server_connection server_connection_t; - - -server_connection_t * -server_connection_get (xlator_t *this, const char *id); - -void -server_connection_put (xlator_t *this, server_connection_t *conn); - -int -server_connection_destroy (xlator_t *this, server_connection_t *conn); - -int -server_connection_cleanup (xlator_t *this, server_connection_t *conn); - -int -server_nop_cbk (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno); - - -struct _volfile_ctx { - struct _volfile_ctx *next; - char *key; - uint32_t checksum; -}; - -typedef struct { - struct _volfile_ctx *volfile; - - dict_t *auth_modules; - transport_t *trans; - int32_t max_block_size; - int32_t inode_lru_limit; - pthread_mutex_t mutex; - struct list_head conns; - gf_boolean_t verify_volfile_checksum; -} server_conf_t; - - -struct _server_state { - transport_t *trans; - xlator_t *bound_xl; - loc_t loc; - loc_t loc2; - int flags; - fd_t *fd; - size_t size; - off_t offset; - mode_t mode; - dev_t dev; - uid_t uid; - gid_t gid; - size_t nr_count; - int cmd; - int type; - char *name; - int name_len; - inode_table_t *itable; - int64_t fd_no; - ino_t ino; - ino_t par; - ino_t ino2; - ino_t par2; - char *path; - char *path2; - char *bname; - char *bname2; - int mask; - char is_revalidate; - dict_t *xattr_req; - struct flock flock; - struct timespec tv[2]; - char *resolved; - const char *volume; -}; - - -int -server_stub_resume (call_stub_t *stub, int32_t op_ret, int32_t op_errno, - inode_t *inode, inode_t *parent); - -int -do_path_lookup (call_stub_t *stub, const loc_t *loc); - -#endif diff --git a/xlators/protocol/server/src/server-resolve.c b/xlators/protocol/server/src/server-resolve.c new file mode 100644 index 000000000..cc4686a03 --- /dev/null +++ b/xlators/protocol/server/src/server-resolve.c @@ -0,0 +1,598 @@ +/* + Copyright (c) 2010-2013 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 _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "server.h" +#include "server-helpers.h" + + +int +server_resolve_all (call_frame_t *frame); +int +resolve_entry_simple (call_frame_t *frame); +int +resolve_inode_simple (call_frame_t *frame); +int +resolve_continue (call_frame_t *frame); +int +resolve_anonfd_simple (call_frame_t *frame); + +int +resolve_loc_touchup (call_frame_t *frame) +{ + server_state_t *state = NULL; + server_resolve_t *resolve = NULL; + loc_t *loc = NULL; + char *path = NULL; + int ret = 0; + + state = CALL_STATE (frame); + + resolve = state->resolve_now; + loc = state->loc_now; + + if (!loc->path) { + if (loc->parent && resolve->bname) { + ret = inode_path (loc->parent, resolve->bname, &path); + } else if (loc->inode) { + ret = inode_path (loc->inode, NULL, &path); + } + if (ret) + gf_log (frame->this->name, GF_LOG_TRACE, + "return value inode_path %d", ret); + loc->path = path; + } + + return 0; +} + + +int +resolve_gfid_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata, + struct iatt *postparent) +{ + server_state_t *state = NULL; + server_resolve_t *resolve = NULL; + inode_t *link_inode = NULL; + loc_t *resolve_loc = NULL; + + state = CALL_STATE (frame); + resolve = state->resolve_now; + resolve_loc = &resolve->resolve_loc; + + if (op_ret == -1) { + gf_log (this->name, ((op_errno == ENOENT) ? GF_LOG_DEBUG : + GF_LOG_WARNING), + "%s/%s: failed to resolve (%s)", + uuid_utoa (resolve_loc->pargfid), resolve_loc->name, + strerror (op_errno)); + goto out; + } + + link_inode = inode_link (inode, resolve_loc->parent, + resolve_loc->name, buf); + + if (!link_inode) + goto out; + + inode_lookup (link_inode); + + inode_unref (link_inode); + +out: + loc_wipe (resolve_loc); + + resolve_continue (frame); + return 0; +} + + +int +resolve_gfid_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, inode_t *inode, struct iatt *buf, + dict_t *xdata, struct iatt *postparent) +{ + server_state_t *state = NULL; + server_resolve_t *resolve = NULL; + inode_t *link_inode = NULL; + loc_t *resolve_loc = NULL; + + state = CALL_STATE (frame); + resolve = state->resolve_now; + resolve_loc = &resolve->resolve_loc; + + if (op_ret == -1) { + gf_log (this->name, ((op_errno == ENOENT) ? GF_LOG_DEBUG : + GF_LOG_WARNING), + "%s: failed to resolve (%s)", + uuid_utoa (resolve_loc->gfid), strerror (op_errno)); + loc_wipe (&resolve->resolve_loc); + goto out; + } + + loc_wipe (resolve_loc); + + link_inode = inode_link (inode, NULL, NULL, buf); + + if (!link_inode) + goto out; + + inode_lookup (link_inode); + + if (uuid_is_null (resolve->pargfid)) { + inode_unref (link_inode); + goto out; + } + + resolve_loc->parent = link_inode; + uuid_copy (resolve_loc->pargfid, resolve_loc->parent->gfid); + + resolve_loc->name = resolve->bname; + + resolve_loc->inode = inode_new (state->itable); + inode_path (resolve_loc->parent, resolve_loc->name, + (char **) &resolve_loc->path); + + STACK_WIND (frame, resolve_gfid_entry_cbk, + frame->root->client->bound_xl, + frame->root->client->bound_xl->fops->lookup, + &resolve->resolve_loc, NULL); + return 0; +out: + resolve_continue (frame); + return 0; +} + + +int +resolve_gfid (call_frame_t *frame) +{ + server_state_t *state = NULL; + xlator_t *this = NULL; + server_resolve_t *resolve = NULL; + loc_t *resolve_loc = NULL; + int ret = 0; + + state = CALL_STATE (frame); + this = frame->this; + resolve = state->resolve_now; + resolve_loc = &resolve->resolve_loc; + + if (!uuid_is_null (resolve->pargfid)) + uuid_copy (resolve_loc->gfid, resolve->pargfid); + else if (!uuid_is_null (resolve->gfid)) + uuid_copy (resolve_loc->gfid, resolve->gfid); + + resolve_loc->inode = inode_new (state->itable); + ret = loc_path (resolve_loc, NULL); + + STACK_WIND (frame, resolve_gfid_cbk, + frame->root->client->bound_xl, + frame->root->client->bound_xl->fops->lookup, + &resolve->resolve_loc, NULL); + return 0; +} + +int +resolve_continue (call_frame_t *frame) +{ + server_state_t *state = NULL; + xlator_t *this = NULL; + server_resolve_t *resolve = NULL; + int ret = 0; + + state = CALL_STATE (frame); + this = frame->this; + resolve = state->resolve_now; + + resolve->op_ret = 0; + resolve->op_errno = 0; + + if (resolve->fd_no != -1) { + ret = resolve_anonfd_simple (frame); + goto out; + } else if (!uuid_is_null (resolve->pargfid)) + ret = resolve_entry_simple (frame); + else if (!uuid_is_null (resolve->gfid)) + ret = resolve_inode_simple (frame); + if (ret) + gf_log (this->name, GF_LOG_DEBUG, + "return value of resolve_*_simple %d", ret); + + resolve_loc_touchup (frame); +out: + server_resolve_all (frame); + + return 0; +} + + +/* + Check if the requirements are fulfilled by entries in the inode cache itself + Return value: + <= 0 - simple resolution was decisive and complete (either success or failure) + > 0 - indecisive, need to perform deep resolution +*/ + +int +resolve_entry_simple (call_frame_t *frame) +{ + server_state_t *state = NULL; + xlator_t *this = NULL; + server_resolve_t *resolve = NULL; + inode_t *parent = NULL; + inode_t *inode = NULL; + int ret = 0; + + state = CALL_STATE (frame); + this = frame->this; + resolve = state->resolve_now; + + parent = inode_find (state->itable, resolve->pargfid); + if (!parent) { + /* simple resolution is indecisive. need to perform + deep resolution */ + resolve->op_ret = -1; + resolve->op_errno = ENOENT; + ret = 1; + goto out; + } + + /* expected @parent was found from the inode cache */ + uuid_copy (state->loc_now->pargfid, resolve->pargfid); + state->loc_now->parent = inode_ref (parent); + state->loc_now->name = resolve->bname; + + inode = inode_grep (state->itable, parent, resolve->bname); + if (!inode) { + switch (resolve->type) { + case RESOLVE_DONTCARE: + case RESOLVE_NOT: + ret = 0; + break; + case RESOLVE_MAY: + ret = 1; + break; + default: + resolve->op_ret = -1; + resolve->op_errno = ENOENT; + ret = 1; + break; + } + + goto out; + } + + if (resolve->type == RESOLVE_NOT) { + gf_log (this->name, GF_LOG_DEBUG, "inode (pointer: %p gfid:%s" + " found for path (%s) while type is RESOLVE_NOT", + inode, uuid_utoa (inode->gfid), resolve->path); + resolve->op_ret = -1; + resolve->op_errno = EEXIST; + ret = -1; + goto out; + } + + ret = 0; + + state->loc_now->inode = inode_ref (inode); + +out: + if (parent) + inode_unref (parent); + + if (inode) + inode_unref (inode); + + return ret; +} + + +int +server_resolve_entry (call_frame_t *frame) +{ + server_state_t *state = NULL; + int ret = 0; + loc_t *loc = NULL; + + state = CALL_STATE (frame); + loc = state->loc_now; + + ret = resolve_entry_simple (frame); + + if (ret > 0) { + loc_wipe (loc); + resolve_gfid (frame); + return 0; + } + + if (ret == 0) + resolve_loc_touchup (frame); + + server_resolve_all (frame); + + return 0; +} + + +int +resolve_inode_simple (call_frame_t *frame) +{ + server_state_t *state = NULL; + server_resolve_t *resolve = NULL; + inode_t *inode = NULL; + int ret = 0; + + state = CALL_STATE (frame); + resolve = state->resolve_now; + + inode = inode_find (state->itable, resolve->gfid); + + if (!inode) { + resolve->op_ret = -1; + resolve->op_errno = ENOENT; + ret = 1; + goto out; + } + + ret = 0; + + state->loc_now->inode = inode_ref (inode); + uuid_copy (state->loc_now->gfid, resolve->gfid); + +out: + if (inode) + inode_unref (inode); + + return ret; +} + + +int +server_resolve_inode (call_frame_t *frame) +{ + server_state_t *state = NULL; + int ret = 0; + loc_t *loc = NULL; + + state = CALL_STATE (frame); + loc = state->loc_now; + + ret = resolve_inode_simple (frame); + + if (ret > 0) { + loc_wipe (loc); + resolve_gfid (frame); + return 0; + } + + if (ret == 0) + resolve_loc_touchup (frame); + + server_resolve_all (frame); + + return 0; +} + + +int +resolve_anonfd_simple (call_frame_t *frame) +{ + server_state_t *state = NULL; + server_resolve_t *resolve = NULL; + inode_t *inode = NULL; + int ret = 0; + + state = CALL_STATE (frame); + resolve = state->resolve_now; + + inode = inode_find (state->itable, resolve->gfid); + + if (!inode) { + resolve->op_ret = -1; + resolve->op_errno = ENOENT; + ret = 1; + goto out; + } + + ret = 0; + + state->fd = fd_anonymous (inode); +out: + if (inode) + inode_unref (inode); + + if (ret != 0) + gf_log ("server", GF_LOG_WARNING, "inode for the gfid (%s) is " + "not found. anonymous fd creation failed", + uuid_utoa (resolve->gfid)); + return ret; +} + + +int +server_resolve_anonfd (call_frame_t *frame) +{ + server_state_t *state = NULL; + int ret = 0; + loc_t *loc = NULL; + + state = CALL_STATE (frame); + loc = state->loc_now; + + ret = resolve_anonfd_simple (frame); + + if (ret > 0) { + loc_wipe (loc); + resolve_gfid (frame); + return 0; + } + + server_resolve_all (frame); + + return 0; + +} + + +int +server_resolve_fd (call_frame_t *frame) +{ + server_ctx_t *serv_ctx = NULL; + server_state_t *state = NULL; + client_t *client = NULL; + server_resolve_t *resolve = NULL; + uint64_t fd_no = -1; + + state = CALL_STATE (frame); + resolve = state->resolve_now; + + fd_no = resolve->fd_no; + + if (fd_no == GF_ANON_FD_NO) { + server_resolve_anonfd (frame); + return 0; + } + + client = frame->root->client; + + serv_ctx = server_ctx_get (client, client->this); + + if (serv_ctx == NULL) { + gf_log ("", GF_LOG_INFO, "server_ctx_get() failed"); + resolve->op_ret = -1; + resolve->op_errno = ENOMEM; + return 0; + } + + state->fd = gf_fd_fdptr_get (serv_ctx->fdtable, fd_no); + + if (!state->fd) { + gf_log ("", GF_LOG_INFO, "fd not found in context"); + resolve->op_ret = -1; + resolve->op_errno = EBADF; + } + + server_resolve_all (frame); + + return 0; +} + + +int +server_resolve (call_frame_t *frame) +{ + server_state_t *state = NULL; + server_resolve_t *resolve = NULL; + + state = CALL_STATE (frame); + resolve = state->resolve_now; + + if (resolve->fd_no != -1) { + + server_resolve_fd (frame); + + } else if (!uuid_is_null (resolve->pargfid)) { + + server_resolve_entry (frame); + + } else if (!uuid_is_null (resolve->gfid)) { + + server_resolve_inode (frame); + + } else { + if (resolve == &state->resolve) + gf_log (frame->this->name, GF_LOG_WARNING, + "no resolution type for %s (%s)", + resolve->path, gf_fop_list[frame->root->op]); + + resolve->op_ret = -1; + resolve->op_errno = EINVAL; + + server_resolve_all (frame); + } + + return 0; +} + + +int +server_resolve_done (call_frame_t *frame) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + server_print_request (frame); + + state->resume_fn (frame, frame->root->client->bound_xl); + + return 0; +} + + +/* + * This function is called multiple times, once per resolving one location/fd. + * state->resolve_now is used to decide which location/fd is to be resolved now + */ +int +server_resolve_all (call_frame_t *frame) +{ + server_state_t *state = NULL; + xlator_t *this = NULL; + + this = frame->this; + state = CALL_STATE (frame); + + if (state->resolve_now == NULL) { + + state->resolve_now = &state->resolve; + state->loc_now = &state->loc; + + server_resolve (frame); + + } else if (state->resolve_now == &state->resolve) { + + state->resolve_now = &state->resolve2; + state->loc_now = &state->loc2; + + server_resolve (frame); + + } else if (state->resolve_now == &state->resolve2) { + + server_resolve_done (frame); + + } else { + gf_log (this->name, GF_LOG_ERROR, + "Invalid pointer for state->resolve_now"); + } + + return 0; +} + + +int +resolve_and_resume (call_frame_t *frame, server_resume_fn_t fn) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + state->resume_fn = fn; + + server_resolve_all (frame); + + return 0; +} diff --git a/xlators/protocol/server/src/server-rpc-fops.c b/xlators/protocol/server/src/server-rpc-fops.c new file mode 100644 index 000000000..138e601ce --- /dev/null +++ b/xlators/protocol/server/src/server-rpc-fops.c @@ -0,0 +1,6179 @@ +/* + Copyright (c) 2010-2013 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 _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <openssl/md5.h> + +#include "server.h" +#include "server-helpers.h" +#include "glusterfs3-xdr.h" +#include "glusterfs3.h" +#include "compat-errno.h" + +#include "xdr-nfs3.h" + +#define SERVER_REQ_SET_ERROR(req, ret) \ + do { \ + rpcsvc_request_seterr (req, GARBAGE_ARGS); \ + ret = RPCSVC_ACTOR_ERROR; \ + } while (0) + +/* Callback function section */ +int +server_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct statvfs *buf, + dict_t *xdata) +{ + gfs3_statfs_rsp rsp = {0,}; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + gf_log (this->name, GF_LOG_WARNING, "%"PRId64": STATFS (%s)", + frame->root->unique, strerror (op_errno)); + goto out; + } + + gf_statfs_from_statfs (&rsp.statfs, buf); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_statfs_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_lookup_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 *xdata, + struct iatt *postparent) +{ + rpcsvc_request_t *req = NULL; + server_state_t *state = NULL; + inode_t *root_inode = NULL; + inode_t *link_inode = NULL; + loc_t fresh_loc = {0,}; + gfs3_lookup_rsp rsp = {0,}; + uuid_t rootgfid = {0,}; + + state = CALL_STATE (frame); + + if (state->is_revalidate == 1 && op_ret == -1) { + state->is_revalidate = 2; + loc_copy (&fresh_loc, &state->loc); + inode_unref (fresh_loc.inode); + fresh_loc.inode = inode_new (state->itable); + + STACK_WIND (frame, server_lookup_cbk, + frame->root->client->bound_xl, + frame->root->client->bound_xl->fops->lookup, + &fresh_loc, state->xdata); + + loc_wipe (&fresh_loc); + return 0; + } + + gf_stat_from_iatt (&rsp.postparent, postparent); + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret) { + if (state->is_revalidate && op_errno == ENOENT) { + if (!__is_root_gfid (state->resolve.gfid)) { + inode_unlink (state->loc.inode, + state->loc.parent, + state->loc.name); + } + } + goto out; + } + + root_inode = frame->root->client->bound_xl->itable->root; + if (inode == root_inode) { + /* we just looked up root ("/") */ + stbuf->ia_ino = 1; + rootgfid[15] = 1; + uuid_copy (stbuf->ia_gfid, rootgfid); + if (inode->ia_type == 0) + inode->ia_type = stbuf->ia_type; + } + + gf_stat_from_iatt (&rsp.stat, stbuf); + + if (!__is_root_gfid (inode->gfid)) { + link_inode = inode_link (inode, state->loc.parent, + state->loc.name, stbuf); + if (link_inode) { + inode_lookup (link_inode); + inode_unref (link_inode); + } + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + if (op_ret) { + if (state->resolve.bname) { + gf_log (this->name, ((op_errno == ENOENT) ? + GF_LOG_TRACE : GF_LOG_INFO), + "%"PRId64": LOOKUP %s (%s/%s) ==> " + "(%s)", frame->root->unique, + state->loc.path, + uuid_utoa (state->resolve.pargfid), + state->resolve.bname, + strerror (op_errno)); + } else { + gf_log (this->name, ((op_errno == ENOENT) ? + GF_LOG_TRACE : GF_LOG_INFO), + "%"PRId64": LOOKUP %s (%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + } + } + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_lookup_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct gf_flock *lock, + dict_t *xdata) +{ + gfs3_lk_rsp rsp = {0,}; + rpcsvc_request_t *req = NULL; + server_state_t *state = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret) { + if ((op_errno != ENOSYS) && (op_errno != EAGAIN)) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": LK %"PRId64" (%s) ==> " + "(%s)", frame->root->unique, + state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + } + goto out; + } + + switch (lock->l_type) { + case F_RDLCK: + lock->l_type = GF_LK_F_RDLCK; + break; + case F_WRLCK: + lock->l_type = GF_LK_F_WRLCK; + break; + case F_UNLCK: + lock->l_type = GF_LK_F_UNLCK; + break; + default: + gf_log (this->name, GF_LOG_ERROR, + "Unknown lock type: %"PRId32"!", lock->l_type); + break; + } + + gf_proto_flock_from_flock (&rsp.flock, lock); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_lk_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + gf_common_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret < 0) { + if ((op_errno != ENOSYS) && (op_errno != EAGAIN)) { + gf_log (this->name, (op_errno == ENOENT)? + GF_LOG_DEBUG:GF_LOG_ERROR, + "%"PRId64": INODELK %s (%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + } + goto out; + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_finodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + gf_common_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret < 0) { + if ((op_errno != ENOSYS) && (op_errno != EAGAIN)) { + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": FINODELK %"PRId64" (%s) " + "==> (%s)", frame->root->unique, + state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + } + goto out; + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_entrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + gf_common_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret < 0) { + if ((op_errno != ENOSYS) && (op_errno != EAGAIN)) { + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": ENTRYLK %s (%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + } + goto out; + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_fentrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + gf_common_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret < 0) { + if ((op_errno != ENOSYS) && (op_errno != EAGAIN)) { + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": FENTRYLK %"PRId64" (%s) ==>(%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + } + goto out; + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + gf_common_rsp rsp = {0,}; + rpcsvc_request_t *req = NULL; + server_state_t *state = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": ACCESS %s (%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_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, dict_t *xdata) +{ + gfs3_rmdir_rsp rsp = {0,}; + server_state_t *state = NULL; + inode_t *parent = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret) { + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": RMDIR %s (%s/%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.pargfid), + state->resolve.bname, strerror (op_errno)); + goto out; + } + + inode_unlink (state->loc.inode, state->loc.parent, + state->loc.name); + parent = inode_parent (state->loc.inode, 0, NULL); + if (parent) + /* parent should not be found for directories after + * inode_unlink, since directories cannot have + * hardlinks. + */ + inode_unref (parent); + else + inode_forget (state->loc.inode, 0); + + gf_stat_from_iatt (&rsp.preparent, preparent); + gf_stat_from_iatt (&rsp.postparent, postparent); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_rmdir_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *stbuf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + gfs3_mkdir_rsp rsp = {0,}; + server_state_t *state = NULL; + inode_t *link_inode = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret < 0) { + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": MKDIR %s (%s/%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.pargfid), + state->resolve.bname, strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.stat, stbuf); + gf_stat_from_iatt (&rsp.preparent, preparent); + gf_stat_from_iatt (&rsp.postparent, postparent); + + link_inode = inode_link (inode, state->loc.parent, + state->loc.name, stbuf); + inode_lookup (link_inode); + inode_unref (link_inode); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_mkdir_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + inode_t *inode, struct iatt *stbuf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + gfs3_mknod_rsp rsp = {0,}; + server_state_t *state = NULL; + inode_t *link_inode = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret < 0) { + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": MKNOD %s (%s/%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.pargfid), + state->resolve.bname, strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.stat, stbuf); + gf_stat_from_iatt (&rsp.preparent, preparent); + gf_stat_from_iatt (&rsp.postparent, postparent); + + link_inode = inode_link (inode, state->loc.parent, + state->loc.name, stbuf); + inode_lookup (link_inode); + inode_unref (link_inode); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_mknod_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_fsyncdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + gf_common_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": FSYNCDIR %"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata) +{ + gfs3_readdir_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + int ret = 0; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": READDIR %"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + /* (op_ret == 0) is valid, and means EOF */ + if (op_ret) { + ret = serialize_rsp_dirent (entries, &rsp); + if (ret == -1) { + op_ret = -1; + op_errno = ENOMEM; + goto out; + } + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_readdir_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + readdir_rsp_cleanup (&rsp); + + return 0; +} + +int +server_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) +{ + server_state_t *state = NULL; + server_ctx_t *serv_ctx = NULL; + rpcsvc_request_t *req = NULL; + gfs3_opendir_rsp rsp = {0,}; + uint64_t fd_no = 0; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, (op_errno == ENOENT)? + GF_LOG_DEBUG:GF_LOG_ERROR, + "%"PRId64": OPENDIR %s (%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), strerror (op_errno)); + goto out; + } + + serv_ctx = server_ctx_get (frame->root->client, this); + if (serv_ctx == NULL) { + gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed"); + goto out; + } + + fd_bind (fd); + fd_no = gf_fd_unused_get (serv_ctx->fdtable, fd); + fd_ref (fd); // on behalf of the client + +out: + rsp.fd = fd_no; + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_opendir_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + gf_common_rsp rsp = {0,}; + rpcsvc_request_t *req = NULL; + server_state_t *state = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret == -1) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": REMOVEXATTR %s (%s) of key %s ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), + state->name, strerror (op_errno)); + goto out; + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + gf_common_rsp rsp = {0,}; + rpcsvc_request_t *req = NULL; + server_state_t *state = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret == -1) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": FREMOVEXATTR %"PRId64" (%s) (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), state->name, + strerror (op_errno)); + goto out; + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) +{ + gfs3_getxattr_rsp rsp = {0,}; + rpcsvc_request_t *req = NULL; + server_state_t *state = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret == -1) { + state = CALL_STATE (frame); + gf_log (this->name, (((op_errno == ENOTSUP) || + (op_errno == ENODATA) || + (op_errno == ENOENT)) ? + GF_LOG_DEBUG : GF_LOG_INFO), + "%"PRId64": GETXATTR %s (%s) (%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), + state->name, strerror (op_errno)); + goto out; + } + + GF_PROTOCOL_DICT_SERIALIZE (this, dict, &rsp.dict.dict_val, + rsp.dict.dict_len, op_errno, out); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_getxattr_rsp); + + GF_FREE (rsp.dict.dict_val); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_fgetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) +{ + gfs3_fgetxattr_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret == -1) { + state = CALL_STATE (frame); + gf_log (this->name, ((op_errno == ENOTSUP) ? + GF_LOG_DEBUG : GF_LOG_INFO), + "%"PRId64": FGETXATTR %"PRId64" (%s) (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), + state->name, strerror (op_errno)); + goto out; + } + + GF_PROTOCOL_DICT_SERIALIZE (this, dict, &rsp.dict.dict_val, + rsp.dict.dict_len, op_errno, out); + +out: + + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_fgetxattr_rsp); + + GF_FREE (rsp.dict.dict_val); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +/* print every key */ +static int +_gf_server_log_setxattr_failure (dict_t *d, char *k, data_t *v, + void *tmp) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + + frame = tmp; + state = CALL_STATE (frame); + + gf_log (THIS->name, GF_LOG_INFO, + "%"PRId64": SETXATTR %s (%s) ==> %s", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), k); + return 0; +} + +int +server_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + gf_common_rsp rsp = {0,}; + rpcsvc_request_t *req = NULL; + server_state_t *state = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret == -1) { + state = CALL_STATE (frame); + if (op_errno != ENOTSUP) + dict_foreach (state->dict, + _gf_server_log_setxattr_failure, + frame); + + gf_log (THIS->name, ((op_errno == ENOTSUP) ? + GF_LOG_DEBUG : GF_LOG_INFO), + "%s", strerror (op_errno)); + goto out; + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +/* print every key here */ +static int +_gf_server_log_fsetxattr_failure (dict_t *d, char *k, data_t *v, + void *tmp) +{ + call_frame_t *frame = NULL; + server_state_t *state = NULL; + + frame = tmp; + state = CALL_STATE (frame); + + gf_log (THIS->name, GF_LOG_INFO, + "%"PRId64": FSETXATTR %"PRId64" (%s) ==> %s", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), k); + + return 0; +} + +int +server_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + gf_common_rsp rsp = {0,}; + rpcsvc_request_t *req = NULL; + server_state_t *state = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret == -1) { + state = CALL_STATE (frame); + if (op_errno != ENOTSUP) { + dict_foreach (state->dict, + _gf_server_log_fsetxattr_failure, + frame); + } + gf_log (THIS->name, ((op_errno == ENOTSUP) ? + GF_LOG_DEBUG : GF_LOG_INFO), + "%s", strerror (op_errno)); + goto out; + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *stbuf, + struct iatt *preoldparent, struct iatt *postoldparent, + struct iatt *prenewparent, struct iatt *postnewparent, + dict_t *xdata) +{ + gfs3_rename_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + inode_t *tmp_inode = NULL; + inode_t *tmp_parent = NULL; + char oldpar_str[50] = {0,}; + char newpar_str[50] = {0,}; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret == -1) { + uuid_utoa_r (state->resolve.gfid, oldpar_str); + uuid_utoa_r (state->resolve2.gfid, newpar_str); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": RENAME %s (%s/%s) -> %s (%s/%s) ==> (%s)", + frame->root->unique, state->loc.path, + oldpar_str, state->resolve.bname, state->loc2.path, + newpar_str, state->resolve2.bname, strerror (op_errno)); + goto out; + } + + stbuf->ia_type = state->loc.inode->ia_type; + + /* TODO: log gfid of the inodes */ + gf_log (frame->root->client->bound_xl->name, GF_LOG_TRACE, + "%"PRId64": RENAME_CBK %s ==> %s", + frame->root->unique, state->loc.name, state->loc2.name); + + /* Before renaming the inode, we have to get the inode for the + * destination entry (i.e. inode with state->loc2.parent as + * parent and state->loc2.name as name). If it exists, then + * unlink that inode, and send forget on that inode if the + * unlinked entry is the last entry. In case of fuse client + * the fuse kernel module itself sends the forget on the + * unlinked inode. + */ + tmp_inode = inode_grep (state->loc.inode->table, + state->loc2.parent, state->loc2.name); + if (tmp_inode) { + inode_unlink (tmp_inode, state->loc2.parent, + state->loc2.name); + tmp_parent = inode_parent (tmp_inode, 0, NULL); + if (tmp_parent) + inode_unref (tmp_parent); + else + inode_forget (tmp_inode, 0); + + inode_unref (tmp_inode); + } + + inode_rename (state->itable, + state->loc.parent, state->loc.name, + state->loc2.parent, state->loc2.name, + state->loc.inode, stbuf); + gf_stat_from_iatt (&rsp.stat, stbuf); + + gf_stat_from_iatt (&rsp.preoldparent, preoldparent); + gf_stat_from_iatt (&rsp.postoldparent, postoldparent); + + gf_stat_from_iatt (&rsp.prenewparent, prenewparent); + gf_stat_from_iatt (&rsp.postnewparent, postnewparent); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_rename_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_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, dict_t *xdata) +{ + gfs3_unlink_rsp rsp = {0,}; + server_state_t *state = NULL; + inode_t *parent = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret) { + gf_log (this->name, (op_errno == ENOENT)? + GF_LOG_DEBUG:GF_LOG_ERROR, + "%"PRId64": UNLINK %s (%s/%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.pargfid), + state->resolve.bname, strerror (op_errno)); + goto out; + } + + /* TODO: log gfid of the inodes */ + gf_log (frame->root->client->bound_xl->name, GF_LOG_TRACE, + "%"PRId64": UNLINK_CBK %s", + frame->root->unique, state->loc.name); + + inode_unlink (state->loc.inode, state->loc.parent, + state->loc.name); + + parent = inode_parent (state->loc.inode, 0, NULL); + if (parent) + inode_unref (parent); + else + inode_forget (state->loc.inode, 0); + + gf_stat_from_iatt (&rsp.preparent, preparent); + gf_stat_from_iatt (&rsp.postparent, postparent); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_unlink_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *stbuf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + gfs3_symlink_rsp rsp = {0,}; + server_state_t *state = NULL; + inode_t *link_inode = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret < 0) { + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": SYMLINK %s (%s/%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.pargfid), + state->resolve.bname, strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.stat, stbuf); + gf_stat_from_iatt (&rsp.preparent, preparent); + gf_stat_from_iatt (&rsp.postparent, postparent); + + link_inode = inode_link (inode, state->loc.parent, + state->loc.name, stbuf); + inode_lookup (link_inode); + inode_unref (link_inode); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_symlink_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *stbuf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + gfs3_link_rsp rsp = {0,}; + server_state_t *state = NULL; + inode_t *link_inode = NULL; + rpcsvc_request_t *req = NULL; + char gfid_str[50] = {0,}; + char newpar_str[50] = {0,}; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret) { + uuid_utoa_r (state->resolve.gfid, gfid_str); + uuid_utoa_r (state->resolve2.pargfid, newpar_str); + + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": LINK %s (%s) -> %s/%s ==> (%s)", + frame->root->unique, state->loc.path, + gfid_str, newpar_str, state->resolve2.bname, + strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.stat, stbuf); + gf_stat_from_iatt (&rsp.preparent, preparent); + gf_stat_from_iatt (&rsp.postparent, postparent); + + link_inode = inode_link (inode, state->loc2.parent, + state->loc2.name, stbuf); + inode_unref (link_inode); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_link_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_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, dict_t *xdata) +{ + gfs3_truncate_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": TRUNCATE %s (%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.prestat, prebuf); + gf_stat_from_iatt (&rsp.poststat, postbuf); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_truncate_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *stbuf, + dict_t *xdata) +{ + gfs3_fstat_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": FSTAT %"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.stat, stbuf); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_fstat_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + gfs3_ftruncate_rsp rsp = {0}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": FTRUNCATE %"PRId64" (%s)==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.prestat, prebuf); + gf_stat_from_iatt (&rsp.poststat, postbuf); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_ftruncate_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + gf_common_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, (op_errno == ENOENT)? + GF_LOG_DEBUG:GF_LOG_ERROR, + "%"PRId64": FLUSH %"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), strerror (op_errno)); + goto out; + } + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_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, dict_t *xdata) +{ + gfs3_fsync_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": FSYNC %"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&(rsp.prestat), prebuf); + gf_stat_from_iatt (&(rsp.poststat), postbuf); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_fsync_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_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, dict_t *xdata) +{ + gfs3_write_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": WRITEV %"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.prestat, prebuf); + gf_stat_from_iatt (&rsp.poststat, postbuf); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_write_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_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, dict_t *xdata) +{ + gfs3_read_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + +#ifdef GF_TESTING_IO_XDATA + { + int ret = 0; + if (!xdata) + xdata = dict_new (); + + ret = dict_set_str (xdata, "testing-the-xdata-key", + "testing-xdata-value"); + } +#endif + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": READV %"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.stat, stbuf); + rsp.size = op_ret; + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, vector, count, iobref, + (xdrproc_t)xdr_gfs3_read_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_rchecksum_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + uint32_t weak_checksum, uint8_t *strong_checksum, + dict_t *xdata) +{ + gfs3_rchecksum_rsp rsp = {0,}; + rpcsvc_request_t *req = NULL; + server_state_t *state = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": RCHECKSUM %"PRId64" (%s)==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), strerror (op_errno)); + goto out; + } + + rsp.weak_checksum = weak_checksum; + + rsp.strong_checksum.strong_checksum_val = (char *)strong_checksum; + rsp.strong_checksum.strong_checksum_len = MD5_DIGEST_LENGTH; + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_rchecksum_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) +{ + server_state_t *state = NULL; + server_ctx_t *serv_ctx = NULL; + rpcsvc_request_t *req = NULL; + uint64_t fd_no = 0; + gfs3_open_rsp rsp = {0,}; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, (op_errno == ENOENT)? + GF_LOG_DEBUG:GF_LOG_ERROR, + "%"PRId64": OPEN %s (%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + serv_ctx = server_ctx_get (frame->root->client, this); + if (serv_ctx == NULL) { + gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed"); + goto out; + } + + fd_bind (fd); + fd_no = gf_fd_unused_get (serv_ctx->fdtable, fd); + fd_ref (fd); + rsp.fd = fd_no; + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_open_rsp); + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_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 *stbuf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + server_state_t *state = NULL; + server_ctx_t *serv_ctx = NULL; + inode_t *link_inode = NULL; + rpcsvc_request_t *req = NULL; + uint64_t fd_no = 0; + gfs3_create_rsp rsp = {0,}; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret < 0) { + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": CREATE %s (%s/%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.pargfid), + state->resolve.bname, strerror (op_errno)); + goto out; + } + + /* TODO: log gfid too */ + gf_log (frame->root->client->bound_xl->name, GF_LOG_TRACE, + "%"PRId64": CREATE %s (%s)", + frame->root->unique, state->loc.name, + uuid_utoa (stbuf->ia_gfid)); + + link_inode = inode_link (inode, state->loc.parent, + state->loc.name, stbuf); + + if (!link_inode) { + op_ret = -1; + op_errno = ENOENT; + goto out; + } + + if (link_inode != inode) { + /* + VERY racy code (if used anywhere else) + -- don't do this without understanding + */ + + inode_unref (fd->inode); + fd->inode = inode_ref (link_inode); + } + + inode_lookup (link_inode); + inode_unref (link_inode); + + serv_ctx = server_ctx_get (frame->root->client, this); + if (serv_ctx == NULL) { + gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed"); + goto out; + } + + fd_bind (fd); + fd_no = gf_fd_unused_get (serv_ctx->fdtable, fd); + fd_ref (fd); + + if ((fd_no < 0) || (fd == 0)) { + op_ret = fd_no; + op_errno = errno; + } + + gf_stat_from_iatt (&rsp.stat, stbuf); + gf_stat_from_iatt (&rsp.preparent, preparent); + gf_stat_from_iatt (&rsp.postparent, postparent); + +out: + rsp.fd = fd_no; + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_create_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, const char *buf, + struct iatt *stbuf, dict_t *xdata) +{ + gfs3_readlink_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": READLINK %s (%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.buf, stbuf); + rsp.path = (char *)buf; + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + if (!rsp.path) + rsp.path = ""; + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_readlink_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *stbuf, + dict_t *xdata) +{ + gfs3_stat_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret) { + state = CALL_STATE (frame); + gf_log (this->name, (op_errno == ENOENT)? + GF_LOG_DEBUG:GF_LOG_ERROR, + "%"PRId64": STAT %s (%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.stat, stbuf); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_stat_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_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, dict_t *xdata) +{ + gfs3_setattr_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": SETATTR %s (%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.statpre, statpre); + gf_stat_from_iatt (&rsp.statpost, statpost); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_setattr_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, dict_t *xdata) +{ + gfs3_fsetattr_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": FSETATTR %"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.statpre, statpre); + gf_stat_from_iatt (&rsp.statpost, statpost); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_fsetattr_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_xattrop_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) +{ + gfs3_xattrop_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": XATTROP %s (%s) ==> (%s)", + frame->root->unique, state->loc.path, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + GF_PROTOCOL_DICT_SERIALIZE (this, dict, &rsp.dict.dict_val, + rsp.dict.dict_len, op_errno, out); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_xattrop_rsp); + + GF_FREE (rsp.dict.dict_val); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_fxattrop_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) +{ + gfs3_xattrop_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": FXATTROP %"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + GF_PROTOCOL_DICT_SERIALIZE (this, dict, &rsp.dict.dict_val, + rsp.dict.dict_len, op_errno, out); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_fxattrop_rsp); + + GF_FREE (rsp.dict.dict_val); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +int +server_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata) +{ + gfs3_readdirp_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + int ret = 0; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": READDIRP %"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + /* (op_ret == 0) is valid, and means EOF */ + if (op_ret) { + ret = serialize_rsp_direntp (entries, &rsp); + if (ret == -1) { + op_ret = -1; + op_errno = ENOMEM; + goto out; + } + } + + /* TODO: need more clear thoughts before calling this function. */ + /* gf_link_inodes_from_dirent (this, state->fd->inode, entries); */ + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs3_readdirp_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + readdirp_rsp_cleanup (&rsp); + + return 0; +} + +int +server_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, dict_t *xdata) +{ + gfs3_fallocate_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": FALLOCATE %"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.statpre, statpre); + gf_stat_from_iatt (&rsp.statpost, statpost); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply(frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t) xdr_gfs3_fallocate_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, dict_t *xdata) +{ + gfs3_discard_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret) { + state = CALL_STATE (frame); + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": DISCARD %"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.statpre, statpre); + gf_stat_from_iatt (&rsp.statpost, statpost); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply(frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t) xdr_gfs3_discard_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_zerofill_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, dict_t *xdata) +{ + gfs3_zerofill_rsp rsp = {0,}; + server_state_t *state = NULL; + rpcsvc_request_t *req = NULL; + + req = frame->local; + state = CALL_STATE (frame); + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, (&rsp.xdata.xdata_val), + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret) { + gf_log (this->name, GF_LOG_INFO, + "%"PRId64": ZEROFILL%"PRId64" (%s) ==> (%s)", + frame->root->unique, state->resolve.fd_no, + uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + gf_stat_from_iatt (&rsp.statpre, statpre); + gf_stat_from_iatt (&rsp.statpost, statpost); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + server_submit_reply(frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t) xdr_gfs3_zerofill_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + + +/* Resume function section */ + +int +server_rchecksum_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + int op_ret = 0; + int op_errno = EINVAL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) { + op_ret = state->resolve.op_ret; + op_errno = state->resolve.op_errno; + goto err; + } + + STACK_WIND (frame, server_rchecksum_cbk, bound_xl, + bound_xl->fops->rchecksum, state->fd, + state->offset, state->size, state->xdata); + + return 0; +err: + server_rchecksum_cbk (frame, NULL, frame->this, op_ret, op_errno, 0, + NULL, NULL); + + return 0; + +} + +int +server_lk_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_lk_cbk, bound_xl, bound_xl->fops->lk, + state->fd, state->cmd, &state->flock, state->xdata); + + return 0; + +err: + server_lk_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL); + return 0; +} + +int +server_rename_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + int op_ret = 0; + int op_errno = 0; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) { + op_ret = state->resolve.op_ret; + op_errno = state->resolve.op_errno; + goto err; + } + + if (state->resolve2.op_ret != 0) { + op_ret = state->resolve2.op_ret; + op_errno = state->resolve2.op_errno; + goto err; + } + + STACK_WIND (frame, server_rename_cbk, + bound_xl, bound_xl->fops->rename, + &state->loc, &state->loc2, state->xdata); + return 0; +err: + server_rename_cbk (frame, NULL, frame->this, op_ret, op_errno, + NULL, NULL, NULL, NULL, NULL, NULL); + return 0; +} + + +int +server_link_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + int op_ret = 0; + int op_errno = 0; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) { + op_ret = state->resolve.op_ret; + op_errno = state->resolve.op_errno; + goto err; + } + + if (state->resolve2.op_ret != 0) { + op_ret = state->resolve2.op_ret; + op_errno = state->resolve2.op_errno; + goto err; + } + + state->loc2.inode = inode_ref (state->loc.inode); + + STACK_WIND (frame, server_link_cbk, bound_xl, bound_xl->fops->link, + &state->loc, &state->loc2, state->xdata); + + return 0; +err: + server_link_cbk (frame, NULL, frame->this, op_ret, op_errno, + NULL, NULL, NULL, NULL, NULL); + return 0; +} + +int +server_symlink_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + state->loc.inode = inode_new (state->itable); + + STACK_WIND (frame, server_symlink_cbk, + bound_xl, bound_xl->fops->symlink, + state->name, &state->loc, state->umask, state->xdata); + + return 0; +err: + server_symlink_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL, NULL, NULL); + return 0; +} + + +int +server_access_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_access_cbk, + bound_xl, bound_xl->fops->access, + &state->loc, state->mask, state->xdata); + return 0; +err: + server_access_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL); + return 0; +} + +int +server_fentrylk_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + GF_UNUSED int ret = -1; + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + if (!state->xdata) + state->xdata = dict_new (); + + if (state->xdata) + ret = dict_set_str (state->xdata, "connection-id", + frame->root->client->client_uid); + + STACK_WIND (frame, server_fentrylk_cbk, bound_xl, + bound_xl->fops->fentrylk, + state->volume, state->fd, state->name, + state->cmd, state->type, state->xdata); + + return 0; +err: + server_fentrylk_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL); + return 0; +} + + +int +server_entrylk_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + GF_UNUSED int ret = -1; + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + if (!state->xdata) + state->xdata = dict_new (); + + if (state->xdata) + ret = dict_set_str (state->xdata, "connection-id", + frame->root->client->client_uid); + + STACK_WIND (frame, server_entrylk_cbk, + bound_xl, bound_xl->fops->entrylk, + state->volume, &state->loc, state->name, + state->cmd, state->type, state->xdata); + return 0; +err: + server_entrylk_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL); + return 0; +} + + +int +server_finodelk_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + GF_UNUSED int ret = -1; + server_state_t *state = NULL; + + gf_log (bound_xl->name, GF_LOG_WARNING, "frame %p, xlator %p", + frame, bound_xl); + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + if (!state->xdata) + state->xdata = dict_new (); + + if (state->xdata) + ret = dict_set_str (state->xdata, "connection-id", + frame->root->client->client_uid); + + STACK_WIND (frame, server_finodelk_cbk, bound_xl, + bound_xl->fops->finodelk, state->volume, state->fd, + state->cmd, &state->flock, state->xdata); + + return 0; +err: + server_finodelk_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL); + + return 0; +} + +int +server_inodelk_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + GF_UNUSED int ret = -1; + server_state_t *state = NULL; + + gf_log (bound_xl->name, GF_LOG_WARNING, "frame %p, xlator %p", + frame, bound_xl); + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + if (!state->xdata) + state->xdata = dict_new (); + + if (state->xdata) + ret = dict_set_str (state->xdata, "connection-id", + frame->root->client->client_uid); + + STACK_WIND (frame, server_inodelk_cbk, bound_xl, + bound_xl->fops->inodelk, state->volume, &state->loc, + state->cmd, &state->flock, state->xdata); + return 0; +err: + server_inodelk_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL); + return 0; +} + +int +server_rmdir_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_rmdir_cbk, bound_xl, bound_xl->fops->rmdir, + &state->loc, state->flags, state->xdata); + return 0; +err: + server_rmdir_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + return 0; +} + +int +server_mkdir_resume (call_frame_t *frame, xlator_t *bound_xl) + +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + state->loc.inode = inode_new (state->itable); + + STACK_WIND (frame, server_mkdir_cbk, + bound_xl, bound_xl->fops->mkdir, + &(state->loc), state->mode, state->umask, state->xdata); + + return 0; +err: + server_mkdir_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL, NULL, NULL); + return 0; +} + + +int +server_mknod_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + state->loc.inode = inode_new (state->itable); + + STACK_WIND (frame, server_mknod_cbk, + bound_xl, bound_xl->fops->mknod, + &(state->loc), state->mode, state->dev, + state->umask, state->xdata); + + return 0; +err: + server_mknod_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL, NULL, NULL); + return 0; +} + + +int +server_fsyncdir_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_fsyncdir_cbk, + bound_xl, + bound_xl->fops->fsyncdir, + state->fd, state->flags, state->xdata); + return 0; + +err: + server_fsyncdir_cbk (frame, NULL, frame->this, + state->resolve.op_ret, + state->resolve.op_errno, NULL); + return 0; +} + + +int +server_readdir_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + GF_ASSERT (state->fd); + + STACK_WIND (frame, server_readdir_cbk, + bound_xl, + bound_xl->fops->readdir, + state->fd, state->size, state->offset, state->xdata); + + return 0; +err: + server_readdir_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL); + return 0; +} + +int +server_readdirp_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_readdirp_cbk, bound_xl, + bound_xl->fops->readdirp, state->fd, state->size, + state->offset, state->dict); + + return 0; +err: + server_readdirp_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL); + return 0; +} + + +int +server_opendir_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + state->fd = fd_create (state->loc.inode, frame->root->pid); + if (!state->fd) { + gf_log ("server", GF_LOG_ERROR, "could not create the fd"); + goto err; + } + + STACK_WIND (frame, server_opendir_cbk, + bound_xl, bound_xl->fops->opendir, + &state->loc, state->fd, state->xdata); + return 0; +err: + server_opendir_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL); + return 0; +} + + +int +server_statfs_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret !=0) + goto err; + + STACK_WIND (frame, server_statfs_cbk, + bound_xl, bound_xl->fops->statfs, + &state->loc, state->xdata); + return 0; + +err: + server_statfs_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL); + return 0; +} + + +int +server_removexattr_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_removexattr_cbk, + bound_xl, bound_xl->fops->removexattr, + &state->loc, state->name, state->xdata); + return 0; +err: + server_removexattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL); + return 0; +} + +int +server_fremovexattr_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_fremovexattr_cbk, + bound_xl, bound_xl->fops->fremovexattr, + state->fd, state->name, state->xdata); + return 0; +err: + server_fremovexattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL); + return 0; +} + +int +server_fgetxattr_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_fgetxattr_cbk, + bound_xl, bound_xl->fops->fgetxattr, + state->fd, state->name, state->xdata); + return 0; +err: + server_fgetxattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL); + return 0; +} + + +int +server_xattrop_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_xattrop_cbk, + bound_xl, bound_xl->fops->xattrop, + &state->loc, state->flags, state->dict, state->xdata); + return 0; +err: + server_xattrop_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL); + return 0; +} + +int +server_fxattrop_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_fxattrop_cbk, + bound_xl, bound_xl->fops->fxattrop, + state->fd, state->flags, state->dict, state->xdata); + return 0; +err: + server_fxattrop_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL); + return 0; +} + +int +server_fsetxattr_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_setxattr_cbk, + bound_xl, bound_xl->fops->fsetxattr, + state->fd, state->dict, state->flags, state->xdata); + return 0; +err: + server_fsetxattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL); + + return 0; +} + +int +server_unlink_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_unlink_cbk, + bound_xl, bound_xl->fops->unlink, + &state->loc, state->flags, state->xdata); + return 0; +err: + server_unlink_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + return 0; +} + +int +server_truncate_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_truncate_cbk, + bound_xl, bound_xl->fops->truncate, + &state->loc, state->offset, state->xdata); + return 0; +err: + server_truncate_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + return 0; +} + + + +int +server_fstat_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_fstat_cbk, + bound_xl, bound_xl->fops->fstat, + state->fd, state->xdata); + return 0; +err: + server_fstat_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL); + return 0; +} + + +int +server_setxattr_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_setxattr_cbk, + bound_xl, bound_xl->fops->setxattr, + &state->loc, state->dict, state->flags, state->xdata); + return 0; +err: + server_setxattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL); + + return 0; +} + + +int +server_getxattr_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_getxattr_cbk, + bound_xl, bound_xl->fops->getxattr, + &state->loc, state->name, state->xdata); + return 0; +err: + server_getxattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL); + return 0; +} + + +int +server_ftruncate_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_ftruncate_cbk, + bound_xl, bound_xl->fops->ftruncate, + state->fd, state->offset, state->xdata); + return 0; +err: + server_ftruncate_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + + return 0; +} + + +int +server_flush_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_flush_cbk, + bound_xl, bound_xl->fops->flush, state->fd, state->xdata); + return 0; +err: + server_flush_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL); + + return 0; +} + + +int +server_fsync_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_fsync_cbk, + bound_xl, bound_xl->fops->fsync, + state->fd, state->flags, state->xdata); + return 0; +err: + server_fsync_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + + return 0; +} + +int +server_writev_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_writev_cbk, + bound_xl, bound_xl->fops->writev, + state->fd, state->payload_vector, state->payload_count, + state->offset, state->flags, state->iobref, state->xdata); + + return 0; +err: + server_writev_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + return 0; +} + + +int +server_readv_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_readv_cbk, + bound_xl, bound_xl->fops->readv, + state->fd, state->size, state->offset, state->flags, state->xdata); + + return 0; +err: + server_readv_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, 0, NULL, NULL, NULL); + return 0; +} + + +int +server_create_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + state->loc.inode = inode_new (state->itable); + + state->fd = fd_create (state->loc.inode, frame->root->pid); + if (!state->fd) { + gf_log ("server", GF_LOG_ERROR, "fd creation for the inode %s " + "failed", state->loc.inode? + uuid_utoa (state->loc.inode->gfid):NULL); + state->resolve.op_ret = -1; + state->resolve.op_errno = ENOMEM; + goto err; + } + state->fd->flags = state->flags; + + STACK_WIND (frame, server_create_cbk, + bound_xl, bound_xl->fops->create, + &(state->loc), state->flags, state->mode, + state->umask, state->fd, state->xdata); + + return 0; +err: + server_create_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL, + NULL, NULL, NULL); + return 0; +} + + +int +server_open_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + state->fd = fd_create (state->loc.inode, frame->root->pid); + state->fd->flags = state->flags; + + STACK_WIND (frame, server_open_cbk, + bound_xl, bound_xl->fops->open, + &state->loc, state->flags, state->fd, state->xdata); + + return 0; +err: + server_open_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL); + return 0; +} + + +int +server_readlink_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_readlink_cbk, + bound_xl, bound_xl->fops->readlink, + &state->loc, state->size, state->xdata); + return 0; +err: + server_readlink_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + return 0; +} + + +int +server_fsetattr_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_fsetattr_cbk, + bound_xl, bound_xl->fops->fsetattr, + state->fd, &state->stbuf, state->valid, state->xdata); + return 0; +err: + server_fsetattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + + return 0; +} + + +int +server_setattr_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_setattr_cbk, + bound_xl, bound_xl->fops->setattr, + &state->loc, &state->stbuf, state->valid, state->xdata); + return 0; +err: + server_setattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + + return 0; +} + + +int +server_stat_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_stat_cbk, + bound_xl, bound_xl->fops->stat, &state->loc, state->xdata); + return 0; +err: + server_stat_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL); + return 0; +} + +int +server_lookup_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + if (!state->loc.inode) + state->loc.inode = inode_new (state->itable); + else + state->is_revalidate = 1; + + STACK_WIND (frame, server_lookup_cbk, + bound_xl, bound_xl->fops->lookup, + &state->loc, state->xdata); + + return 0; +err: + server_lookup_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL, NULL); + + return 0; +} + +int +server_fallocate_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_fallocate_cbk, + bound_xl, bound_xl->fops->fallocate, + state->fd, state->flags, state->offset, state->size, + state->xdata); + return 0; +err: + server_fallocate_cbk(frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + + return 0; +} + +int +server_discard_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_discard_cbk, + bound_xl, bound_xl->fops->discard, + state->fd, state->offset, state->size, state->xdata); + return 0; +err: + server_discard_cbk(frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + + return 0; +} + +int +server_zerofill_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + STACK_WIND (frame, server_zerofill_cbk, + bound_xl, bound_xl->fops->zerofill, + state->fd, state->offset, state->size, state->xdata); + return 0; +err: + server_zerofill_cbk(frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + + return 0; +} + + + +/* Fop section */ + +int +server3_3_stat (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_stat_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return 0; + + /* Initialize args first, then decode */ + + ret = xdr_to_generic (req->msg[0], &args, (xdrproc_t)xdr_gfs3_stat_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_STAT; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + + ret = 0; + resolve_and_resume (frame, server_stat_resume); + +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_setattr (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_setattr_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return 0; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_setattr_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_SETATTR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + memcpy (state->resolve.gfid, args.gfid, 16); + + gf_stat_to_iatt (&args.stbuf, &state->stbuf); + state->valid = args.valid; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_setattr_resume); + +out: + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + free (args.xdata.xdata_val); + + return ret; +} + + +int +server3_3_fsetattr (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_fsetattr_req args = {0,}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_fsetattr_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FSETATTR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + + gf_stat_to_iatt (&args.stbuf, &state->stbuf); + state->valid = args.valid; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_fsetattr_resume); + +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + +int +server3_3_fallocate(rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_fallocate_req args = {{0},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_fallocate_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FALLOCATE; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + + state->flags = args.flags; + state->offset = args.offset; + state->size = args.size; + memcpy(state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_fallocate_resume); + +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_discard(rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_discard_req args = {{0},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_discard_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_DISCARD; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + + state->offset = args.offset; + state->size = args.size; + memcpy(state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_discard_resume); + +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_zerofill(rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_zerofill_req args = {{0},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_zerofill_req); + if (ret < 0) { + /*failed to decode msg*/; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + /* something wrong, mostly insufficient memory*/ + req->rpc_err = GARBAGE_ARGS; /* TODO */ + goto out; + } + frame->root->op = GF_FOP_ZEROFILL; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + + state->offset = args.offset; + state->size = args.size; + memcpy(state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, state->xdata, + (args.xdata.xdata_val), + (args.xdata.xdata_len), ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_zerofill_resume); + +out: + free (args.xdata.xdata_val); + + if (op_errno) + req->rpc_err = GARBAGE_ARGS; + + return ret; +} + +int +server3_3_readlink (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_readlink_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_readlink_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_READLINK; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + memcpy (state->resolve.gfid, args.gfid, 16); + + state->size = args.size; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_readlink_resume); + +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_create (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_create_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.bname = alloca (req->msg[0].iov_len); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_create_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_CREATE; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + + state->resolve.bname = gf_strdup (args.bname); + state->mode = args.mode; + state->umask = args.umask; + state->flags = gf_flags_to_flags (args.flags); + memcpy (state->resolve.pargfid, args.pargfid, 16); + + if (state->flags & O_EXCL) { + state->resolve.type = RESOLVE_NOT; + } else { + state->resolve.type = RESOLVE_DONTCARE; + } + + /* TODO: can do alloca for xdata field instead of stdalloc */ + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_create_resume); + +out: + /* memory allocated by libc, don't use GF_FREE */ + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_open (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_open_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, (xdrproc_t)xdr_gfs3_open_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_OPEN; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + memcpy (state->resolve.gfid, args.gfid, 16); + + state->flags = gf_flags_to_flags (args.flags); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_open_resume); +out: + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + free (args.xdata.xdata_val); + + return ret; +} + + +int +server3_3_readv (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_read_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + goto out; + + ret = xdr_to_generic (req->msg[0], &args, (xdrproc_t)xdr_gfs3_read_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_READ; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + state->size = args.size; + state->offset = args.offset; + state->flags = args.flag; + + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_readv_resume); +out: + /* memory allocated by libc, don't use GF_FREE */ + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_writev (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_write_req args = {{0,},}; + ssize_t len = 0; + int i = 0; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + len = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_write_req); + if (len < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_WRITE; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + state->offset = args.offset; + state->flags = args.flag; + state->iobref = iobref_ref (req->iobref); + memcpy (state->resolve.gfid, args.gfid, 16); + + if (len < req->msg[0].iov_len) { + state->payload_vector[0].iov_base + = (req->msg[0].iov_base + len); + state->payload_vector[0].iov_len + = req->msg[0].iov_len - len; + state->payload_count = 1; + } + + for (i = 1; i < req->count; i++) { + state->payload_vector[state->payload_count++] + = req->msg[i]; + } + + for (i = 0; i < state->payload_count; i++) { + state->size += state->payload_vector[i].iov_len; + } + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + +#ifdef GF_TESTING_IO_XDATA + dict_dump (state->xdata); +#endif + + ret = 0; + resolve_and_resume (frame, server_writev_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +#define SERVER3_3_VECWRITE_START 0 +#define SERVER3_3_VECWRITE_READING_HDR 1 +#define SERVER3_3_VECWRITE_READING_OPAQUE 2 + +int +server3_3_writev_vecsizer (int state, ssize_t *readsize, char *base_addr, + char *curr_addr) +{ + ssize_t size = 0; + int nextstate = 0; + gfs3_write_req write_req = {{0,},}; + XDR xdr; + + switch (state) { + case SERVER3_3_VECWRITE_START: + size = xdr_sizeof ((xdrproc_t) xdr_gfs3_write_req, + &write_req); + *readsize = size; + nextstate = SERVER3_3_VECWRITE_READING_HDR; + break; + case SERVER3_3_VECWRITE_READING_HDR: + size = xdr_sizeof ((xdrproc_t) xdr_gfs3_write_req, + &write_req); + + xdrmem_create (&xdr, base_addr, size, XDR_DECODE); + + /* This will fail if there is xdata sent from client, if not, + well and good */ + xdr_gfs3_write_req (&xdr, &write_req); + + /* need to round off to proper roof (%4), as XDR packing pads + the end of opaque object with '0' */ + size = roof (write_req.xdata.xdata_len, 4); + + *readsize = size; + + if (!size) + nextstate = SERVER3_3_VECWRITE_START; + else + nextstate = SERVER3_3_VECWRITE_READING_OPAQUE; + + free (write_req.xdata.xdata_val); + + break; + + case SERVER3_3_VECWRITE_READING_OPAQUE: + *readsize = 0; + nextstate = SERVER3_3_VECWRITE_START; + break; + default: + gf_log ("server", GF_LOG_ERROR, "wrong state: %d", state); + } + + return nextstate; +} + + +int +server3_3_release (rpcsvc_request_t *req) +{ + client_t *client = NULL; + server_ctx_t *serv_ctx = NULL; + gfs3_release_req args = {{0,},}; + gf_common_rsp rsp = {0,}; + int ret = -1; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_release_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + client = req->trans->xl_private; + if (!client) { + /* Handshake is not complete yet. */ + req->rpc_err = SYSTEM_ERR; + goto out; + } + + serv_ctx = server_ctx_get (client, client->this); + if (serv_ctx == NULL) { + gf_log (req->trans->name, GF_LOG_INFO, + "server_ctx_get() failed"); + req->rpc_err = SYSTEM_ERR; + goto out; + } + + gf_fd_put (serv_ctx->fdtable, args.fd); + + server_submit_reply (NULL, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + ret = 0; +out: + return ret; +} + +int +server3_3_releasedir (rpcsvc_request_t *req) +{ + client_t *client = NULL; + server_ctx_t *serv_ctx = NULL; + gfs3_releasedir_req args = {{0,},}; + gf_common_rsp rsp = {0,}; + int ret = -1; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_release_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + client = req->trans->xl_private; + if (!client) { + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + serv_ctx = server_ctx_get (client, client->this); + if (serv_ctx == NULL) { + gf_log (req->trans->name, GF_LOG_INFO, + "server_ctx_get() failed"); + req->rpc_err = SYSTEM_ERR; + goto out; + } + + gf_fd_put (serv_ctx->fdtable, args.fd); + + server_submit_reply (NULL, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + ret = 0; +out: + return ret; +} + + +int +server3_3_fsync (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_fsync_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_fsync_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FSYNC; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + state->flags = args.data; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_fsync_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + + +int +server3_3_flush (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_flush_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_flush_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FLUSH; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_flush_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + + +int +server3_3_ftruncate (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_ftruncate_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_ftruncate_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FTRUNCATE; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + state->offset = args.offset; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_ftruncate_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_fstat (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_fstat_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_fstat_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FSTAT; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_fstat_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_truncate (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_truncate_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_truncate_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_TRUNCATE; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + memcpy (state->resolve.gfid, args.gfid, 16); + state->offset = args.offset; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_truncate_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + + +int +server3_3_unlink (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_unlink_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.bname = alloca (req->msg[0].iov_len); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_unlink_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_UNLINK; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.bname = gf_strdup (args.bname); + memcpy (state->resolve.pargfid, args.pargfid, 16); + + state->flags = args.xflags; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_unlink_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_setxattr (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + dict_t *dict = NULL; + call_frame_t *frame = NULL; + gfs3_setxattr_req args = {{0,},}; + int32_t ret = -1; + int32_t op_errno = 0; + + if (!req) + return ret; + + args.dict.dict_val = alloca (req->msg[0].iov_len); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_setxattr_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_SETXATTR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->flags = args.flags; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + dict, + (args.dict.dict_val), + (args.dict.dict_len), ret, + op_errno, out); + + state->dict = dict; + + /* There can be some commands hidden in key, check and proceed */ + gf_server_check_setxattr_cmd (frame, dict); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_setxattr_resume); + + return ret; +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + if (dict) + dict_unref (dict); + + return ret; +} + + + +int +server3_3_fsetxattr (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + dict_t *dict = NULL; + call_frame_t *frame = NULL; + gfs3_fsetxattr_req args = {{0,},}; + int32_t ret = -1; + int32_t op_errno = 0; + + if (!req) + return ret; + + args.dict.dict_val = alloca (req->msg[0].iov_len); + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_fsetxattr_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FSETXATTR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + state->flags = args.flags; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + dict, + (args.dict.dict_val), + (args.dict.dict_len), ret, + op_errno, out); + + state->dict = dict; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_fsetxattr_resume); + + return ret; +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + if (dict) + dict_unref (dict); + + return ret; +} + + + +int +server3_3_fxattrop (rpcsvc_request_t *req) +{ + dict_t *dict = NULL; + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_fxattrop_req args = {{0,},}; + int32_t ret = -1; + int32_t op_errno = 0; + + if (!req) + return ret; + + args.dict.dict_val = alloca (req->msg[0].iov_len); + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_fxattrop_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FXATTROP; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + state->flags = args.flags; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + dict, + (args.dict.dict_val), + (args.dict.dict_len), ret, + op_errno, out); + + state->dict = dict; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_fxattrop_resume); + + return ret; + +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + if (dict) + dict_unref (dict); + + return ret; +} + + + +int +server3_3_xattrop (rpcsvc_request_t *req) +{ + dict_t *dict = NULL; + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_xattrop_req args = {{0,},}; + int32_t ret = -1; + int32_t op_errno = 0; + + if (!req) + return ret; + + args.dict.dict_val = alloca (req->msg[0].iov_len); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_xattrop_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_XATTROP; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->flags = args.flags; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + dict, + (args.dict.dict_val), + (args.dict.dict_len), ret, + op_errno, out); + + state->dict = dict; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_xattrop_resume); + + return ret; +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + if (dict) + dict_unref (dict); + + return ret; +} + + +int +server3_3_getxattr (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_getxattr_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.name = alloca (256); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_getxattr_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_GETXATTR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + memcpy (state->resolve.gfid, args.gfid, 16); + + if (args.namelen) { + state->name = gf_strdup (args.name); + /* There can be some commands hidden in key, check and proceed */ + gf_server_check_getxattr_cmd (frame, state->name); + } + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_getxattr_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_fgetxattr (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_fgetxattr_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.name = alloca (256); + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_fgetxattr_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FGETXATTR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + memcpy (state->resolve.gfid, args.gfid, 16); + + if (args.namelen) + state->name = gf_strdup (args.name); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_fgetxattr_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + + +int +server3_3_removexattr (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_removexattr_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.name = alloca (256); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_removexattr_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_REMOVEXATTR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + memcpy (state->resolve.gfid, args.gfid, 16); + state->name = gf_strdup (args.name); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_removexattr_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + +int +server3_3_fremovexattr (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_fremovexattr_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.name = alloca (4096); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_fremovexattr_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FREMOVEXATTR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + memcpy (state->resolve.gfid, args.gfid, 16); + state->name = gf_strdup (args.name); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_fremovexattr_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + + + +int +server3_3_opendir (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_opendir_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_opendir_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_OPENDIR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_opendir_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_readdirp (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_readdirp_req args = {{0,},}; + size_t headers_size = 0; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_readdirp_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_READDIRP; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + /* FIXME: this should go away when variable sized iobufs are introduced + * and transport layer can send msgs bigger than current page-size. + */ + headers_size = sizeof (struct rpc_msg) + sizeof (gfs3_readdir_rsp); + if ((frame->this->ctx->page_size < args.size) + || ((frame->this->ctx->page_size - args.size) < headers_size)) { + state->size = frame->this->ctx->page_size - headers_size; + } else { + state->size = args.size; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + state->offset = args.offset; + memcpy (state->resolve.gfid, args.gfid, 16); + + /* here, dict itself works as xdata */ + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->dict, + (args.dict.dict_val), + (args.dict.dict_len), ret, + op_errno, out); + + + ret = 0; + resolve_and_resume (frame, server_readdirp_resume); +out: + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + free (args.dict.dict_val); + + return ret; +} + +int +server3_3_readdir (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_readdir_req args = {{0,},}; + size_t headers_size = 0; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_readdir_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_READDIR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + /* FIXME: this should go away when variable sized iobufs are introduced + * and transport layer can send msgs bigger than current page-size. + */ + headers_size = sizeof (struct rpc_msg) + sizeof (gfs3_readdir_rsp); + if ((frame->this->ctx->page_size < args.size) + || ((frame->this->ctx->page_size - args.size) < headers_size)) { + state->size = frame->this->ctx->page_size - headers_size; + } else { + state->size = args.size; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + state->offset = args.offset; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_readdir_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + +int +server3_3_fsyncdir (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_fsyncdir_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_fsyncdir_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FSYNCDIR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.fd_no = args.fd; + state->flags = args.data; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_fsyncdir_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + + +int +server3_3_mknod (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_mknod_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.bname = alloca (req->msg[0].iov_len); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_mknod_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_MKNOD; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_NOT; + memcpy (state->resolve.pargfid, args.pargfid, 16); + state->resolve.bname = gf_strdup (args.bname); + + state->mode = args.mode; + state->dev = args.dev; + state->umask = args.umask; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_mknod_resume); + +out: + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + /* memory allocated by libc, don't use GF_FREE */ + free (args.xdata.xdata_val); + + return ret; + +} + + +int +server3_3_mkdir (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_mkdir_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.bname = alloca (req->msg[0].iov_len); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_mkdir_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_MKDIR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_NOT; + memcpy (state->resolve.pargfid, args.pargfid, 16); + state->resolve.bname = gf_strdup (args.bname); + + state->mode = args.mode; + state->umask = args.umask; + + /* TODO: can do alloca for xdata field instead of stdalloc */ + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_mkdir_resume); + +out: + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + free (args.xdata.xdata_val); + + return ret; +} + + +int +server3_3_rmdir (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_rmdir_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.bname = alloca (req->msg[0].iov_len); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_rmdir_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_RMDIR; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + memcpy (state->resolve.pargfid, args.pargfid, 16); + state->resolve.bname = gf_strdup (args.bname); + + state->flags = args.xflags; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_rmdir_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + + +int +server3_3_inodelk (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_inodelk_req args = {{0,},}; + int cmd = 0; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.volume = alloca (256); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_inodelk_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_INODELK; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_EXACT; + memcpy (state->resolve.gfid, args.gfid, 16); + + cmd = args.cmd; + switch (cmd) { + case GF_LK_GETLK: + state->cmd = F_GETLK; + break; + case GF_LK_SETLK: + state->cmd = F_SETLK; + break; + case GF_LK_SETLKW: + state->cmd = F_SETLKW; + break; + } + + state->type = args.type; + state->volume = gf_strdup (args.volume); + + gf_proto_flock_to_flock (&args.flock, &state->flock); + + switch (state->type) { + case GF_LK_F_RDLCK: + state->flock.l_type = F_RDLCK; + break; + case GF_LK_F_WRLCK: + state->flock.l_type = F_WRLCK; + break; + case GF_LK_F_UNLCK: + state->flock.l_type = F_UNLCK; + break; + } + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_inodelk_resume); +out: + free (args.xdata.xdata_val); + + free (args.flock.lk_owner.lk_owner_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + +int +server3_3_finodelk (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_finodelk_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.volume = alloca (256); + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_finodelk_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FINODELK; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_EXACT; + state->volume = gf_strdup (args.volume); + state->resolve.fd_no = args.fd; + state->cmd = args.cmd; + memcpy (state->resolve.gfid, args.gfid, 16); + + switch (state->cmd) { + case GF_LK_GETLK: + state->cmd = F_GETLK; + break; + case GF_LK_SETLK: + state->cmd = F_SETLK; + break; + case GF_LK_SETLKW: + state->cmd = F_SETLKW; + break; + } + + state->type = args.type; + + gf_proto_flock_to_flock (&args.flock, &state->flock); + + switch (state->type) { + case GF_LK_F_RDLCK: + state->flock.l_type = F_RDLCK; + break; + case GF_LK_F_WRLCK: + state->flock.l_type = F_WRLCK; + break; + case GF_LK_F_UNLCK: + state->flock.l_type = F_UNLCK; + break; + } + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_finodelk_resume); +out: + free (args.xdata.xdata_val); + + free (args.flock.lk_owner.lk_owner_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_entrylk (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_entrylk_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.volume = alloca (256); + args.name = alloca (256); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_entrylk_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_ENTRYLK; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_EXACT; + memcpy (state->resolve.gfid, args.gfid, 16); + + if (args.namelen) + state->name = gf_strdup (args.name); + state->volume = gf_strdup (args.volume); + + state->cmd = args.cmd; + state->type = args.type; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_entrylk_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + +int +server3_3_fentrylk (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_fentrylk_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.name = alloca (256); + args.volume = alloca (256); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_fentrylk_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_FENTRYLK; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_EXACT; + state->resolve.fd_no = args.fd; + state->cmd = args.cmd; + state->type = args.type; + memcpy (state->resolve.gfid, args.gfid, 16); + + if (args.namelen) + state->name = gf_strdup (args.name); + state->volume = gf_strdup (args.volume); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_fentrylk_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + +int +server3_3_access (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_access_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_access_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_ACCESS; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + memcpy (state->resolve.gfid, args.gfid, 16); + state->mask = args.mask; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_access_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + + +int +server3_3_symlink (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_symlink_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.bname = alloca (req->msg[0].iov_len); + args.linkname = alloca (4096); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_symlink_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_SYMLINK; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_NOT; + memcpy (state->resolve.pargfid, args.pargfid, 16); + state->resolve.bname = gf_strdup (args.bname); + state->name = gf_strdup (args.linkname); + state->umask = args.umask; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_symlink_resume); + +out: + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + /* memory allocated by libc, don't use GF_FREE */ + free (args.xdata.xdata_val); + + return ret; +} + + + +int +server3_3_link (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_link_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.newbname = alloca (req->msg[0].iov_len); + + ret = xdr_to_generic (req->msg[0], &args, (xdrproc_t)xdr_gfs3_link_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_LINK; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + memcpy (state->resolve.gfid, args.oldgfid, 16); + + state->resolve2.type = RESOLVE_NOT; + state->resolve2.bname = gf_strdup (args.newbname); + memcpy (state->resolve2.pargfid, args.newgfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_link_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_rename (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_rename_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + args.oldbname = alloca (req->msg[0].iov_len); + args.newbname = alloca (req->msg[0].iov_len); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_rename_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_RENAME; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + state->resolve.bname = gf_strdup (args.oldbname); + memcpy (state->resolve.pargfid, args.oldgfid, 16); + + state->resolve2.type = RESOLVE_MAY; + state->resolve2.bname = gf_strdup (args.newbname); + memcpy (state->resolve2.pargfid, args.newgfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_rename_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + +int +server3_3_lk (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_lk_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, (xdrproc_t)xdr_gfs3_lk_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_LK; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.fd_no = args.fd; + state->cmd = args.cmd; + state->type = args.type; + memcpy (state->resolve.gfid, args.gfid, 16); + + switch (state->cmd) { + case GF_LK_GETLK: + state->cmd = F_GETLK; + break; + case GF_LK_SETLK: + state->cmd = F_SETLK; + break; + case GF_LK_SETLKW: + state->cmd = F_SETLKW; + break; + case GF_LK_RESLK_LCK: + state->cmd = F_RESLK_LCK; + break; + case GF_LK_RESLK_LCKW: + state->cmd = F_RESLK_LCKW; + break; + case GF_LK_RESLK_UNLCK: + state->cmd = F_RESLK_UNLCK; + break; + case GF_LK_GETLK_FD: + state->cmd = F_GETLK_FD; + break; + + } + + + gf_proto_flock_to_flock (&args.flock, &state->flock); + + switch (state->type) { + case GF_LK_F_RDLCK: + state->flock.l_type = F_RDLCK; + break; + case GF_LK_F_WRLCK: + state->flock.l_type = F_WRLCK; + break; + case GF_LK_F_UNLCK: + state->flock.l_type = F_UNLCK; + break; + default: + gf_log (frame->root->client->bound_xl->name, GF_LOG_ERROR, + "fd - %"PRId64" (%s): Unknown lock type: %"PRId32"!", + state->resolve.fd_no, + uuid_utoa (state->fd->inode->gfid), state->type); + break; + } + + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_lk_resume); +out: + free (args.xdata.xdata_val); + + free (args.flock.lk_owner.lk_owner_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +int +server3_3_rchecksum (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_rchecksum_req args = {0,}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_rchecksum_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_RCHECKSUM; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MAY; + state->resolve.fd_no = args.fd; + state->offset = args.offset; + state->size = args.len; + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_rchecksum_resume); +out: + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + +int +server_null (rpcsvc_request_t *req) +{ + gf_common_rsp rsp = {0,}; + + /* Accepted */ + rsp.op_ret = 0; + + server_submit_reply (NULL, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_common_rsp); + + return 0; +} + +int +server3_3_lookup (rpcsvc_request_t *req) +{ + call_frame_t *frame = NULL; + server_state_t *state = NULL; + gfs3_lookup_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + GF_VALIDATE_OR_GOTO ("server", req, err); + + args.bname = alloca (req->msg[0].iov_len); + args.xdata.xdata_val = alloca (req->msg[0].iov_len); + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_lookup_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto err; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto err; + } + frame->root->op = GF_FOP_LOOKUP; + + /* NOTE: lookup() uses req->ino only to identify if a lookup() + * is requested for 'root' or not + */ + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_DONTCARE; + + if (args.bname && strcmp (args.bname, "")) { + memcpy (state->resolve.pargfid, args.pargfid, 16); + state->resolve.bname = gf_strdup (args.bname); + } else { + memcpy (state->resolve.gfid, args.gfid, 16); + } + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_lookup_resume); + + return ret; +out: + + server_lookup_cbk (frame, NULL, frame->this, -1, EINVAL, NULL, NULL, + NULL, NULL); + ret = 0; +err: + return ret; +} + +int +server3_3_statfs (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs3_statfs_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gfs3_statfs_req); + if (ret < 0) { + //failed to decode msg; + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + frame = get_frame_from_request (req); + if (!frame) { + // something wrong, mostly insufficient memory + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + frame->root->op = GF_FOP_STATFS; + + state = CALL_STATE (frame); + if (!frame->root->client->bound_xl) { + /* auth failure, request on subvolume without setvolume */ + SERVER_REQ_SET_ERROR (req, ret); + goto out; + } + + state->resolve.type = RESOLVE_MUST; + memcpy (state->resolve.gfid, args.gfid, 16); + + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_statfs_resume); +out: + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + + +rpcsvc_actor_t glusterfs3_3_fop_actors[] = { + [GFS3_OP_NULL] = {"NULL", GFS3_OP_NULL, server_null, NULL, 0, DRC_NA}, + [GFS3_OP_STAT] = {"STAT", GFS3_OP_STAT, server3_3_stat, NULL, 0, DRC_NA}, + [GFS3_OP_READLINK] = {"READLINK", GFS3_OP_READLINK, server3_3_readlink, NULL, 0, DRC_NA}, + [GFS3_OP_MKNOD] = {"MKNOD", GFS3_OP_MKNOD, server3_3_mknod, NULL, 0, DRC_NA}, + [GFS3_OP_MKDIR] = {"MKDIR", GFS3_OP_MKDIR, server3_3_mkdir, NULL, 0, DRC_NA}, + [GFS3_OP_UNLINK] = {"UNLINK", GFS3_OP_UNLINK, server3_3_unlink, NULL, 0, DRC_NA}, + [GFS3_OP_RMDIR] = {"RMDIR", GFS3_OP_RMDIR, server3_3_rmdir, NULL, 0, DRC_NA}, + [GFS3_OP_SYMLINK] = {"SYMLINK", GFS3_OP_SYMLINK, server3_3_symlink, NULL, 0, DRC_NA}, + [GFS3_OP_RENAME] = {"RENAME", GFS3_OP_RENAME, server3_3_rename, NULL, 0, DRC_NA}, + [GFS3_OP_LINK] = {"LINK", GFS3_OP_LINK, server3_3_link, NULL, 0, DRC_NA}, + [GFS3_OP_TRUNCATE] = {"TRUNCATE", GFS3_OP_TRUNCATE, server3_3_truncate, NULL, 0, DRC_NA}, + [GFS3_OP_OPEN] = {"OPEN", GFS3_OP_OPEN, server3_3_open, NULL, 0, DRC_NA}, + [GFS3_OP_READ] = {"READ", GFS3_OP_READ, server3_3_readv, NULL, 0, DRC_NA}, + [GFS3_OP_WRITE] = {"WRITE", GFS3_OP_WRITE, server3_3_writev, server3_3_writev_vecsizer, 0, DRC_NA}, + [GFS3_OP_STATFS] = {"STATFS", GFS3_OP_STATFS, server3_3_statfs, NULL, 0, DRC_NA}, + [GFS3_OP_FLUSH] = {"FLUSH", GFS3_OP_FLUSH, server3_3_flush, NULL, 0, DRC_NA}, + [GFS3_OP_FSYNC] = {"FSYNC", GFS3_OP_FSYNC, server3_3_fsync, NULL, 0, DRC_NA}, + [GFS3_OP_SETXATTR] = {"SETXATTR", GFS3_OP_SETXATTR, server3_3_setxattr, NULL, 0, DRC_NA}, + [GFS3_OP_GETXATTR] = {"GETXATTR", GFS3_OP_GETXATTR, server3_3_getxattr, NULL, 0, DRC_NA}, + [GFS3_OP_REMOVEXATTR] = {"REMOVEXATTR", GFS3_OP_REMOVEXATTR, server3_3_removexattr, NULL, 0, DRC_NA}, + [GFS3_OP_OPENDIR] = {"OPENDIR", GFS3_OP_OPENDIR, server3_3_opendir, NULL, 0, DRC_NA}, + [GFS3_OP_FSYNCDIR] = {"FSYNCDIR", GFS3_OP_FSYNCDIR, server3_3_fsyncdir, NULL, 0, DRC_NA}, + [GFS3_OP_ACCESS] = {"ACCESS", GFS3_OP_ACCESS, server3_3_access, NULL, 0, DRC_NA}, + [GFS3_OP_CREATE] = {"CREATE", GFS3_OP_CREATE, server3_3_create, NULL, 0, DRC_NA}, + [GFS3_OP_FTRUNCATE] = {"FTRUNCATE", GFS3_OP_FTRUNCATE, server3_3_ftruncate, NULL, 0, DRC_NA}, + [GFS3_OP_FSTAT] = {"FSTAT", GFS3_OP_FSTAT, server3_3_fstat, NULL, 0, DRC_NA}, + [GFS3_OP_LK] = {"LK", GFS3_OP_LK, server3_3_lk, NULL, 0, DRC_NA}, + [GFS3_OP_LOOKUP] = {"LOOKUP", GFS3_OP_LOOKUP, server3_3_lookup, NULL, 0, DRC_NA}, + [GFS3_OP_READDIR] = {"READDIR", GFS3_OP_READDIR, server3_3_readdir, NULL, 0, DRC_NA}, + [GFS3_OP_INODELK] = {"INODELK", GFS3_OP_INODELK, server3_3_inodelk, NULL, 0, DRC_NA}, + [GFS3_OP_FINODELK] = {"FINODELK", GFS3_OP_FINODELK, server3_3_finodelk, NULL, 0, DRC_NA}, + [GFS3_OP_ENTRYLK] = {"ENTRYLK", GFS3_OP_ENTRYLK, server3_3_entrylk, NULL, 0, DRC_NA}, + [GFS3_OP_FENTRYLK] = {"FENTRYLK", GFS3_OP_FENTRYLK, server3_3_fentrylk, NULL, 0, DRC_NA}, + [GFS3_OP_XATTROP] = {"XATTROP", GFS3_OP_XATTROP, server3_3_xattrop, NULL, 0, DRC_NA}, + [GFS3_OP_FXATTROP] = {"FXATTROP", GFS3_OP_FXATTROP, server3_3_fxattrop, NULL, 0, DRC_NA}, + [GFS3_OP_FGETXATTR] = {"FGETXATTR", GFS3_OP_FGETXATTR, server3_3_fgetxattr, NULL, 0, DRC_NA}, + [GFS3_OP_FSETXATTR] = {"FSETXATTR", GFS3_OP_FSETXATTR, server3_3_fsetxattr, NULL, 0, DRC_NA}, + [GFS3_OP_RCHECKSUM] = {"RCHECKSUM", GFS3_OP_RCHECKSUM, server3_3_rchecksum, NULL, 0, DRC_NA}, + [GFS3_OP_SETATTR] = {"SETATTR", GFS3_OP_SETATTR, server3_3_setattr, NULL, 0, DRC_NA}, + [GFS3_OP_FSETATTR] = {"FSETATTR", GFS3_OP_FSETATTR, server3_3_fsetattr, NULL, 0, DRC_NA}, + [GFS3_OP_READDIRP] = {"READDIRP", GFS3_OP_READDIRP, server3_3_readdirp, NULL, 0, DRC_NA}, + [GFS3_OP_RELEASE] = {"RELEASE", GFS3_OP_RELEASE, server3_3_release, NULL, 0, DRC_NA}, + [GFS3_OP_RELEASEDIR] = {"RELEASEDIR", GFS3_OP_RELEASEDIR, server3_3_releasedir, NULL, 0, DRC_NA}, + [GFS3_OP_FREMOVEXATTR] = {"FREMOVEXATTR", GFS3_OP_FREMOVEXATTR, server3_3_fremovexattr, NULL, 0, DRC_NA}, + [GFS3_OP_FALLOCATE] = {"FALLOCATE", GFS3_OP_FALLOCATE, server3_3_fallocate, NULL, 0, DRC_NA}, + [GFS3_OP_DISCARD] = {"DISCARD", GFS3_OP_DISCARD, server3_3_discard, NULL, 0, DRC_NA}, + [GFS3_OP_ZEROFILL] = {"ZEROFILL", GFS3_OP_ZEROFILL, server3_3_zerofill, NULL, 0, DRC_NA}, +}; + + +struct rpcsvc_program glusterfs3_3_fop_prog = { + .progname = "GlusterFS 3.3", + .prognum = GLUSTER_FOP_PROGRAM, + .progver = GLUSTER_FOP_VERSION, + .numactors = GLUSTER_FOP_PROCCNT, + .actors = glusterfs3_3_fop_actors, +}; diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c new file mode 100644 index 000000000..589bd7b36 --- /dev/null +++ b/xlators/protocol/server/src/server.c @@ -0,0 +1,1214 @@ +/* + Copyright (c) 2010-2013 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 _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <sys/time.h> +#include <sys/resource.h> + + +#include "server.h" +#include "server-helpers.h" +#include "glusterfs3-xdr.h" +#include "call-stub.h" +#include "statedump.h" +#include "defaults.h" +#include "authenticate.h" + +void +grace_time_handler (void *data) +{ + client_t *client = NULL; + xlator_t *this = NULL; + gf_timer_t *timer = NULL; + server_ctx_t *serv_ctx = NULL; + gf_boolean_t cancelled = _gf_false; + gf_boolean_t detached = _gf_false; + + client = data; + this = client->this; + + GF_VALIDATE_OR_GOTO (THIS->name, this, out); + + gf_log (this->name, GF_LOG_INFO, "grace timer expired for %s", + client->client_uid); + + serv_ctx = server_ctx_get (client, this); + + if (serv_ctx == NULL) { + gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed"); + goto out; + } + + LOCK (&serv_ctx->fdtable_lock); + { + if (serv_ctx->grace_timer) { + timer = serv_ctx->grace_timer; + serv_ctx->grace_timer = NULL; + } + } + UNLOCK (&serv_ctx->fdtable_lock); + if (timer) { + gf_timer_call_cancel (this->ctx, timer); + cancelled = _gf_true; + } + if (cancelled) { + + /* + * client must not be destroyed in gf_client_put(), + * so take a ref. + */ + gf_client_ref (client); + gf_client_put (client, &detached); + if (detached)//reconnection did not happen :-( + server_connection_cleanup (this, client, + INTERNAL_LOCKS | POSIX_LOCKS); + gf_client_unref (client); + } +out: + return; +} + +struct iobuf * +gfs_serialize_reply (rpcsvc_request_t *req, void *arg, struct iovec *outmsg, + xdrproc_t xdrproc) +{ + struct iobuf *iob = NULL; + ssize_t retlen = 0; + ssize_t xdr_size = 0; + + GF_VALIDATE_OR_GOTO ("server", req, ret); + + /* First, get the io buffer into which the reply in arg will + * be serialized. + */ + if (arg && xdrproc) { + xdr_size = xdr_sizeof (xdrproc, arg); + iob = iobuf_get2 (req->svc->ctx->iobuf_pool, xdr_size); + if (!iob) { + gf_log_callingfn (THIS->name, GF_LOG_ERROR, + "Failed to get iobuf"); + goto ret; + }; + + iobuf_to_iovec (iob, outmsg); + /* Use the given serializer to translate the give C structure in arg + * to XDR format which will be written into the buffer in outmsg. + */ + /* retlen is used to received the error since size_t is unsigned and we + * need -1 for error notification during encoding. + */ + + retlen = xdr_serialize_generic (*outmsg, arg, xdrproc); + if (retlen == -1) { + /* Failed to Encode 'GlusterFS' msg in RPC is not exactly + failure of RPC return values.. client should get + notified about this, so there are no missing frames */ + gf_log_callingfn ("", GF_LOG_ERROR, "Failed to encode message"); + req->rpc_err = GARBAGE_ARGS; + retlen = 0; + } + } + outmsg->iov_len = retlen; +ret: + if (retlen == -1) { + iobuf_unref (iob); + iob = NULL; + } + + return iob; +} + +int +server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg, + struct iovec *payload, int payloadcount, + struct iobref *iobref, xdrproc_t xdrproc) +{ + struct iobuf *iob = NULL; + int ret = -1; + struct iovec rsp = {0,}; + server_state_t *state = NULL; + char new_iobref = 0; + client_t *client = NULL; + gf_boolean_t lk_heal = _gf_false; + server_conf_t *conf = NULL; + gf_barrier_t *barrier = NULL; + gf_barrier_payload_t *stub = NULL; + gf_boolean_t barriered = _gf_false; + + GF_VALIDATE_OR_GOTO ("server", req, ret); + + if (frame) { + state = CALL_STATE (frame); + frame->local = NULL; + client = frame->root->client; + conf = (server_conf_t *) client->this->private; + } + + if (client) + lk_heal = ((server_conf_t *) client->this->private)->lk_heal; + + if (!iobref) { + iobref = iobref_new (); + if (!iobref) { + goto ret; + } + + new_iobref = 1; + } + + iob = gfs_serialize_reply (req, arg, &rsp, xdrproc); + if (!iob) { + gf_log ("", GF_LOG_ERROR, "Failed to serialize reply"); + goto ret; + } + + iobref_add (iobref, iob); + + if (conf) + barrier = conf->barrier; + if (barrier) { + /* todo: write's with fd flags set to O_SYNC and O_DIRECT */ + LOCK (&barrier->lock); + { + if (is_fop_barriered (barrier->fops, req->procnum) && + (barrier_add_to_queue (barrier))) { + stub = gf_barrier_payload (req, &rsp, frame, + payload, + payloadcount, iobref, + iob, new_iobref); + if (stub) { + gf_barrier_enqueue (barrier, stub); + barriered = _gf_true; + } else { + gf_log ("", GF_LOG_ERROR, "Failed to " + " barrier fop %"PRIu64, + ((uint64_t)1 << req->procnum)); + } + } + } + UNLOCK (&barrier->lock); + if (barriered == _gf_true) + goto out; + } + /* Then, submit the message for transmission. */ + ret = rpcsvc_submit_generic (req, &rsp, 1, payload, payloadcount, + iobref); + + /* TODO: this is demo purpose only */ + /* ret = rpcsvc_callback_submit (req->svc, req->trans, req->prog, + GF_CBK_NULL, &rsp, 1); + */ + /* Now that we've done our job of handing the message to the RPC layer + * we can safely unref the iob in the hope that RPC layer must have + * ref'ed the iob on receiving into the txlist. + */ + iobuf_unref (iob); + if (ret == -1) { + gf_log_callingfn ("", GF_LOG_ERROR, "Reply submission failed"); + if (frame && client && !lk_heal) { + server_connection_cleanup (frame->this, client, + INTERNAL_LOCKS | POSIX_LOCKS); + } else { + gf_log_callingfn ("", GF_LOG_ERROR, + "Reply submission failed"); + /* TODO: Failure of open(dir), create, inodelk, entrylk + or lk fops send failure must be handled specially. */ + } + goto ret; + } + + ret = 0; +ret: + if (state) { + free_state (state); + } + + if (frame) { + gf_client_unref (client); + STACK_DESTROY (frame->root); + } + + if (new_iobref) { + iobref_unref (iobref); + } +out: + return ret; +} + + +int +server_priv_to_dict (xlator_t *this, dict_t *dict) +{ + server_conf_t *conf = NULL; + rpc_transport_t *xprt = NULL; + peer_info_t *peerinfo = NULL; + char key[32] = {0,}; + int count = 0; + int ret = -1; + + GF_VALIDATE_OR_GOTO (THIS->name, this, out); + GF_VALIDATE_OR_GOTO (THIS->name, dict, out); + + conf = this->private; + if (!conf) + return 0; + //TODO: Dump only specific info to dict + + pthread_mutex_lock (&conf->mutex); + { + list_for_each_entry (xprt, &conf->xprt_list, list) { + peerinfo = &xprt->peerinfo; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "client%d.hostname", + count); + ret = dict_set_str (dict, key, peerinfo->identifier); + if (ret) + goto unlock; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "client%d.bytesread", + count); + ret = dict_set_uint64 (dict, key, + xprt->total_bytes_read); + if (ret) + goto unlock; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "client%d.byteswrite", + count); + ret = dict_set_uint64 (dict, key, + xprt->total_bytes_write); + if (ret) + goto unlock; + + count++; + } + } +unlock: + pthread_mutex_unlock (&conf->mutex); + if (ret) + goto out; + + ret = dict_set_int32 (dict, "clientcount", count); + +out: + return ret; +} + +int +server_priv (xlator_t *this) +{ + server_conf_t *conf = NULL; + rpc_transport_t *xprt = NULL; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + uint64_t total_read = 0; + uint64_t total_write = 0; + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO ("server", this, out); + + conf = this->private; + if (!conf) + return 0; + + gf_proc_dump_build_key (key, "xlator.protocol.server", "priv"); + gf_proc_dump_add_section (key); + + ret = pthread_mutex_trylock (&conf->mutex); + if (ret != 0) + goto out; + { + list_for_each_entry (xprt, &conf->xprt_list, list) { + total_read += xprt->total_bytes_read; + total_write += xprt->total_bytes_write; + } + } + pthread_mutex_unlock (&conf->mutex); + + gf_proc_dump_build_key(key, "server", "total-bytes-read"); + gf_proc_dump_write(key, "%"PRIu64, total_read); + + gf_proc_dump_build_key(key, "server", "total-bytes-write"); + gf_proc_dump_write(key, "%"PRIu64, total_write); + + ret = 0; +out: + if (ret) + gf_proc_dump_write ("Unable to print priv", + "(Lock acquisition failed) %s", + this?this->name:"server"); + + return ret; +} + + +static int +get_auth_types (dict_t *this, char *key, data_t *value, void *data) +{ + dict_t *auth_dict = NULL; + char *saveptr = NULL; + char *tmp = NULL; + char *key_cpy = NULL; + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO ("server", this, out); + GF_VALIDATE_OR_GOTO ("server", key, out); + GF_VALIDATE_OR_GOTO ("server", data, out); + + auth_dict = data; + key_cpy = gf_strdup (key); + GF_VALIDATE_OR_GOTO("server", key_cpy, out); + + tmp = strtok_r (key_cpy, ".", &saveptr); + ret = strcmp (tmp, "auth"); + if (ret == 0) { + tmp = strtok_r (NULL, ".", &saveptr); + if (strcmp (tmp, "ip") == 0) { + /* TODO: backward compatibility, remove when + newer versions are available */ + tmp = "addr"; + gf_log ("server", GF_LOG_WARNING, + "assuming 'auth.ip' to be 'auth.addr'"); + } + ret = dict_set_dynptr (auth_dict, tmp, NULL, 0); + if (ret < 0) { + gf_log ("server", GF_LOG_DEBUG, + "failed to dict_set_dynptr"); + } + } + + GF_FREE (key_cpy); +out: + return 0; +} + +int +_check_for_auth_option (dict_t *d, char *k, data_t *v, + void *tmp) +{ + int ret = 0; + xlator_t *xl = NULL; + char *tail = NULL; + char *tmp_addr_list = NULL; + char *addr = NULL; + char *tmp_str = NULL; + + xl = tmp; + + tail = strtail (k, "auth."); + if (!tail) + goto out; + + /* fast fwd thru module type */ + tail = strchr (tail, '.'); + if (!tail) + goto out; + tail++; + + tail = strtail (tail, xl->name); + if (!tail) + goto out; + + if (*tail == '.') { + /* when we are here, the key is checked for + * valid auth.allow.<xlator> + * Now we verify the ip address + */ + if (!strcmp (v->data, "*")) { + ret = 0; + goto out; + } + + tmp_addr_list = gf_strdup (v->data); + addr = strtok_r (tmp_addr_list, ",", &tmp_str); + if (!addr) + addr = v->data; + + while (addr) { + if (valid_internet_address (addr, _gf_true)) { + ret = 0; + } else { + ret = -1; + gf_log (xl->name, GF_LOG_ERROR, + "internet address '%s'" + " does not conform to" + " standards.", addr); + goto out; + } + if (tmp_str) + addr = strtok_r (NULL, ",", &tmp_str); + else + addr = NULL; + } + + GF_FREE (tmp_addr_list); + tmp_addr_list = NULL; + } +out: + return ret; +} + +int +validate_auth_options (xlator_t *this, dict_t *dict) +{ + int error = -1; + xlator_list_t *trav = NULL; + + GF_VALIDATE_OR_GOTO ("server", this, out); + GF_VALIDATE_OR_GOTO ("server", dict, out); + + trav = this->children; + while (trav) { + error = dict_foreach (dict, _check_for_auth_option, + trav->xlator); + + if (-1 == error) { + gf_log (this->name, GF_LOG_ERROR, + "volume '%s' defined as subvolume, but no " + "authentication defined for the same", + trav->xlator->name); + break; + } + trav = trav->next; + } + +out: + return error; +} + + +int +server_rpc_notify (rpcsvc_t *rpc, void *xl, rpcsvc_event_t event, + void *data) +{ + gf_boolean_t detached = _gf_false; + xlator_t *this = NULL; + rpc_transport_t *trans = NULL; + server_conf_t *conf = NULL; + client_t *client = NULL; + server_ctx_t *serv_ctx = NULL; + + if (!xl || !data) { + gf_log_callingfn ("server", GF_LOG_WARNING, + "Calling rpc_notify without initializing"); + goto out; + } + + this = xl; + trans = data; + conf = this->private; + + switch (event) { + case RPCSVC_EVENT_ACCEPT: + { + /* Have a structure per new connection */ + /* TODO: Should we create anything here at all ? * / + client->conn = create_server_conn_state (this, trans); + if (!client->conn) + goto out; + + trans->protocol_private = client->conn; + */ + INIT_LIST_HEAD (&trans->list); + + pthread_mutex_lock (&conf->mutex); + { + list_add_tail (&trans->list, &conf->xprt_list); + } + pthread_mutex_unlock (&conf->mutex); + + break; + } + case RPCSVC_EVENT_DISCONNECT: + /* transport has to be removed from the list upon disconnect + * irrespective of whether lock self heal is off or on, since + * new transport will be created upon reconnect. + */ + pthread_mutex_lock (&conf->mutex); + { + list_del_init (&trans->list); + } + pthread_mutex_unlock (&conf->mutex); + + client = trans->xl_private; + if (!client) + break; + + gf_log (this->name, GF_LOG_INFO, "disconnecting connection" + "from %s", client->client_uid); + + /* If lock self heal is off, then destroy the + conn object, else register a grace timer event */ + if (!conf->lk_heal) { + gf_client_ref (client); + gf_client_put (client, &detached); + if (detached) + server_connection_cleanup (this, client, + INTERNAL_LOCKS | POSIX_LOCKS); + gf_client_unref (client); + break; + } + trans->xl_private = NULL; + server_connection_cleanup (this, client, INTERNAL_LOCKS); + + serv_ctx = server_ctx_get (client, this); + + if (serv_ctx == NULL) { + gf_log (this->name, GF_LOG_INFO, + "server_ctx_get() failed"); + goto out; + } + + LOCK (&serv_ctx->fdtable_lock); + { + if (!serv_ctx->grace_timer) { + + gf_log (this->name, GF_LOG_INFO, + "starting a grace timer for %s", + client->client_uid); + + serv_ctx->grace_timer = + gf_timer_call_after (this->ctx, + conf->grace_ts, + grace_time_handler, + client); + } + } + UNLOCK (&serv_ctx->fdtable_lock); + break; + case RPCSVC_EVENT_TRANSPORT_DESTROY: + /*- conn obj has been disassociated from trans on first + * disconnect. + * conn cleanup and destruction is handed over to + * grace_time_handler or the subsequent handler that 'owns' + * the conn. Nothing left to be done here. */ + break; + default: + break; + } + +out: + return 0; +} + +int32_t +mem_acct_init (xlator_t *this) +{ + int ret = -1; + + GF_VALIDATE_OR_GOTO ("server", this, out); + + ret = xlator_mem_acct_init (this, gf_server_mt_end + 1); + + if (ret != 0) { + gf_log (this->name, GF_LOG_ERROR, "Memory accounting init" + "failed"); + return ret; + } +out: + return ret; +} + + +static int +_delete_auth_opt (dict_t *this, char *key, data_t *value, void *data) +{ + char *auth_option_pattern[] = { "auth.addr.*.allow", + "auth.addr.*.reject", + NULL}; + int i = 0; + + for (i = 0; auth_option_pattern[i]; i++) { + if (fnmatch (auth_option_pattern[i], key, 0) == 0) { + dict_del (this, key); + break; + } + } + + return 0; +} + + +static int +_copy_auth_opt (dict_t *unused, char *key, data_t *value, void *xl_dict) +{ + char *auth_option_pattern[] = { "auth.addr.*.allow", + "auth.addr.*.reject", + NULL}; + int i = 0; + + for (i = 0; auth_option_pattern [i]; i++) { + if (fnmatch (auth_option_pattern[i], key, 0) == 0) { + dict_set ((dict_t *)xl_dict, key, value); + break; + } + } + + return 0; +} + + +int +server_init_grace_timer (xlator_t *this, dict_t *options, + server_conf_t *conf) +{ + int32_t ret = -1; + int32_t grace_timeout = -1; + char *lk_heal = NULL; + + GF_VALIDATE_OR_GOTO ("server", this, out); + GF_VALIDATE_OR_GOTO (this->name, options, out); + GF_VALIDATE_OR_GOTO (this->name, conf, out); + + conf->lk_heal = _gf_false; + + ret = dict_get_str (options, "lk-heal", &lk_heal); + if (!ret) + gf_string2boolean (lk_heal, &conf->lk_heal); + + gf_log (this->name, GF_LOG_DEBUG, "lk-heal = %s", + (conf->lk_heal) ? "on" : "off"); + + ret = dict_get_int32 (options, "grace-timeout", &grace_timeout); + if (!ret) + conf->grace_ts.tv_sec = grace_timeout; + else + conf->grace_ts.tv_sec = 10; + + gf_log (this->name, GF_LOG_DEBUG, "Server grace timeout " + "value = %"PRIu64, conf->grace_ts.tv_sec); + + conf->grace_ts.tv_nsec = 0; + + ret = 0; +out: + return ret; +} + +int +reconfigure (xlator_t *this, dict_t *options) +{ + + server_conf_t *conf =NULL; + rpcsvc_t *rpc_conf; + rpcsvc_listener_t *listeners; + int inode_lru_limit; + gf_boolean_t trace; + data_t *data; + int ret = 0; + char *statedump_path = NULL; + conf = this->private; + + if (!conf) { + gf_log_callingfn (this->name, GF_LOG_DEBUG, "conf == null!!!"); + goto out; + } + if (dict_get_int32 ( options, "inode-lru-limit", &inode_lru_limit) == 0){ + conf->inode_lru_limit = inode_lru_limit; + gf_log (this->name, GF_LOG_TRACE, "Reconfigured inode-lru-limit" + " to %d", conf->inode_lru_limit); + } + + data = dict_get (options, "trace"); + if (data) { + ret = gf_string2boolean (data->data, &trace); + if (ret != 0) { + gf_log (this->name, GF_LOG_WARNING, + "'trace' takes on only boolean values. " + "Neglecting option"); + ret = -1; + goto out; + } + conf->trace = trace; + gf_log (this->name, GF_LOG_TRACE, "Reconfigured trace" + " to %d", conf->trace); + + } + + GF_OPTION_RECONF ("statedump-path", statedump_path, + options, path, out); + if (!statedump_path) { + gf_log (this->name, GF_LOG_ERROR, + "Error while reconfiguring statedump path"); + ret = -1; + goto out; + } + gf_path_strip_trailing_slashes (statedump_path); + GF_FREE (this->ctx->statedump_path); + this->ctx->statedump_path = gf_strdup (statedump_path); + + if (!conf->auth_modules) + conf->auth_modules = dict_new (); + + dict_foreach (options, get_auth_types, conf->auth_modules); + ret = validate_auth_options (this, options); + if (ret == -1) { + /* logging already done in validate_auth_options function. */ + goto out; + } + dict_foreach (this->options, _delete_auth_opt, this->options); + dict_foreach (options, _copy_auth_opt, this->options); + + ret = gf_auth_init (this, conf->auth_modules); + if (ret) { + dict_unref (conf->auth_modules); + goto out; + } + + rpc_conf = conf->rpc; + if (!rpc_conf) { + gf_log (this->name, GF_LOG_ERROR, "No rpc_conf !!!!"); + goto out; + } + + (void) rpcsvc_set_allow_insecure (rpc_conf, options); + (void) rpcsvc_set_root_squash (rpc_conf, options); + (void) rpcsvc_set_outstanding_rpc_limit (rpc_conf, options); + list_for_each_entry (listeners, &(rpc_conf->listeners), list) { + if (listeners->trans != NULL) { + if (listeners->trans->reconfigure ) + listeners->trans->reconfigure (listeners->trans, options); + else + gf_log (this->name, GF_LOG_ERROR, + "Reconfigure not found for transport" ); + } + } + ret = server_init_grace_timer (this, options, conf); + +out: + gf_log ("", GF_LOG_DEBUG, "returning %d", ret); + return ret; +} + +static int32_t +client_destroy_cbk (xlator_t *this, client_t *client) +{ + void *tmp = NULL; + server_ctx_t *ctx = NULL; + + client_ctx_del (client, this, &tmp); + + ctx = tmp; + + if (ctx == NULL) + return 0; + + gf_fd_fdtable_destroy (ctx->fdtable); + LOCK_DESTROY (&ctx->fdtable_lock); + GF_FREE (ctx); + + return 0; +} + +int +init (xlator_t *this) +{ + int32_t ret = -1; + server_conf_t *conf = NULL; + rpcsvc_listener_t *listener = NULL; + char *statedump_path = NULL; + gf_barrier_t *barrier = NULL; + char *str = NULL; + GF_VALIDATE_OR_GOTO ("init", this, out); + + if (this->children == NULL) { + gf_log (this->name, GF_LOG_ERROR, + "protocol/server should have subvolume"); + goto out; + } + + if (this->parents != NULL) { + gf_log (this->name, GF_LOG_ERROR, + "protocol/server should not have parent volumes"); + goto out; + } + + conf = GF_CALLOC (1, sizeof (server_conf_t), + gf_server_mt_server_conf_t); + + GF_VALIDATE_OR_GOTO(this->name, conf, out); + + INIT_LIST_HEAD (&conf->xprt_list); + pthread_mutex_init (&conf->mutex, NULL); + + ret = server_init_grace_timer (this, this->options, conf); + if (ret) + goto out; + + ret = server_build_config (this, conf); + if (ret) + goto out; + + ret = dict_get_str (this->options, "config-directory", &conf->conf_dir); + if (ret) + conf->conf_dir = CONFDIR; + + /*ret = dict_get_str (this->options, "statedump-path", &statedump_path); + if (!ret) { + gf_path_strip_trailing_slashes (statedump_path); + this->ctx->statedump_path = statedump_path; + }*/ + GF_OPTION_INIT ("statedump-path", statedump_path, path, out); + if (statedump_path) { + gf_path_strip_trailing_slashes (statedump_path); + this->ctx->statedump_path = gf_strdup (statedump_path); + } else { + gf_log (this->name, GF_LOG_ERROR, + "Error setting statedump path"); + ret = -1; + goto out; + } + + /* Authentication modules */ + conf->auth_modules = dict_new (); + GF_VALIDATE_OR_GOTO(this->name, conf->auth_modules, out); + + dict_foreach (this->options, get_auth_types, conf->auth_modules); + ret = validate_auth_options (this, this->options); + if (ret == -1) { + /* logging already done in validate_auth_options function. */ + goto out; + } + + ret = gf_auth_init (this, conf->auth_modules); + if (ret) { + dict_unref (conf->auth_modules); + goto out; + } + + /* RPC related */ + conf->rpc = rpcsvc_init (this, this->ctx, this->options, 0); + if (conf->rpc == NULL) { + gf_log (this->name, GF_LOG_WARNING, + "creation of rpcsvc failed"); + ret = -1; + goto out; + } + + ret = rpcsvc_create_listeners (conf->rpc, this->options, + this->name); + if (ret < 1) { + gf_log (this->name, GF_LOG_WARNING, + "creation of listener failed"); + ret = -1; + goto out; + } + + ret = rpcsvc_register_notify (conf->rpc, server_rpc_notify, this); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "registration of notify with rpcsvc failed"); + goto out; + } + + glusterfs3_3_fop_prog.options = this->options; + ret = rpcsvc_program_register (conf->rpc, &glusterfs3_3_fop_prog); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "registration of program (name:%s, prognum:%d, " + "progver:%d) failed", glusterfs3_3_fop_prog.progname, + glusterfs3_3_fop_prog.prognum, + glusterfs3_3_fop_prog.progver); + goto out; + } + + gluster_handshake_prog.options = this->options; + ret = rpcsvc_program_register (conf->rpc, &gluster_handshake_prog); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "registration of program (name:%s, prognum:%d, " + "progver:%d) failed", gluster_handshake_prog.progname, + gluster_handshake_prog.prognum, + gluster_handshake_prog.progver); + rpcsvc_program_unregister (conf->rpc, &glusterfs3_3_fop_prog); + goto out; + } + +#ifndef GF_DARWIN_HOST_OS + { + struct rlimit lim; + + lim.rlim_cur = 1048576; + lim.rlim_max = 1048576; + + if (setrlimit (RLIMIT_NOFILE, &lim) == -1) { + gf_log (this->name, GF_LOG_WARNING, + "WARNING: Failed to set 'ulimit -n 1M': %s", + strerror(errno)); + lim.rlim_cur = 65536; + lim.rlim_max = 65536; + + if (setrlimit (RLIMIT_NOFILE, &lim) == -1) { + gf_log (this->name, GF_LOG_WARNING, + "Failed to set max open fd to 64k: %s", + strerror(errno)); + } else { + gf_log (this->name, GF_LOG_TRACE, + "max open fd set to 64k"); + } + } + } +#endif + /* barrier related */ + barrier = GF_CALLOC (1, sizeof (*barrier),1); + if (!barrier) { + gf_log (this->name, GF_LOG_WARNING, + "WARNING: Failed to allocate barrier"); + ret = -1; + goto out; + } + + LOCK_INIT (&barrier->lock); + INIT_LIST_HEAD (&barrier->queue); + barrier->on = _gf_false; + + GF_OPTION_INIT ("barrier-queue-length", barrier->max_size, + int64, out); + GF_OPTION_INIT ("barrier-timeout", barrier->time_out, + uint64, out); + + ret = dict_get_str (this->options, "barrier-fops", &str); + if (ret) { + gf_log (this->name, GF_LOG_DEBUG, + "setting barrier fops to default value"); + } + ret = gf_barrier_fops_configure (this, barrier, str); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "invalid barrier fops specified"); + goto out; + } + + conf->barrier = barrier; + this->private = conf; + + ret = 0; +out: + if (ret) { + if (this != NULL) { + this->fini (this); + } + + if (listener != NULL) { + rpcsvc_listener_destroy (listener); + } + } + + return ret; +} + + +void +fini (xlator_t *this) +{ +#if 0 + server_conf_t *conf = NULL; + + conf = this->private; + + if (conf) { + if (conf->rpc) { + /* TODO: memory leak here, have to free RPC */ + /* + if (conf->rpc->conn) { + rpcsvc_conn_destroy (conf->rpc->conn); + } + rpcsvc_fini (conf->rpc); + */ + ; + } + + if (conf->auth_modules) + dict_unref (conf->auth_modules); + + GF_FREE (conf); + } + + this->private = NULL; +#endif + return; +} + +int +notify (xlator_t *this, int32_t event, void *data, ...) +{ + int ret = 0; + int32_t val = 0; + dict_t *dict = NULL; + dict_t *output = NULL; + va_list ap; + + dict = data; + va_start (ap, data); + output = va_arg (ap, dict_t*); + va_end (ap); + + switch (event) { + case GF_EVENT_VOLUME_BARRIER_OP: + ret = dict_get_int32 (dict, "barrier", &val); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Wrong BARRIER event"); + goto out; + } + /* !val un-barrier, if val, barrier */ + if (val) { + ret = gf_barrier_start (this); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Barrier start failed"); + } else { + ret = gf_barrier_stop (this); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Barrier stop failed"); + } + ret = dict_set_int32 (output, "barrier-status", ret); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Failed to set barrier-status in dict"); + break; + + /* todo: call default_notify to make other xlators handle it.*/ + default: + default_notify (this, event, data); + break; + } +out: + return ret; +} + + +struct xlator_fops fops; + +struct xlator_cbks cbks = { + .client_destroy = client_destroy_cbk, +}; + +struct xlator_dumpops dumpops = { + .priv = server_priv, + .fd = gf_client_dump_fdtables, + .inode = gf_client_dump_inodes, + .priv_to_dict = server_priv_to_dict, + .fd_to_dict = gf_client_dump_fdtables_to_dict, + .inode_to_dict = gf_client_dump_inodes_to_dict, +}; + + +struct volume_options options[] = { + { .key = {"transport-type"}, + .value = {"rpc", "rpc-over-rdma", "tcp", "socket", "ib-verbs", + "unix", "ib-sdp", "tcp/server", "ib-verbs/server", "rdma", + "rdma*([ \t]),*([ \t])socket", + "rdma*([ \t]),*([ \t])tcp", + "tcp*([ \t]),*([ \t])rdma", + "socket*([ \t]),*([ \t])rdma"}, + .type = GF_OPTION_TYPE_STR + }, + { .key = {"volume-filename.*"}, + .type = GF_OPTION_TYPE_PATH, + }, + { .key = {"transport.*"}, + .type = GF_OPTION_TYPE_ANY, + }, + { .key = {"rpc*"}, + .type = GF_OPTION_TYPE_ANY, + }, + { .key = {"inode-lru-limit"}, + .type = GF_OPTION_TYPE_INT, + .min = 0, + .max = (1 * GF_UNIT_MB), + .default_value = "16384", + .description = "Specifies the maximum megabytes of memory to be " + "used in the inode cache." + }, + { .key = {"verify-volfile-checksum"}, + .type = GF_OPTION_TYPE_BOOL + }, + { .key = {"trace"}, + .type = GF_OPTION_TYPE_BOOL + }, + { .key = {"config-directory", + "conf-dir"}, + .type = GF_OPTION_TYPE_PATH, + }, + { .key = {"rpc-auth-allow-insecure"}, + .type = GF_OPTION_TYPE_BOOL, + }, + { .key = {"root-squash"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "off", + .description = "Map requests from uid/gid 0 to the anonymous " + "uid/gid. Note that this does not apply to any other" + "uids or gids that might be equally sensitive, such as" + "user bin or group staff." + }, + { .key = {"statedump-path"}, + .type = GF_OPTION_TYPE_PATH, + .default_value = DEFAULT_VAR_RUN_DIRECTORY, + .description = "Specifies directory in which gluster should save its" + " statedumps. By default it is the /tmp directory" + }, + { .key = {"lk-heal"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "off", + }, + {.key = {"grace-timeout"}, + .type = GF_OPTION_TYPE_INT, + .min = 10, + .max = 1800, + }, + {.key = {"tcp-window-size"}, + .type = GF_OPTION_TYPE_SIZET, + .min = GF_MIN_SOCKET_WINDOW_SIZE, + .max = GF_MAX_SOCKET_WINDOW_SIZE, + .description = "Specifies the window size for tcp socket." + }, + + /* The following two options are defined in addr.c, redifined here * + * for the sake of validation during volume set from cli */ + + { .key = {"auth.addr.*.allow"}, + .type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST, + .description = "Allow a comma separated list of addresses and/or " + "hostnames to connect to the server. By default, all" + " connections are allowed." + }, + { .key = {"auth.addr.*.reject"}, + .type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST, + .description = "Reject a comma separated list of addresses and/or " + "hostnames to connect to the server. By default, all" + " connections are allowed." + }, + {.key = {"barrier-timeout"}, + .type = GF_OPTION_TYPE_INT, + .default_value = "60", + .min = 0, + .max = 360, + .description = "Barrier timeout in seconds", + }, + {.key = {"barrier-queue-length"}, + .type = GF_OPTION_TYPE_INT, + .default_value = "4096", + .min = 0, + .max = 16384, + .description = "Barrier queue length", + }, + {.key = {"barrier-fops"}, + .type = GF_OPTION_TYPE_STR, + .description = "Allow a comma seperated fop lists", + }, + { .key = {NULL} }, +}; diff --git a/xlators/protocol/server/src/server.h b/xlators/protocol/server/src/server.h new file mode 100644 index 000000000..782327d77 --- /dev/null +++ b/xlators/protocol/server/src/server.h @@ -0,0 +1,196 @@ +/* + Copyright (c) 2010-2013 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 _SERVER_H +#define _SERVER_H + +#include <pthread.h> + +#include "fd.h" +#include "rpcsvc.h" + +#include "fd.h" +#include "protocol-common.h" +#include "server-mem-types.h" +#include "glusterfs3.h" +#include "timer.h" +#include "client_t.h" + +#define DEFAULT_BLOCK_SIZE 4194304 /* 4MB */ +#define DEFAULT_VOLUME_FILE_PATH CONFDIR "/glusterfs.vol" +#define GF_MAX_SOCKET_WINDOW_SIZE (1 * GF_UNIT_MB) +#define GF_MIN_SOCKET_WINDOW_SIZE (0) + +struct _gf_barrier_payload { + rpcsvc_request_t *req; + struct iovec rsp; + call_frame_t *frame; + struct iovec *payload; + struct iobref *iobref; + struct iobuf *iob; + int payload_count; + gf_boolean_t free_iobref; + struct list_head list; +}; + +typedef struct _gf_barrier_payload gf_barrier_payload_t; + +struct _gf_barrier { + gf_lock_t lock; + gf_boolean_t on; + gf_boolean_t force; + size_t cur_size; + int64_t max_size; + uint64_t fops; + gf_timer_t *timer; + uint64_t time_out; + struct list_head queue; +}; + +typedef struct _gf_barrier gf_barrier_t; + +typedef enum { + INTERNAL_LOCKS = 1, + POSIX_LOCKS = 2, +} server_lock_flags_t; + +typedef struct _server_state server_state_t; + +int server_null (rpcsvc_request_t *req); + +struct _volfile_ctx { + struct _volfile_ctx *next; + char *key; + uint32_t checksum; +}; + +struct server_conf { + rpcsvc_t *rpc; + struct rpcsvc_config rpc_conf; + int inode_lru_limit; + gf_boolean_t verify_volfile; + gf_boolean_t trace; + gf_boolean_t lk_heal; /* If true means lock self + heal is on else off. */ + char *conf_dir; + struct _volfile_ctx *volfile; + struct timespec grace_ts; + dict_t *auth_modules; + pthread_mutex_t mutex; + gf_barrier_t *barrier; + struct list_head xprt_list; + pthread_t barrier_th; +}; +typedef struct server_conf server_conf_t; + + +typedef enum { + RESOLVE_MUST = 1, + RESOLVE_NOT, + RESOLVE_MAY, + RESOLVE_DONTCARE, + RESOLVE_EXACT +} server_resolve_type_t; + + +struct resolve_comp { + char *basename; + inode_t *inode; +}; + +typedef struct { + server_resolve_type_t type; + int64_t fd_no; + u_char gfid[16]; + u_char pargfid[16]; + char *path; + char *bname; + int op_ret; + int op_errno; + loc_t resolve_loc; +} server_resolve_t; + + +typedef int (*server_resume_fn_t) (call_frame_t *frame, xlator_t *bound_xl); + +int +resolve_and_resume (call_frame_t *frame, server_resume_fn_t fn); + +struct _server_state { + rpc_transport_t *xprt; + inode_table_t *itable; + + server_resume_fn_t resume_fn; + + loc_t loc; + loc_t loc2; + server_resolve_t resolve; + server_resolve_t resolve2; + + /* used within resolve_and_resume */ + loc_t *loc_now; + server_resolve_t *resolve_now; + + struct iatt stbuf; + int valid; + + fd_t *fd; + dict_t *params; + int32_t flags; + int wbflags; + struct iovec payload_vector[MAX_IOVEC]; + int payload_count; + struct iobuf *iobuf; + struct iobref *iobref; + + size_t size; + off_t offset; + mode_t mode; + dev_t dev; + size_t nr_count; + int cmd; + int type; + char *name; + int name_len; + + int mask; + char is_revalidate; + dict_t *dict; + struct gf_flock flock; + const char *volume; + dir_entry_t *entry; + + dict_t *xdata; + mode_t umask; +}; + + +extern struct rpcsvc_program gluster_handshake_prog; +extern struct rpcsvc_program glusterfs3_3_fop_prog; +extern struct rpcsvc_program gluster_ping_prog; + + +typedef struct _server_ctx { + gf_lock_t fdtable_lock; + fdtable_t *fdtable; + struct _gf_timer *grace_timer; + uint32_t lk_version; +} server_ctx_t; + + +int +server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg, + struct iovec *payload, int payloadcount, + struct iobref *iobref, xdrproc_t xdrproc); + +int gf_server_check_setxattr_cmd (call_frame_t *frame, dict_t *dict); +int gf_server_check_getxattr_cmd (call_frame_t *frame, const char *name); + +#endif /* !_SERVER_H */ |
