diff options
| author | Anand Avati <avati@redhat.com> | 2012-01-30 15:03:56 +0530 | 
|---|---|---|
| committer | Anand Avati <avati@gluster.com> | 2012-02-08 03:13:08 -0800 | 
| commit | 8e81cbacc53adc77bc4eabb5a26d6d13012f5f86 (patch) | |
| tree | 4788e3a14fb2d276689c4423cc7542f0d72c3348 /xlators/mount/fuse/src/fuse-resolve.c | |
| parent | aec6d5d89249868dc99d8fb432d8ab120bb38ef1 (diff) | |
fuse: fix resolver to handle graph switches properly
perform resolution on the latest graph by caching it in state->itable
and use fuse_nodeid as just a hint to the possible final resolved inode
(in case it was resolved off the latest graph). GFID is the primary key
for resolving inodes on the latest graph.
Change-Id: I3921c6f59c9ff80e4ff076bec3bd334423fc36cc
BUG: 785675
Reviewed-on: http://review.gluster.com/2703
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Amar Tumballi <amar@gluster.com>
Reviewed-by: Anand Avati <avati@gluster.com>
Diffstat (limited to 'xlators/mount/fuse/src/fuse-resolve.c')
| -rw-r--r-- | xlators/mount/fuse/src/fuse-resolve.c | 431 | 
1 files changed, 183 insertions, 248 deletions
diff --git a/xlators/mount/fuse/src/fuse-resolve.c b/xlators/mount/fuse/src/fuse-resolve.c index 755e2f429f1..1af80b93c57 100644 --- a/xlators/mount/fuse/src/fuse-resolve.c +++ b/xlators/mount/fuse/src/fuse-resolve.c @@ -46,8 +46,11 @@ fuse_resolve_loc_touchup (fuse_state_t *state)          if (!loc->path) {                  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 (THIS->name, GF_LOG_TRACE, @@ -60,10 +63,10 @@ fuse_resolve_loc_touchup (fuse_state_t *state)  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_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;          fuse_resolve_t *resolve    = NULL; @@ -88,13 +91,7 @@ fuse_resolve_gfid_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          link_inode = inode_link (inode, resolve_loc->parent,                                   resolve_loc->name, buf); -        if (!link_inode) -                goto out; - -        inode_lookup (link_inode); - -        inode_unref (link_inode); - +	state->loc_now->inode = link_inode;  out:          loc_wipe (resolve_loc); @@ -104,6 +101,30 @@ out:  int +fuse_resolve_entry (fuse_state_t *state) +{ +	fuse_resolve_t   *resolve = NULL; +	loc_t            *resolve_loc = NULL; + +	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); + +        inode_path (resolve_loc->parent, resolve_loc->name, +                    (char **) &resolve_loc->path); + +        FUSE_FOP (state, fuse_resolve_entry_cbk, GF_FOP_LOOKUP, +                  lookup, resolve_loc, NULL); + +	return 0; +} + + +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) @@ -111,11 +132,11 @@ fuse_resolve_gfid_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          fuse_state_t   *state      = NULL;          fuse_resolve_t *resolve    = NULL;          inode_t        *link_inode = NULL; -        loc_t          *resolve_loc   = NULL; +        loc_t          *loc_now   = NULL;          state = frame->root->state;          resolve = state->resolve_now; -        resolve_loc = &resolve->resolve_loc; +	loc_now = state->loc_now;          STACK_DESTROY (frame->root); @@ -123,36 +144,27 @@ fuse_resolve_gfid_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  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)); +                        uuid_utoa (resolve->resolve_loc.gfid), +			strerror (op_errno));                  loc_wipe (&resolve->resolve_loc);                  goto out;          } -        loc_wipe (resolve_loc); +        loc_wipe (&resolve->resolve_loc);          link_inode = inode_link (inode, NULL, NULL, buf);          if (!link_inode)                  goto out; -        inode_lookup (link_inode); - -        if (uuid_is_null (resolve->pargfid)) { -                inode_unref (link_inode); -                goto out; -        } - -        resolve_loc->parent = link_inode; -        uuid_copy (resolve_loc->pargfid, resolve_loc->parent->gfid); +	if (!uuid_is_null (resolve->gfid)) { +		loc_now->inode = link_inode; +		goto out; +	} -        resolve_loc->name = resolve->bname; - -        resolve_loc->inode = inode_new (state->itable); -        inode_path (resolve_loc->parent, resolve_loc->name, -                    (char **) &resolve_loc->path); +	loc_now->parent = link_inode; -        FUSE_FOP (state, fuse_resolve_gfid_entry_cbk, GF_FOP_LOOKUP, -                  lookup, &resolve->resolve_loc, NULL); +	fuse_resolve_entry (state);          return 0;  out: @@ -173,15 +185,14 @@ fuse_resolve_gfid (fuse_state_t *state)          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);          } + +	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", @@ -189,122 +200,83 @@ fuse_resolve_gfid (fuse_state_t *state)          }          FUSE_FOP (state, fuse_resolve_gfid_cbk, GF_FOP_LOOKUP, -                  lookup, &resolve->resolve_loc, NULL); - -        return 0; -} - - -int -fuse_resolve_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; - -        /* 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); - -        fuse_resolve_loc_touchup (state); - -        fuse_resolve_all (state); +                  lookup, resolve_loc, NULL);          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 -*/ + * 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_entry_simple (fuse_state_t *state) +fuse_resolve_parent_simple (fuse_state_t *state)  {          fuse_resolve_t *resolve   = NULL; -        inode_t      *parent    = NULL; -        inode_t      *inode     = NULL; -        int           ret       = 0; +	loc_t          *loc       = NULL; +        inode_t        *parent    = NULL; +        inode_t        *inode     = NULL;          resolve = state->resolve_now; +	loc = state->loc_now; -        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; -                ret = 1; -                goto out; -        } - -        /* expected @parent was found from the inode cache */ -        if (state->loc_now->parent) { -                inode_unref (state->loc_now->parent); -        } - -        state->loc_now->parent = inode_ref (parent); +	loc->name = resolve->bname; -        inode = inode_grep (state->itable, parent, resolve->bname); -        if (!inode) { -                resolve->op_ret   = -1; -                resolve->op_errno = ENOENT; -                ret = 1; -                goto out; -        } - -        ret = 0; - -        if (state->loc_now->inode) { -                inode_unref (state->loc_now->inode); -                state->loc_now->inode = NULL; -        } +	parent = resolve->parhint; +	if (parent->table == state->itable) { +		/* no graph switches since */ +		loc->parent = inode_ref (parent); +		loc->inode = inode_grep (state->itable, parent, loc->name); +		/* decisive result - resolution success */ +		return 0; +	} -        state->loc_now->inode  = inode_ref (inode); -        uuid_copy (state->loc_now->gfid, resolve->gfid); - -out: -        if (parent) -                inode_unref (parent); - -        if (inode) -                inode_unref (inode); - -        return ret; +        parent = inode_find (state->itable, resolve->pargfid); +	if (!parent) { +		resolve->op_ret   = -1; +		resolve->op_errno = ENOENT; +		/* non decisive result - parent missing */ +		return 1; +	} + +	loc->parent = parent; + +	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;  }  int -fuse_resolve_entry (fuse_state_t *state) +fuse_resolve_parent (fuse_state_t *state)  {          int    ret = 0;          loc_t *loc = NULL;          loc  = state->loc_now; -        ret = fuse_resolve_entry_simple (state); +        ret = fuse_resolve_parent_simple (state);          if (ret > 0) { -                loc_wipe (loc);                  fuse_resolve_gfid (state);                  return 0;          } -        if (ret == 0) -                fuse_resolve_loc_touchup (state); +	if (ret < 0) { +		fuse_resolve_entry (state); +		return 0; +	} -        fuse_resolve_all (state); +        fuse_resolve_continue (state);          return 0;  } @@ -314,33 +286,29 @@ int  fuse_resolve_inode_simple (fuse_state_t *state)  {          fuse_resolve_t *resolve   = NULL; -        inode_t      *inode     = NULL; -        int           ret       = 0; +	loc_t          *loc = NULL; +        inode_t        *inode     = NULL;          resolve = state->resolve_now; +	loc = state->loc_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 (state->loc_now->inode) { -                inode_unref (state->loc_now->inode); -        } - -        state->loc_now->inode = inode_ref (inode); -        uuid_copy (state->loc_now->gfid, resolve->gfid); +	inode = resolve->hint; +	if (inode->table == state->itable) { +		inode_ref (inode); +		goto found; +	} -out: +        inode = inode_find (state->itable, resolve->gfid);          if (inode) -                inode_unref (inode); +		goto found; -        return ret; +	resolve->op_ret   = -1; +	resolve->op_errno = ENOENT; + +        return 1; +found: +	loc->inode = inode; +	return 0;  } @@ -355,15 +323,11 @@ fuse_resolve_inode (fuse_state_t *state)          ret = fuse_resolve_inode_simple (state);          if (ret > 0) { -                loc_wipe (loc);                  fuse_resolve_gfid (state);                  return 0;          } -        if (ret == 0) -                fuse_resolve_loc_touchup (state); - -        fuse_resolve_all (state); +        fuse_resolve_continue (state);          return 0;  } @@ -372,46 +336,87 @@ static int  fuse_resolve_fd (fuse_state_t *state)  {          fuse_resolve_t  *resolve    = NULL; -        fd_t          *fd         = NULL; -        int            ret        = 0; -        uint64_t       tmp_fd_ctx = 0; -        char          *path       = NULL; -        char          *name       = NULL; +	fd_t            *fd         = NULL; +	xlator_t        *active_subvol = NULL;          resolve = state->resolve_now;          fd = resolve->fd; +	active_subvol = fd->inode->table->xl; -        ret = fd_ctx_get (fd, state->this, &tmp_fd_ctx); -        if (!ret) { -                state->fd = (fd_t *)(long)tmp_fd_ctx; -                fd_ref (state->fd); -                fuse_resolve_all (state); +	state->active_subvol = active_subvol; + +        fuse_resolve_continue (state); + +        return 0; +} + + +int +fuse_gfid_set (fuse_state_t *state) +{ +        int   ret = 0; + +        if (uuid_is_null (state->gfid)) +                goto out; + +        if (!state->dict) +                state->dict = dict_new (); + +        if (!state->dict) { +                ret = -1;                  goto out;          } -        ret = inode_path (fd->inode, 0, &path); -        if (ret <= 0) -                gf_log ("", GF_LOG_WARNING, -                        "failed to do inode-path on fd %d %s", ret, path); +        ret = dict_set_static_bin (state->dict, "gfid-req", +                                   state->gfid, sizeof (state->gfid)); +out: +        return ret; +} -        name = strrchr (path, '/'); -        if (name) -                name++; -        resolve->path = path; -        resolve->bname = gf_strdup (name); +int +fuse_resolve_entry_init (fuse_state_t *state, fuse_resolve_t *resolve, +			 ino_t par, char *name) +{ +	inode_t       *parent = NULL; -        state->loc_now     = &state->loc; +	parent = fuse_ino_to_inode (par, state->this); +	uuid_copy (resolve->pargfid, parent->gfid); +	resolve->parhint = parent; +	resolve->bname = gf_strdup (name); -out: -        return 0; +	return 0; +} + + +int +fuse_resolve_inode_init (fuse_state_t *state, fuse_resolve_t *resolve, +			 ino_t ino) +{ +	inode_t       *inode = NULL; + +	inode = fuse_ino_to_inode (ino, state->this); +	uuid_copy (resolve->gfid, inode->gfid); +	resolve->hint = inode; + +	return 0; +} + + +int +fuse_resolve_fd_init (fuse_state_t *state, fuse_resolve_t *resolve, +		      fd_t *fd) +{ +	resolve->fd = fd_ref (fd); + +	return 0;  }  static int  fuse_resolve (fuse_state_t *state) - { +{          fuse_resolve_t   *resolve = NULL;          resolve = state->resolve_now; @@ -422,7 +427,7 @@ fuse_resolve (fuse_state_t *state)          } else if (!uuid_is_null (resolve->pargfid)) { -                fuse_resolve_entry (state); +                fuse_resolve_parent (state);          } else if (!uuid_is_null (resolve->gfid)) { @@ -445,17 +450,10 @@ fuse_resolve_done (fuse_state_t *state)  {          fuse_resume_fn_t fn = NULL; -        if (state->resolve.op_ret || state->resolve2.op_ret) { -                send_fuse_err (state->this, state->finh, -                               state->resolve.op_errno); -                free_fuse_state (state); -                goto out; -        }          fn = state->resume_fn; -        if (fn) -                fn (state); -out: +	fn (state); +          return 0;  } @@ -495,87 +493,24 @@ fuse_resolve_all (fuse_state_t *state)  int -fuse_gfid_set (fuse_state_t *state) +fuse_resolve_continue (fuse_state_t *state)  { -        int   ret = 0; - -        if (uuid_is_null (state->gfid)) -                goto out; - -        if (!state->dict) -                state->dict = dict_new (); +        fuse_resolve_loc_touchup (state); -        if (!state->dict) { -                ret = -1; -                goto out; -        } +        fuse_resolve_all (state); -        ret = dict_set_static_bin (state->dict, "gfid-req", -                                   state->gfid, sizeof (state->gfid)); -out: -        return ret; +        return 0;  }  int  fuse_resolve_and_resume (fuse_state_t *state, fuse_resume_fn_t fn)  { -        xlator_t *inode_xl = NULL; -        xlator_t *active_xl = NULL; -          fuse_gfid_set (state);          state->resume_fn = fn; -        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) { -                /* Lets move to resume if there is no other inode to check */ -                if (!(state->loc2.parent || state->loc2.inode)) -                        goto resume; - -                inode_xl = NULL; -                /* We have to make sure both inodes we are -                   working on are in same inode table */ -                if (state->loc2.inode) -                        inode_xl = state->loc2.inode->table->xl; -                if (!inode_xl && state->loc2.parent) -                        inode_xl = state->loc2.parent->table->xl; - -                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 */ - -        /* TODO: fix it later */ -        /* if (state->fd && ((state->fd->flags & O_RDWR) || -                          (state->fd->flags & O_WRONLY))) -        */ -        if (state->fd) -                goto resume; - -        /* -        if (state->fd) { -                state->resolve.fd = state->fd; -                state->fd = NULL; // TODO: we may need a 'fd_unref()' here, not very sure' -        } -        */ - -        /* now we have to resolve the inode to 'itable' */ -        state->itable = active_xl->itable; -          fuse_resolve_all (state);          return 0; -resume: -        fn (state); - -        return 0;  }  | 
