diff options
Diffstat (limited to 'xlators/mount/fuse/src/fuse-resolve.c')
| -rw-r--r-- | xlators/mount/fuse/src/fuse-resolve.c | 989 |
1 files changed, 484 insertions, 505 deletions
diff --git a/xlators/mount/fuse/src/fuse-resolve.c b/xlators/mount/fuse/src/fuse-resolve.c index 77a55cd70..8565ce0e4 100644 --- a/xlators/mount/fuse/src/fuse-resolve.c +++ b/xlators/mount/fuse/src/fuse-resolve.c @@ -1,22 +1,12 @@ /* - 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 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/>. -*/ + Copyright (c) 2010-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ #ifndef _CONFIG_H #define _CONFIG_H #include "config.h" @@ -25,616 +15,638 @@ #include "fuse-bridge.h" static int -gf_resolve_all (fuse_state_t *state); -static int -resolve_entry_simple (fuse_state_t *state); -static int -resolve_inode_simple (fuse_state_t *state); -static int -resolve_path_simple (fuse_state_t *state); +fuse_resolve_all (fuse_state_t *state); -static int -component_count (const char *path) -{ - int count = 0; - const char *trav = NULL; +int fuse_resolve_continue (fuse_state_t *state); +int fuse_resolve_entry_simple (fuse_state_t *state); +int fuse_resolve_inode_simple (fuse_state_t *state); +int fuse_migrate_fd (xlator_t *this, fd_t *fd, xlator_t *old_subvol, + xlator_t *new_subvol); - for (trav = path; *trav; trav++) { - if (*trav == '/') - count++; - } - - return count + 2; -} - - -static int -prepare_components (fuse_state_t *state) -{ - xlator_t *active_xl = NULL; - gf_resolve_t *resolve = NULL; - char *resolved = NULL; - struct gf_resolve_comp *components = NULL; - char *trav = NULL; - int count = 0; - int i = 0; - - resolve = state->resolve_now; - - resolved = gf_strdup (resolve->path); - resolve->resolved = resolved; - - count = component_count (resolve->path); - components = GF_CALLOC (sizeof (*components), count, 0); //TODO - if (!components) - goto out; - resolve->components = components; - - active_xl = fuse_active_subvol (state->this); - - components[0].basename = ""; - components[0].ino = 1; - components[0].gen = 0; - components[0].inode = inode_ref (active_xl->itable->root); - - i = 1; - for (trav = resolved; *trav; trav++) { - if (*trav == '/') { - components[i].basename = trav + 1; - *trav = 0; - i++; - } - } -out: - return 0; -} +fuse_fd_ctx_t * +fuse_fd_ctx_get (xlator_t *this, fd_t *fd); +gf_boolean_t fuse_inode_needs_lookup (inode_t *inode, xlator_t *this); static int -resolve_loc_touchup (fuse_state_t *state) +fuse_resolve_loc_touchup (fuse_state_t *state) { - gf_resolve_t *resolve = NULL; - loc_t *loc = NULL; - char *path = NULL; - int ret = 0; + fuse_resolve_t *resolve = NULL; + loc_t *loc = NULL; + char *path = NULL; + int ret = 0; resolve = state->resolve_now; loc = state->loc_now; if (!loc->path) { - if (loc->parent) { + if (loc->parent && resolve->bname) { ret = inode_path (loc->parent, resolve->bname, &path); + uuid_copy (loc->pargfid, loc->parent->gfid); + loc->name = resolve->bname; } else if (loc->inode) { ret = inode_path (loc->inode, NULL, &path); + uuid_copy (loc->gfid, loc->inode->gfid); } if (ret) - gf_log ("", GF_LOG_TRACE, + gf_log (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; } -static int -fuse_resolve_newfd_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, fd_t *fd) + +int +fuse_resolve_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 *xattr, + struct iatt *postparent) { - fuse_state_t *state = NULL; - gf_resolve_t *resolve = NULL; - fd_t *old_fd = NULL; - fd_t *tmp_fd = NULL; - uint64_t tmp_fd_ctx = 0; - int ret = 0; + fuse_state_t *state = NULL; + fuse_resolve_t *resolve = NULL; + inode_t *link_inode = NULL; + loc_t *resolve_loc = NULL; state = frame->root->state; resolve = state->resolve_now; + resolve_loc = &resolve->resolve_loc; STACK_DESTROY (frame->root); 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)); + resolve->op_ret = -1; + resolve->op_errno = op_errno; goto out; } - old_fd = resolve->fd; - - state->fd = fd_ref (fd); + link_inode = inode_link (inode, resolve_loc->parent, + resolve_loc->name, buf); - fd_bind (fd); + state->loc_now->inode = link_inode; - resolve->fd = NULL; - ret = fd_ctx_del (old_fd, state->this, &tmp_fd_ctx); - if (!ret) { - tmp_fd = (fd_t *)(long)tmp_fd_ctx; - fd_unref (tmp_fd); - } - ret = fd_ctx_set (old_fd, state->this, (uint64_t)(long)fd); - if (ret) - gf_log ("resolve", GF_LOG_WARNING, - "failed to set the fd ctx with resolved fd"); out: - gf_resolve_all (state); + loc_wipe (resolve_loc); + + fuse_resolve_continue (state); return 0; } -static void -gf_resolve_new_fd (fuse_state_t *state) + +int +fuse_resolve_entry (fuse_state_t *state) { - gf_resolve_t *resolve = NULL; - fd_t *new_fd = NULL; - fd_t *fd = NULL; + fuse_resolve_t *resolve = NULL; + loc_t *resolve_loc = NULL; - resolve = state->resolve_now; - fd = resolve->fd; + resolve = state->resolve_now; + resolve_loc = &resolve->resolve_loc; + + resolve_loc->parent = inode_ref (state->loc_now->parent); + uuid_copy (resolve_loc->pargfid, state->loc_now->pargfid); + resolve_loc->name = resolve->bname; + resolve_loc->inode = inode_new (state->itable); - new_fd = fd_create (state->loc.inode, state->finh->pid); - new_fd->flags = (fd->flags & ~O_TRUNC); + inode_path (resolve_loc->parent, resolve_loc->name, + (char **) &resolve_loc->path); - gf_log ("resolve", GF_LOG_DEBUG, - "%"PRIu64": OPEN %s", state->finh->unique, - state->loc.path); + FUSE_FOP (state, fuse_resolve_entry_cbk, GF_FOP_LOOKUP, + lookup, resolve_loc, NULL); - FUSE_FOP (state, fuse_resolve_newfd_cbk, GF_FOP_OPEN, - open, &state->loc, new_fd->flags, new_fd, 0); + return 0; } -static int -resolve_deep_continue (fuse_state_t *state) + +int +fuse_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) { - gf_resolve_t *resolve = NULL; - int ret = 0; + fuse_state_t *state = NULL; + fuse_resolve_t *resolve = NULL; + inode_t *link_inode = NULL; + loc_t *loc_now = NULL; + state = frame->root->state; resolve = state->resolve_now; + loc_now = state->loc_now; + + STACK_DESTROY (frame->root); + + if (op_ret == -1) { + gf_log (this->name, (op_errno == ENOENT) + ? GF_LOG_DEBUG : GF_LOG_WARNING, + "%s: failed to resolve (%s)", + uuid_utoa (resolve->resolve_loc.gfid), + strerror (op_errno)); + loc_wipe (&resolve->resolve_loc); + + /* resolve->op_ret can have 3 values: 0, -1, -2. + * 0 : resolution was successful. + * -1: parent inode could not be resolved. + * -2: entry (inode corresponding to path) could not be resolved + */ + + if (uuid_is_null (resolve->gfid)) { + resolve->op_ret = -1; + } else { + resolve->op_ret = -2; + } - resolve->op_ret = 0; - resolve->op_errno = 0; + resolve->op_errno = op_errno; + goto out; + } - if (resolve->par) - ret = resolve_entry_simple (state); - else if (resolve->ino) - ret = resolve_inode_simple (state); - else if (resolve->path) - ret = resolve_path_simple (state); - if (ret) - gf_log ("resolve", GF_LOG_TRACE, - "return value of resolve_*_simple %d", ret); + loc_wipe (&resolve->resolve_loc); + + link_inode = inode_link (inode, NULL, NULL, buf); + + if (!link_inode) + goto out; - resolve_loc_touchup (state); + if (!uuid_is_null (resolve->gfid)) { + loc_now->inode = link_inode; + goto out; + } - /* This function is called by either fd resolve or inode resolve */ - if (!resolve->fd) - gf_resolve_all (state); - else - gf_resolve_new_fd (state); + loc_now->parent = link_inode; + uuid_copy (loc_now->pargfid, link_inode->gfid); + fuse_resolve_entry (state); + + return 0; +out: + fuse_resolve_continue (state); return 0; } -static int -resolve_deep_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) +int +fuse_resolve_gfid (fuse_state_t *state) { - xlator_t *active_xl = NULL; - fuse_state_t *state = NULL; - gf_resolve_t *resolve = NULL; - struct gf_resolve_comp *components = NULL; - inode_t *link_inode = NULL; - int i = 0; + fuse_resolve_t *resolve = NULL; + loc_t *resolve_loc = NULL; + int ret = 0; - state = frame->root->state; resolve = state->resolve_now; - components = resolve->components; + resolve_loc = &resolve->resolve_loc; - i = (long) cookie; - - STACK_DESTROY (frame->root); - - if (op_ret == -1) { - goto get_out_of_here; + 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 (i != 0) { - inode_ref (inode); - /* no linking for root inode */ - link_inode = inode_link (inode, resolve->deep_loc.parent, - resolve->deep_loc.name, buf); - components[i].inode = inode_ref (link_inode); - link_inode = NULL; - } - inode_ref (resolve->deep_loc.parent); - inode_ref (inode); - loc_wipe (&resolve->deep_loc); - i++; /* next component */ - - if (!components[i].basename) { - /* all components of the path are resolved */ - goto get_out_of_here; + /* inode may already exist in case we are looking up an inode which was + linked through readdirplus */ + resolve_loc->inode = inode_find (state->itable, resolve_loc->gfid); + if (!resolve_loc->inode) + resolve_loc->inode = inode_new (state->itable); + ret = loc_path (resolve_loc, NULL); + + if (ret <= 0) { + gf_log (THIS->name, GF_LOG_WARNING, + "failed to get the path for inode %s", + uuid_utoa (resolve->gfid)); } - /* join the current component with the path resolved until now */ - *(components[i].basename - 1) = '/'; - - active_xl = fuse_active_subvol (state->this); + FUSE_FOP (state, fuse_resolve_gfid_cbk, GF_FOP_LOOKUP, + lookup, resolve_loc, NULL); - resolve->deep_loc.path = gf_strdup (resolve->resolved); - resolve->deep_loc.parent = inode_ref (components[i-1].inode); - resolve->deep_loc.inode = inode_new (active_xl->itable); - resolve->deep_loc.name = components[i].basename; - - FUSE_FOP_COOKIE (state, active_xl, resolve_deep_cbk, (void *)(long)i, - GF_FOP_LOOKUP, lookup, &resolve->deep_loc, NULL); - return 0; - -get_out_of_here: - resolve_deep_continue (state); return 0; } -static int -resolve_path_deep (fuse_state_t *state) +/* + * Return value: + * 0 - resolved parent and entry (as necessary) + * -1 - resolved parent but not entry (though necessary) + * 1 - resolved neither parent nor entry + */ + +int +fuse_resolve_parent_simple (fuse_state_t *state) { - xlator_t *active_xl = NULL; - gf_resolve_t *resolve = NULL; - struct gf_resolve_comp *components = NULL; - inode_t *inode = NULL; - long i = 0; + fuse_resolve_t *resolve = NULL; + loc_t *loc = NULL; + inode_t *parent = NULL; + inode_t *inode = NULL; resolve = state->resolve_now; + loc = state->loc_now; + + loc->name = resolve->bname; + + parent = resolve->parhint; + if (parent->table == state->itable) { + if (fuse_inode_needs_lookup (parent, THIS)) + return 1; + + /* no graph switches since */ + loc->parent = inode_ref (parent); + uuid_copy (loc->pargfid, parent->gfid); + loc->inode = inode_grep (state->itable, parent, loc->name); + + /* nodeid for root is 1 and we blindly take the latest graph's + * table->root as the parhint and because of this there is + * ambiguity whether the entry should have existed or not, and + * we took the conservative approach of assuming entry should + * have been there even though it need not have (bug #804592). + */ + if ((loc->inode == NULL) + && __is_root_gfid (parent->gfid)) { + /* non decisive result - entry missing */ + return -1; + } - prepare_components (state); + /* decisive result - resolution success */ + return 0; + } + + parent = inode_find (state->itable, resolve->pargfid); + if (!parent) { + /* non decisive result - parent missing */ + return 1; + } + if (fuse_inode_needs_lookup (parent, THIS)) { + inode_unref (parent); + return 1; + } + + loc->parent = parent; + uuid_copy (loc->pargfid, resolve->pargfid); + + inode = inode_grep (state->itable, parent, loc->name); + if (inode) { + loc->inode = inode; + /* decisive result - resolution success */ + return 0; + } + + /* non decisive result - entry missing */ + return -1; +} - components = resolve->components; - /* start from the root */ - active_xl = fuse_active_subvol (state->this); - resolve->deep_loc.inode = inode_ref (active_xl->itable->root); - resolve->deep_loc.path = gf_strdup ("/"); - resolve->deep_loc.name = ""; +int +fuse_resolve_parent (fuse_state_t *state) +{ + int ret = 0; - for (i = 1; components[i].basename; i++) { - *(components[i].basename - 1) = '/'; - inode = inode_grep (active_xl->itable, components[i-1].inode, - components[i].basename); - if (!inode) - break; - components[i].inode = inode_ref (inode); + ret = fuse_resolve_parent_simple (state); + if (ret > 0) { + fuse_resolve_gfid (state); + return 0; } - if (!components[i].basename) - goto resolved; - - resolve->deep_loc.path = gf_strdup (resolve->resolved); - resolve->deep_loc.parent = inode_ref (components[i-1].inode); - resolve->deep_loc.inode = inode_new (active_xl->itable); - resolve->deep_loc.name = components[i].basename; + if (ret < 0) { + fuse_resolve_entry (state); + return 0; + } - FUSE_FOP_COOKIE (state, active_xl, resolve_deep_cbk, (void *)(long)i, - GF_FOP_LOOKUP, lookup, &resolve->deep_loc, NULL); + fuse_resolve_continue (state); return 0; -resolved: - resolve_deep_continue (state); - return 0; } -static int -resolve_path_simple (fuse_state_t *state) +int +fuse_resolve_inode_simple (fuse_state_t *state) { - gf_resolve_t *resolve = NULL; - struct gf_resolve_comp *components = NULL; - int ret = -1; - int par_idx = 0; - int ino_idx = 0; - int i = 0; + fuse_resolve_t *resolve = NULL; + loc_t *loc = NULL; + inode_t *inode = NULL; resolve = state->resolve_now; - components = resolve->components; - - if (!components) { - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - goto out; - } + loc = state->loc_now; + + inode = resolve->hint; + if (inode->table == state->itable) + inode_ref (inode); + else + inode = inode_find (state->itable, resolve->gfid); + + if (inode) { + if (!fuse_inode_needs_lookup (inode, THIS)) + goto found; + /* inode was linked through readdirplus */ + inode_unref (inode); + } + + return 1; +found: + loc->inode = inode; + return 0; +} - 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; - } +int +fuse_resolve_inode (fuse_state_t *state) +{ + int ret = 0; - if (!components[ino_idx].inode && - (resolve->type == RESOLVE_MUST || resolve->type == RESOLVE_EXACT)) { - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - goto out; - } + ret = fuse_resolve_inode_simple (state); - if (components[ino_idx].inode && resolve->type == RESOLVE_NOT) { - resolve->op_ret = -1; - resolve->op_errno = EEXIST; - goto out; + if (ret > 0) { + fuse_resolve_gfid (state); + return 0; } - 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; + fuse_resolve_continue (state); -out: - return ret; + return 0; } -/* - Check if the requirements are fulfilled by entries in the inode cache itself - Return value: - <= 0 - simple resolution was decisive and complete (either success or failure) - > 0 - indecisive, need to perform deep resolution -*/ -static int -resolve_entry_simple (fuse_state_t *state) +int +fuse_migrate_fd_task (void *data) { - xlator_t *this = NULL; - xlator_t *active_xl = NULL; - gf_resolve_t *resolve = NULL; - inode_t *parent = NULL; - inode_t *inode = NULL; - int ret = 0; - - this = state->this; - resolve = state->resolve_now; - - active_xl = fuse_active_subvol (this); - - parent = inode_get (active_xl->itable, resolve->par, 0); - if (!parent) { - /* simple resolution is indecisive. need to perform - deep resolution */ - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - ret = 1; - - inode = inode_grep (active_xl->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)", 0L, - inode, inode->ino, resolve->path); - inode_unref (inode); - } + int ret = -1; + fuse_state_t *state = NULL; + fd_t *basefd = NULL, *oldfd = NULL; + fuse_fd_ctx_t *basefd_ctx = NULL; + xlator_t *old_subvol = NULL; + + state = data; + if (state == NULL) { goto out; } - /* expected @parent was found from the inode cache */ - state->loc_now->parent = inode_ref (parent); - - inode = inode_grep (active_xl->itable, parent, resolve->bname); - if (!inode) { - switch (resolve->type) { - case RESOLVE_DONTCARE: - case RESOLVE_NOT: - ret = 0; - break; - case RESOLVE_MAY: - ret = 1; - break; - default: - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - ret = 1; - break; - } + basefd = state->fd; - goto out; + basefd_ctx = fuse_fd_ctx_get (state->this, basefd); + + LOCK (&basefd->lock); + { + oldfd = basefd_ctx->activefd ? basefd_ctx->activefd : basefd; + fd_ref (oldfd); } + UNLOCK (&basefd->lock); - 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); - resolve->op_ret = -1; - resolve->op_errno = EEXIST; - ret = -1; - goto out; + old_subvol = oldfd->inode->table->xl; + + ret = fuse_migrate_fd (state->this, basefd, old_subvol, + state->active_subvol); + + LOCK (&basefd->lock); + { + if (ret < 0) { + basefd_ctx->migration_failed = 1; + } else { + basefd_ctx->migration_failed = 0; + } } + UNLOCK (&basefd->lock); ret = 0; - state->loc_now->inode = inode_ref (inode); - out: - if (parent) - inode_unref (parent); - - if (inode) - inode_unref (inode); + if (oldfd) + fd_unref (oldfd); return ret; } -static int -gf_resolve_entry (fuse_state_t *state) +static inline int +fuse_migrate_fd_error (xlator_t *this, fd_t *fd) { - int ret = 0; - loc_t *loc = NULL; - - loc = state->loc_now; + fuse_fd_ctx_t *fdctx = NULL; + char error = 0; - ret = resolve_entry_simple (state); - - if (ret > 0) { - loc_wipe (loc); - resolve_path_deep (state); - return 0; + fdctx = fuse_fd_ctx_get (this, fd); + if (fdctx != NULL) { + if (fdctx->migration_failed) { + error = 1; + } } - if (ret == 0) - resolve_loc_touchup (state); - - gf_resolve_all (state); - - return 0; + return error; } +#define FUSE_FD_GET_ACTIVE_FD(activefd, basefd) \ + do { \ + LOCK (&basefd->lock); \ + { \ + activefd = basefd_ctx->activefd ? \ + basefd_ctx->activefd : basefd; \ + if (activefd != basefd) { \ + fd_ref (activefd); \ + } \ + } \ + UNLOCK (&basefd->lock); \ + \ + if (activefd == basefd) { \ + fd_ref (activefd); \ + } \ + } while (0); + static int -resolve_inode_simple (fuse_state_t *state) +fuse_resolve_fd (fuse_state_t *state) { - xlator_t *active_xl = NULL; - gf_resolve_t *resolve = NULL; - inode_t *inode = NULL; - int ret = 0; + fuse_resolve_t *resolve = NULL; + fd_t *basefd = NULL, *activefd = NULL; + xlator_t *active_subvol = NULL, *this = NULL; + int ret = 0; + char fd_migration_error = 0; + fuse_fd_ctx_t *basefd_ctx = NULL; resolve = state->resolve_now; - active_xl = fuse_active_subvol (state->this); + this = state->this; - if (resolve->type == RESOLVE_EXACT) { - inode = inode_get (active_xl->itable, resolve->ino, - resolve->gen); - } else { - inode = inode_get (active_xl->itable, resolve->ino, 0); + basefd = resolve->fd; + basefd_ctx = fuse_fd_ctx_get (this, basefd); + if (basefd_ctx == NULL) { + gf_log (state->this->name, GF_LOG_WARNING, + "fdctx is NULL for basefd (ptr:%p inode-gfid:%s), " + "resolver erroring out with errno EINVAL", + basefd, uuid_utoa (basefd->inode->gfid)); + resolve->op_ret = -1; + resolve->op_errno = EINVAL; + goto resolve_continue; } - if (!inode) { - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - ret = 1; - goto out; + FUSE_FD_GET_ACTIVE_FD (activefd, basefd); + + active_subvol = activefd->inode->table->xl; + + fd_migration_error = fuse_migrate_fd_error (state->this, basefd); + if (fd_migration_error) { + resolve->op_ret = -1; + resolve->op_errno = EBADF; + } else if (state->active_subvol != active_subvol) { + ret = synctask_new (state->this->ctx->env, fuse_migrate_fd_task, + NULL, NULL, state); + + fd_migration_error = fuse_migrate_fd_error (state->this, + basefd); + fd_unref (activefd); + + FUSE_FD_GET_ACTIVE_FD (activefd, basefd); + active_subvol = activefd->inode->table->xl; + + if ((ret == -1) || fd_migration_error + || (state->active_subvol != active_subvol)) { + if (ret == -1) { + gf_log (state->this->name, GF_LOG_WARNING, + "starting sync-task to migrate " + "basefd (ptr:%p inode-gfid:%s) failed " + "(old-subvolume:%s-%d " + "new-subvolume:%s-%d)", + basefd, + uuid_utoa (basefd->inode->gfid), + active_subvol->name, + active_subvol->graph->id, + state->active_subvol->name, + state->active_subvol->graph->id); + } else { + gf_log (state->this->name, GF_LOG_WARNING, + "fd migration of basefd " + "(ptr:%p inode-gfid:%s) failed " + "(old-subvolume:%s-%d " + "new-subvolume:%s-%d)", + basefd, + uuid_utoa (basefd->inode->gfid), + active_subvol->name, + active_subvol->graph->id, + state->active_subvol->name, + state->active_subvol->graph->id); + } + + resolve->op_ret = -1; + resolve->op_errno = EBADF; + } else { + gf_log (state->this->name, GF_LOG_DEBUG, + "basefd (ptr:%p inode-gfid:%s) migrated " + "successfully in resolver " + "(old-subvolume:%s-%d new-subvolume:%s-%d)", + basefd, uuid_utoa (basefd->inode->gfid), + active_subvol->name, active_subvol->graph->id, + state->active_subvol->name, + state->active_subvol->graph->id); + } } - ret = 0; + if ((resolve->op_ret == -1) && (resolve->op_errno == EBADF)) { + gf_log ("fuse-resolve", GF_LOG_WARNING, + "migration of basefd (ptr:%p inode-gfid:%s) " + "did not complete, failing fop with EBADF " + "(old-subvolume:%s-%d new-subvolume:%s-%d)", basefd, + uuid_utoa (basefd->inode->gfid), + active_subvol->name, active_subvol->graph->id, + state->active_subvol->name, + state->active_subvol->graph->id); + } - state->loc_now->inode = inode_ref (inode); + if (activefd != basefd) { + state->fd = fd_ref (activefd); + fd_unref (basefd); + } -out: - if (inode) - inode_unref (inode); + /* state->active_subvol = active_subvol; */ - return ret; +resolve_continue: + if (activefd != NULL) { + fd_unref (activefd); + } + + fuse_resolve_continue (state); + + return 0; } -static int -gf_resolve_inode (fuse_state_t *state) +int +fuse_gfid_set (fuse_state_t *state) { - int ret = 0; - loc_t *loc = NULL; + int ret = 0; - loc = state->loc_now; + if (uuid_is_null (state->gfid)) + goto out; - ret = resolve_inode_simple (state); + if (!state->xdata) + state->xdata = dict_new (); - if (ret > 0) { - loc_wipe (loc); - resolve_path_deep (state); - return 0; + if (!state->xdata) { + ret = -1; + goto out; } - if (ret == 0) - resolve_loc_touchup (state); - - gf_resolve_all (state); - - return 0; + ret = dict_set_static_bin (state->xdata, "gfid-req", + state->gfid, sizeof (state->gfid)); +out: + return ret; } -static int -gf_resolve_fd (fuse_state_t *state) +int +fuse_resolve_entry_init (fuse_state_t *state, fuse_resolve_t *resolve, + ino_t par, char *name) { - gf_resolve_t *resolve = NULL; - fd_t *fd = NULL; - int ret = 0; - uint64_t tmp_fd_ctx = 0; - char *path = NULL; - char *name = NULL; + inode_t *parent = NULL; - resolve = state->resolve_now; + parent = fuse_ino_to_inode (par, state->this); + uuid_copy (resolve->pargfid, parent->gfid); + resolve->parhint = parent; + resolve->bname = gf_strdup (name); - fd = resolve->fd; + return 0; +} - ret = fd_ctx_get (fd, state->this, &tmp_fd_ctx); - if (!ret) { - state->fd = (fd_t *)(long)tmp_fd_ctx; - fd_ref (state->fd); - gf_resolve_all (state); - goto out; - } - ret = inode_path (fd->inode, 0, &path); - if (!ret || !path) - gf_log ("", GF_LOG_WARNING, - "failed to do inode-path on fd %d %s", ret, path); +int +fuse_resolve_inode_init (fuse_state_t *state, fuse_resolve_t *resolve, + ino_t ino) +{ + inode_t *inode = NULL; - name = strrchr (path, '/'); - if (name) - name++; + inode = fuse_ino_to_inode (ino, state->this); + uuid_copy (resolve->gfid, inode->gfid); + resolve->hint = inode; - resolve->path = path; - resolve->bname = gf_strdup (name); + return 0; +} - state->loc_now = &state->loc; - resolve_path_deep (state); +int +fuse_resolve_fd_init (fuse_state_t *state, fuse_resolve_t *resolve, + fd_t *fd) +{ + resolve->fd = fd_ref (fd); -out: - return 0; + return 0; } static int -gf_resolve (fuse_state_t *state) - { - gf_resolve_t *resolve = NULL; +fuse_resolve (fuse_state_t *state) +{ + fuse_resolve_t *resolve = NULL; resolve = state->resolve_now; if (resolve->fd) { - gf_resolve_fd (state); - - } else if (resolve->par) { - - gf_resolve_entry (state); + fuse_resolve_fd (state); - } else if (resolve->ino) { + } else if (!uuid_is_null (resolve->pargfid)) { - gf_resolve_inode (state); + fuse_resolve_parent (state); - } else if (resolve->path) { + } else if (!uuid_is_null (resolve->gfid)) { - resolve_path_deep (state); + fuse_resolve_inode (state); - } else { - - resolve->op_ret = -1; - resolve->op_errno = EINVAL; - - gf_resolve_all (state); + } else { + fuse_resolve_all (state); } return 0; @@ -642,13 +654,13 @@ gf_resolve (fuse_state_t *state) static int -gf_resolve_done (fuse_state_t *state) +fuse_resolve_done (fuse_state_t *state) { fuse_resume_fn_t fn = NULL; fn = state->resume_fn; - if (fn) - fn (state); + + fn (state); return 0; } @@ -659,25 +671,25 @@ gf_resolve_done (fuse_state_t *state) * state->resolve_now is used to decide which location/fd is to be resolved now */ static int -gf_resolve_all (fuse_state_t *state) +fuse_resolve_all (fuse_state_t *state) { if (state->resolve_now == NULL) { state->resolve_now = &state->resolve; state->loc_now = &state->loc; - gf_resolve (state); + fuse_resolve (state); } else if (state->resolve_now == &state->resolve) { state->resolve_now = &state->resolve2; state->loc_now = &state->loc2; - gf_resolve (state); + fuse_resolve (state); } else if (state->resolve_now == &state->resolve2) { - gf_resolve_done (state); + fuse_resolve_done (state); } else { gf_log ("fuse-resolve", GF_LOG_ERROR, @@ -689,57 +701,24 @@ gf_resolve_all (fuse_state_t *state) int -fuse_resolve_and_resume (fuse_state_t *state, fuse_resume_fn_t fn) +fuse_resolve_continue (fuse_state_t *state) { - xlator_t *inode_xl = NULL; - xlator_t *active_xl = NULL; + fuse_resolve_loc_touchup (state); - state->resume_fn = fn; + fuse_resolve_all (state); - active_xl = fuse_active_subvol (state->this); - inode_xl = fuse_state_subvol (state); - if (!inode_xl && state->loc.parent) - inode_xl = state->loc.parent->table->xl; - - /* If inode or fd is already in new graph, goto resume */ - if (inode_xl == active_xl) - goto resume; - - /* If the resolve is for 'fd' and its open with 'write' flag - set, don't switch to new graph yet */ - if (state->fd && ((state->fd->flags & O_RDWR) || - (state->fd->flags & O_WRONLY))) - goto resume; - - if (state->loc.path) { - state->resolve.path = gf_strdup (state->loc.path); - state->resolve.bname = gf_strdup (state->loc.name); - /* TODO: make sure there is no leaks in inode refs */ - //loc_wipe (&state->loc); - state->loc.inode = NULL; - state->loc.parent = NULL; - } + return 0; +} - /* Needed for rename and link */ - if (state->loc2.path) { - state->resolve2.path = gf_strdup (state->loc2.path); - state->resolve2.bname = gf_strdup (state->loc2.name); - //loc_wipe (&state->loc2); - state->loc2.inode = NULL; - state->loc2.parent = NULL; - } - if (state->fd) { - state->resolve.fd = state->fd; - /* TODO: check if its a leak, if yes, then do 'unref' */ - state->fd = NULL; - } +int +fuse_resolve_and_resume (fuse_state_t *state, fuse_resume_fn_t fn) +{ + fuse_gfid_set (state); - gf_resolve_all (state); + state->resume_fn = fn; - return 0; -resume: - fn (state); + fuse_resolve_all (state); return 0; } |
