diff options
Diffstat (limited to 'xlators/protocol/server/src')
| -rw-r--r-- | xlators/protocol/server/src/Makefile.am | 20 | ||||
| -rw-r--r-- | xlators/protocol/server/src/authenticate.c | 108 | ||||
| -rw-r--r-- | xlators/protocol/server/src/authenticate.h | 19 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-handshake.c | 230 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-helpers.c | 1388 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-helpers.h | 68 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-mem-types.h | 20 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-resolve.c | 457 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-rpc-fops.c | 6179 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server.c | 887 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server.h | 143 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server3_1-fops.c | 5198 |
12 files changed, 7903 insertions, 6814 deletions
diff --git a/xlators/protocol/server/src/Makefile.am b/xlators/protocol/server/src/Makefile.am index 72a581ddf..6a18bf025 100644 --- a/xlators/protocol/server/src/Makefile.am +++ b/xlators/protocol/server/src/Makefile.am @@ -1,24 +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.c server-resolve.c server-helpers.c \ - server3_1-fops.c server-handshake.c authenticate.c + server-rpc-fops.c server-handshake.c authenticate.c 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 \ - -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles \ - -DCONFDIR=\"$(sysconfdir)/glusterfs\" -D$(GF_HOST_OS) \ +AM_CPPFLAGS = $(GF_CPPFLAGS) \ + -I$(top_srcdir)/libglusterfs/src \ + -DCONFDIR=\"$(sysconfdir)/glusterfs\" \ -DLIBDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/auth\" \ - $(GF_CFLAGS) -I$(top_srcdir)/xlators/protocol/lib/src \ - -I$(top_srcdir)/rpc/rpc-lib/src/ \ - -I$(top_srcdir)/rpc/xdr/src/ \ - -I$(top_srcdir)/contrib/md5/ + -I$(top_srcdir)/xlators/protocol/lib/src \ + -I$(top_srcdir)/rpc/rpc-lib/src \ + -I$(top_srcdir)/rpc/xdr/src + +AM_CFLAGS = -Wall $(GF_CFLAGS) \ + -DDATADIR=\"$(localstatedir)\" CLEANFILES = *~ diff --git a/xlators/protocol/server/src/authenticate.c b/xlators/protocol/server/src/authenticate.c index 5a1c2a8c8..d8d138a84 100644 --- a/xlators/protocol/server/src/authenticate.c +++ b/xlators/protocol/server/src/authenticate.c @@ -1,21 +1,14 @@ /* - Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2007-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 Affero General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. + 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. +*/ - 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 - Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. -*/ #ifndef _CONFIG_H #define _CONFIG_H @@ -31,15 +24,15 @@ #include <errno.h> #include "authenticate.h" -static void +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; + 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; @@ -59,7 +52,7 @@ init (dict_t *this, char *key, data_t *value, void *data) if (-1 == ret) { dict_set (this, key, data_from_dynptr (NULL, 0)); *error = -1; - return; + return -1; } handle = dlopen (auth_file, RTLD_LAZY); @@ -69,7 +62,7 @@ init (dict_t *this, char *key, data_t *value, void *data) dict_set (this, key, data_from_dynptr (NULL, 0)); GF_FREE (auth_file); *error = -1; - return; + return -1; } GF_FREE (auth_file); @@ -78,8 +71,9 @@ init (dict_t *this, char *key, data_t *value, void *data) 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; + return -1; } auth_handle = GF_CALLOC (1, sizeof (*auth_handle), @@ -87,10 +81,18 @@ init (dict_t *this, char *key, data_t *value, void *data) if (!auth_handle) { dict_set (this, key, data_from_dynptr (NULL, 0)); *error = -1; - return; + 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, @@ -102,46 +104,54 @@ init (dict_t *this, char *key, data_t *value, void *data) dict_set (this, key, data_from_dynptr (auth_handle, sizeof (*auth_handle))); + return 0; } -static void +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; - auth_handle_t *handle = NULL; - data_pair_t *pair = NULL; dict_foreach (auth_modules, init, &ret); if (ret) goto out; - pair = auth_modules->members_list; - while (pair) { - handle = data_to_ptr (pair->value); - if (!handle) { - pair = pair->next; - continue; - } - - list_add_tail (&(handle->vol_opt->list), - &(xl->volume_options)); - ret = validate_xlator_volume_options (xl, - handle->vol_opt->given_opt); - if (ret) - gf_log ("authenticate", GF_LOG_ERROR, - "volume option validation failed"); - - pair = pair->next; - } + ret = dict_foreach (auth_modules, _gf_auth_option_validate, xl); out: if (ret) { @@ -155,7 +165,7 @@ out: static dict_t *__input_params; static dict_t *__config_params; -void +int map (dict_t *this, char *key, data_t *value, void *data) { dict_t *res = data; @@ -170,15 +180,16 @@ map (dict_t *this, char *key, data_t *value, void *data) } else { dict_set (res, key, int_to_data (AUTH_DONT_CARE)); } + return 0; } -void +int reduce (dict_t *this, char *key, data_t *value, void *data) { int64_t val = 0; int64_t *res = data; if (!data) - return; + return 0; val = data_to_int64 (value); switch (val) @@ -195,6 +206,7 @@ reduce (dict_t *this, char *key, data_t *value, void *data) case AUTH_DONT_CARE: break; } + return 0; } diff --git a/xlators/protocol/server/src/authenticate.h b/xlators/protocol/server/src/authenticate.h index 7c9dd58d2..d4d43e498 100644 --- a/xlators/protocol/server/src/authenticate.h +++ b/xlators/protocol/server/src/authenticate.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2007-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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 _AUTHENTICATE_H diff --git a/xlators/protocol/server/src/server-handshake.c b/xlators/protocol/server/src/server-handshake.c index 66b9ea78d..d4941011d 100644 --- a/xlators/protocol/server/src/server-handshake.c +++ b/xlators/protocol/server/src/server-handshake.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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. */ @@ -40,7 +31,7 @@ gf_compare_client_version (rpcsvc_request_t *req, int fop_prognum, { int ret = -1; /* TODO: think.. */ - if (glusterfs3_1_fop_prog.prognum == fop_prognum) + if (glusterfs3_3_fop_prog.prognum == fop_prognum) ret = 0; return ret; @@ -103,9 +94,9 @@ _volfile_update_checksum (xlator_t *this, char *key, uint32_t checksum) if (temp_volfile->checksum != checksum) { gf_log (this->name, GF_LOG_INFO, - "the volume file got modified between earlier access " - "and now, this may lead to inconsistency between " - "clients, advised to remount client"); + "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; } @@ -118,10 +109,10 @@ static size_t getspec_build_volfile_path (xlator_t *this, const char *key, char *path, size_t path_len) { - int ret = -1; + char *filename = NULL; + server_conf_t *conf = NULL; + int ret = -1; int free_filename = 0; - char *filename = NULL; - server_conf_t *conf = NULL; char data_key[256] = {0,}; conf = this->private; @@ -190,7 +181,7 @@ int _validate_volfile_checksum (xlator_t *this, char *key, uint32_t checksum) { - char filename[ZR_PATH_MAX] = {0,}; + char filename[PATH_MAX] = {0,}; server_conf_t *conf = NULL; struct _volfile_ctx *temp_volfile = NULL; int ret = 0; @@ -253,7 +244,7 @@ server_getspec (rpcsvc_request_t *req) int32_t op_errno = ENOENT; int32_t spec_fd = -1; size_t file_len = 0; - char filename[ZR_PATH_MAX] = {0,}; + char filename[PATH_MAX] = {0,}; struct stat stbuf = {0,}; uint32_t checksum = 0; char *key = NULL; @@ -261,12 +252,12 @@ server_getspec (rpcsvc_request_t *req) xlator_t *this = NULL; gf_getspec_req args = {0,}; gf_getspec_rsp rsp = {0,}; - server_connection_t *conn = NULL; - conn = req->trans->private; this = req->svc->mydata; conf = this->private; - if (xdr_to_glusterfs_req (req, &args, xdr_to_getspec_req)) { + 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; @@ -313,8 +304,6 @@ server_getspec (rpcsvc_request_t *req) goto fail; } ret = read (spec_fd, rsp.spec, file_len); - - close (spec_fd); } /* convert to XDR */ @@ -325,8 +314,11 @@ fail: 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, - (gfs_serialize_t)xdr_serialize_getspec_rsp); + (xdrproc_t)xdr_gf_getspec_rsp); return 0; } @@ -337,14 +329,16 @@ server_setvolume (rpcsvc_request_t *req) { gf_setvolume_req args = {{0,},}; gf_setvolume_rsp rsp = {0,}; - server_connection_t *conn = NULL; + 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 *process_uuid = NULL; + char *client_uid = NULL; + char *clnt_version = NULL; xlator_t *xl = NULL; char *msg = NULL; char *volfile_key = NULL; @@ -355,11 +349,15 @@ server_setvolume (rpcsvc_request_t *req) 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 (); - if (xdr_to_glusterfs_req (req, &args, xdr_to_setvolume_req)) { + 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; @@ -396,7 +394,7 @@ server_setvolume (rpcsvc_request_t *req) params->extra_free = buf; buf = NULL; - ret = dict_get_str (params, "process-uuid", &process_uuid); + ret = dict_get_str (params, "process-uuid", &client_uid); if (ret < 0) { ret = dict_set_str (reply, "ERROR", "UUID not specified"); @@ -409,10 +407,46 @@ server_setvolume (rpcsvc_request_t *req) 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"); - conn = server_connection_get (this, process_uuid); - if (req->trans->xl_private != conn) - req->trans->xl_private = conn; + 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) { @@ -525,34 +559,42 @@ server_setvolume (rpcsvc_request_t *req) "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", - (peerinfo)?peerinfo->identifier:""); + "accepted client from %s (version: %s)", + client->client_uid, + (clnt_version) ? clnt_version : "old"); op_ret = 0; - conn->bound_xl = xl; + 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", - (peerinfo)? peerinfo->identifier:"<>"); + "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 (conn->bound_xl == NULL) { + if (client->bound_xl == NULL) { ret = dict_set_str (reply, "ERROR", "Check volfile and handshake " "options in protocol/client"); @@ -565,20 +607,21 @@ server_setvolume (rpcsvc_request_t *req) goto fail; } - if ((conn->bound_xl != NULL) && + if ((client->bound_xl != NULL) && (ret >= 0) && - (conn->bound_xl->itable == NULL)) { + (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, - conn->bound_xl->name); + client->bound_xl->name); /* TODO: what is this ? */ - conn->bound_xl->itable = inode_table_new (conf->inode_lru_limit, - conn->bound_xl); + client->bound_xl->itable = + inode_table_new (conf->inode_lru_limit, + client->bound_xl); } ret = dict_set_str (reply, "process-uuid", @@ -587,6 +630,11 @@ server_setvolume (rpcsvc_request_t *req) 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) @@ -619,23 +667,34 @@ fail: 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, - (gfs_serialize_t)xdr_serialize_setvolume_rsp); + (xdrproc_t)xdr_gf_setvolume_rsp); - if (args.dict.dict_val) - free (args.dict.dict_val); + free (args.dict.dict_val); - if (rsp.dict.dict_val) - GF_FREE (rsp.dict.dict_val); + GF_FREE (rsp.dict.dict_val); dict_unref (params); dict_unref (reply); dict_unref (config_params); - if (buf) { - GF_FREE (buf); - } + GF_FREE (buf); return 0; } @@ -650,17 +709,66 @@ server_ping (rpcsvc_request_t *req) rsp.op_ret = 0; server_submit_reply (NULL, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); + (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, NULL }, - [GF_HNDSK_SETVOLUME] = {"SETVOLUME", GF_HNDSK_SETVOLUME, server_setvolume, NULL, NULL }, - [GF_HNDSK_GETSPEC] = {"GETSPEC", GF_HNDSK_GETSPEC, server_getspec, NULL, NULL }, - [GF_HNDSK_PING] = {"PING", GF_HNDSK_PING, server_ping, NULL, NULL }, + [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}, }; diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c index 1abe4d2d8..f0b040c74 100644 --- a/xlators/protocol/server/src/server-helpers.c +++ b/xlators/protocol/server/src/server-helpers.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -35,11 +26,14 @@ server_decode_groups (call_frame_t *frame, rpcsvc_request_t *req) 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_REQUEST_MAXGROUPS) + if (frame->root->ngrps > GF_MAX_AUX_GROUPS) return -1; for (; i < frame->root->ngrps; ++i) @@ -48,6 +42,7 @@ out: return 0; } + void server_loc_wipe (loc_t *loc) { @@ -61,47 +56,24 @@ server_loc_wipe (loc_t *loc) loc->inode = NULL; } - if (loc->path) - GF_FREE ((void *)loc->path); + GF_FREE ((void *)loc->path); } void server_resolve_wipe (server_resolve_t *resolve) { - struct resolve_comp *comp = NULL; - int i = 0; - - if (resolve->path) - GF_FREE ((void *)resolve->path); + GF_FREE ((void *)resolve->path); - if (resolve->bname) - GF_FREE ((void *)resolve->bname); - - if (resolve->resolved) - GF_FREE ((void *)resolve->resolved); + GF_FREE ((void *)resolve->bname); - loc_wipe (&resolve->deep_loc); - - comp = resolve->components; - if (comp) { - for (i = 0; comp[i].basename; i++) { - if (comp[i].inode) - inode_unref (comp[i].inode); - } - GF_FREE ((void *)resolve->components); - } + loc_wipe (&resolve->resolve_loc); } void free_state (server_state_t *state) { - if (state->conn) { - //xprt_svc_unref (state->conn); - state->conn = NULL; - } - if (state->xprt) { rpc_transport_unref (state->xprt); state->xprt = NULL; @@ -131,11 +103,14 @@ free_state (server_state_t *state) state->dict = NULL; } - if (state->volume) - GF_FREE ((void *)state->volume); + if (state->xdata) { + dict_unref (state->xdata); + state->xdata = NULL; + } - if (state->name) - GF_FREE ((void *)state->name); + GF_FREE ((void *)state->volume); + + GF_FREE ((void *)state->name); server_loc_wipe (&state->loc); server_loc_wipe (&state->loc2); @@ -147,302 +122,26 @@ free_state (server_state_t *state) } -int -gf_add_locker (struct _lock_table *table, const char *volume, - loc_t *loc, fd_t *fd, pid_t pid, uint64_t owner, - glusterfs_fop_t type) -{ - int32_t ret = -1; - struct _locker *new = NULL; - - GF_VALIDATE_OR_GOTO ("server", table, out); - GF_VALIDATE_OR_GOTO ("server", volume, out); - - new = GF_CALLOC (1, sizeof (struct _locker), gf_server_mt_locker_t); - if (new == NULL) { - goto out; - } - INIT_LIST_HEAD (&new->lockers); - - new->volume = gf_strdup (volume); - - if (fd == NULL) { - loc_copy (&new->loc, loc); - } else { - new->fd = fd_ref (fd); - } - - new->pid = pid; - new->owner = owner; - - LOCK (&table->lock); - { - if (type == GF_FOP_ENTRYLK) - list_add_tail (&new->lockers, &table->entrylk_lockers); - else - list_add_tail (&new->lockers, &table->inodelk_lockers); - } - UNLOCK (&table->lock); -out: - return ret; -} - - -int -gf_del_locker (struct _lock_table *table, const char *volume, - loc_t *loc, fd_t *fd, uint64_t owner, glusterfs_fop_t type) -{ - struct _locker *locker = NULL; - struct _locker *tmp = NULL; - int32_t ret = -1; - struct list_head *head = NULL; - struct list_head del; - - GF_VALIDATE_OR_GOTO ("server", table, out); - GF_VALIDATE_OR_GOTO ("server", volume, out); - - INIT_LIST_HEAD (&del); - - LOCK (&table->lock); - { - if (type == GF_FOP_ENTRYLK) { - head = &table->entrylk_lockers; - } else { - head = &table->inodelk_lockers; - } - - list_for_each_entry_safe (locker, tmp, head, lockers) { - if (locker->fd && fd && - (locker->fd == fd) && (locker->owner == owner) - && !strcmp (locker->volume, volume)) { - list_move_tail (&locker->lockers, &del); - } else if (locker->loc.inode && - loc && - (locker->loc.inode == loc->inode) && - (locker->owner == owner) - && !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); - - GF_FREE (locker->volume); - GF_FREE (locker); - } - - ret = 0; -out: - return ret; -} - -static struct _lock_table * -gf_lock_table_new (void) -{ - struct _lock_table *new = NULL; - - new = GF_CALLOC (1, sizeof (struct _lock_table), gf_server_mt_lock_table_t); - if (new == NULL) { - goto out; - } - INIT_LIST_HEAD (&new->entrylk_lockers); - INIT_LIST_HEAD (&new->inodelk_lockers); - LOCK_INIT (&new->lock); -out: - return new; -} - -static int -server_nop_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - int ret = -1; - server_state_t *state = NULL; - - GF_VALIDATE_OR_GOTO ("server", frame, out); - GF_VALIDATE_OR_GOTO ("server", cookie, out); - GF_VALIDATE_OR_GOTO ("server", this, out); - - state = CALL_STATE(frame); - - if (state) - free_state (state); - STACK_DESTROY (frame->root); - - ret = 0; -out: - return ret; -} - -int -do_lock_table_cleanup (xlator_t *this, server_connection_t *conn, - call_frame_t *frame, struct _lock_table *ltable) -{ - struct list_head inodelk_lockers, entrylk_lockers; - call_frame_t *tmp_frame = NULL; - struct gf_flock flock = {0, }; - xlator_t *bound_xl = NULL; - struct _locker *locker = NULL, *tmp = NULL; - int ret = -1; - char *path = NULL; - - GF_VALIDATE_OR_GOTO ("server", this, out); - GF_VALIDATE_OR_GOTO ("server", conn, out); - GF_VALIDATE_OR_GOTO ("server", frame, out); - GF_VALIDATE_OR_GOTO ("server", ltable, out); - - bound_xl = conn->bound_xl; - INIT_LIST_HEAD (&inodelk_lockers); - INIT_LIST_HEAD (&entrylk_lockers); - - LOCK (<able->lock); - { - list_splice_init (<able->inodelk_lockers, - &inodelk_lockers); - - list_splice_init (<able->entrylk_lockers, &entrylk_lockers); - } - UNLOCK (<able->lock); - - GF_FREE (ltable); - - flock.l_type = F_UNLCK; - flock.l_start = 0; - flock.l_len = 0; - list_for_each_entry_safe (locker, - tmp, &inodelk_lockers, lockers) { - tmp_frame = copy_frame (frame); - if (tmp_frame == NULL) { - goto out; - } - /* - lock owner = 0 is a special case that tells posix-locks - to release all locks from this transport - */ - tmp_frame->root->pid = 0; - tmp_frame->root->lk_owner = 0; - tmp_frame->root->trans = conn; - - if (locker->fd) { - GF_ASSERT (locker->fd->inode); - - ret = inode_path (locker->fd->inode, NULL, &path); - - if (ret > 0) { - gf_log (this->name, GF_LOG_INFO, "finodelk " - "released on %s", path); - GF_FREE (path); - } else { - - gf_log (this->name, GF_LOG_INFO, "finodelk " - "released on ino %"PRId64" with gfid %s", - locker->fd->inode->ino, - uuid_utoa (locker->fd->inode->gfid)); - } - - 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 { - gf_log (this->name, GF_LOG_INFO, "inodelk released " - "on %s", locker->loc.path); - - STACK_WIND (tmp_frame, server_nop_cbk, bound_xl, - bound_xl->fops->inodelk, - locker->volume, - &(locker->loc), F_SETLK, &flock); - loc_wipe (&locker->loc); - } - - GF_FREE (locker->volume); - - list_del_init (&locker->lockers); - GF_FREE (locker); - } - - tmp = NULL; - locker = NULL; - list_for_each_entry_safe (locker, tmp, &entrylk_lockers, lockers) { - tmp_frame = copy_frame (frame); - - tmp_frame->root->lk_owner = 0; - tmp_frame->root->pid = 0; - tmp_frame->root->trans = conn; - - if (locker->fd) { - GF_ASSERT (locker->fd->inode); - - ret = inode_path (locker->fd->inode, NULL, &path); - - if (ret > 0) { - gf_log (this->name, GF_LOG_INFO, "fentrylk " - "released on %s", path); - GF_FREE (path); - } else { - - gf_log (this->name, GF_LOG_INFO, "fentrylk " - "released on ino %lu", locker->fd->inode->ino); - } - - 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 { - gf_log (this->name, GF_LOG_INFO, "entrylk released " - "on %s", locker->loc.path); - - 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); - } - - GF_FREE (locker->volume); - - list_del_init (&locker->lockers); - GF_FREE (locker); - } - ret = 0; - -out: - return ret; -} - - static int server_connection_cleanup_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno) + int32_t op_errno, dict_t *xdata) { - int32_t ret = -1; - fd_t *fd = NULL; + 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; @@ -451,9 +150,8 @@ out: } -int -do_fd_cleanup (xlator_t *this, server_connection_t *conn, call_frame_t *frame, - fdentry_t *fdentries, int fd_count) +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; @@ -462,16 +160,14 @@ do_fd_cleanup (xlator_t *this, server_connection_t *conn, call_frame_t *frame, char *path = NULL; GF_VALIDATE_OR_GOTO ("server", this, out); - GF_VALIDATE_OR_GOTO ("server", conn, out); - GF_VALIDATE_OR_GOTO ("server", frame, out); GF_VALIDATE_OR_GOTO ("server", fdentries, out); - bound_xl = conn->bound_xl; + bound_xl = client->bound_xl; for (i = 0;i < fd_count; i++) { fd = fdentries[i].fd; if (fd != NULL) { - tmp_frame = copy_frame (frame); + tmp_frame = create_frame (this, this->ctx->pool); if (tmp_frame == NULL) { goto out; } @@ -481,25 +177,26 @@ do_fd_cleanup (xlator_t *this, server_connection_t *conn, call_frame_t *frame, ret = inode_path (fd->inode, NULL, &path); if (ret > 0) { - gf_log (this->name, GF_LOG_INFO, "fd cleanup on " - "%s", path); + 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 " - "ino %"PRId64" with gfid %s", - fd->inode->ino, + 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; - tmp_frame->root->trans = conn; - tmp_frame->root->lk_owner = 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); + bound_xl, bound_xl->fops->flush, fd, NULL); } } @@ -510,379 +207,72 @@ out: return ret; } + int -do_connection_cleanup (xlator_t *this, server_connection_t *conn, - struct _lock_table *ltable, fdentry_t *fdentries, int fd_count) +server_connection_cleanup (xlator_t *this, client_t *client, + int32_t flags) { - int ret = 0; - int saved_ret = 0; - call_frame_t *frame = NULL; - server_state_t *state = NULL; - - GF_VALIDATE_OR_GOTO ("server", this, out); - GF_VALIDATE_OR_GOTO ("server", conn, out); - GF_VALIDATE_OR_GOTO ("server", fdentries, out); - GF_VALIDATE_OR_GOTO ("server", ltable, out); - - frame = create_frame (this, this->ctx->pool); - if (frame == NULL) { - goto out; - } - - saved_ret = do_lock_table_cleanup (this, conn, frame, ltable); - - if (fdentries != NULL) { - ret = do_fd_cleanup (this, conn, frame, fdentries, fd_count); - } + server_ctx_t *serv_ctx = NULL; + fdentry_t *fdentries = NULL; + uint32_t fd_count = 0; + int cd_ret = 0; + int ret = 0; - state = CALL_STATE (frame); - if (state) - GF_FREE (state); + GF_VALIDATE_OR_GOTO (this->name, this, out); + GF_VALIDATE_OR_GOTO (this->name, client, out); + GF_VALIDATE_OR_GOTO (this->name, flags, out); - STACK_DESTROY (frame->root); + serv_ctx = server_ctx_get (client, client->this); - if (saved_ret || ret) { - ret = -1; + if (serv_ctx == NULL) { + gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed"); + goto out; } -out: - return ret; -} - - -int -server_connection_cleanup (xlator_t *this, server_connection_t *conn) -{ - char do_cleanup = 0; - struct _lock_table *ltable = NULL; - fdentry_t *fdentries = NULL; - uint32_t fd_count = 0; - int ret = 0; - - GF_VALIDATE_OR_GOTO ("server", this, out); - GF_VALIDATE_OR_GOTO ("server", conn, out); - - pthread_mutex_lock (&conn->lock); + LOCK (&serv_ctx->fdtable_lock); { - conn->active_transports--; - if (conn->active_transports == 0) { - if (conn->ltable) { - ltable = conn->ltable; - conn->ltable = gf_lock_table_new (); - } - - if (conn->fdtable) { - fdentries = gf_fd_fdtable_get_all_fds (conn->fdtable, - &fd_count); - } - do_cleanup = 1; - } + if (serv_ctx->fdtable && (flags & POSIX_LOCKS)) + fdentries = gf_fd_fdtable_get_all_fds (serv_ctx->fdtable, + &fd_count); } - pthread_mutex_unlock (&conn->lock); - - if (do_cleanup && conn->bound_xl) - ret = do_connection_cleanup (this, conn, ltable, fdentries, fd_count); - -out: - return ret; -} - - -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 inodelk_lockers; - struct list_head entrylk_lockers; - struct _lock_table *ltable = NULL; - struct _locker *locker = NULL, *tmp = NULL; - struct gf_flock flock = {0,}; - fd_t *fd = NULL; - int32_t i = 0; - fdentry_t *fdentries = NULL; - uint32_t fd_count = 0; - char *path = NULL; - - GF_VALIDATE_OR_GOTO ("server", this, out); - GF_VALIDATE_OR_GOTO ("server", conn, out); - - 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 (&inodelk_lockers); - INIT_LIST_HEAD (&entrylk_lockers); - - if (ltable) { - LOCK (<able->lock); - { - list_splice_init (<able->inodelk_lockers, - &inodelk_lockers); + UNLOCK (&serv_ctx->fdtable_lock); - list_splice_init (<able->entrylk_lockers, &entrylk_lockers); - } - UNLOCK (<able->lock); - GF_FREE (ltable); - } - - flock.l_type = F_UNLCK; - flock.l_start = 0; - flock.l_len = 0; - list_for_each_entry_safe (locker, - tmp, &inodelk_lockers, lockers) { - tmp_frame = copy_frame (frame); - /* - lock_owner = 0 is a special case that tells posix-locks - to release all locks from this transport - */ - tmp_frame->root->lk_owner = 0; - tmp_frame->root->trans = conn; - - if (locker->fd) { - GF_ASSERT (locker->fd->inode); - - ret = inode_path (locker->fd->inode, NULL, &path); - - if (ret > 0) { - gf_log (this->name, GF_LOG_INFO, "finodelk " - "released on %s", path); - GF_FREE (path); - } else { - - gf_log (this->name, GF_LOG_INFO, "finodelk " - "released on ino %"PRId64 "with gfid %s", - locker->fd->inode->ino, - uuid_utoa (locker->fd->inode->gfid)); - } - - 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 { - gf_log (this->name, GF_LOG_INFO, "inodelk " - "released on %s", locker->loc.path); - - STACK_WIND (tmp_frame, server_nop_cbk, bound_xl, - bound_xl->fops->inodelk, - locker->volume, - &(locker->loc), F_SETLK, &flock); - loc_wipe (&locker->loc); - } - - GF_FREE (locker->volume); - - list_del_init (&locker->lockers); - GF_FREE (locker); - } - - tmp = NULL; - locker = NULL; - list_for_each_entry_safe (locker, tmp, &entrylk_lockers, lockers) { - tmp_frame = copy_frame (frame); - - tmp_frame->root->lk_owner = 0; - tmp_frame->root->trans = conn; - - if (locker->fd) { - GF_ASSERT (locker->fd->inode); - - ret = inode_path (locker->fd->inode, NULL, &path); - - if (ret > 0) { - gf_log (this->name, GF_LOG_INFO, "fentrylk " - "released on %s", path); - - GF_FREE (path); - } else { - - gf_log (this->name, GF_LOG_INFO, "fentrylk " - "released on ino %"PRId64" and gfid= %s", - locker->fd->inode->ino, - uuid_utoa (locker->fd->inode->gfid)); - } - - 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 { - gf_log (this->name, GF_LOG_INFO, "entrylk " - "released on %s", locker->loc.path); - - 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); - } - - GF_FREE (locker->volume); - - list_del_init (&locker->lockers); - GF_FREE (locker); - } - - pthread_mutex_lock (&(conn->lock)); - { - if (conn->fdtable) { - fdentries = 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 (fdentries != NULL) { - for (i = 0; i < fd_count; i++) { - fd = fdentries[i].fd; - 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); - } - } - GF_FREE (fdentries); - } - } + if (client->bound_xl == NULL) + goto out; - if (frame) { - state = CALL_STATE (frame); - if (state) - GF_FREE (state); - STACK_DESTROY (frame->root); + if (flags & INTERNAL_LOCKS) { + cd_ret = gf_client_disconnect (client); } - gf_log (this->name, GF_LOG_INFO, "destroyed connection of %s", - conn->id); + if (fdentries != NULL) + ret = do_fd_cleanup (this, client, fdentries, fd_count); + else + gf_log (this->name, GF_LOG_INFO, "no fdentries to clean"); - GF_FREE (conn->id); - GF_FREE (conn); + if (cd_ret || ret) + ret = -1; out: return ret; } -server_connection_t * -server_connection_get (xlator_t *this, const char *id) -{ - server_connection_t *conn = NULL; - server_connection_t *trav = NULL; - server_conf_t *conf = NULL; - - GF_VALIDATE_OR_GOTO ("server", this, out); - GF_VALIDATE_OR_GOTO ("server", id, out); - - conf = this->private; - - pthread_mutex_lock (&conf->mutex); - { - list_for_each_entry (trav, &conf->conns, list) { - if (!strcmp (id, trav->id)) { - conn = trav; - break; - } - } - - if (!conn) { - conn = (void *) GF_CALLOC (1, sizeof (*conn), - gf_server_mt_conn_t); - if (!conn) - goto unlock; - - conn->id = gf_strdup (id); - conn->fdtable = gf_fd_fdtable_alloc (); - conn->ltable = gf_lock_table_new (); - conn->this = this; - pthread_mutex_init (&conn->lock, NULL); - - list_add (&conn->list, &conf->conns); - } - - conn->ref++; - conn->active_transports++; - } -unlock: - pthread_mutex_unlock (&conf->mutex); -out: - return conn; -} - - -void -server_connection_put (xlator_t *this, server_connection_t *conn) -{ - server_conf_t *conf = NULL; - server_connection_t *todel = NULL; - - GF_VALIDATE_OR_GOTO ("server", this, out); - GF_VALIDATE_OR_GOTO ("server", conn, out); - - conf = this->private; - GF_VALIDATE_OR_GOTO ("server", conf, out); - - pthread_mutex_lock (&conf->mutex); - { - conn->ref--; - - if (!conn->ref) { - list_del_init (&conn->list); - todel = conn; - } - } - pthread_mutex_unlock (&conf->mutex); - - if (todel) { - server_connection_destroy (this, todel); - } - -out: - return; -} - static call_frame_t * server_alloc_frame (rpcsvc_request_t *req) { - call_frame_t *frame = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; + 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); - conn = (server_connection_t *)req->trans->xl_private; - GF_VALIDATE_OR_GOTO ("server", conn, out); + client = req->trans->xl_private; + GF_VALIDATE_OR_GOTO ("server", client, out); - frame = create_frame (conn->this, req->svc->ctx->pool); + frame = create_frame (client->this, req->svc->ctx->pool); if (!frame) goto out; @@ -890,45 +280,46 @@ server_alloc_frame (rpcsvc_request_t *req) if (!state) goto out; - if (conn->bound_xl) - state->itable = conn->bound_xl->itable; + if (client->bound_xl) + state->itable = client->bound_xl->itable; state->xprt = rpc_transport_ref (req->trans); - state->conn = conn; - 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 = conn->this; + frame->this = client->this; out: return frame; } - call_frame_t * get_frame_from_request (rpcsvc_request_t *req) { - call_frame_t *frame = NULL; + call_frame_t *frame = NULL; + client_t *client = NULL; GF_VALIDATE_OR_GOTO ("server", req, out); + client = req->trans->xl_private; + frame = server_alloc_frame (req); if (!frame) goto out; frame->root->op = req->procnum; - frame->root->type = req->type; frame->root->unique = req->xid; frame->root->uid = req->uid; frame->root->gid = req->gid; frame->root->pid = req->pid; - frame->root->trans = req->trans->xl_private; + gf_client_ref (client); + frame->root->client = client; frame->root->lk_owner = req->lk_owner; server_decode_groups (frame, req); @@ -952,7 +343,7 @@ server_build_config (xlator_t *this, server_conf_t *conf) ret = dict_get_int32 (this->options, "inode-lru-limit", &conf->inode_lru_limit); if (ret < 0) { - conf->inode_lru_limit = 1024; + conf->inode_lru_limit = 16384; } conf->verify_volfile = 1; @@ -1013,73 +404,6 @@ out: return ret; } -server_connection_t * -get_server_conn_state (xlator_t *this, rpc_transport_t *xprt) -{ - GF_VALIDATE_OR_GOTO ("server", this, out); - GF_VALIDATE_OR_GOTO ("server", xprt, out); - - return (server_connection_t *)xprt->xl_private; -out: - return NULL; -} - -server_connection_t * -create_server_conn_state (xlator_t *this, rpc_transport_t *xprt) -{ - server_connection_t *conn = NULL; - int ret = -1; - - GF_VALIDATE_OR_GOTO ("server", this, out); - GF_VALIDATE_OR_GOTO ("server", xprt, out); - - conn = GF_CALLOC (1, sizeof (*conn), gf_server_mt_conn_t); - if (!conn) - goto out; - - pthread_mutex_init (&conn->lock, NULL); - - conn->fdtable = gf_fd_fdtable_alloc (); - if (!conn->fdtable) - goto out; - - conn->ltable = gf_lock_table_new (); - if (!conn->ltable) - goto out; - - conn->this = this; - - xprt->xl_private = conn; - - ret = 0; -out: - if (ret) - destroy_server_conn_state (conn); - - return conn; -} - -void -destroy_server_conn_state (server_connection_t *conn) -{ - GF_VALIDATE_OR_GOTO ("server", conn, out); - - if (conn->ltable) { - /* TODO */ - //FREE (conn->ltable); - ; - } - - if (conn->fdtable) - gf_fd_fdtable_destroy (conn->fdtable); - - pthread_mutex_destroy (&conn->lock); - - GF_FREE (conn); -out: - return; -} - void print_caller (char *str, int size, call_frame_t *frame) @@ -1118,15 +442,6 @@ server_print_resolve (char *str, int size, server_resolve_t *resolve) if (resolve->fd_no != -1) filled += snprintf (str + filled, size - filled, "fd=%"PRId64",", (uint64_t) resolve->fd_no); - if (resolve->ino) - filled += snprintf (str + filled, size - filled, - "ino=%"PRIu64",", (uint64_t) resolve->ino); - if (resolve->par) - filled += snprintf (str + filled, size - filled, - "par=%"PRIu64",", (uint64_t) resolve->par); - if (resolve->gen) - filled += snprintf (str + filled, size - filled, - "gen=%"PRIu64",", (uint64_t) resolve->gen); if (resolve->bname) filled += snprintf (str + filled, size - filled, "bname=%s,", resolve->bname); @@ -1215,27 +530,21 @@ server_print_params (char *str, int size, server_state_t *state) filled += snprintf (str + filled, size - filled, "volume=%s,", state->volume); +/* FIXME snprintf (str + filled, size - filled, - "bound_xl=%s}", state->conn->bound_xl->name); + "bound_xl=%s}", state->client->bound_xl->name); +*/ out: return; } + int server_resolve_is_empty (server_resolve_t *resolve) { if (resolve->fd_no != -1) return 0; - if (resolve->ino != 0) - return 0; - - if (resolve->gen != 0) - return 0; - - if (resolve->par != 0) - return 0; - if (resolve->path != 0) return 0; @@ -1245,6 +554,7 @@ server_resolve_is_empty (server_resolve_t *resolve) return 1; } + void server_print_reply (call_frame_t *frame, int op_ret, int op_errno) { @@ -1269,10 +579,7 @@ server_print_reply (call_frame_t *frame, int op_ret, int op_errno) switch (frame->root->type) { case GF_OP_TYPE_FOP: - op = gf_fop_list[frame->root->op]; - break; - case GF_OP_TYPE_MGMT: - op = gf_mgmt_list[frame->root->op]; + op = (char *)gf_fop_list[frame->root->op]; break; default: op = ""; @@ -1293,16 +600,16 @@ out: void server_print_request (call_frame_t *frame) { - server_conf_t *conf = NULL; - xlator_t *this = NULL; + 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]; - char *op = "UNKNOWN"; GF_VALIDATE_OR_GOTO ("server", frame, out); @@ -1338,10 +645,7 @@ server_print_request (call_frame_t *frame) switch (frame->root->type) { case GF_OP_TYPE_FOP: - op = gf_fop_list[frame->root->op]; - break; - case GF_OP_TYPE_MGMT: - op = gf_mgmt_list[frame->root->op]; + op = (char *)gf_fop_list[frame->root->op]; break; default: op = ""; @@ -1356,13 +660,14 @@ 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; + 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); @@ -1376,21 +681,53 @@ serialize_rsp_direntp (gf_dirent_t *entries, gfs3_readdirp_rsp *rsp) trav->d_off = entry->d_off; trav->d_len = entry->d_len; trav->d_type = entry->d_type; - //trav->name = memdup (entry->d_name, entry->d_len + 1); 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; + } + + 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; + } + } + if (prev) prev->nextentry = trav; else rsp->reply = trav; prev = trav; + trav = NULL; } ret = 0; out: + GF_FREE (trav); + return ret; } @@ -1398,10 +735,10 @@ out: 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_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); @@ -1428,11 +765,12 @@ out: return ret; } + int readdir_rsp_cleanup (gfs3_readdir_rsp *rsp) { - gfs3_dirlist *prev = NULL; - gfs3_dirlist *trav = NULL; + gfs3_dirlist *prev = NULL; + gfs3_dirlist *trav = NULL; trav = rsp->reply; prev = trav; @@ -1445,6 +783,7 @@ readdir_rsp_cleanup (gfs3_readdir_rsp *rsp) return 0; } + int readdirp_rsp_cleanup (gfs3_readdirp_rsp *rsp) { @@ -1455,6 +794,7 @@ readdirp_rsp_cleanup (gfs3_readdirp_rsp *rsp) prev = trav; while (trav) { trav = trav->nextentry; + GF_FREE (prev->dict.dict_val); GF_FREE (prev); prev = trav; } @@ -1462,6 +802,7 @@ readdirp_rsp_cleanup (gfs3_readdirp_rsp *rsp) return 0; } + int gf_server_check_getxattr_cmd (call_frame_t *frame, const char *key) { @@ -1475,10 +816,14 @@ gf_server_check_getxattr_cmd (call_frame_t *frame, const char *key) if (fnmatch ("*list*mount*point*", key, 0) == 0) { /* list all the client protocol connecting to this process */ - list_for_each_entry (xprt, &conf->xprt_list, list) { - gf_log ("mount-point-list", GF_LOG_INFO, - "%s", xprt->peerinfo.identifier); + 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); + } } + pthread_mutex_unlock (&conf->mutex); } /* Add more options/keys here */ @@ -1486,34 +831,431 @@ gf_server_check_getxattr_cmd (call_frame_t *frame, const char *key) return 0; } + int gf_server_check_setxattr_cmd (call_frame_t *frame, dict_t *dict) { - data_pair_t *pair = NULL; - server_conf_t *conf = NULL; - rpc_transport_t *xprt = NULL; - uint64_t total_read = 0; + 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) + if (!conf || !dict) return 0; - for (pair = dict->members_list; pair; pair = pair->next) { - /* this exact key is used in 'io-stats' too. - * But this is better place for this information dump. - */ - if (fnmatch ("*io*stat*dump", pair->key, 0) == 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); + 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; } + + +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) +{ + 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; + } + +out: + return ctx; +} + +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; + } + + ret = 0; +ret: + if (state) { + free_state (state); + } + + if (frame) { + gf_client_unref (client); + STACK_DESTROY (frame->root); + } + + if (payload->free_iobref) { + iobref_unref (payload->iobref); + } +out: + return ret; +} + +gf_barrier_payload_t * +gf_barrier_dequeue (gf_barrier_t *barrier) +{ + gf_barrier_payload_t *payload = NULL; + + if (!barrier || list_empty (&barrier->queue)) + return NULL; + + payload = list_entry (barrier->queue.next, + gf_barrier_payload_t, list); + if (payload) { + list_del_init (&payload->list); + barrier->cur_size--; + } + + 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 +gf_barrier_timeout (void *data) +{ + server_conf_t *conf = NULL; + gf_barrier_t *barrier = NULL; + gf_boolean_t need_dequeue = _gf_false; + + 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); + + ret = 0; +out: + return ret; +} + +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; + + 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 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 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 85929bbba..b455aa6df 100644 --- a/xlators/protocol/server/src/server-helpers.h +++ b/xlators/protocol/server/src/server-helpers.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -24,13 +15,8 @@ #define CALL_STATE(frame) ((server_state_t *)frame->root->state) -#define BOUND_XL(frame) ((xlator_t *) CALL_STATE(frame)->conn->bound_xl) - #define XPRT_FROM_FRAME(frame) ((rpc_transport_t *) CALL_STATE(frame)->xprt) -#define SERVER_CONNECTION(frame) \ - ((server_connection_t *) CALL_STATE(frame)->conn) - #define SERVER_CONF(frame) \ ((server_conf_t *)XPRT_FROM_FRAME(frame)->this->private) @@ -43,39 +29,26 @@ #define IS_NOT_ROOT(pathlen) ((pathlen > 2)? 1 : 0) +#define is_fop_barriered(fops, procnum) (fops & ((uint64_t)1 << procnum)) + +#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, - uint64_t owner, - glusterfs_fop_t type); - -int32_t -gf_del_locker (struct _lock_table *table, const char *volume, - loc_t *loc, - fd_t *fd, - uint64_t owner, - glusterfs_fop_t type); - void server_print_request (call_frame_t *frame); call_frame_t * get_frame_from_request (rpcsvc_request_t *req); -server_connection_t * -get_server_conn_state (xlator_t *this, rpc_transport_t *xptr); +int +server_connection_cleanup (xlator_t *this, struct _client_t *client, + int32_t flags); -server_connection_t * -create_server_conn_state (xlator_t *this, rpc_transport_t *xptr); - -void -destroy_server_conn_state (server_connection_t *conn); +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); @@ -85,4 +58,17 @@ 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); +server_ctx_t *server_ctx_get (client_t *client, xlator_t *xlator); + +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 */ diff --git a/xlators/protocol/server/src/server-mem-types.h b/xlators/protocol/server/src/server-mem-types.h index bf1a2faa5..19c3466d3 100644 --- a/xlators/protocol/server/src/server-mem-types.h +++ b/xlators/protocol/server/src/server-mem-types.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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. */ @@ -33,6 +24,7 @@ enum gf_server_mem_types_ { 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-resolve.c b/xlators/protocol/server/src/server-resolve.c index 0b0487a24..cc4686a03 100644 --- a/xlators/protocol/server/src/server-resolve.c +++ b/xlators/protocol/server/src/server-resolve.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -33,74 +24,9 @@ resolve_entry_simple (call_frame_t *frame); int resolve_inode_simple (call_frame_t *frame); int -resolve_path_simple (call_frame_t *frame); - -int -component_count (const char *path) -{ - int count = 0; - const char *trav = NULL; - - for (trav = path; *trav; trav++) { - if (*trav == '/') - count++; - } - - return count + 2; -} - - +resolve_continue (call_frame_t *frame); int -prepare_components (call_frame_t *frame) -{ - server_state_t *state = NULL; - server_resolve_t *resolve = NULL; - char *resolved = NULL; - int count = 0; - struct resolve_comp *components = NULL; - int i = 0; - char *trav = NULL; - - state = CALL_STATE (frame); - resolve = state->resolve_now; - - resolved = gf_strdup (resolve->path); - resolve->resolved = resolved; - - count = component_count (resolve->path); - components = GF_CALLOC (sizeof (*components), count, - gf_server_mt_resolv_comp_t); - if (!components) - goto out; - - resolve->components = components; - - components[0].basename = ""; - components[0].ino = 1; - components[0].gen = 0; - components[0].inode = state->itable->root; - - i = 1; - for (trav = resolved; *trav; trav++) { - if (*trav == '/') { - *trav = 0; - - if (!(*(trav + 1))) { - /* Skip trailing "/" in a path. - This is the check which prevents - inode_link'age of itable->root - */ - break; - } - - components[i].basename = trav + 1; - i++; - } - } -out: - return 0; -} - +resolve_anonfd_simple (call_frame_t *frame); int resolve_loc_touchup (call_frame_t *frame) @@ -125,231 +51,175 @@ resolve_loc_touchup (call_frame_t *frame) if (ret) gf_log (frame->this->name, GF_LOG_TRACE, "return value inode_path %d", ret); - - if (!path) - path = gf_strdup (resolve->path); - loc->path = path; } - loc->name = strrchr (loc->path, '/'); - if (loc->name) - loc->name++; - - if (!loc->parent && loc->inode) { - loc->parent = inode_parent (loc->inode, 0, NULL); - } - return 0; } int -resolve_deep_continue (call_frame_t *frame) +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; - xlator_t *this = NULL; server_resolve_t *resolve = NULL; - int ret = 0; + inode_t *link_inode = NULL; + loc_t *resolve_loc = NULL; state = CALL_STATE (frame); - this = frame->this; resolve = state->resolve_now; + resolve_loc = &resolve->resolve_loc; - resolve->op_ret = 0; - resolve->op_errno = 0; + 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; + } - if (!uuid_is_null (resolve->pargfid)) - ret = resolve_entry_simple (frame); - else if (!uuid_is_null (resolve->gfid)) - ret = resolve_inode_simple (frame); - else if (resolve->path) - ret = resolve_path_simple (frame); - if (ret) - gf_log (this->name, GF_LOG_DEBUG, - "return value of resolve_*_simple %d", ret); + link_inode = inode_link (inode, resolve_loc->parent, + resolve_loc->name, buf); - resolve_loc_touchup (frame); + if (!link_inode) + goto out; - server_resolve_all (frame); + inode_lookup (link_inode); + + inode_unref (link_inode); + +out: + loc_wipe (resolve_loc); + resolve_continue (frame); return 0; } int -resolve_deep_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +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 *xattr, struct iatt *postparent) + dict_t *xdata, struct iatt *postparent) { server_state_t *state = NULL; server_resolve_t *resolve = NULL; - struct resolve_comp *components = NULL; - int i = 0; inode_t *link_inode = NULL; + loc_t *resolve_loc = NULL; state = CALL_STATE (frame); resolve = state->resolve_now; - components = resolve->components; - - i = (long) cookie; + 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)", - resolve->resolved, strerror (op_errno)); - goto get_out_of_here; + uuid_utoa (resolve_loc->gfid), strerror (op_errno)); + loc_wipe (&resolve->resolve_loc); + goto out; } - if (i != 0) { - /* no linking for root inode */ - link_inode = inode_link (inode, resolve->deep_loc.parent, - resolve->deep_loc.name, buf); - inode_lookup (link_inode); - components[i].inode = link_inode; - link_inode = NULL; - } + loc_wipe (resolve_loc); - loc_wipe (&resolve->deep_loc); + link_inode = inode_link (inode, NULL, NULL, buf); - i++; /* next component */ + if (!link_inode) + goto out; + + inode_lookup (link_inode); - if (!components[i].basename) { - /* all components of the path are resolved */ - goto get_out_of_here; + if (uuid_is_null (resolve->pargfid)) { + inode_unref (link_inode); + goto out; } - /* join the current component with the path resolved until now */ - *(components[i].basename - 1) = '/'; + resolve_loc->parent = link_inode; + uuid_copy (resolve_loc->pargfid, resolve_loc->parent->gfid); - resolve->deep_loc.path = gf_strdup (resolve->resolved); - resolve->deep_loc.parent = inode_ref (components[i-1].inode); - resolve->deep_loc.inode = inode_new (state->itable); - resolve->deep_loc.name = components[i].basename; + resolve_loc->name = resolve->bname; - if (frame && frame->root->state && BOUND_XL (frame)) { - STACK_WIND_COOKIE (frame, resolve_deep_cbk, (void *) (long) i, - BOUND_XL (frame), BOUND_XL (frame)->fops->lookup, - &resolve->deep_loc, NULL); - return 0; - } + resolve_loc->inode = inode_new (state->itable); + inode_path (resolve_loc->parent, resolve_loc->name, + (char **) &resolve_loc->path); -get_out_of_here: - resolve_deep_continue (frame); + 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_path_deep (call_frame_t *frame) +resolve_gfid (call_frame_t *frame) { - server_state_t *state = NULL; - server_resolve_t *resolve = NULL; - int i = 0; + 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; - gf_log (BOUND_XL (frame)->name, GF_LOG_DEBUG, - "RESOLVE %s() seeking deep resolution of %s", - gf_fop_list[frame->root->op], resolve->path); - - prepare_components (frame); - - /* start from the root */ - resolve->deep_loc.inode = state->itable->root; - resolve->deep_loc.path = gf_strdup ("/"); - resolve->deep_loc.name = ""; + 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); - if (frame && frame->root->state && BOUND_XL (frame)) { - STACK_WIND_COOKIE (frame, resolve_deep_cbk, (void *) (long) i, - BOUND_XL (frame), BOUND_XL (frame)->fops->lookup, - &resolve->deep_loc, NULL); - return 0; - } + resolve_loc->inode = inode_new (state->itable); + ret = loc_path (resolve_loc, NULL); - resolve_deep_continue (frame); + 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_path_simple (call_frame_t *frame) +resolve_continue (call_frame_t *frame) { server_state_t *state = NULL; + xlator_t *this = NULL; server_resolve_t *resolve = NULL; - struct resolve_comp *components = NULL; - int ret = -1; - int par_idx = -1; - int ino_idx = -1; - int i = 0; + int ret = 0; state = CALL_STATE (frame); + this = frame->this; resolve = state->resolve_now; - components = resolve->components; - if (!components) { - gf_log ("", GF_LOG_INFO, - "failed to resolve, component not found"); - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - goto out; - } - - for (i = 0; components[i].basename; i++) { - par_idx = ino_idx; - ino_idx = i; - } - - if (ino_idx == -1) { - gf_log ("", GF_LOG_INFO, - "failed to resolve, inode index not found"); - resolve->op_ret = -1; - resolve->op_errno = EINVAL; - goto out; - } - - if (par_idx == -1) - /* "/" will not have a parent */ - goto noparent; - - if (!components[par_idx].inode) { - gf_log ("", GF_LOG_INFO, - "failed to resolve, parent inode not found"); - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - goto out; - } - state->loc_now->parent = inode_ref (components[par_idx].inode); -noparent: - - if (!components[ino_idx].inode && - (resolve->type == RESOLVE_MUST || resolve->type == RESOLVE_EXACT)) { - gf_log ("", GF_LOG_INFO, - "failed to resolve, inode not found"); - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - goto out; - } + resolve->op_ret = 0; + resolve->op_errno = 0; - if (components[ino_idx].inode && resolve->type == RESOLVE_NOT) { - gf_log ("", GF_LOG_INFO, - "failed to resolve, inode found"); - resolve->op_ret = -1; - resolve->op_errno = EEXIST; + if (resolve->fd_no != -1) { + ret = resolve_anonfd_simple (frame); goto out; - } - - if (components[ino_idx].inode) - state->loc_now->inode = inode_ref (components[ino_idx].inode); - - ret = 0; + } 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: - return ret; + server_resolve_all (frame); + + return 0; } + /* Check if the requirements are fulfilled by entries in the inode cache itself Return value: @@ -378,20 +248,13 @@ resolve_entry_simple (call_frame_t *frame) resolve->op_ret = -1; resolve->op_errno = ENOENT; ret = 1; - - inode = inode_grep (state->itable, parent, resolve->bname); - if (inode != NULL) { - gf_log (this->name, GF_LOG_DEBUG, "%"PRId64": inode " - "(pointer:%p ino: %"PRIu64") present but parent" - " is NULL for path (%s)", frame->root->unique, - inode, inode->ino, resolve->path); - inode_unref (inode); - } 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) { @@ -414,9 +277,9 @@ resolve_entry_simple (call_frame_t *frame) } if (resolve->type == RESOLVE_NOT) { - gf_log (this->name, GF_LOG_INFO, "inode (pointer: %p ino:%" - PRIu64") found for path (%s) while type is RESOLVE_NOT", - inode, inode->ino, resolve->path); + 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; @@ -452,7 +315,7 @@ server_resolve_entry (call_frame_t *frame) if (ret > 0) { loc_wipe (loc); - resolve_path_deep (frame); + resolve_gfid (frame); return 0; } @@ -488,6 +351,7 @@ resolve_inode_simple (call_frame_t *frame) ret = 0; state->loc_now->inode = inode_ref (inode); + uuid_copy (state->loc_now->gfid, resolve->gfid); out: if (inode) @@ -511,7 +375,7 @@ server_resolve_inode (call_frame_t *frame) if (ret > 0) { loc_wipe (loc); - resolve_path_deep (frame); + resolve_gfid (frame); return 0; } @@ -525,20 +389,96 @@ server_resolve_inode (call_frame_t *frame) 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_state_t *state = NULL; - server_resolve_t *resolve = NULL; - server_connection_t *conn = NULL; - uint64_t fd_no = -1; + 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; - conn = SERVER_CONNECTION (frame); fd_no = resolve->fd_no; - state->fd = gf_fd_fdptr_get (conn->fdtable, 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"); @@ -573,14 +513,11 @@ server_resolve (call_frame_t *frame) server_resolve_inode (frame); - } else if (resolve->path) { - - gf_log (frame->this->name, GF_LOG_INFO, - "pure path resolution for %s (%s)", - resolve->path, gf_fop_list[frame->root->op]); - resolve_path_deep (frame); - - } else { + } 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; @@ -596,14 +533,12 @@ int server_resolve_done (call_frame_t *frame) { server_state_t *state = NULL; - xlator_t *bound_xl = NULL; state = CALL_STATE (frame); - bound_xl = BOUND_XL (frame); server_print_request (frame); - state->resume_fn (frame, bound_xl); + state->resume_fn (frame, frame->root->client->bound_xl); 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 index 967863d09..589bd7b36 100644 --- a/xlators/protocol/server/src/server.c +++ b/xlators/protocol/server/src/server.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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. */ @@ -34,43 +25,101 @@ #include "statedump.h" #include "defaults.h" #include "authenticate.h" -#include "rpcsvc.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, gfs_serialize_t sfunc, - struct iovec *outmsg) +gfs_serialize_reply (rpcsvc_request_t *req, void *arg, struct iovec *outmsg, + xdrproc_t xdrproc) { - struct iobuf *iob = NULL; - ssize_t retlen = -1; + 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. */ - iob = iobuf_get (req->svc->ctx->iobuf_pool); - if (!iob) { - gf_log_callingfn ("", 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 = sfunc (*outmsg, arg); - 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; + 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) { @@ -81,27 +130,35 @@ ret: return iob; } - - -/* Generic reply function for NFSv3 specific replies. */ int server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg, struct iovec *payload, int payloadcount, - struct iobref *iobref, gfs_serialize_t sfunc) + 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) { @@ -111,7 +168,7 @@ server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg, new_iobref = 1; } - iob = gfs_serialize_reply (req, arg, sfunc, &rsp); + iob = gfs_serialize_reply (req, arg, &rsp, xdrproc); if (!iob) { gf_log ("", GF_LOG_ERROR, "Failed to serialize reply"); goto ret; @@ -119,6 +176,32 @@ server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg, 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); @@ -134,6 +217,15 @@ server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg, 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; } @@ -144,86 +236,73 @@ ret: } if (frame) { + gf_client_unref (client); STACK_DESTROY (frame->root); } if (new_iobref) { iobref_unref (iobref); } - - return ret; -} - -/* */ -int -xdr_to_glusterfs_req (rpcsvc_request_t *req, void *arg, gfs_serialize_t sfunc) -{ - int ret = -1; - - GF_VALIDATE_OR_GOTO ("server", req, out); - - ret = sfunc (req->msg[0], arg); - - if (ret > 0) - ret = 0; out: return ret; } + int -server_fd (xlator_t *this) +server_priv_to_dict (xlator_t *this, dict_t *dict) { - server_conf_t *conf = NULL; - server_connection_t *trav = NULL; - char key[GF_DUMP_MAX_BUF_LEN]; - int i = 1; - int ret = -1; + 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 ("server", this, out); + GF_VALIDATE_OR_GOTO (THIS->name, this, out); + GF_VALIDATE_OR_GOTO (THIS->name, dict, out); conf = this->private; - if (!conf) { - gf_log (this->name, GF_LOG_WARNING, - "conf null in xlator"); - return -1; - } - - gf_proc_dump_add_section("xlator.protocol.server.conn"); - - ret = pthread_mutex_trylock (&conf->mutex); - if (ret) { - gf_log("", GF_LOG_WARNING, "Unable to dump fdtable" - " errno: %d", errno); - return -1; - } - - list_for_each_entry (trav, &conf->conns, list) { - if (trav->id) { - gf_proc_dump_build_key(key, - "xlator.protocol.server.conn", - "%d.id", i); - gf_proc_dump_write(key, "%s", trav->id); - } + if (!conf) + return 0; + //TODO: Dump only specific info to dict - gf_proc_dump_build_key(key,"xlator.protocol.server.conn", - "%d.ref",i) - gf_proc_dump_write(key, "%d", trav->ref); - if (trav->bound_xl) { - gf_proc_dump_build_key(key, - "xlator.protocol.server.conn", - "%d.bound_xl", i); - gf_proc_dump_write(key, "%s", trav->bound_xl->name); + 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++; } - - gf_proc_dump_build_key(key, - "xlator.protocol.server.conn", - "%d.id", i); - fdtable_dump(trav->fdtable,key); - i++; } +unlock: pthread_mutex_unlock (&conf->mutex); + if (ret) + goto out; + + ret = dict_set_int32 (dict, "clientcount", count); - ret = 0; out: return ret; } @@ -244,10 +323,19 @@ server_priv (xlator_t *this) if (!conf) return 0; - list_for_each_entry (xprt, &conf->xprt_list, list) { - total_read += xprt->total_bytes_read; - total_write += xprt->total_bytes_write; + 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); @@ -257,53 +345,16 @@ server_priv (xlator_t *this) ret = 0; out: - return ret; -} - -int -server_inode (xlator_t *this) -{ - server_conf_t *conf = NULL; - server_connection_t *trav = NULL; - char key[GF_DUMP_MAX_BUF_LEN]; - int i = 1; - int ret = -1; - - GF_VALIDATE_OR_GOTO ("server", this, out); - - conf = this->private; - if (!conf) { - gf_log (this->name, GF_LOG_WARNING, - "conf null in xlator"); - return -1; - } - - ret = pthread_mutex_trylock (&conf->mutex); - if (ret) { - gf_log("", GF_LOG_WARNING, "Unable to dump itable" - " errno: %d", errno); - return -1; - } - - list_for_each_entry (trav, &conf->conns, list) { - if (trav->bound_xl && trav->bound_xl->itable) { - gf_proc_dump_build_key(key, - "xlator.protocol.server.conn", - "%d.bound_xl.%s", - i, trav->bound_xl->name); - inode_table_dump(trav->bound_xl->itable,key); - i++; - } - } - pthread_mutex_unlock (&conf->mutex); + if (ret) + gf_proc_dump_write ("Unable to print priv", + "(Lock acquisition failed) %s", + this?this->name:"server"); - ret = 0; -out: return ret; } -static void +static int get_auth_types (dict_t *this, char *key, data_t *value, void *data) { dict_t *auth_dict = NULL; @@ -340,43 +391,89 @@ get_auth_types (dict_t *this, char *key, data_t *value, void *data) GF_FREE (key_cpy); out: - return; + 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; - data_pair_t *pair = NULL; - char *tail = NULL; GF_VALIDATE_OR_GOTO ("server", this, out); GF_VALIDATE_OR_GOTO ("server", dict, out); trav = this->children; while (trav) { - error = -1; - for (pair = dict->members_list; pair; pair = pair->next) { - tail = strtail (pair->key, "auth."); - if (!tail) - continue; - /* fast fwd thru module type */ - tail = strchr (tail, '.'); - if (!tail) - continue; - tail++; - - tail = strtail (tail, trav->xlator->name); - if (!tail) - continue; - - if (*tail == '.') { - error = 0; - break; - } - } + 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 " @@ -386,6 +483,7 @@ validate_auth_options (xlator_t *this, dict_t *dict) } trav = trav->next; } + out: return error; } @@ -395,11 +493,12 @@ int server_rpc_notify (rpcsvc_t *rpc, void *xl, rpcsvc_event_t event, void *data) { - xlator_t *this = NULL; - rpc_transport_t *xprt = NULL; - server_connection_t *conn = NULL; - server_conf_t *conf = NULL; - + 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, @@ -408,7 +507,7 @@ server_rpc_notify (rpcsvc_t *rpc, void *xl, rpcsvc_event_t event, } this = xl; - xprt = data; + trans = data; conf = this->private; switch (event) { @@ -416,34 +515,85 @@ server_rpc_notify (rpcsvc_t *rpc, void *xl, rpcsvc_event_t event, { /* Have a structure per new connection */ /* TODO: Should we create anything here at all ? * / - conn = create_server_conn_state (this, xprt); - if (!conn) + client->conn = create_server_conn_state (this, trans); + if (!client->conn) goto out; - xprt->protocol_private = conn; + trans->protocol_private = client->conn; */ - INIT_LIST_HEAD (&xprt->list); + INIT_LIST_HEAD (&trans->list); - list_add_tail (&xprt->list, &conf->xprt_list); + pthread_mutex_lock (&conf->mutex); + { + list_add_tail (&trans->list, &conf->xprt_list); + } + pthread_mutex_unlock (&conf->mutex); break; } case RPCSVC_EVENT_DISCONNECT: - conn = get_server_conn_state (this, xprt); - if (conn) - server_connection_cleanup (this, conn); + /* 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); - gf_log (this->name, GF_LOG_INFO, - "disconnected connection from %s", - xprt->peerinfo.identifier); + client = trans->xl_private; + if (!client) + break; - list_del (&xprt->list); + 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 = get_server_conn_state (this, xprt); - if (conn) - server_connection_put (this, conn); + /*- 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; @@ -471,70 +621,81 @@ out: return ret; } -int -validate_options ( xlator_t *this, char **op_errstr) -{ - int ret = 0; - volume_opt_list_t *vol_opt = NULL; - volume_opt_list_t *tmp; - - if (!this) { - gf_log (this->name, GF_LOG_DEBUG, "'this' not a valid ptr"); - ret =-1; - goto out; - } - if (list_empty (&this->volume_options)) - goto out; +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; - vol_opt = list_entry (this->volume_options.next, - volume_opt_list_t, list); - list_for_each_entry_safe (vol_opt, tmp, &this->volume_options, list) { - ret = validate_xlator_volume_options_attacherr (this, - vol_opt->given_opt, - op_errstr); + for (i = 0; auth_option_pattern[i]; i++) { + if (fnmatch (auth_option_pattern[i], key, 0) == 0) { + dict_del (this, key); + break; + } } -out: - - return ret; + return 0; } -static void -_delete_auth_opt (dict_t *this, - char *key, - data_t *value, - void *data) + +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"}; - if (fnmatch ( auth_option_pattern[0], key, 0) != 0) { - dict_del (this, key); - return; - } + "auth.addr.*.reject", + NULL}; + int i = 0; - if (fnmatch ( auth_option_pattern[1], key, 0) != 0) { - dict_del (this, key); - return; + 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; } -static void -_copy_auth_opt (dict_t *unused, - char *key, - data_t *value, - void *xl_dict) +int +server_init_grace_timer (xlator_t *this, dict_t *options, + server_conf_t *conf) { - char *auth_option_pattern[] = { "auth.addr.*.allow", - "auth.addr.*.reject"}; - if (fnmatch ( auth_option_pattern[0], key, 0) != 0) - dict_set ((dict_t *)xl_dict, key, (value)); + int32_t ret = -1; + int32_t grace_timeout = -1; + char *lk_heal = NULL; - if (fnmatch ( auth_option_pattern[1], key, 0) != 0) - dict_set ((dict_t *)xl_dict, key, (value)); -} + 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) @@ -547,7 +708,7 @@ reconfigure (xlator_t *this, dict_t *options) gf_boolean_t trace; data_t *data; int ret = 0; - + char *statedump_path = NULL; conf = this->private; if (!conf) { @@ -567,14 +728,27 @@ reconfigure (xlator_t *this, dict_t *options) gf_log (this->name, GF_LOG_WARNING, "'trace' takes on only boolean values. " "Neglecting option"); - ret = -1; + ret = -1; goto out; - } - conf->trace = trace; - gf_log (this->name, GF_LOG_TRACE, "Reconfigured trace" - " to %d", conf->trace); + } + 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 (); @@ -600,6 +774,8 @@ reconfigure (xlator_t *this, dict_t *options) } (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 ) @@ -609,19 +785,42 @@ reconfigure (xlator_t *this, dict_t *options) "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) { @@ -641,10 +840,13 @@ init (xlator_t *this) GF_VALIDATE_OR_GOTO(this->name, conf, out); - INIT_LIST_HEAD (&conf->conns); 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; @@ -653,6 +855,22 @@ init (xlator_t *this) 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); @@ -671,8 +889,7 @@ init (xlator_t *this) } /* RPC related */ - //conf->rpc = rpc_svc_init (&conf->rpc_conf); - conf->rpc = rpcsvc_init (this->ctx, this->options); + 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"); @@ -696,14 +913,14 @@ init (xlator_t *this) goto out; } - glusterfs3_1_fop_prog.options = this->options; - ret = rpcsvc_program_register (conf->rpc, &glusterfs3_1_fop_prog); + 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_1_fop_prog.progname, - glusterfs3_1_fop_prog.prognum, - glusterfs3_1_fop_prog.progver); + "progver:%d) failed", glusterfs3_3_fop_prog.progname, + glusterfs3_3_fop_prog.prognum, + glusterfs3_3_fop_prog.progver); goto out; } @@ -715,7 +932,7 @@ init (xlator_t *this) "progver:%d) failed", gluster_handshake_prog.progname, gluster_handshake_prog.prognum, gluster_handshake_prog.progver); - rpcsvc_program_unregister (conf->rpc, &glusterfs3_1_fop_prog); + rpcsvc_program_unregister (conf->rpc, &glusterfs3_3_fop_prog); goto out; } @@ -744,6 +961,37 @@ init (xlator_t *this) } } #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; @@ -797,26 +1045,65 @@ 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_fops fops; struct xlator_cbks cbks = { + .client_destroy = client_destroy_cbk, }; struct xlator_dumpops dumpops = { - .priv = server_priv, - .fd = server_fd, - .inode = server_inode, + .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, }; @@ -842,7 +1129,10 @@ struct volume_options options[] = { { .key = {"inode-lru-limit"}, .type = GF_OPTION_TYPE_INT, .min = 0, - .max = (1 * GF_UNIT_MB) + .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 @@ -857,5 +1147,68 @@ struct volume_options options[] = { { .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 index 55ca63248..782327d77 100644 --- a/xlators/protocol/server/src/server.h +++ b/xlators/protocol/server/src/server.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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_H @@ -22,61 +13,55 @@ #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" - -typedef struct _server_state server_state_t; - -struct _locker { - struct list_head lockers; - char *volume; - loc_t loc; - fd_t *fd; - uint64_t owner; - pid_t pid; +#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; }; -struct _lock_table { - struct list_head inodelk_lockers; - struct list_head entrylk_lockers; - gf_lock_t lock; - size_t count; +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; }; -/* private structure per connection (transport object) - * used as transport_t->xl_private - */ -struct _server_connection { - struct list_head list; - char *id; - int ref; - int active_transports; - pthread_mutex_t lock; - char disconnected; - fdtable_t *fdtable; - struct _lock_table *ltable; - xlator_t *bound_xl; - xlator_t *this; -}; - -typedef struct _server_connection server_connection_t; - +typedef struct _gf_barrier gf_barrier_t; -server_connection_t * -server_connection_get (xlator_t *this, const char *id); - -void -server_connection_put (xlator_t *this, server_connection_t *conn); +typedef enum { + INTERNAL_LOCKS = 1, + POSIX_LOCKS = 2, +} server_lock_flags_t; -int -server_connection_cleanup (xlator_t *this, server_connection_t *conn); +typedef struct _server_state server_state_t; int server_null (rpcsvc_request_t *req); @@ -92,13 +77,16 @@ struct server_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; - struct list_head conns; + gf_barrier_t *barrier; struct list_head xprt_list; + pthread_t barrier_th; }; typedef struct server_conf server_conf_t; @@ -114,27 +102,19 @@ typedef enum { struct resolve_comp { char *basename; - ino_t ino; - uint64_t gen; inode_t *inode; }; typedef struct { server_resolve_type_t type; - uint64_t fd_no; - ino_t ino; - uint64_t gen; - ino_t par; + int64_t fd_no; u_char gfid[16]; u_char pargfid[16]; char *path; char *bname; - char *resolved; int op_ret; int op_errno; - loc_t deep_loc; - struct resolve_comp *components; - int comp_count; + loc_t resolve_loc; } server_resolve_t; @@ -144,11 +124,10 @@ int resolve_and_resume (call_frame_t *frame, server_resume_fn_t fn); struct _server_state { - server_connection_t *conn; - rpc_transport_t *xprt; - inode_table_t *itable; + rpc_transport_t *xprt; + inode_table_t *itable; - server_resume_fn_t resume_fn; + server_resume_fn_t resume_fn; loc_t loc; loc_t loc2; @@ -164,7 +143,7 @@ struct _server_state { fd_t *fd; dict_t *params; - int flags; + int32_t flags; int wbflags; struct iovec payload_vector[MAX_IOVEC]; int payload_count; @@ -184,24 +163,32 @@ struct _server_state { int mask; char is_revalidate; dict_t *dict; - struct gf_flock flock; + 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_1_fop_prog; +extern struct rpcsvc_program glusterfs3_3_fop_prog; extern struct rpcsvc_program gluster_ping_prog; -typedef ssize_t (*gfs_serialize_t) (struct iovec outmsg, void *args); + +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, gfs_serialize_t sfunc); - -int xdr_to_glusterfs_req (rpcsvc_request_t *req, void *arg, - gfs_serialize_t sfunc); + 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); diff --git a/xlators/protocol/server/src/server3_1-fops.c b/xlators/protocol/server/src/server3_1-fops.c deleted file mode 100644 index eb51640d9..000000000 --- a/xlators/protocol/server/src/server3_1-fops.c +++ /dev/null @@ -1,5198 +0,0 @@ -/* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> - This file is part of GlusterFS. - - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 "server.h" -#include "server-helpers.h" -#include "glusterfs3-xdr.h" -#include "glusterfs3.h" -#include "compat-errno.h" - -#include "md5.h" - - -/* 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) -{ - gfs3_statfs_rsp rsp = {0,}; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - if (op_ret >= 0) { - gf_statfs_from_statfs (&rsp.statfs, buf); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": STATFS %"PRId32" (%s)", - frame->root->unique, op_ret, strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_statfs_rsp); - - 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 *dict, - 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,}; - int32_t ret = -1; - uuid_t rootgfid = {0,}; - - state = CALL_STATE(frame); - - req = frame->local; - - 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, BOUND_XL (frame), - BOUND_XL (frame)->fops->lookup, - &fresh_loc, state->dict); - - loc_wipe (&fresh_loc); - return 0; - } - - if ((op_ret >= 0) && dict) { - rsp.dict.dict_len = dict_serialized_length (dict); - if (rsp.dict.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; - rsp.dict.dict_len = 0; - goto out; - } - - rsp.dict.dict_val = GF_CALLOC (1, rsp.dict.dict_len, - gf_server_mt_rsp_buf_t); - if (!rsp.dict.dict_val) { - op_ret = -1; - op_errno = ENOMEM; - rsp.dict.dict_len = 0; - goto out; - } - ret = dict_serialize (dict, rsp.dict.dict_val); - 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; - rsp.dict.dict_len = 0; - goto out; - } - } - - gf_stat_from_iatt (&rsp.postparent, postparent); - - if (op_ret == 0) { - root_inode = BOUND_XL(frame)->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 (inode->ino != 1) { - link_inode = inode_link (inode, state->loc.parent, - state->loc.name, stbuf); - inode_lookup (link_inode); - inode_unref (link_inode); - } - } else { - if (state->is_revalidate && op_errno == ENOENT) { - if (state->loc.inode->ino != 1) { - inode_unlink (state->loc.inode, - state->loc.parent, - state->loc.name); - } - } - } -out: - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - if (op_ret) { - gf_log (this->name, - (op_errno == ENOENT ? GF_LOG_TRACE : GF_LOG_INFO), - "%"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_submit_reply (frame, req, &rsp, NULL, 0, NULL, - (gfs_serialize_t)xdr_serialize_lookup_rsp); - - if (rsp.dict.dict_val) - GF_FREE (rsp.dict.dict_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) -{ - gfs3_lk_rsp rsp = {0,}; - rpcsvc_request_t *req = NULL; - server_state_t *state = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - - if (op_ret == 0) { - 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); - } else if ((op_errno != ENOSYS) && (op_errno != EAGAIN)) { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": LK %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_lk_rsp); - - return 0; -} - - -int -server_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - gf_common_rsp rsp = {0,}; - server_connection_t *conn = NULL; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - conn = SERVER_CONNECTION(frame); - state = CALL_STATE(frame); - - if (op_ret >= 0) { - if (state->flock.l_type == F_UNLCK) - gf_del_locker (conn->ltable, state->volume, - &state->loc, NULL, frame->root->lk_owner, GF_FOP_INODELK); - else - gf_add_locker (conn->ltable, state->volume, - &state->loc, NULL, frame->root->pid, - frame->root->lk_owner, GF_FOP_INODELK); - } else if ((op_errno != ENOSYS) && (op_errno != EAGAIN)) { - gf_log (this->name, GF_LOG_INFO, - "%"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_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); - - return 0; -} - - -int -server_finodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - gf_common_rsp rsp = {0,}; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - conn = SERVER_CONNECTION(frame); - 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->lk_owner, GF_FOP_INODELK); - else - gf_add_locker (conn->ltable, state->volume, - NULL, state->fd, - frame->root->pid, - frame->root->lk_owner, GF_FOP_INODELK); - } else if ((op_errno != ENOSYS) && (op_errno != EAGAIN)) { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": FINODELK %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); - - return 0; -} - -int -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; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - gf_common_rsp rsp = {0,}; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - conn = SERVER_CONNECTION(frame); - state = CALL_STATE(frame); - - if (op_ret >= 0) { - if (state->cmd == ENTRYLK_UNLOCK) - gf_del_locker (conn->ltable, state->volume, - &state->loc, NULL, frame->root->lk_owner, GF_FOP_ENTRYLK); - else - gf_add_locker (conn->ltable, state->volume, - &state->loc, NULL, frame->root->pid, - frame->root->lk_owner, GF_FOP_ENTRYLK); - } else if ((op_errno != ENOSYS) && (op_errno != EAGAIN)) { - gf_log (this->name, GF_LOG_INFO, - "%"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_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); - return 0; -} - - -int -server_fentrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - gf_common_rsp rsp = {0,}; - server_connection_t *conn = NULL; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - conn = SERVER_CONNECTION(frame); - state = CALL_STATE(frame); - if (op_ret >= 0) { - if (state->cmd == ENTRYLK_UNLOCK) - gf_del_locker (conn->ltable, state->volume, - NULL, state->fd, frame->root->lk_owner, GF_FOP_ENTRYLK); - else - gf_add_locker (conn->ltable, state->volume, - NULL, state->fd, frame->root->pid, - frame->root->lk_owner, GF_FOP_ENTRYLK); - } else if ((op_errno != ENOSYS) && (op_errno != EAGAIN)) { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": FENTRYLK %"PRId64" (%"PRId64") " - " ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); - - return 0; -} - - -int -server_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - gf_common_rsp rsp = {0,}; - rpcsvc_request_t *req = NULL; - server_state_t *state = NULL; - - req = frame->local; - - state = CALL_STATE(frame); - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - if (op_ret) - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": ACCESS %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); - - 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) -{ - gfs3_rmdir_rsp rsp = {0,}; - server_state_t *state = NULL; - inode_t *parent = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - - if (op_ret == 0) { - 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); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"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)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_rmdir_rsp); - - 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) -{ - gfs3_mkdir_rsp rsp = {0,}; - server_state_t *state = NULL; - inode_t *link_inode = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - if (op_ret >= 0) { - 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); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": MKDIR %s ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - op_ret, strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_mkdir_rsp); - - 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) -{ - gfs3_mknod_rsp rsp = {0,}; - server_state_t *state = NULL; - inode_t *link_inode = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - if (op_ret >= 0) { - 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); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": MKNOD %s ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - op_ret, strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_mknod_rsp); - - - return 0; -} - -int -server_fsyncdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - gf_common_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - - if (op_ret < 0) { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": FSYNCDIR %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); - - 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) -{ - gfs3_readdir_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - int ret = 0; - - req = frame->local; - - state = CALL_STATE(frame); - if (op_ret > 0) { - ret = serialize_rsp_dirent (entries, &rsp); - if (ret == -1) { - op_ret = -1; - op_errno = ENOMEM; - goto unwind; - } - } else { - /* (op_ret == 0) is valid, and means EOF, don't log for that */ - gf_log (this->name, (op_ret) ? GF_LOG_INFO : GF_LOG_TRACE, - "%"PRId64": READDIR %"PRId64" (%"PRId64") ==> %"PRId32 - " (%s)", frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } -unwind: - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_readdir_rsp); - - readdir_rsp_cleanup (&rsp); - - return 0; -} - - -int -server_releasedir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - gf_common_rsp rsp = {0,}; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_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) -{ - server_connection_t *conn = NULL; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - gfs3_opendir_rsp rsp = {0,}; - uint64_t fd_no = 0; - - conn = SERVER_CONNECTION (frame); - state = CALL_STATE (frame); - - if (op_ret >= 0) { - fd_bind (fd); - - fd_no = gf_fd_unused_get (conn->fdtable, fd); - fd_ref (fd); // on behalf of the client - } else { - gf_log (this->name, GF_LOG_INFO, - "%"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)); - } - - req = frame->local; - - rsp.fd = fd_no; - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_opendir_rsp); - - return 0; -} - -int -server_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - gf_common_rsp rsp = {0,}; - rpcsvc_request_t *req = NULL; - server_state_t *state = NULL; - - req = frame->local; - state = CALL_STATE(frame); - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - if (op_ret == -1) - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": REMOVEXATTR %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); - - 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) -{ - gfs3_getxattr_rsp rsp = {0,}; - int32_t len = 0; - int32_t ret = -1; - rpcsvc_request_t *req = NULL; - server_state_t *state = NULL; - - 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->resolve.ino); - op_ret = -1; - op_errno = EINVAL; - len = 0; - goto out; - } - - rsp.dict.dict_val = GF_CALLOC (len, sizeof (char), - gf_server_mt_rsp_buf_t); - if (!rsp.dict.dict_val) { - op_ret = -1; - op_errno = ENOMEM; - len = 0; - goto out; - } - ret = dict_serialize (dict, rsp.dict.dict_val); - if (ret < 0) { - gf_log (this->name, GF_LOG_ERROR, - "%s (%"PRId64"): failed to serialize reply dict", - state->loc.path, state->resolve.ino); - op_ret = -1; - op_errno = EINVAL; - len = 0; - } - } -out: - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - rsp.dict.dict_len = len; - if (op_ret == -1) - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": GETXATTR %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_getxattr_rsp); - - if (rsp.dict.dict_val) - GF_FREE (rsp.dict.dict_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) -{ - gfs3_fgetxattr_rsp rsp = {0,}; - int32_t len = 0; - int32_t ret = -1; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - 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->resolve.ino); - op_ret = -1; - op_errno = EINVAL; - len = 0; - goto out; - } - rsp.dict.dict_val = GF_CALLOC (1, len, gf_server_mt_rsp_buf_t); - if (!rsp.dict.dict_val) { - op_ret = -1; - op_errno = ENOMEM; - len = 0; - goto out; - } - ret = dict_serialize (dict, rsp.dict.dict_val); - if (ret < 0) { - gf_log (this->name, GF_LOG_ERROR, - "%s (%"PRId64"): failed to serialize reply dict", - state->loc.path, state->resolve.ino); - op_ret = -1; - op_errno = -ret; - len = 0; - } - } - -out: - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - rsp.dict.dict_len = len; - if (op_ret == -1) - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": FGETXATTR %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_fgetxattr_rsp); - - if (rsp.dict.dict_val) - GF_FREE (rsp.dict.dict_val); - - return 0; -} - -int -server_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - gf_common_rsp rsp = {0,}; - rpcsvc_request_t *req = NULL; - server_state_t *state = NULL; - - req = frame->local; - - state = CALL_STATE(frame); - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - if (op_ret == -1) - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": SETXATTR %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); - - return 0; -} - - -int -server_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - gf_common_rsp rsp = {0,}; - rpcsvc_request_t *req = NULL; - server_state_t *state = NULL; - - req = frame->local; - - state = CALL_STATE(frame); - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - if (op_ret == -1) - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": FSETXATTR %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); - - 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) -{ - gfs3_rename_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - - if (op_ret == 0) { - stbuf->ia_ino = state->loc.inode->ino; - stbuf->ia_type = state->loc.inode->ia_type; - - gf_log (state->conn->bound_xl->name, GF_LOG_TRACE, - "%"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_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); - } - - if (op_ret == -1) - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": RENAME %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_rename_rsp); - - 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) -{ - gfs3_unlink_rsp rsp = {0,}; - server_state_t *state = NULL; - inode_t *parent = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - - if (op_ret == 0) { - gf_log (state->conn->bound_xl->name, GF_LOG_TRACE, - "%"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); - - 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); - - } else { - gf_log (this->name, GF_LOG_INFO, - "%"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)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_unlink_rsp); - - 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) -{ - gfs3_symlink_rsp rsp = {0,}; - server_state_t *state = NULL; - inode_t *link_inode = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - if (op_ret >= 0) { - 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); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"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_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_symlink_rsp); - - 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) -{ - gfs3_link_rsp rsp = {0,}; - server_state_t *state = NULL; - inode_t *link_inode = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - - if (op_ret == 0) { - stbuf->ia_ino = state->loc.inode->ino; - - 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); - } - - if (op_ret == -1) - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": LINK %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_link_rsp); - - 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) -{ - gfs3_truncate_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE (frame); - - if (op_ret == 0) { - gf_stat_from_iatt (&rsp.prestat, prebuf); - gf_stat_from_iatt (&rsp.poststat, postbuf); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"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_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_truncate_rsp); - - 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) -{ - gfs3_fstat_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - - if (op_ret == 0) { - gf_stat_from_iatt (&rsp.stat, stbuf); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": FSTAT %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_fstat_rsp); - - 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) -{ - gfs3_ftruncate_rsp rsp = {0}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE (frame); - - if (op_ret == 0) { - gf_stat_from_iatt (&rsp.prestat, prebuf); - gf_stat_from_iatt (&rsp.poststat, postbuf); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": FTRUNCATE %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_ftruncate_rsp); - - return 0; -} - -int -server_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - gf_common_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - if (op_ret < 0) { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": FLUSH %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); - - - 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) -{ - gfs3_fsync_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - - if (op_ret >= 0) { - gf_stat_from_iatt (&(rsp.prestat), prebuf); - gf_stat_from_iatt (&(rsp.poststat), postbuf); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": FSYNC %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_fsync_rsp); - - 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) -{ - gfs3_write_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - if (op_ret >= 0) { - gf_stat_from_iatt (&rsp.prestat, prebuf); - gf_stat_from_iatt (&rsp.poststat, postbuf); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": WRITEV %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_writev_rsp); - - 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) -{ - gfs3_read_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE(frame); - if (op_ret >= 0) { - gf_stat_from_iatt (&rsp.stat, stbuf); - rsp.size = op_ret; - } else { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": READV %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, vector, count, iobref, - xdr_serialize_readv_rsp); - - 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) -{ - gfs3_rchecksum_rsp rsp = {0,}; - rpcsvc_request_t *req = NULL; - server_state_t *state = NULL; - - req = frame->local; - - state = CALL_STATE(frame); - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - if (op_ret >= 0) { - rsp.weak_checksum = weak_checksum; - - rsp.strong_checksum.strong_checksum_val = (char *)strong_checksum; - rsp.strong_checksum.strong_checksum_len = MD5_DIGEST_LEN; - } - if (op_ret == -1) - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": RCHECKSUM %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_rchecksum_rsp); - - 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) -{ - server_connection_t *conn = NULL; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - uint64_t fd_no = 0; - gfs3_open_rsp rsp = {0,}; - - conn = SERVER_CONNECTION (frame); - state = CALL_STATE (frame); - - if (op_ret >= 0) { - fd_bind (fd); - fd_no = gf_fd_unused_get (conn->fdtable, fd); - fd_ref (fd); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"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)); - } - - req = frame->local; - - rsp.fd = fd_no; - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_open_rsp); - 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) -{ - server_connection_t *conn = NULL; - server_state_t *state = NULL; - inode_t *link_inode = NULL; - rpcsvc_request_t *req = NULL; - uint64_t fd_no = 0; - gfs3_create_rsp rsp = {0,}; - - conn = SERVER_CONNECTION (frame); - state = CALL_STATE (frame); - - if (op_ret >= 0) { - gf_log (state->conn->bound_xl->name, GF_LOG_TRACE, - "%"PRId64": CREATE %"PRId64"/%s (%"PRId64")", - frame->root->unique, state->loc.parent->ino, - state->loc.name, stbuf->ia_ino); - - 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); - - fd_bind (fd); - - fd_no = gf_fd_unused_get (conn->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); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"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)); - } - -out: - req = frame->local; - - rsp.fd = fd_no; - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_create_rsp); - - 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) -{ - gfs3_readlink_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - - state = CALL_STATE(frame); - - if (op_ret >= 0) { - gf_stat_from_iatt (&rsp.buf, stbuf); - rsp.path = (char *)buf; - } else { - gf_log (this->name, GF_LOG_INFO, - "%"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)); - } - - if (!rsp.path) - rsp.path = ""; - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_readlink_rsp); - - 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) -{ - gfs3_stat_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE (frame); - - if (op_ret == 0) { - gf_stat_from_iatt (&rsp.stat, stbuf); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"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_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_stat_rsp); - - 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) -{ - gfs3_setattr_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - state = CALL_STATE (frame); - - if (op_ret == 0) { - gf_stat_from_iatt (&rsp.statpre, statpre); - gf_stat_from_iatt (&rsp.statpost, statpost); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": SETATTR %s (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->loc.path, - state->loc.inode ? state->loc.inode->ino : 0, - op_ret, strerror (op_errno)); - } - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_setattr_rsp); - - 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) -{ - gfs3_fsetattr_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - state = CALL_STATE (frame); - - if (op_ret == 0) { - gf_stat_from_iatt (&rsp.statpre, statpre); - gf_stat_from_iatt (&rsp.statpost, statpost); - } else { - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": FSETATTR %"PRId64" (%"PRId64") ==> " - "%"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, - op_ret, strerror (op_errno)); - } - - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_fsetattr_rsp); - - 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) -{ - gfs3_xattrop_rsp rsp = {0,}; - int32_t len = 0; - int32_t ret = -1; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - - 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)); - goto out; - } - - 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; - goto out; - } - rsp.dict.dict_val = GF_CALLOC (1, len, gf_server_mt_rsp_buf_t); - if (!rsp.dict.dict_val) { - op_ret = -1; - op_errno = ENOMEM; - len = 0; - goto out; - } - ret = dict_serialize (dict, rsp.dict.dict_val); - 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; - } - } -out: - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - rsp.dict.dict_len = len; - if (op_ret == -1) - gf_log (this->name, GF_LOG_INFO, - "%"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)); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_xattrop_rsp); - - if (rsp.dict.dict_val) - GF_FREE (rsp.dict.dict_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) -{ - gfs3_xattrop_rsp rsp = {0,}; - int32_t len = 0; - int32_t ret = -1; - server_state_t *state = NULL; - rpcsvc_request_t *req = 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->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - goto out; - } - - 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->resolve.fd_no, state->fd->inode->ino); - op_ret = -1; - op_errno = EINVAL; - len = 0; - goto out; - } - rsp.dict.dict_val = GF_CALLOC (1, len, gf_server_mt_rsp_buf_t); - if (!rsp.dict.dict_val) { - op_ret = -1; - op_errno = ENOMEM; - len = 0; - goto out; - } - ret = dict_serialize (dict, rsp.dict.dict_val); - if (ret < 0) { - gf_log (this->name, GF_LOG_ERROR, - "fd - %"PRId64" (%"PRId64"): failed to " - "serialize reply dict", - state->resolve.fd_no, state->fd->inode->ino); - op_ret = -1; - op_errno = -ret; - len = 0; - } - } -out: - req = frame->local; - - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - rsp.dict.dict_len = len; - if (op_ret == -1) - gf_log (this->name, GF_LOG_INFO, - "%"PRId64": FXATTROP %"PRId64" (%"PRId64") ==> %"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_fxattrop_rsp); - - if (rsp.dict.dict_val) - GF_FREE (rsp.dict.dict_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) -{ - gfs3_readdirp_rsp rsp = {0,}; - server_state_t *state = NULL; - rpcsvc_request_t *req = NULL; - int ret = 0; - - req = frame->local; - - state = CALL_STATE(frame); - if (op_ret > 0) { - ret = serialize_rsp_direntp (entries, &rsp); - if (ret == -1) { - op_ret = -1; - op_errno = ENOMEM; - goto out; - } - } else { - /* (op_ret == 0) is valid, and means EOF, don't log for that */ - gf_log (this->name, (op_ret) ? GF_LOG_INFO : GF_LOG_TRACE, - "%"PRId64": READDIRP %"PRId64" (%"PRId64") ==>" - "%"PRId32" (%s)", - frame->root->unique, state->resolve.fd_no, - state->fd ? state->fd->inode->ino : 0, op_ret, - strerror (op_errno)); - } - -out: - rsp.op_ret = op_ret; - rsp.op_errno = gf_errno_to_error (op_errno); - - server_submit_reply (frame, req, &rsp, NULL, 0, NULL, - xdr_serialize_readdirp_rsp); - - readdirp_rsp_cleanup (&rsp); - - 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); - - return 0; -err: - server_rchecksum_cbk (frame, NULL, frame->this, op_ret, op_errno, 0, 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); - - return 0; - -err: - server_lk_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_rename_cbk (frame, NULL, frame->this, op_ret, op_errno, - 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); - - return 0; -err: - server_link_cbk (frame, NULL, frame->this, op_ret, op_errno, - 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->params); - - return 0; -err: - server_symlink_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_access_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno); - return 0; -} - -int -server_fentrylk_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_fentrylk_cbk, bound_xl, - bound_xl->fops->fentrylk, - state->volume, state->fd, state->name, - state->cmd, state->type); - - return 0; -err: - server_fentrylk_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno); - return 0; -} - - -int -server_entrylk_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_entrylk_cbk, - bound_xl, bound_xl->fops->entrylk, - state->volume, &state->loc, state->name, - state->cmd, state->type); - return 0; -err: - server_entrylk_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno); - return 0; -} - - -int -server_finodelk_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_finodelk_cbk, bound_xl, - bound_xl->fops->finodelk, - state->volume, state->fd, state->cmd, &state->flock); - - return 0; -err: - server_finodelk_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno); - - return 0; -} - -int -server_inodelk_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_inodelk_cbk, - bound_xl, bound_xl->fops->inodelk, - state->volume, &state->loc, state->cmd, &state->flock); - return 0; -err: - server_inodelk_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno); - 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); - return 0; -err: - server_rmdir_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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->params); - - return 0; -err: - server_mkdir_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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->params); - - return 0; -err: - server_mknod_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; - -err: - server_fsyncdir_cbk (frame, NULL, frame->this, - state->resolve.op_ret, - state->resolve.op_errno); - 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; - - STACK_WIND (frame, server_readdir_cbk, - bound_xl, - bound_xl->fops->readdir, - state->fd, state->size, state->offset); - - return 0; -err: - server_readdir_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - - return 0; -err: - server_readdirp_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - - STACK_WIND (frame, server_opendir_cbk, - bound_xl, bound_xl->fops->opendir, - &state->loc, state->fd); - return 0; -err: - server_opendir_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; - -err: - server_statfs_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_removexattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno); - 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); - return 0; -err: - server_fgetxattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_xattrop_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_fxattrop_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_fsetxattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno); - - 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); - return 0; -err: - server_unlink_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_truncate_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_fstat_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_setxattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno); - - 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); - return 0; -err: - server_getxattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_ftruncate_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_flush_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno); - - 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); - return 0; -err: - server_fsync_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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->iobref); - - return 0; -err: - server_writev_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - - return 0; -err: - server_readv_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, NULL, 0, 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); - state->fd->flags = state->flags; - - STACK_WIND (frame, server_create_cbk, - bound_xl, bound_xl->fops->create, - &(state->loc), state->flags, state->mode, - state->fd, state->params); - - return 0; -err: - server_create_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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, 0); - - return 0; -err: - server_open_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_readlink_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_fsetattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_setattr_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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); - return 0; -err: - server_stat_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, 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->dict); - - return 0; -err: - server_lookup_cbk (frame, NULL, frame->this, state->resolve.op_ret, - state->resolve.op_errno, NULL, NULL, NULL, NULL); - - return 0; -} - - - - -/* Fop section */ - -int -server_stat (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_stat_req args = {{0,},}; - int ret = -1; - - if (!req) - return 0; - - /* Initialize args first, then decode */ - args.path = alloca (req->msg[0].iov_len); - - if (!xdr_to_stat_req (req->msg[0], &args)) { - //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_STAT; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - memcpy (state->resolve.gfid, args.gfid, 16); - state->resolve.path = gf_strdup (args.path); - - ret = 0; - resolve_and_resume (frame, server_stat_resume); -out: - return ret; -} - - -int -server_setattr (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_setattr_req args = {{0,},}; - int ret = -1; - - if (!req) - return 0; - - args.path = alloca (req->msg[0].iov_len); - - if (!xdr_to_setattr_req (req->msg[0], &args)) { - //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_SETATTR; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - memcpy (state->resolve.gfid, args.gfid, 16); - state->resolve.path = gf_strdup (args.path); - - gf_stat_to_iatt (&args.stbuf, &state->stbuf); - state->valid = args.valid; - - ret = 0; - resolve_and_resume (frame, server_setattr_resume); -out: - return ret; -} - - -int -server_fsetattr (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_fsetattr_req args = {0,}; - int ret = -1; - - if (!req) - return ret; - - if (!xdr_to_fsetattr_req (req->msg[0], &args)) { - //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_FSETATTR; - - state = CALL_STATE (frame); - if (!state->conn->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; - - gf_stat_to_iatt (&args.stbuf, &state->stbuf); - state->valid = args.valid; - - ret = 0; - resolve_and_resume (frame, server_fsetattr_resume); -out: - return ret; -} - - -int -server_readlink (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_readlink_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - - if (!xdr_to_readlink_req (req->msg[0], &args)) { - //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_READLINK; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - memcpy (state->resolve.gfid, args.gfid, 16); - state->resolve.path = gf_strdup (args.path); - - state->size = args.size; - - ret = 0; - resolve_and_resume (frame, server_readlink_resume); -out: - return ret; -} - - -int -server_create (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - dict_t *params = NULL; - char *buf = NULL; - gfs3_create_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - args.bname = alloca (req->msg[0].iov_len); - - if (!xdr_to_create_req (req->msg[0], &args)) { - //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_CREATE; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - if (args.dict.dict_len) { - /* Unserialize the dictionary */ - params = dict_new (); - - buf = memdup (args.dict.dict_val, args.dict.dict_len); - if (buf == NULL) { - goto out; - } - - ret = dict_unserialize (buf, args.dict.dict_len, - ¶ms); - if (ret < 0) { - gf_log (state->conn->bound_xl->name, GF_LOG_ERROR, - "%"PRId64": %s (%"PRId64"): failed to " - "unserialize req-buffer to dictionary", - frame->root->unique, state->resolve.path, - state->resolve.ino); - goto out; - } - - state->params = params; - - params->extra_free = buf; - - buf = NULL; - } - - state->resolve.type = RESOLVE_NOT; - state->resolve.path = gf_strdup (args.path); - state->resolve.bname = gf_strdup (args.bname); - state->mode = args.mode; - state->flags = gf_flags_to_flags (args.flags); - memcpy (state->resolve.pargfid, args.pargfid, 16); - - ret = 0; - resolve_and_resume (frame, server_create_resume); - - /* memory allocated by libc, don't use GF_FREE */ - if (args.dict.dict_val != NULL) { - free (args.dict.dict_val); - } - - return ret; -out: - if (params) - dict_unref (params); - - if (buf) { - GF_FREE (buf); - } - - /* memory allocated by libc, don't use GF_FREE */ - if (args.dict.dict_val != NULL) { - free (args.dict.dict_val); - } - - return ret; -} - - -int -server_open (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_open_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - - if (!xdr_to_open_req (req->msg[0], &args)) { - //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_OPEN; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - memcpy (state->resolve.gfid, args.gfid, 16); - state->resolve.path = gf_strdup (args.path); - - state->flags = gf_flags_to_flags (args.flags); - - ret = 0; - resolve_and_resume (frame, server_open_resume); -out: - return ret; -} - - -int -server_readv (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_read_req args = {{0,},}; - int ret = -1; - - if (!req) - goto out; - - if (!xdr_to_readv_req (req->msg[0], &args)) { - //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_READ; - - state = CALL_STATE (frame); - if (!state->conn->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->size = args.size; - state->offset = args.offset; - - ret = 0; - resolve_and_resume (frame, server_readv_resume); -out: - return ret; -} - - -int -server_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; - - if (!req) - return ret; - - len = xdr_to_writev_req (req->msg[0], &args); - if (len == 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_WRITE; - - state = CALL_STATE (frame); - if (!state->conn->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->iobref = iobref_ref (req->iobref); - - 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; - } - - ret = 0; - resolve_and_resume (frame, server_writev_resume); -out: - return ret; -} - - -int -server_writev_vec (rpcsvc_request_t *req, struct iovec *payload, - int payload_count, struct iobref *iobref) -{ - return server_writev (req); -} - - -int -server_release (rpcsvc_request_t *req) -{ - server_connection_t *conn = NULL; - gfs3_release_req args = {{0,},}; - gf_common_rsp rsp = {0,}; - int ret = -1; - - if (!xdr_to_release_req (req->msg[0], &args)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - conn = req->trans->xl_private; - gf_fd_put (conn->fdtable, args.fd); - - server_submit_reply (NULL, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); - ret = 0; -out: - return ret; -} - -int -server_releasedir (rpcsvc_request_t *req) -{ - server_connection_t *conn = NULL; - gfs3_releasedir_req args = {{0,},}; - gf_common_rsp rsp = {0,}; - int ret = -1; - - if (!xdr_to_release_req (req->msg[0], &args)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - conn = req->trans->xl_private; - gf_fd_put (conn->fdtable, args.fd); - - server_submit_reply (NULL, req, &rsp, NULL, 0, NULL, - xdr_serialize_common_rsp); - ret = 0; -out: - return ret; -} - - -int -server_fsync (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_fsync_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - if (!xdr_to_fsync_req (req->msg[0], &args)) { - //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_FSYNC; - - state = CALL_STATE (frame); - if (!state->conn->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->flags = args.data; - - ret = 0; - resolve_and_resume (frame, server_fsync_resume); -out: - return ret; -} - - - -int -server_flush (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_flush_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - if (!xdr_to_flush_req (req->msg[0], &args)) { - //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_FLUSH; - - state = CALL_STATE (frame); - if (!state->conn->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; - - ret = 0; - resolve_and_resume (frame, server_flush_resume); -out: - return ret; -} - - - -int -server_ftruncate (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_ftruncate_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - if (!xdr_to_ftruncate_req (req->msg[0], &args)) { - //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_FTRUNCATE; - - state = CALL_STATE (frame); - if (!state->conn->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; - - ret = 0; - resolve_and_resume (frame, server_ftruncate_resume); -out: - return ret; -} - - -int -server_fstat (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_write_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - if (!xdr_to_fstat_req (req->msg[0], &args)) { - //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_FSTAT; - - state = CALL_STATE (frame); - if (!state->conn->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; - - ret = 0; - resolve_and_resume (frame, server_fstat_resume); -out: - return ret; -} - - -int -server_truncate (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_truncate_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - if (!xdr_to_truncate_req (req->msg[0], &args)) { - //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_TRUNCATE; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - state->resolve.path = gf_strdup (args.path); - memcpy (state->resolve.gfid, args.gfid, 16); - state->offset = args.offset; - - ret = 0; - resolve_and_resume (frame, server_truncate_resume); -out: - return ret; -} - - - -int -server_unlink (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_unlink_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - args.bname = alloca (req->msg[0].iov_len); - - if (!xdr_to_unlink_req (req->msg[0], &args)) { - //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_UNLINK; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - state->resolve.path = gf_strdup (args.path); - state->resolve.bname = gf_strdup (args.bname); - memcpy (state->resolve.pargfid, args.pargfid, 16); - - ret = 0; - resolve_and_resume (frame, server_unlink_resume); -out: - return ret; -} - - -int -server_setxattr (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - dict_t *dict = NULL; - call_frame_t *frame = NULL; - server_connection_t *conn = NULL; - char *buf = NULL; - gfs3_setxattr_req args = {{0,},}; - int32_t ret = -1; - - if (!req) - return ret; - - conn = req->trans->xl_private; - - args.path = alloca (req->msg[0].iov_len); - args.dict.dict_val = alloca (req->msg[0].iov_len); - - if (!xdr_to_setxattr_req (req->msg[0], &args)) { - //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_SETXATTR; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - state->resolve.path = gf_strdup (args.path); - state->flags = args.flags; - memcpy (state->resolve.gfid, args.gfid, 16); - - if (args.dict.dict_len) { - dict = dict_new (); - buf = memdup (args.dict.dict_val, args.dict.dict_len); - GF_VALIDATE_OR_GOTO (conn->bound_xl->name, buf, out); - - ret = dict_unserialize (buf, args.dict.dict_len, &dict); - if (ret < 0) { - gf_log (conn->bound_xl->name, GF_LOG_ERROR, - "%"PRId64": %s (%"PRId64"): failed to " - "unserialize request buffer to dictionary", - frame->root->unique, state->loc.path, - state->resolve.ino); - goto err; - } - - dict->extra_free = buf; - buf = NULL; - - state->dict = dict; - } - - /* There can be some commands hidden in key, check and proceed */ - gf_server_check_setxattr_cmd (frame, dict); - - ret = 0; - resolve_and_resume (frame, server_setxattr_resume); - - return ret; -err: - if (dict) - dict_unref (dict); - - server_setxattr_cbk (frame, NULL, frame->this, -1, EINVAL); - ret = 0; -out: - if (buf) - GF_FREE (buf); - return ret; - -} - - - -int -server_fsetxattr (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - dict_t *dict = NULL; - server_connection_t *conn = NULL; - call_frame_t *frame = NULL; - char *buf = NULL; - gfs3_fsetxattr_req args = {{0,},}; - int32_t ret = -1; - - if (!req) - return ret; - - conn = req->trans->xl_private; - - args.dict.dict_val = alloca (req->msg[0].iov_len); - if (!xdr_to_fsetxattr_req (req->msg[0], &args)) { - //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_FSETXATTR; - - state = CALL_STATE (frame); - if (!state->conn->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->flags = args.flags; - - if (args.dict.dict_len) { - dict = dict_new (); - buf = memdup (args.dict.dict_val, args.dict.dict_len); - GF_VALIDATE_OR_GOTO (conn->bound_xl->name, buf, out); - - ret = dict_unserialize (buf, args.dict.dict_len, &dict); - if (ret < 0) { - gf_log (conn->bound_xl->name, GF_LOG_ERROR, - "%"PRId64": %s (%"PRId64"): failed to " - "unserialize request buffer to dictionary", - frame->root->unique, state->loc.path, - state->resolve.ino); - goto err; - } - dict->extra_free = buf; - buf = NULL; - state->dict = dict; - } - - ret = 0; - resolve_and_resume (frame, server_fsetxattr_resume); - - return ret; -err: - if (dict) - dict_unref (dict); - - server_setxattr_cbk (frame, NULL, frame->this, -1, EINVAL); - ret = 0; -out: - if (buf) - GF_FREE (buf); - return ret; -} - - - -int -server_fxattrop (rpcsvc_request_t *req) -{ - dict_t *dict = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - call_frame_t *frame = NULL; - char *buf = NULL; - gfs3_fxattrop_req args = {{0,},}; - int32_t ret = -1; - - if (!req) - return ret; - - conn = req->trans->xl_private; - - args.dict.dict_val = alloca (req->msg[0].iov_len); - if (!xdr_to_fxattrop_req (req->msg[0], &args)) { - //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_FXATTROP; - - state = CALL_STATE(frame); - if (!state->conn->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->flags = args.flags; - memcpy (state->resolve.gfid, args.gfid, 16); - - if (args.dict.dict_len) { - /* Unserialize the dictionary */ - dict = dict_new (); - - buf = memdup (args.dict.dict_val, args.dict.dict_len); - GF_VALIDATE_OR_GOTO (conn->bound_xl->name, buf, out); - - ret = dict_unserialize (buf, args.dict.dict_len, &dict); - if (ret < 0) { - gf_log (conn->bound_xl->name, GF_LOG_ERROR, - "fd - %"PRId64" (%"PRId64"): failed to unserialize " - "request buffer to dictionary", - state->resolve.fd_no, state->fd->inode->ino); - goto fail; - } - dict->extra_free = buf; - buf = NULL; - - state->dict = dict; - } - - ret = 0; - resolve_and_resume (frame, server_fxattrop_resume); - - return ret; - -fail: - if (dict) - dict_unref (dict); - - server_fxattrop_cbk (frame, NULL, frame->this, -1, EINVAL, NULL); - ret = 0; -out: - return ret; -} - - - -int -server_xattrop (rpcsvc_request_t *req) -{ - dict_t *dict = NULL; - server_state_t *state = NULL; - server_connection_t *conn = NULL; - call_frame_t *frame = NULL; - char *buf = NULL; - gfs3_xattrop_req args = {{0,},}; - int32_t ret = -1; - - if (!req) - return ret; - - conn = req->trans->xl_private; - - args.dict.dict_val = alloca (req->msg[0].iov_len); - args.path = alloca (req->msg[0].iov_len); - - if (!xdr_to_xattrop_req (req->msg[0], &args)) { - //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_XATTROP; - - state = CALL_STATE(frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - state->resolve.path = gf_strdup (args.path); - state->flags = args.flags; - memcpy (state->resolve.gfid, args.gfid, 16); - - if (args.dict.dict_len) { - /* Unserialize the dictionary */ - dict = dict_new (); - - buf = memdup (args.dict.dict_val, args.dict.dict_len); - GF_VALIDATE_OR_GOTO (conn->bound_xl->name, buf, out); - - ret = dict_unserialize (buf, args.dict.dict_len, &dict); - if (ret < 0) { - gf_log (conn->bound_xl->name, GF_LOG_ERROR, - "fd - %"PRId64" (%"PRId64"): failed to unserialize " - "request buffer to dictionary", - state->resolve.fd_no, state->fd->inode->ino); - goto fail; - } - dict->extra_free = buf; - buf = NULL; - - state->dict = dict; - } - - ret = 0; - resolve_and_resume (frame, server_xattrop_resume); - - return ret; -fail: - if (dict) - dict_unref (dict); - - server_xattrop_cbk (frame, NULL, frame->this, -1, EINVAL, NULL); - ret = 0; -out: - return ret; -} - - -int -server_getxattr (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_getxattr_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - args.name = alloca (4096); - - if (!xdr_to_getxattr_req (req->msg[0], &args)) { - //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_GETXATTR; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - state->resolve.path = gf_strdup (args.path); - 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); - } - - ret = 0; - resolve_and_resume (frame, server_getxattr_resume); -out: - return ret; -} - - -int -server_fgetxattr (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_fgetxattr_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.name = alloca (4096); - if (!xdr_to_fgetxattr_req (req->msg[0], &args)) { - //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_FGETXATTR; - - state = CALL_STATE (frame); - if (!state->conn->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; - - if (args.namelen) - state->name = gf_strdup (args.name); - - ret = 0; - resolve_and_resume (frame, server_fgetxattr_resume); -out: - return ret; -} - - - -int -server_removexattr (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_removexattr_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - args.name = alloca (4096); - - if (!xdr_to_removexattr_req (req->msg[0], &args)) { - //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_REMOVEXATTR; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - state->resolve.path = gf_strdup (args.path); - memcpy (state->resolve.gfid, args.gfid, 16); - state->name = gf_strdup (args.name); - - ret = 0; - resolve_and_resume (frame, server_removexattr_resume); -out: - return ret; -} - - - - -int -server_opendir (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_opendir_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - - if (!xdr_to_opendir_req (req->msg[0], &args)) { - //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_OPENDIR; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - state->resolve.path = gf_strdup (args.path); - memcpy (state->resolve.gfid, args.gfid, 16); - - ret = 0; - resolve_and_resume (frame, server_opendir_resume); -out: - return ret; -} - - -int -server_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; - - if (!req) - return ret; - - if (!xdr_to_readdirp_req (req->msg[0], &args)) { - //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_READDIRP; - - state = CALL_STATE(frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - 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; - - ret = 0; - resolve_and_resume (frame, server_readdirp_resume); -out: - return ret; -} - -int -server_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; - - if (!req) - return ret; - - if (!xdr_to_readdir_req (req->msg[0], &args)) { - //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_READDIR; - - state = CALL_STATE(frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - 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; - - ret = 0; - resolve_and_resume (frame, server_readdir_resume); -out: - return ret; -} - -int -server_fsyncdir (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_fsyncdir_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - if (!xdr_to_fsyncdir_req (req->msg[0], &args)) { - //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_FSYNCDIR; - - state = CALL_STATE(frame); - if (!state->conn->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->flags = args.data; - - ret = 0; - resolve_and_resume (frame, server_fsyncdir_resume); -out: - return ret; -} - - - -int -server_mknod (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - dict_t *params = NULL; - char *buf = NULL; - gfs3_mknod_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - args.bname = alloca (req->msg[0].iov_len); - - if (!xdr_to_mknod_req (req->msg[0], &args)) { - //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_MKNOD; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - if (args.dict.dict_len) { - /* Unserialize the dictionary */ - params = dict_new (); - - buf = memdup (args.dict.dict_val, args.dict.dict_len); - if (buf == NULL) { - goto out; - } - - ret = dict_unserialize (buf, args.dict.dict_len, - ¶ms); - if (ret < 0) { - gf_log (state->conn->bound_xl->name, GF_LOG_ERROR, - "%"PRId64": %s (%"PRId64"): failed to " - "unserialize req-buffer to dictionary", - frame->root->unique, state->resolve.path, - state->resolve.ino); - goto out; - } - - state->params = params; - - params->extra_free = buf; - - buf = NULL; - } - - state->resolve.type = RESOLVE_NOT; - memcpy (state->resolve.pargfid, args.pargfid, 16); - state->resolve.path = gf_strdup (args.path); - state->resolve.bname = gf_strdup (args.bname); - - state->mode = args.mode; - state->dev = args.dev; - - ret = 0; - resolve_and_resume (frame, server_mknod_resume); - - /* memory allocated by libc, don't use GF_FREE */ - if (args.dict.dict_val != NULL) { - free (args.dict.dict_val); - } - - return ret; -out: - if (params) - dict_unref (params); - - if (buf) { - GF_FREE (buf); - } - - /* memory allocated by libc, don't use GF_FREE */ - if (args.dict.dict_val != NULL) { - free (args.dict.dict_val); - } - - return ret; - -} - - -int -server_mkdir (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - dict_t *params = NULL; - char *buf = NULL; - gfs3_mkdir_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - args.bname = alloca (req->msg[0].iov_len); - - if (!xdr_to_mkdir_req (req->msg[0], &args)) { - //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_MKDIR; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - if (args.dict.dict_len) { - /* Unserialize the dictionary */ - params = dict_new (); - - buf = memdup (args.dict.dict_val, args.dict.dict_len); - if (buf == NULL) { - goto out; - } - - ret = dict_unserialize (buf, args.dict.dict_len, - ¶ms); - if (ret < 0) { - gf_log (state->conn->bound_xl->name, GF_LOG_ERROR, - "%"PRId64": %s (%"PRId64"): failed to " - "unserialize req-buffer to dictionary", - frame->root->unique, state->resolve.path, - state->resolve.ino); - goto out; - } - - state->params = params; - - params->extra_free = buf; - - buf = NULL; - } - - state->resolve.type = RESOLVE_NOT; - memcpy (state->resolve.pargfid, args.pargfid, 16); - state->resolve.path = gf_strdup (args.path); - state->resolve.bname = gf_strdup (args.bname); - - state->mode = args.mode; - - ret = 0; - resolve_and_resume (frame, server_mkdir_resume); - - if (args.dict.dict_val != NULL) { - /* memory allocated by libc, don't use GF_FREE */ - free (args.dict.dict_val); - } - - return ret; -out: - if (params) - dict_unref (params); - - if (buf) { - GF_FREE (buf); - } - - if (args.dict.dict_val != NULL) { - /* memory allocated by libc, don't use GF_FREE */ - free (args.dict.dict_val); - } - - return ret; -} - - -int -server_rmdir (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_rmdir_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - args.bname = alloca (req->msg[0].iov_len); - - if (!xdr_to_rmdir_req (req->msg[0], &args)) { - //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_RMDIR; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - memcpy (state->resolve.pargfid, args.pargfid, 16); - state->resolve.path = gf_strdup (args.path); - state->resolve.bname = gf_strdup (args.bname); - - state->flags = args.flags; - - ret = 0; - resolve_and_resume (frame, server_rmdir_resume); -out: - return ret; -} - - - -int -server_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; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - args.volume = alloca (4096); - - if (!xdr_to_inodelk_req (req->msg[0], &args)) { - //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_INODELK; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_EXACT; - memcpy (state->resolve.gfid, args.gfid, 16); - state->resolve.path = gf_strdup (args.path); - - 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; - } - - ret = 0; - resolve_and_resume (frame, server_inodelk_resume); -out: - return ret; -} - -int -server_finodelk (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_finodelk_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.volume = alloca (4096); - if (!xdr_to_finodelk_req (req->msg[0], &args)) { - //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_FINODELK; - - state = CALL_STATE(frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_EXACT; - state->volume = gf_strdup (args.volume); - state->resolve.fd_no = args.fd; - state->cmd = args.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 = 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; - } - - ret = 0; - resolve_and_resume (frame, server_finodelk_resume); -out: - return ret; -} - - -int -server_entrylk (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_entrylk_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - args.volume = alloca (4096); - args.name = alloca (4096); - - if (!xdr_to_entrylk_req (req->msg[0], &args)) { - //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_ENTRYLK; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_EXACT; - state->resolve.path = gf_strdup (args.path); - 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; - - ret = 0; - resolve_and_resume (frame, server_entrylk_resume); -out: - return ret; -} - -int -server_fentrylk (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_fentrylk_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.name = alloca (4096); - args.volume = alloca (4096); - - if (!xdr_to_fentrylk_req (req->msg[0], &args)) { - //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_FENTRYLK; - - state = CALL_STATE(frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_EXACT; - state->resolve.fd_no = args.fd; - state->cmd = args.cmd; - state->type = args.type; - - if (args.namelen) - state->name = gf_strdup (args.name); - state->volume = gf_strdup (args.volume); - - ret = 0; - resolve_and_resume (frame, server_fentrylk_resume); -out: - return ret; -} - -int -server_access (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_access_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - if (!xdr_to_access_req (req->msg[0], &args)) { - //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_ACCESS; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - memcpy (state->resolve.gfid, args.gfid, 16); - state->resolve.path = gf_strdup (args.path); - state->mask = args.mask; - - ret = 0; - resolve_and_resume (frame, server_access_resume); -out: - return ret; -} - - - -int -server_symlink (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - dict_t *params = NULL; - char *buf = NULL; - gfs3_symlink_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - args.bname = alloca (req->msg[0].iov_len); - args.linkname = alloca (4096); - - if (!xdr_to_symlink_req (req->msg[0], &args)) { - //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_SYMLINK; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - if (args.dict.dict_len) { - /* Unserialize the dictionary */ - params = dict_new (); - - buf = memdup (args.dict.dict_val, args.dict.dict_len); - if (buf == NULL) { - goto out; - } - - ret = dict_unserialize (buf, args.dict.dict_len, - ¶ms); - if (ret < 0) { - gf_log (state->conn->bound_xl->name, GF_LOG_ERROR, - "%"PRId64": %s (%"PRId64"): failed to " - "unserialize req-buffer to dictionary", - frame->root->unique, state->resolve.path, - state->resolve.ino); - goto out; - } - - state->params = params; - - params->extra_free = buf; - - buf = NULL; - } - - state->resolve.type = RESOLVE_NOT; - memcpy (state->resolve.pargfid, args.pargfid, 16); - state->resolve.path = gf_strdup (args.path); - state->resolve.bname = gf_strdup (args.bname); - state->name = gf_strdup (args.linkname); - - ret = 0; - resolve_and_resume (frame, server_symlink_resume); - - /* memory allocated by libc, don't use GF_FREE */ - if (args.dict.dict_val != NULL) { - free (args.dict.dict_val); - } - return ret; -out: - if (params) - dict_unref (params); - - if (buf) { - GF_FREE (buf); - } - - /* memory allocated by libc, don't use GF_FREE */ - if (args.dict.dict_val != NULL) { - free (args.dict.dict_val); - } - - return ret; -} - - - -int -server_link (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_link_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.oldpath = alloca (req->msg[0].iov_len); - args.newpath = alloca (req->msg[0].iov_len); - args.newbname = alloca (req->msg[0].iov_len); - - if (!xdr_to_link_req (req->msg[0], &args)) { - //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_LINK; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - state->resolve.path = gf_strdup (args.oldpath); - memcpy (state->resolve.gfid, args.oldgfid, 16); - - state->resolve2.type = RESOLVE_NOT; - state->resolve2.path = gf_strdup (args.newpath); - state->resolve2.bname = gf_strdup (args.newbname); - memcpy (state->resolve2.pargfid, args.newgfid, 16); - - ret = 0; - resolve_and_resume (frame, server_link_resume); -out: - return ret; -} - - -int -server_rename (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_rename_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.oldpath = alloca (req->msg[0].iov_len); - args.oldbname = alloca (req->msg[0].iov_len); - args.newpath = alloca (req->msg[0].iov_len); - args.newbname = alloca (req->msg[0].iov_len); - - if (!xdr_to_rename_req (req->msg[0], &args)) { - //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_RENAME; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - state->resolve.path = gf_strdup (args.oldpath); - state->resolve.bname = gf_strdup (args.oldbname); - memcpy (state->resolve.pargfid, args.oldgfid, 16); - - state->resolve2.type = RESOLVE_MAY; - state->resolve2.path = gf_strdup (args.newpath); - state->resolve2.bname = gf_strdup (args.newbname); - memcpy (state->resolve2.pargfid, args.newgfid, 16); - - ret = 0; - resolve_and_resume (frame, server_rename_resume); -out: - return ret; -} - -int -server_lk (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - server_connection_t *conn = NULL; - call_frame_t *frame = NULL; - gfs3_lk_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - conn = req->trans->xl_private; - - if (!xdr_to_lk_req (req->msg[0], &args)) { - //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_LK; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.fd_no = args.fd; - state->cmd = args.cmd; - state->type = args.type; - - 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 (conn->bound_xl->name, GF_LOG_ERROR, - "fd - %"PRId64" (%"PRId64"): Unknown lock type: %"PRId32"!", - state->resolve.fd_no, state->fd->inode->ino, state->type); - break; - } - - - ret = 0; - resolve_and_resume (frame, server_lk_resume); -out: - return ret; -} - - -int -server_rchecksum (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_rchecksum_req args = {0,}; - int ret = -1; - - if (!req) - return ret; - - if (!xdr_to_rchecksum_req (req->msg[0], &args)) { - //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_RCHECKSUM; - - state = CALL_STATE(frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MAY; - state->resolve.fd_no = args.fd; - state->offset = args.offset; - state->size = args.len; - - ret = 0; - resolve_and_resume (frame, server_rchecksum_resume); -out: - 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, - (gfs_serialize_t)xdr_serialize_common_rsp); - - return 0; -} - -int -server_lookup (rpcsvc_request_t *req) -{ - call_frame_t *frame = NULL; - server_connection_t *conn = NULL; - server_state_t *state = NULL; - dict_t *xattr_req = NULL; - char *buf = NULL; - gfs3_lookup_req args = {{0,},}; - int ret = -1; - - GF_VALIDATE_OR_GOTO ("server", req, err); - - conn = req->trans->xl_private; - - args.path = alloca (req->msg[0].iov_len); - args.bname = alloca (req->msg[0].iov_len); - args.dict.dict_val = alloca (req->msg[0].iov_len); - - if (!xdr_to_lookup_req (req->msg[0], &args)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto err; - } - - frame = get_frame_from_request (req); - if (!frame) { - // something wrong, mostly insufficient memory - req->rpc_err = GARBAGE_ARGS; - 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 (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - memcpy (state->resolve.gfid, args.gfid, 16); - - state->resolve.type = RESOLVE_DONTCARE; - memcpy (state->resolve.pargfid, args.pargfid, 16); - state->resolve.path = gf_strdup (args.path); - - if (IS_NOT_ROOT (STRLEN_0 (args.path))) { - state->resolve.bname = gf_strdup (args.bname); - } - - if (args.dict.dict_len) { - /* Unserialize the dictionary */ - xattr_req = dict_new (); - - buf = memdup (args.dict.dict_val, args.dict.dict_len); - if (buf == NULL) { - goto out; - } - - ret = dict_unserialize (buf, args.dict.dict_len, - &xattr_req); - if (ret < 0) { - gf_log (conn->bound_xl->name, GF_LOG_ERROR, - "%"PRId64": %s (%"PRId64"): failed to " - "unserialize req-buffer to dictionary", - frame->root->unique, state->resolve.path, - state->resolve.ino); - goto out; - } - - state->dict = xattr_req; - - xattr_req->extra_free = buf; - - buf = NULL; - } - - ret = 0; - resolve_and_resume (frame, server_lookup_resume); - - return ret; -out: - if (xattr_req) - dict_unref (xattr_req); - - if (buf) { - GF_FREE (buf); - } - - server_lookup_cbk (frame, NULL, frame->this, -1, EINVAL, NULL, NULL, - NULL, NULL); - ret = 0; -err: - return ret; -} - -int -server_statfs (rpcsvc_request_t *req) -{ - server_state_t *state = NULL; - call_frame_t *frame = NULL; - gfs3_statfs_req args = {{0,},}; - int ret = -1; - - if (!req) - return ret; - - args.path = alloca (req->msg[0].iov_len); - if (!xdr_to_statfs_req (req->msg[0], &args)) { - //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_STATFS; - - state = CALL_STATE (frame); - if (!state->conn->bound_xl) { - /* auth failure, request on subvolume without setvolume */ - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - state->resolve.type = RESOLVE_MUST; - memcpy (state->resolve.gfid, args.gfid, 16); - state->resolve.path = gf_strdup (args.path); - - ret = 0; - resolve_and_resume (frame, server_statfs_resume); -out: - return ret; -} - - -rpcsvc_actor_t glusterfs3_1_fop_actors[] = { - [GFS3_OP_NULL] = { "NULL", GFS3_OP_NULL, server_null, NULL, NULL}, - [GFS3_OP_STAT] = { "STAT", GFS3_OP_STAT, server_stat, NULL, NULL }, - [GFS3_OP_READLINK] = { "READLINK", GFS3_OP_READLINK, server_readlink, NULL, NULL }, - [GFS3_OP_MKNOD] = { "MKNOD", GFS3_OP_MKNOD, server_mknod, NULL, NULL }, - [GFS3_OP_MKDIR] = { "MKDIR", GFS3_OP_MKDIR, server_mkdir, NULL, NULL }, - [GFS3_OP_UNLINK] = { "UNLINK", GFS3_OP_UNLINK, server_unlink, NULL, NULL }, - [GFS3_OP_RMDIR] = { "RMDIR", GFS3_OP_RMDIR, server_rmdir, NULL, NULL }, - [GFS3_OP_SYMLINK] = { "SYMLINK", GFS3_OP_SYMLINK, server_symlink, NULL, NULL }, - [GFS3_OP_RENAME] = { "RENAME", GFS3_OP_RENAME, server_rename, NULL, NULL }, - [GFS3_OP_LINK] = { "LINK", GFS3_OP_LINK, server_link, NULL, NULL }, - [GFS3_OP_TRUNCATE] = { "TRUNCATE", GFS3_OP_TRUNCATE, server_truncate, NULL, NULL }, - [GFS3_OP_OPEN] = { "OPEN", GFS3_OP_OPEN, server_open, NULL, NULL }, - [GFS3_OP_READ] = { "READ", GFS3_OP_READ, server_readv, NULL, NULL }, - [GFS3_OP_WRITE] = { "WRITE", GFS3_OP_WRITE, server_writev, server_writev_vec, NULL }, - [GFS3_OP_STATFS] = { "STATFS", GFS3_OP_STATFS, server_statfs, NULL, NULL }, - [GFS3_OP_FLUSH] = { "FLUSH", GFS3_OP_FLUSH, server_flush, NULL, NULL }, - [GFS3_OP_FSYNC] = { "FSYNC", GFS3_OP_FSYNC, server_fsync, NULL, NULL }, - [GFS3_OP_SETXATTR] = { "SETXATTR", GFS3_OP_SETXATTR, server_setxattr, NULL, NULL }, - [GFS3_OP_GETXATTR] = { "GETXATTR", GFS3_OP_GETXATTR, server_getxattr, NULL, NULL }, - [GFS3_OP_REMOVEXATTR] = { "REMOVEXATTR", GFS3_OP_REMOVEXATTR, server_removexattr, NULL, NULL }, - [GFS3_OP_OPENDIR] = { "OPENDIR", GFS3_OP_OPENDIR, server_opendir, NULL, NULL }, - [GFS3_OP_FSYNCDIR] = { "FSYNCDIR", GFS3_OP_FSYNCDIR, server_fsyncdir, NULL, NULL }, - [GFS3_OP_ACCESS] = { "ACCESS", GFS3_OP_ACCESS, server_access, NULL, NULL }, - [GFS3_OP_CREATE] = { "CREATE", GFS3_OP_CREATE, server_create, NULL, NULL }, - [GFS3_OP_FTRUNCATE] = { "FTRUNCATE", GFS3_OP_FTRUNCATE, server_ftruncate, NULL, NULL }, - [GFS3_OP_FSTAT] = { "FSTAT", GFS3_OP_FSTAT, server_fstat, NULL, NULL }, - [GFS3_OP_LK] = { "LK", GFS3_OP_LK, server_lk, NULL, NULL }, - [GFS3_OP_LOOKUP] = { "LOOKUP", GFS3_OP_LOOKUP, server_lookup, NULL, NULL }, - [GFS3_OP_READDIR] = { "READDIR", GFS3_OP_READDIR, server_readdir, NULL, NULL }, - [GFS3_OP_INODELK] = { "INODELK", GFS3_OP_INODELK, server_inodelk, NULL, NULL }, - [GFS3_OP_FINODELK] = { "FINODELK", GFS3_OP_FINODELK, server_finodelk, NULL, NULL }, - [GFS3_OP_ENTRYLK] = { "ENTRYLK", GFS3_OP_ENTRYLK, server_entrylk, NULL, NULL }, - [GFS3_OP_FENTRYLK] = { "FENTRYLK", GFS3_OP_FENTRYLK, server_fentrylk, NULL, NULL }, - [GFS3_OP_XATTROP] = { "XATTROP", GFS3_OP_XATTROP, server_xattrop, NULL, NULL }, - [GFS3_OP_FXATTROP] = { "FXATTROP", GFS3_OP_FXATTROP, server_fxattrop, NULL, NULL }, - [GFS3_OP_FGETXATTR] = { "FGETXATTR", GFS3_OP_FGETXATTR, server_fgetxattr, NULL, NULL }, - [GFS3_OP_FSETXATTR] = { "FSETXATTR", GFS3_OP_FSETXATTR, server_fsetxattr, NULL, NULL }, - [GFS3_OP_RCHECKSUM] = { "RCHECKSUM", GFS3_OP_RCHECKSUM, server_rchecksum, NULL, NULL }, - [GFS3_OP_SETATTR] = { "SETATTR", GFS3_OP_SETATTR, server_setattr, NULL, NULL }, - [GFS3_OP_FSETATTR] = { "FSETATTR", GFS3_OP_FSETATTR, server_fsetattr, NULL, NULL }, - [GFS3_OP_READDIRP] = { "READDIRP", GFS3_OP_READDIRP, server_readdirp, NULL, NULL }, - [GFS3_OP_RELEASE] = { "RELEASE", GFS3_OP_RELEASE, server_release, NULL, NULL }, - [GFS3_OP_RELEASEDIR] = { "RELEASEDIR", GFS3_OP_RELEASEDIR, server_releasedir, NULL, NULL }, -}; - - -struct rpcsvc_program glusterfs3_1_fop_prog = { - .progname = "GlusterFS-3.1.0", - .prognum = GLUSTER3_1_FOP_PROGRAM, - .progver = GLUSTER3_1_FOP_VERSION, - .numactors = GLUSTER3_1_FOP_PROCCNT, - .actors = glusterfs3_1_fop_actors, -}; |
