diff options
Diffstat (limited to 'xlators/protocol/server/src/server-resolve.c')
| -rw-r--r-- | xlators/protocol/server/src/server-resolve.c | 551 |
1 files changed, 272 insertions, 279 deletions
diff --git a/xlators/protocol/server/src/server-resolve.c b/xlators/protocol/server/src/server-resolve.c index 77336216f19..1ad45394dd7 100644 --- a/xlators/protocol/server/src/server-resolve.c +++ b/xlators/protocol/server/src/server-resolve.c @@ -1,29 +1,16 @@ /* - 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - #include "server.h" #include "server-helpers.h" +#include "server-messages.h" int @@ -33,67 +20,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; - - trav = path; - - 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; - xlator_t *this = 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); - this = frame->this; - 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); - 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 == '/') { - components[i].basename = trav + 1; - *trav = 0; - i++; - } - } - - return 0; -} - +resolve_anonfd_simple (call_frame_t *frame); int resolve_loc_touchup (call_frame_t *frame) @@ -109,206 +38,231 @@ resolve_loc_touchup (call_frame_t *frame) resolve = state->resolve_now; loc = state->loc_now; - if (!loc->path) { - if (loc->parent) { - ret = inode_path (loc->parent, resolve->bname, &path); - } else if (loc->inode) { - ret = inode_path (loc->inode, NULL, &path); - } - - 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); - } - + loc_touchup (loc, resolve->bname); 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) { + if (op_errno == ENOENT) { + gf_msg_debug (this->name, 0, "%s/%s: failed to resolve" + " (%s)", + uuid_utoa (resolve_loc->pargfid), + resolve_loc->name, strerror (op_errno)); + } else { + gf_msg (this->name, GF_LOG_WARNING, op_errno, + PS_MSG_GFID_RESOLVE_FAILED, "%s/%s: failed to " + "resolve (%s)", + uuid_utoa (resolve_loc->pargfid), + resolve_loc->name, strerror (op_errno)); + } + goto out; + } - if (resolve->par) - ret = resolve_entry_simple (frame); - else if (resolve->ino) - ret = resolve_inode_simple (frame); - else if (resolve->path) - ret = resolve_path_simple (frame); + 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; + dict_t *dict = NULL; state = CALL_STATE (frame); resolve = state->resolve_now; - components = resolve->components; - - i = (long) cookie; + resolve_loc = &resolve->resolve_loc; if (op_ret == -1) { - goto get_out_of_here; + if (op_errno == ENOENT) { + gf_msg_debug (this->name, GF_LOG_DEBUG, + "%s: failed to resolve (%s)", + uuid_utoa (resolve_loc->gfid), + strerror (op_errno)); + } else { + gf_msg (this->name, GF_LOG_WARNING, op_errno, + PS_MSG_GFID_RESOLVE_FAILED, + "%s: failed to resolve (%s)", + 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; + link_inode = inode_link (inode, NULL, NULL, buf); + + if (!link_inode) { + loc_wipe (resolve_loc); + goto out; } - loc_wipe (&resolve->deep_loc); + inode_lookup (link_inode); + + /* wipe the loc only after the inode has been linked to the inode + table. Otherwise before inode gets linked to the inode table, + inode would have been unrefed (this might have been destroyed + if refcount becomes 0, and put back to mempool). So once the + inode gets destroyed, inode_link is a redundant operation. But + without knowing that the destroyed inode's pointer is saved in + the resolved_loc as parent (while constructing loc for resolving + the entry) and the inode_new call for resolving the entry will + return the same pointer to the inode as the parent (because in + reality the inode is a free inode present in cold list of the + inode mem-pool). + */ + loc_wipe (resolve_loc); + + if (gf_uuid_is_null (resolve->pargfid)) { + inode_unref (link_inode); + goto out; + } - i++; /* next component */ + resolve_loc->parent = link_inode; + gf_uuid_copy (resolve_loc->pargfid, resolve_loc->parent->gfid); - if (!components[i].basename) { - /* all components of the path are resolved */ - goto get_out_of_here; - } + resolve_loc->name = resolve->bname; - /* join the current component with the path resolved until now */ - *(components[i].basename - 1) = '/'; + resolve_loc->inode = server_inode_new (state->itable, + resolve_loc->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; + inode_path (resolve_loc->parent, resolve_loc->name, + (char **) &resolve_loc->path); - STACK_WIND_COOKIE (frame, resolve_deep_cbk, (void *) (long) i, - BOUND_XL (frame), BOUND_XL (frame)->fops->lookup, - &resolve->deep_loc, NULL); - return 0; + if (state->xdata) { + dict = dict_copy_with_ref (state->xdata, NULL); + if (!dict) + gf_msg (this->name, GF_LOG_ERROR, ENOMEM, PS_MSG_NO_MEMORY, + "BUG: dict allocation failed (pargfid: %s, name: %s), " + "still continuing", uuid_utoa (resolve_loc->gfid), + resolve_loc->name); + } -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, dict); + if (dict) + dict_unref (dict); + 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; - xlator_t *this = 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; + dict_t *xdata = NULL; state = CALL_STATE (frame); this = frame->this; resolve = state->resolve_now; + resolve_loc = &resolve->resolve_loc; + + if (!gf_uuid_is_null (resolve->pargfid)) + gf_uuid_copy (resolve_loc->gfid, resolve->pargfid); + else if (!gf_uuid_is_null (resolve->gfid)) + gf_uuid_copy (resolve_loc->gfid, resolve->gfid); + + resolve_loc->inode = server_inode_new (state->itable, + resolve_loc->gfid); + ret = loc_path (resolve_loc, NULL); + + if (state->xdata) { + xdata = dict_copy_with_ref (state->xdata, NULL); + if (!xdata) + gf_msg (this->name, GF_LOG_ERROR, ENOMEM, PS_MSG_NO_MEMORY, + "BUG: dict allocation failed (gfid: %s), " + "still continuing", + uuid_utoa (resolve_loc->gfid)); + } - gf_log (BOUND_XL (frame)->name, GF_LOG_TRACE, - "RESOLVE %s() seeking deep resolution of %s", - gf_fop_list[frame->root->op], resolve->path); - - prepare_components (frame); + STACK_WIND (frame, resolve_gfid_cbk, + frame->root->client->bound_xl, + frame->root->client->bound_xl->fops->lookup, + &resolve->resolve_loc, xdata); - /* start from the root */ - resolve->deep_loc.inode = state->itable->root; - resolve->deep_loc.path = gf_strdup ("/"); - resolve->deep_loc.name = ""; + if (xdata) + dict_unref (xdata); - STACK_WIND_COOKIE (frame, resolve_deep_cbk, (void *) (long) i, - BOUND_XL (frame), BOUND_XL (frame)->fops->lookup, - &resolve->deep_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 = 0; - int ino_idx = 0; - int i = 0; + int ret = 0; state = CALL_STATE (frame); this = frame->this; resolve = state->resolve_now; - components = resolve->components; - - if (!components) { - 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 (!components[par_idx].inode) { - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - goto out; - } - if (!components[ino_idx].inode && - (resolve->type == RESOLVE_MUST || resolve->type == RESOLVE_EXACT)) { - 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) { - 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); - state->loc_now->parent = inode_ref (components[par_idx].inode); - - ret = 0; + } else if (!gf_uuid_is_null (resolve->pargfid)) + ret = resolve_entry_simple (frame); + else if (!gf_uuid_is_null (resolve->gfid)) + ret = resolve_inode_simple (frame); + if (ret) + gf_msg_debug (this->name, 0, "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: @@ -330,36 +284,20 @@ resolve_entry_simple (call_frame_t *frame) this = frame->this; resolve = state->resolve_now; - parent = inode_get (state->itable, resolve->par, 0); + parent = inode_find (state->itable, resolve->pargfid); if (!parent) { /* simple resolution is indecisive. need to perform deep resolution */ resolve->op_ret = -1; - resolve->op_errno = ENOENT; + resolve->op_errno = ESTALE; 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; - } - - if (parent->ino != 1 && parent->generation != resolve->gen) { - /* simple resolution is decisive - request was for a - stale handle */ - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - ret = -1; goto out; } /* expected @parent was found from the inode cache */ + gf_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) { @@ -382,9 +320,9 @@ resolve_entry_simple (call_frame_t *frame) } if (resolve->type == RESOLVE_NOT) { - gf_log (this->name, GF_LOG_DEBUG, "inode (pointer: %p ino:%" - PRIu64") found for path (%s) while type is RESOLVE_NOT", - inode, inode->ino, resolve->path); + gf_msg_debug (this->name, 0, "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; @@ -410,21 +348,17 @@ int server_resolve_entry (call_frame_t *frame) { server_state_t *state = NULL; - xlator_t *this = NULL; - server_resolve_t *resolve = NULL; int ret = 0; loc_t *loc = NULL; state = CALL_STATE (frame); - this = frame->this; - resolve = state->resolve_now; loc = state->loc_now; ret = resolve_entry_simple (frame); if (ret > 0) { loc_wipe (loc); - resolve_path_deep (frame); + resolve_gfid (frame); return 0; } @@ -441,38 +375,26 @@ int resolve_inode_simple (call_frame_t *frame) { server_state_t *state = NULL; - xlator_t *this = NULL; server_resolve_t *resolve = NULL; inode_t *inode = NULL; int ret = 0; state = CALL_STATE (frame); - this = frame->this; resolve = state->resolve_now; - if (resolve->type == RESOLVE_EXACT) { - inode = inode_get (state->itable, resolve->ino, resolve->gen); - } else { - inode = inode_get (state->itable, resolve->ino, 0); - } + inode = inode_find (state->itable, resolve->gfid); if (!inode) { resolve->op_ret = -1; - resolve->op_errno = ENOENT; + resolve->op_errno = ESTALE; ret = 1; goto out; } - if (inode->ino != 1 && inode->generation != resolve->gen) { - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - ret = -1; - goto out; - } - ret = 0; state->loc_now->inode = inode_ref (inode); + gf_uuid_copy (state->loc_now->gfid, resolve->gfid); out: if (inode) @@ -486,21 +408,17 @@ int server_resolve_inode (call_frame_t *frame) { server_state_t *state = NULL; - xlator_t *this = NULL; - server_resolve_t *resolve = NULL; int ret = 0; loc_t *loc = NULL; state = CALL_STATE (frame); - this = frame->this; - resolve = state->resolve_now; loc = state->loc_now; ret = resolve_inode_simple (frame); if (ret > 0) { loc_wipe (loc); - resolve_path_deep (frame); + resolve_gfid (frame); return 0; } @@ -514,24 +432,104 @@ 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; + + if (frame->root->op == GF_FOP_READ || frame->root->op == GF_FOP_WRITE) + state->fd = fd_anonymous_with_flags (inode, state->flags); + else + state->fd = fd_anonymous (inode); +out: + if (inode) + inode_unref (inode); + + if (ret != 0) + gf_msg_debug ("server", 0, "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; - xlator_t *this = 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); - this = frame->this; 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_msg ("", GF_LOG_INFO, ENOMEM, PS_MSG_NO_MEMORY, + "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_msg ("", GF_LOG_INFO, EBADF, PS_MSG_FD_NOT_FOUND, "fd not " + "found in context"); resolve->op_ret = -1; resolve->op_errno = EBADF; } @@ -546,30 +544,29 @@ int server_resolve (call_frame_t *frame) { server_state_t *state = NULL; - xlator_t *this = NULL; server_resolve_t *resolve = NULL; state = CALL_STATE (frame); - this = frame->this; resolve = state->resolve_now; if (resolve->fd_no != -1) { server_resolve_fd (frame); - } else if (resolve->par) { + } else if (!gf_uuid_is_null (resolve->pargfid)) { server_resolve_entry (frame); - } else if (resolve->ino) { + } else if (!gf_uuid_is_null (resolve->gfid)) { server_resolve_inode (frame); - } else if (resolve->path) { - - resolve_path_deep (frame); - - } else { + } else { + if (resolve == &state->resolve) + gf_msg (frame->this->name, GF_LOG_WARNING, 0, + PS_MSG_INVALID_ENTRY, + "no resolution type for %s (%s)", + resolve->path, gf_fop_list[frame->root->op]); resolve->op_ret = -1; resolve->op_errno = EINVAL; @@ -585,14 +582,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; } @@ -630,8 +625,9 @@ server_resolve_all (call_frame_t *frame) server_resolve_done (frame); } else { - gf_log (this->name, GF_LOG_ERROR, - "Invalid pointer for state->resolve_now"); + gf_msg (this->name, GF_LOG_ERROR, EINVAL, + PS_MSG_INVALID_ENTRY, "Invalid pointer for " + "state->resolve_now"); } return 0; @@ -642,13 +638,10 @@ int resolve_and_resume (call_frame_t *frame, server_resume_fn_t fn) { server_state_t *state = NULL; - xlator_t *this = NULL; state = CALL_STATE (frame); state->resume_fn = fn; - this = frame->this; - server_resolve_all (frame); return 0; |
