diff options
Diffstat (limited to 'xlators/mount/fuse/src/fuse-resolve.c')
| -rw-r--r-- | xlators/mount/fuse/src/fuse-resolve.c | 400 | 
1 files changed, 112 insertions, 288 deletions
diff --git a/xlators/mount/fuse/src/fuse-resolve.c b/xlators/mount/fuse/src/fuse-resolve.c index 33606f87919..755e2f429f1 100644 --- a/xlators/mount/fuse/src/fuse-resolve.c +++ b/xlators/mount/fuse/src/fuse-resolve.c @@ -26,375 +26,203 @@  static int  fuse_resolve_all (fuse_state_t *state); -static int -fuse_resolve_path_simple (fuse_state_t *state); - -static int -component_count (const char *path) -{ -        int         count = 0; -        const char *trav = NULL; - -        for (trav = path; *trav; trav++) { -                if (*trav == '/') -                        count++; -        } - -        return count + 2; -} - -static int -prepare_components (fuse_state_t *state) -{ -        fuse_resolve_t           *resolve    = NULL; -        char                   *resolved   = NULL; -        struct fuse_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; - -        components[0].basename = ""; -        components[0].ino      = 1; -        components[0].gen      = 0; -        components[0].inode    = inode_ref (state->itable->root); - -        i = 1; -        for (trav = resolved; *trav; trav++) { -                if (*trav == '/') { -                        components[i].basename = trav + 1; -                        *trav = 0; -                        i++; -                } -        } -out: -        return 0; -} +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);  static int  fuse_resolve_loc_touchup (fuse_state_t *state)  {          fuse_resolve_t *resolve = NULL; -        loc_t        *loc     = NULL; -        char         *path    = NULL; -        int           ret     = 0; +        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);                  } else if (loc->inode) {                          ret = inode_path (loc->inode, NULL, &path);                  }                  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_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 *xattr, +                             struct iatt *postparent)  {          fuse_state_t   *state      = NULL;          fuse_resolve_t *resolve    = NULL; -        fd_t           *old_fd     = NULL; -        fd_t           *tmp_fd     = NULL; -        fuse_fd_ctx_t  *tmp_fd_ctx = 0; -        uint64_t        val        = 0; -        int             ret        = 0; +        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) { -                resolve->op_ret   = -1; -                resolve->op_errno = op_errno; +                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;          } -        old_fd = resolve->fd; - -        state->fd = fd_ref (fd); - -        fd_bind (fd); +        link_inode = inode_link (inode, resolve_loc->parent, +                                 resolve_loc->name, buf); -        resolve->fd = NULL; +        if (!link_inode) +                goto out; -        LOCK (&old_fd->lock); -        { -                ret = __fd_ctx_get (old_fd, state->this, &val); -                if (!ret) { -                        tmp_fd_ctx = (fuse_fd_ctx_t *)(unsigned long)val; -                        tmp_fd = tmp_fd_ctx->fd; -                        if (tmp_fd) { -                                fd_unref (tmp_fd); -                                tmp_fd_ctx->fd = NULL; -                        } -                } else { -                        tmp_fd_ctx = __fuse_fd_ctx_check_n_create (old_fd, -                                                                   state->this); -                } +        inode_lookup (link_inode); -                if (tmp_fd_ctx) { -                        tmp_fd_ctx->fd = fd; -                } else { -                        gf_log ("resolve", GF_LOG_WARNING, -                                "failed to set the fd ctx with resolved fd"); -                } -        } -        UNLOCK (&old_fd->lock); +        inode_unref (link_inode);  out: -        fuse_resolve_all (state); -        return 0; -} - -static void -fuse_resolve_new_fd (fuse_state_t *state) -{ -        fuse_resolve_t *resolve = NULL; -        fd_t         *new_fd  = NULL; -        fd_t         *fd      = NULL; - -        resolve = state->resolve_now; -        fd = resolve->fd; - -        new_fd = fd_create (state->loc.inode, state->finh->pid); -        new_fd->flags = (fd->flags & ~O_TRUNC); - -        gf_log ("resolve", GF_LOG_DEBUG, -                "%"PRIu64": OPEN %s", state->finh->unique, -                state->loc.path); - -        FUSE_FOP (state, fuse_resolve_newfd_cbk, GF_FOP_OPEN, -                  open, &state->loc, new_fd->flags, new_fd, 0); -} - -static int -fuse_resolve_deep_continue (fuse_state_t *state) -{ -        fuse_resolve_t     *resolve = NULL; -        int               ret = 0; - -        resolve = state->resolve_now; - -        resolve->op_ret   = 0; -        resolve->op_errno = 0; - -        if (resolve->path) -                ret = fuse_resolve_path_simple (state); -        if (ret) -                gf_log ("resolve", GF_LOG_TRACE, -                        "return value of resolve_*_simple %d", ret); - -        fuse_resolve_loc_touchup (state); - -        /* This function is called by either fd resolve or inode resolve */ -        if (!resolve->fd) -                fuse_resolve_all (state); -        else -                fuse_resolve_new_fd (state); +        loc_wipe (resolve_loc); +        fuse_resolve_continue (state);          return 0;  } -static int -fuse_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_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; -        fuse_resolve_t           *resolve    = NULL; -        struct fuse_resolve_comp *components = NULL; -        inode_t                *link_inode = NULL; -        int                     i          = 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; -        components = resolve->components; - -        i = (long) cookie; +        resolve_loc = &resolve->resolve_loc;          STACK_DESTROY (frame->root);          if (op_ret == -1) { -                goto get_out_of_here; +                gf_log (this->name, ((op_errno == ENOENT) ? GF_LOG_DEBUG : +                                     GF_LOG_WARNING), +                        "%s: failed to resolve (%s)", +                        uuid_utoa (resolve_loc->gfid), strerror (op_errno)); +                loc_wipe (&resolve->resolve_loc); +                goto out;          } -        if (i != 0) { -                /* no linking for root inode */ -                link_inode = inode_link (inode, resolve->deep_loc.parent, -                                         resolve->deep_loc.name, buf); -                components[i].inode  = link_inode; -                link_inode = NULL; -        } +        loc_wipe (resolve_loc); -        loc_wipe (&resolve->deep_loc); -        i++; /* next component */ +        link_inode = inode_link (inode, NULL, NULL, buf); -        if (!components[i].basename) { -                /* all components of the path are resolved */ -                goto get_out_of_here; +        if (!link_inode) +                goto out; + +        inode_lookup (link_inode); + +        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; -        FUSE_FOP_COOKIE (state, state->itable->xl, fuse_resolve_deep_cbk, -                         (void *)(long)i, -                         GF_FOP_LOOKUP, 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); + +        FUSE_FOP (state, fuse_resolve_gfid_entry_cbk, GF_FOP_LOOKUP, +                  lookup, &resolve->resolve_loc, NULL); -get_out_of_here: -        fuse_resolve_deep_continue (state); +        return 0; +out: +        fuse_resolve_continue (state);          return 0;  } -static int -fuse_resolve_path_deep (fuse_state_t *state) +int +fuse_resolve_gfid (fuse_state_t *state)  { -        fuse_resolve_t           *resolve    = NULL; -        struct fuse_resolve_comp *components = NULL; -        inode_t                *inode      = NULL; -        long                    i          = 0; +        fuse_resolve_t *resolve  = NULL; +        loc_t          *resolve_loc = NULL; +        int             ret      = 0;          resolve = state->resolve_now; +        resolve_loc = &resolve->resolve_loc; -        prepare_components (state); - -        components = resolve->components; - -        /* start from the root */ -        for (i = 1; components[i].basename; i++) { -                *(components[i].basename - 1) = '/'; -                inode = inode_grep (state->itable, components[i-1].inode, -                                    components[i].basename); -                if (!inode) -                        break; -                components[i].inode = inode; +        if (!uuid_is_null (resolve->pargfid)) { +                uuid_copy (resolve_loc->gfid, resolve->pargfid); +                resolve_loc->inode = inode_new (state->itable); +                ret = inode_path (resolve_loc->inode, NULL, +                                  (char **)&resolve_loc->path); +        } else if (!uuid_is_null (resolve->gfid)) { +                uuid_copy (resolve_loc->gfid, resolve->gfid); +                resolve_loc->inode = inode_new (state->itable); +                ret = inode_path (resolve_loc->inode, NULL, +                                  (char **)&resolve_loc->path); +        } +        if (ret <= 0) { +                gf_log (THIS->name, GF_LOG_WARNING, +                        "failed to get the path from inode %s", +                        uuid_utoa (resolve->gfid));          } -        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 (state->itable); -        resolve->deep_loc.name   = components[i].basename; - -        FUSE_FOP_COOKIE (state, state->itable->xl, fuse_resolve_deep_cbk, -                         (void *)(long)i, -                         GF_FOP_LOOKUP, lookup, &resolve->deep_loc, NULL); +        FUSE_FOP (state, fuse_resolve_gfid_cbk, GF_FOP_LOOKUP, +                  lookup, &resolve->resolve_loc, NULL);          return 0; -resolved: -        fuse_resolve_deep_continue (state); -        return 0;  } -static int -fuse_resolve_path_simple (fuse_state_t *state) +int +fuse_resolve_continue (fuse_state_t *state)  { -        fuse_resolve_t           *resolve    = NULL; -        struct fuse_resolve_comp *components = NULL; -        int                     ret        = -1; -        int                     par_idx    = 0; -        int                     ino_idx    = 0; -        int                     i          = 0; +        fuse_resolve_t     *resolve = NULL; +        int                   ret = 0;          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; -        } - -        if (components[ino_idx].inode && resolve->type == RESOLVE_NOT) { -                resolve->op_ret    = -1; -                resolve->op_errno  = EEXIST; -                goto out; -        } -        if (components[ino_idx].inode) { -                if (state->loc_now->inode) { -                        inode_unref (state->loc_now->inode); -                } - -                state->loc_now->inode  = inode_ref (components[ino_idx].inode); -        } +        resolve->op_ret   = 0; +        resolve->op_errno = 0; -        if (state->loc_now->parent) { -                inode_unref (state->loc_now->parent); -        } +        /* TODO: should we handle 'fd' here ? */ +        if (!uuid_is_null (resolve->pargfid)) +                ret = fuse_resolve_entry_simple (state); +        else if (!uuid_is_null (resolve->gfid)) +                ret = fuse_resolve_inode_simple (state); +        if (ret) +                gf_log (THIS->name, GF_LOG_DEBUG, +                        "return value of resolve_*_simple %d", ret); -        state->loc_now->parent = inode_ref (components[par_idx].inode); +        fuse_resolve_loc_touchup (state); -        ret = 0; +        fuse_resolve_all (state); -out: -        return ret; +        return 0;  } +  /*    Check if the requirements are fulfilled by entries in the inode cache itself    Return value: @@ -445,6 +273,7 @@ fuse_resolve_entry_simple (fuse_state_t *state)          }          state->loc_now->inode  = inode_ref (inode); +        uuid_copy (state->loc_now->gfid, resolve->gfid);  out:          if (parent) @@ -468,7 +297,7 @@ fuse_resolve_entry (fuse_state_t *state)          ret = fuse_resolve_entry_simple (state);          if (ret > 0) {                  loc_wipe (loc); -                fuse_resolve_path_deep (state); +                fuse_resolve_gfid (state);                  return 0;          } @@ -505,6 +334,7 @@ fuse_resolve_inode_simple (fuse_state_t *state)          }          state->loc_now->inode = inode_ref (inode); +        uuid_copy (state->loc_now->gfid, resolve->gfid);  out:          if (inode) @@ -526,7 +356,7 @@ fuse_resolve_inode (fuse_state_t *state)          if (ret > 0) {                  loc_wipe (loc); -                fuse_resolve_path_deep (state); +                fuse_resolve_gfid (state);                  return 0;          } @@ -574,8 +404,6 @@ fuse_resolve_fd (fuse_state_t *state)          state->loc_now     = &state->loc; -        fuse_resolve_path_deep (state); -  out:          return 0;  } @@ -600,10 +428,6 @@ fuse_resolve (fuse_state_t *state)                  fuse_resolve_inode (state); -        } else if (resolve->path) { - -                fuse_resolve_path_deep (state); -          } else {                  resolve->op_ret = 0;  | 
