diff options
| author | Raghavendra G <raghavendra@gluster.com> | 2009-12-04 11:32:53 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2009-12-06 09:28:31 -0800 | 
| commit | 58768ac88263ad73d593a319f50c2089719f76bd (patch) | |
| tree | 94b750a2ee7bc0df3cb94455f6a0ef9593232002 | |
| parent | 496ff502e2b00b37051c1319885ff495475196fc (diff) | |
performance/stat-prefetch: dont check for inode context in fops like create, mkdir.
- context will not be set as a fresh inode is passed in each of these calls.
    instead create a new context.
Signed-off-by: Raghavendra G <raghavendra@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 257 (Backport stat-prefetch to 2.0)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=257
| -rw-r--r-- | xlators/performance/stat-prefetch/src/stat-prefetch.c | 610 | 
1 files changed, 293 insertions, 317 deletions
diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.c b/xlators/performance/stat-prefetch/src/stat-prefetch.c index 6ac77dd8c0e..78e4cd5753d 100644 --- a/xlators/performance/stat-prefetch/src/stat-prefetch.c +++ b/xlators/performance/stat-prefetch/src/stat-prefetch.c @@ -22,6 +22,169 @@  #define GF_SP_CACHE_BUCKETS 1  #define GF_SP_CACHE_ENTRIES_EXPECTED 1048576 + +typedef enum { +        SP_EXPECT, +        SP_DONT_EXPECT, +        SP_DONT_CARE +}sp_expect_t; + + +void +sp_inode_ctx_free (xlator_t *this, sp_inode_ctx_t *ctx) +{ +        call_stub_t *stub = NULL, *tmp = NULL; +         +        if (ctx == NULL) { +                goto out; +        } + +        LOCK (&ctx->lock); +        { +                if (!list_empty (&ctx->waiting_ops)) { +                        gf_log (this->name, GF_LOG_CRITICAL, "inode ctx is " +                                "being freed even when there are file " +                                "operations waiting for lookup-behind to " +                                "complete. The operations in the waiting list " +                                "are:"); +                        list_for_each_entry_safe (stub, tmp, &ctx->waiting_ops, +                                                  list) { +                                gf_log (this->name, GF_LOG_CRITICAL, +                                        "OP (%d)", stub->fop); + +                                list_del_init (&stub->list); +                                call_stub_destroy (stub); +                        } +                } +        } +        UNLOCK (&ctx->lock); + +        LOCK_DESTROY (&ctx->lock); +        FREE (ctx); + +out: +        return; +} + + +sp_inode_ctx_t * +sp_inode_ctx_init () +{ +        sp_inode_ctx_t *inode_ctx = NULL; + +        inode_ctx = CALLOC (1, sizeof (*inode_ctx)); +        if (inode_ctx == NULL) { +                goto out; +        } + +        LOCK_INIT (&inode_ctx->lock); +        INIT_LIST_HEAD (&inode_ctx->waiting_ops); + +out: +        return inode_ctx; +} + + +sp_inode_ctx_t *  +sp_check_and_create_inode_ctx (xlator_t *this, inode_t *inode, +                               sp_expect_t expect, glusterfs_fop_t caller) +{ +        uint64_t        value     = 0; +        sp_inode_ctx_t *inode_ctx = NULL; +        int32_t         ret       = 0; + +        if ((this == NULL) || (inode == NULL)) { +                goto out; +        } + +        LOCK (&inode->lock); +        { +                ret = __inode_ctx_get (inode, this, &value); +                if (ret == 0) { +                        if (expect == SP_DONT_EXPECT) { +                                gf_log (this->name, GF_LOG_DEBUG, "inode_ctx " +                                        "is not NULL (caller %d)", caller); +                        } + +                        inode_ctx = (sp_inode_ctx_t *)(long)value; +                } else { +                        if (expect == SP_EXPECT) { +                                gf_log (this->name, GF_LOG_DEBUG, "inode_ctx is" +                                        " NULL (caller %d)", caller); +                        } + +                        inode_ctx = sp_inode_ctx_init (); +                        if (inode_ctx != NULL) { +                                ret = __inode_ctx_put (inode, this, +                                                       (long)inode_ctx); +                                if (ret == -1) { +                                        sp_inode_ctx_free (this, inode_ctx); +                                        inode_ctx = NULL; +                                } +                        } +                } +        } +        UNLOCK (&inode->lock); + +out: +        return inode_ctx; +} + + +int +sp_update_inode_ctx (xlator_t *this, inode_t *inode, int32_t *op_ret, +                     int32_t *op_errno, char *lookup_in_progress, +                     char *looked_up, struct list_head *waiting_ops, +                     int32_t *error) +{ +        int32_t         ret       = 0; +        sp_inode_ctx_t *inode_ctx = NULL; +        uint64_t        value     = 0; + +        ret = inode_ctx_get (inode, this, &value); +        if (ret == 0) { +                inode_ctx = (sp_inode_ctx_t *)(long)value; +        } + +        if (inode_ctx == NULL) { +                ret = -1; +                if (error != NULL) { +                        *error = EINVAL; +                } + +                goto out; +        } + +        LOCK (&inode_ctx->lock); +        { +                if (op_ret != NULL) { +                        inode_ctx->op_ret = *op_ret; +                } + +                if (op_errno != NULL) { +                        inode_ctx->op_errno = *op_errno; +                } + +                if (looked_up != NULL) { +                        inode_ctx->looked_up = *looked_up; +                } + +                if (lookup_in_progress != NULL) { +                        inode_ctx->lookup_in_progress = *lookup_in_progress; +                } + +                if (waiting_ops != NULL) { +                        list_splice_init (&inode_ctx->waiting_ops, +                                          waiting_ops); +                } +        } +        UNLOCK (&inode_ctx->lock); + +out: +        return ret; +} + +  sp_cache_t *  sp_cache_ref (sp_cache_t *cache)  { @@ -749,61 +912,6 @@ out:  } -void -sp_inode_ctx_free (xlator_t *this, sp_inode_ctx_t *ctx) -{ -        call_stub_t *stub = NULL, *tmp = NULL; -         -        if (ctx == NULL) { -                goto out; -        } - -        LOCK (&ctx->lock); -        { -                if (!list_empty (&ctx->waiting_ops)) { -                        gf_log (this->name, GF_LOG_CRITICAL, "inode ctx is " -                                "being freed even when there are file " -                                "operations waiting for lookup-behind to " -                                "complete. The operations in the waiting list " -                                "are:"); -                        list_for_each_entry_safe (stub, tmp, &ctx->waiting_ops, -                                                  list) { -                                gf_log (this->name, GF_LOG_CRITICAL, -                                        "OP (%d)", stub->fop); - -                                list_del_init (&stub->list); -                                call_stub_destroy (stub); -                        } -                } -        } -        UNLOCK (&ctx->lock); - -        LOCK_DESTROY (&ctx->lock); -        FREE (ctx); - -out: -        return; -} - - -sp_inode_ctx_t * -sp_inode_ctx_init () -{ -        sp_inode_ctx_t *inode_ctx = NULL; - -        inode_ctx = CALLOC (1, sizeof (*inode_ctx)); -        if (inode_ctx == NULL) { -                goto out; -        } - -        LOCK_INIT (&inode_ctx->lock); -        INIT_LIST_HEAD (&inode_ctx->waiting_ops); - -out: -        return inode_ctx; -} - -  int32_t  sp_lookup_helper (call_frame_t *frame,xlator_t *this, loc_t *loc,                    dict_t *xattr_req) @@ -1381,8 +1489,9 @@ sp_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                 int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode,                 struct stat *buf)  { -        sp_local_t  *local    = NULL; -        sp_fd_ctx_t *fd_ctx   = NULL; +        sp_local_t  *local              = NULL; +        sp_fd_ctx_t *fd_ctx             = NULL; +        char         lookup_in_progress = 0, looked_up = 0;          if (op_ret == -1) {                  goto out; @@ -1392,6 +1501,14 @@ sp_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, out, op_errno,                                          EINVAL); +        looked_up = 1; +        op_ret = sp_update_inode_ctx (this, local->loc.inode, &op_ret, +                                      &op_errno, &lookup_in_progress, +                                      &looked_up, NULL, &op_errno); +        if (op_ret == -1) { +                goto out; +        } +          fd_ctx = sp_fd_ctx_new (this, local->loc.parent, fd,                                  (char *)local->loc.name, NULL);          if (fd_ctx == NULL) { @@ -1406,55 +1523,13 @@ out:  int32_t -sp_create_helper (call_frame_t *frame,	xlator_t *this,	loc_t *loc, -                  int32_t flags, mode_t mode, fd_t *fd) -{ -        uint64_t        value     = 0; -        sp_inode_ctx_t *inode_ctx = NULL; -        int32_t         ret       = 0, op_ret = -1, op_errno = -1; -         -        ret = inode_ctx_get (loc->inode, this, &value); -        if (ret == -1) { -                gf_log (this->name, GF_LOG_DEBUG, "context not set in inode " -                        "(%p)", loc->inode); -                op_errno = EINVAL; -                goto unwind; -        } - -        inode_ctx = (sp_inode_ctx_t *)(long) value; -        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, inode_ctx, unwind, op_errno, -                                        EINVAL); - -        LOCK (&inode_ctx->lock); -        { -                op_ret = inode_ctx->op_ret; -                op_errno = inode_ctx->op_errno; -        } -        UNLOCK (&inode_ctx->lock); - -        if ((op_ret == -1) && (op_errno != ENOENT)) { -                goto unwind; -        } - -        STACK_WIND (frame, sp_create_cbk, FIRST_CHILD(this), -                    FIRST_CHILD(this)->fops->create, loc, flags, mode, fd); - -        return 0; - -unwind: -        SP_STACK_UNWIND (frame, -1, op_errno, NULL); -        return 0; -} - - -int32_t  sp_create (call_frame_t *frame,	xlator_t *this,	loc_t *loc, int32_t flags,             mode_t mode, fd_t *fd)  { -        sp_local_t     *local        = NULL; -        int32_t         op_errno     = -1, ret = -1; -        call_stub_t    *stub         = NULL; -        char            can_wind     = 0, need_lookup = 0, need_unwind = 1; +        sp_local_t        *local        = NULL; +        int32_t            op_errno     = -1, ret = -1; +        char               need_unwind  = 1; +        sp_inode_ctx_t    *inode_ctx    = NULL;          GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, loc, out, op_errno,                                          EINVAL); @@ -1475,42 +1550,30 @@ sp_create (call_frame_t *frame,	xlator_t *this,	loc_t *loc, int32_t flags,                  goto out;          } -        stub = fop_create_stub (frame, sp_create_helper, loc, flags, mode, fd); -        if (stub == NULL) { +        local = CALLOC (1, sizeof (*local)); +        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, out, op_errno, +                                        ENOMEM); +        frame->local = local; +        ret = loc_copy (&local->loc, loc); +        if (ret == -1) { +                op_errno = errno; +                gf_log (this->name, GF_LOG_ERROR, "%s", strerror (op_errno)); +                goto out; +        } + +        inode_ctx = sp_check_and_create_inode_ctx (this, loc->inode, +                                                   SP_DONT_CARE, GF_FOP_LOOKUP); +        if (inode_ctx == NULL) {                  op_errno = ENOMEM;                  gf_log (this->name, GF_LOG_ERROR, "out of memory");                  goto out;          } -        sp_process_inode_ctx (frame, this, loc, stub, &need_unwind, -                              &need_lookup, &can_wind, &op_errno); - +        need_unwind = 0;  out:          if (need_unwind) {                  SP_STACK_UNWIND (frame, -1, op_errno, NULL); -        } else if (need_lookup) { -                STACK_WIND (frame, sp_lookup_cbk, FIRST_CHILD(this), -                            FIRST_CHILD(this)->fops->lookup, loc, NULL); -        } else if (can_wind) { -                if (frame->local == NULL) { -                        need_unwind = 1; - -                        local = CALLOC (1, sizeof (*local)); -                        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, -                                                        out, op_errno, -                                                        ENOMEM); - -                        frame->local = local; - -                        ret = loc_copy (&local->loc, loc); -                        if (ret == -1) { -                                op_errno = errno; -                                gf_log (this->name, GF_LOG_ERROR, "%s", -                                        strerror (op_errno)); -                                goto out; -                        } -                } - +        } else {                  STACK_WIND (frame, sp_create_cbk, FIRST_CHILD(this),                              FIRST_CHILD(this)->fops->create, loc, flags,                              mode, fd); @@ -1617,64 +1680,37 @@ sp_new_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                    int32_t op_ret, int32_t op_errno, inode_t *inode,                    struct stat *buf)  { -	STACK_UNWIND (frame, op_ret, op_errno, inode, buf); -	return 0; -} +        sp_local_t *local              = NULL; +        char        lookup_in_progress = 0, looked_up = 0; - -int32_t -sp_mkdir_helper (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode) -{ -        uint64_t        value     = 0; -        sp_inode_ctx_t *inode_ctx = NULL; -        int32_t         ret       = 0, op_ret = -1, op_errno = -1; -         -        ret = inode_ctx_get (loc->inode, this, &value); -        if (ret == -1) { -                gf_log (this->name, GF_LOG_DEBUG, "context not set in inode " -                        "(%p)", loc->inode); -                op_errno = EINVAL; -                goto unwind; -        } - -        inode_ctx = (sp_inode_ctx_t *)(long) value; -        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, inode_ctx, unwind, op_errno, -                                        EINVAL); - -        LOCK (&inode_ctx->lock); -        { -                op_ret = inode_ctx->op_ret; -                op_errno = inode_ctx->op_errno; +        if (op_ret == -1) { +                goto out;          } -        UNLOCK (&inode_ctx->lock); -        if (((op_ret == -1) && (op_errno != ENOENT)) -            || (op_ret == 0)) { -                if (op_ret == 0) { -                        op_ret = -1; -                        op_errno = EEXIST; -                } - -                goto unwind; +        local = frame->local; +        if (local == NULL) { +                op_errno = EINVAL; +                goto out;          } -        STACK_WIND (frame, sp_new_entry_cbk, FIRST_CHILD(this), -                    FIRST_CHILD(this)->fops->mkdir, loc, mode); +        looked_up = 1; +        op_ret = sp_update_inode_ctx (this, local->loc.inode, &op_ret, +                                      &op_errno, &lookup_in_progress, +                                      &looked_up, NULL, &op_errno); -        return 0; - -unwind: -        SP_STACK_UNWIND (frame, -1, op_errno, NULL, NULL); -        return 0; +out: +	STACK_UNWIND (frame, op_ret, op_errno, inode, buf); +	return 0;  }  int32_t  sp_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode)  { -        int32_t         ret          = -1, op_errno = -1; -        call_stub_t    *stub         = NULL; -        char            can_wind     = 0, need_lookup = 0, need_unwind = 1; +        char            need_unwind  = 1; +        sp_inode_ctx_t *inode_ctx    = NULL; +        sp_local_t     *local        = NULL; +        int32_t         op_errno     = 0, ret = 0;          GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, loc, out, op_errno,                                          EINVAL); @@ -1687,6 +1723,19 @@ sp_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode)          GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, loc->inode, out,                                          op_errno, EINVAL); +        local = CALLOC (1, sizeof (*local)); +        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, out, op_errno, +                                        ENOMEM); + +        frame->local = local; + +        ret = loc_copy (&local->loc, loc); +        if (ret == -1) { +                op_errno = errno; +                gf_log (this->name, GF_LOG_ERROR, "%s", strerror (op_errno)); +                goto out; +        } +          ret = sp_cache_remove_parent_entry (frame, this, loc->parent->table,                                              (char *)loc->path);          if (ret == -1) { @@ -1695,23 +1744,20 @@ sp_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode)                  goto out;          } -        stub = fop_mkdir_stub (frame, sp_mkdir_helper, loc, mode); -        if (stub == NULL) { +        inode_ctx = sp_check_and_create_inode_ctx (this, loc->inode, +                                                   SP_DONT_EXPECT, +                                                   GF_FOP_MKDIR); +        if (inode_ctx == NULL) {                  op_errno = ENOMEM;                  gf_log (this->name, GF_LOG_ERROR, "out of memory");                  goto out;          } -        sp_process_inode_ctx (frame, this, loc, stub, &need_unwind, -                              &need_lookup, &can_wind, &op_errno); - +        need_unwind = 0;  out:          if (need_unwind) {                  SP_STACK_UNWIND (frame, -1, op_errno, NULL, NULL); -        } else if (need_lookup) { -                STACK_WIND (frame, sp_lookup_cbk, FIRST_CHILD(this), -                            FIRST_CHILD(this)->fops->lookup, loc, NULL); -        } else if (can_wind) { +        } else {                  STACK_WIND (frame, sp_new_entry_cbk, FIRST_CHILD(this),                              FIRST_CHILD(this)->fops->mkdir, loc, mode);          } @@ -1721,59 +1767,13 @@ out:  int32_t -sp_mknod_helper (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, -                 dev_t rdev) -{ -        uint64_t        value     = 0; -        sp_inode_ctx_t *inode_ctx = NULL; -        int32_t         ret       = 0, op_ret = -1, op_errno = -1; -         -        ret = inode_ctx_get (loc->inode, this, &value); -        if (ret == -1) { -                gf_log (this->name, GF_LOG_DEBUG, "context not set in inode " -                        "(%p)", loc->inode); -                op_errno = EINVAL; -                goto unwind; -        } - -        inode_ctx = (sp_inode_ctx_t *)(long) value; -        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, inode_ctx, unwind, op_errno, -                                        EINVAL); - -        LOCK (&inode_ctx->lock); -        { -                op_ret = inode_ctx->op_ret; -                op_errno = inode_ctx->op_errno; -        } -        UNLOCK (&inode_ctx->lock); - -        if (((op_ret == -1) && (op_errno != ENOENT)) -            || (op_ret == 0)) { -                if (op_ret == 0) { -                        op_ret = -1; -                        op_errno = EEXIST; -                } -                goto unwind; -        } - -        STACK_WIND (frame, sp_new_entry_cbk, FIRST_CHILD(this), -                    FIRST_CHILD(this)->fops->mknod, loc, mode, rdev); - -        return 0; - -unwind: -        SP_STACK_UNWIND (frame, -1, op_errno, NULL); -        return 0; -} - - -int32_t  sp_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,            dev_t rdev)  { -        int32_t         op_errno     = -1, ret = -1; -        call_stub_t    *stub         = NULL; -        char            can_wind     = 0, need_lookup = 0, need_unwind = 1; +        char            need_unwind  = 1; +        sp_inode_ctx_t *inode_ctx    = NULL; +        sp_local_t     *local        = NULL; +        int32_t         op_errno     = 0, ret = 0;          GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, loc, out, op_errno,                                          EINVAL); @@ -1794,23 +1794,33 @@ sp_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,                  goto out;          } -        stub = fop_mknod_stub (frame, sp_mknod_helper, loc, mode, rdev); -        if (stub == NULL) { +        local = CALLOC (1, sizeof (*local)); +        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, out, op_errno, +                                        ENOMEM); + +        frame->local = local; + +        ret = loc_copy (&local->loc, loc); +        if (ret == -1) { +                op_errno = errno; +                gf_log (this->name, GF_LOG_ERROR, "%s", strerror (op_errno)); +                goto out; +        } + +        inode_ctx = sp_check_and_create_inode_ctx (this, loc->inode, +                                                   SP_DONT_EXPECT, +                                                   GF_FOP_MKNOD); +        if (inode_ctx == NULL) {                  op_errno = ENOMEM;                  gf_log (this->name, GF_LOG_ERROR, "out of memory");                  goto out;          } -        sp_process_inode_ctx (frame, this, loc, stub, &need_unwind, -                              &need_lookup, &can_wind, &op_errno); - +        need_unwind = 0;  out:          if (need_unwind) {                  SP_STACK_UNWIND (frame, -1, op_errno, NULL, NULL); -        } else if (need_lookup) { -                STACK_WIND (frame, sp_lookup_cbk, FIRST_CHILD(this), -                            FIRST_CHILD(this)->fops->lookup, loc, NULL); -        } else if (can_wind) { +        } else {                  STACK_WIND (frame, sp_new_entry_cbk, FIRST_CHILD(this),                              FIRST_CHILD(this)->fops->mknod, loc, mode, rdev);          } @@ -1820,58 +1830,13 @@ out:  int32_t -sp_symlink_helper (call_frame_t *frame, xlator_t *this, const char *linkpath, -                   loc_t *loc) -{ -        uint64_t        value     = 0; -        sp_inode_ctx_t *inode_ctx = NULL; -        int32_t         ret       = 0, op_ret = -1, op_errno = -1; -         -        ret = inode_ctx_get (loc->inode, this, &value); -        if (ret == -1) { -                gf_log (this->name, GF_LOG_DEBUG, "context not set in inode " -                        "(%p)", loc->inode); -                op_errno = EINVAL; -                goto unwind; -        } - -        inode_ctx = (sp_inode_ctx_t *)(long) value; -        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, inode_ctx, unwind, op_errno, -                                        EINVAL); - -        LOCK (&inode_ctx->lock); -        { -                op_ret = inode_ctx->op_ret; -                op_errno = inode_ctx->op_errno; -        } -        UNLOCK (&inode_ctx->lock); - -        if (((op_ret == -1) && (op_errno != ENOENT)) || (op_ret == 0)) { -                if (op_ret == 0) { -                        op_ret = -1; -                        op_errno = EEXIST; -                } -                goto unwind; -        } - -        STACK_WIND (frame, sp_new_entry_cbk, FIRST_CHILD(this), -                    FIRST_CHILD(this)->fops->symlink, linkpath, loc); - -        return 0; - -unwind: -        SP_STACK_UNWIND (frame, -1, op_errno); -        return 0; -} - - -int32_t  sp_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath,              loc_t *loc)  { -        int32_t         ret          = -1, op_errno = -1; -        call_stub_t    *stub         = NULL; -        char            can_wind     = 0, need_lookup = 0, need_unwind = 1; +        char            need_unwind  = 1; +        sp_inode_ctx_t *inode_ctx    = NULL; +        sp_local_t     *local        = NULL; +        int32_t         op_errno     = 0, ret = 0;          GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, loc, out, op_errno,                                          EINVAL); @@ -1892,23 +1857,33 @@ sp_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath,                  goto out;          } -        stub = fop_symlink_stub (frame, sp_symlink_helper, linkpath, loc); -        if (stub == NULL) { +        local = CALLOC (1, sizeof (*local)); +        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, out, op_errno, +                                        ENOMEM); + +        frame->local = local; + +        ret = loc_copy (&local->loc, loc); +        if (ret == -1) { +                op_errno = errno; +                gf_log (this->name, GF_LOG_ERROR, "%s", strerror (op_errno)); +                goto out; +        } + +        inode_ctx = sp_check_and_create_inode_ctx (this, loc->inode, +                                                   SP_DONT_EXPECT, +                                                   GF_FOP_SYMLINK); +        if (inode_ctx == NULL) {                  op_errno = ENOMEM;                  gf_log (this->name, GF_LOG_ERROR, "out of memory");                  goto out;          } -        sp_process_inode_ctx (frame, this, loc, stub, &need_unwind, -                              &need_lookup, &can_wind, &op_errno); - +        need_unwind = 0;  out:          if (need_unwind) {                  SP_STACK_UNWIND (frame, -1, op_errno); -        } else if (need_lookup) { -                STACK_WIND (frame, sp_lookup_cbk, FIRST_CHILD(this), -                            FIRST_CHILD(this)->fops->lookup, loc, NULL); -        } else if (can_wind) { +        } else {                  STACK_WIND (frame, sp_new_entry_cbk, FIRST_CHILD(this),                              FIRST_CHILD(this)->fops->symlink, linkpath, loc);          } @@ -1918,6 +1893,15 @@ out:  int32_t +sp_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, +             int32_t op_errno, inode_t *inode, struct stat *buf) +{ +	SP_STACK_UNWIND (frame, op_ret, op_errno, inode, buf); +	return 0; +} + + +int32_t  sp_link_helper (call_frame_t *frame, xlator_t *this, loc_t *oldloc,                  loc_t *newloc)  { @@ -1948,7 +1932,7 @@ sp_link_helper (call_frame_t *frame, xlator_t *this, loc_t *oldloc,                  goto unwind;          } -        STACK_WIND (frame, sp_new_entry_cbk, FIRST_CHILD(this), +        STACK_WIND (frame, sp_link_cbk, FIRST_CHILD(this),                      FIRST_CHILD(this)->fops->link, oldloc, newloc);          return 0; @@ -1962,10 +1946,10 @@ unwind:  int32_t  sp_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc)  { -        call_stub_t *stub     = NULL; -        sp_cache_t  *cache    = NULL; -        int32_t      ret      = 0, op_errno = -1;  -        char         can_wind = 0, need_lookup = 0, need_unwind = 1; +        call_stub_t *stub         = NULL; +        sp_cache_t  *cache        = NULL; +        int32_t      ret          = 0, op_errno = -1;  +        char         can_wind     = 0, need_lookup = 0, need_unwind = 1;          GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, oldloc, out, op_errno,                                          EINVAL); @@ -2010,14 +1994,6 @@ sp_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc)          sp_process_inode_ctx (frame, this, oldloc, stub, &need_unwind,                                &need_lookup, &can_wind, &op_errno); -        /* -         * no need to process context in newloc->inode for following reasons: -         * 1. if dentry corresponding to newloc->path was cached, sp_lookup -         *    would've unwound indicating success and link fop itself would've -         *    not been called. -         * 2. if dentry corresponding to newloc->path was not cached, lookup -         *    would've anyways be sent to underlying translators in sp_lookup.  -         */  out:          if (need_unwind) {                  SP_STACK_UNWIND (frame, -1, op_errno, NULL, NULL); @@ -2025,7 +2001,7 @@ out:                  STACK_WIND (frame, sp_lookup_cbk, FIRST_CHILD(this),                              FIRST_CHILD(this)->fops->lookup, oldloc, NULL);          } else if (can_wind) { -                STACK_WIND (frame, sp_new_entry_cbk, FIRST_CHILD(this), +                STACK_WIND (frame, sp_link_cbk, FIRST_CHILD(this),                              FIRST_CHILD(this)->fops->link, oldloc, newloc);          }  | 
