diff options
Diffstat (limited to 'xlators/protocol/server/src/server-helpers.c')
| -rw-r--r-- | xlators/protocol/server/src/server-helpers.c | 1388 |
1 files changed, 565 insertions, 823 deletions
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; +} |
