diff options
Diffstat (limited to 'xlators/features/bit-rot/src/stub')
| -rw-r--r-- | xlators/features/bit-rot/src/stub/bit-rot-common.h | 5 | ||||
| -rw-r--r-- | xlators/features/bit-rot/src/stub/bit-rot-stub.c | 700 | ||||
| -rw-r--r-- | xlators/features/bit-rot/src/stub/bit-rot-stub.h | 3 | 
3 files changed, 388 insertions, 320 deletions
diff --git a/xlators/features/bit-rot/src/stub/bit-rot-common.h b/xlators/features/bit-rot/src/stub/bit-rot-common.h index 7fd584e5970..a8285d2b560 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-common.h +++ b/xlators/features/bit-rot/src/stub/bit-rot-common.h @@ -119,6 +119,11 @@ typedef enum {  /* BitRot stub start time (virtual xattr) */  #define GLUSTERFS_GET_BR_STUB_INIT_TIME  "trusted.glusterfs.bit-rot.stub-init" +/* signing/reopen hint */ +#define BR_OBJECT_RESIGN 0 +#define BR_OBJECT_REOPEN  1 +#define BR_REOPEN_SIGN_HINT_KEY  "trusted.glusterfs.bit-rot.reopen-hint" +  static inline int  br_is_signature_type_valid (int8_t signaturetype)  { diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub.c b/xlators/features/bit-rot/src/stub/bit-rot-stub.c index 93db072f671..524c235b549 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub.c +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub.c @@ -255,7 +255,7 @@ br_stub_fill_local (br_stub_local_t *local,          local->fopstub = stub;          local->versioningtype = versioningtype;          local->u.context.version = memversion; -        if (fd && !local->u.context.fd) +        if (fd)                  local->u.context.fd = fd_ref (fd);          if (inode)                  local->u.context.inode = inode_ref (inode); @@ -279,6 +279,126 @@ br_stub_cleanup_local (br_stub_local_t *local)          memset (local->u.context.gfid, '\0', sizeof (uuid_t));  } +static int +br_stub_need_versioning (xlator_t *this, +                         fd_t *fd, gf_boolean_t *versioning, +                         gf_boolean_t *modified, br_stub_inode_ctx_t **ctx) +{ +        int32_t ret      = -1; +        uint64_t ctx_addr = 0; +        br_stub_inode_ctx_t *c = NULL; + +        *versioning = _gf_false; +        *modified = _gf_false; + +        ret = br_stub_get_inode_ctx (this, fd->inode, &ctx_addr); +        if (ret < 0) { +                gf_log (this->name, GF_LOG_ERROR, "failed to get the inode " +                        "context for the inode %s", +                        uuid_utoa (fd->inode->gfid)); +                goto error_return; +        } + +        c = (br_stub_inode_ctx_t *) (long) ctx_addr; + +        LOCK (&fd->inode->lock); +        { +                if (__br_stub_is_inode_dirty (c)) +                        *versioning = _gf_true; +                if (__br_stub_is_inode_modified (c)) +                        *modified = _gf_true; +        } +        UNLOCK (&fd->inode->lock); + +        if (ctx) +                *ctx = c; +        return 0; + + error_return: +        return -1; +} + +static int32_t +br_stub_anon_fd_ctx (xlator_t *this, fd_t *fd, br_stub_inode_ctx_t *ctx) +{ +        int32_t  ret = -1; +        br_stub_fd_t *br_stub_fd = NULL; + +        br_stub_fd = br_stub_fd_ctx_get (this, fd); +        if (!br_stub_fd) { +                ret = br_stub_add_fd_to_inode (this, fd, ctx); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "failed to " +                                "add fd to the inode (gfid: %s)", +                                uuid_utoa (fd->inode->gfid)); +                        goto out; +                } +        } + +        ret = 0; + +out: +        return ret; +} + +static int +br_stub_versioning_prep (call_frame_t *frame, +                         xlator_t *this, fd_t *fd, br_stub_inode_ctx_t *ctx) +{ +        int32_t          ret = -1; +        br_stub_local_t *local   = NULL; + +        local = br_stub_alloc_local (this); +        if (!local) { +                gf_log (this->name, GF_LOG_ERROR, "local allocation failed " +                        "(gfid: %s)", uuid_utoa (fd->inode->gfid)); +                goto error_return; +        } + +        if (fd_is_anonymous (fd)) { +                ret = br_stub_anon_fd_ctx (this, fd, ctx); +                if (ret) +                        goto free_local; +        } + +        frame->local = local; + +        return 0; + + free_local: +        br_stub_dealloc_local (local); + error_return: +        return -1; +} + +static int +br_stub_mark_inode_modified (xlator_t *this, br_stub_local_t *local) +{ +        fd_t                *fd       = NULL; +        int32_t              ret      = 0; +        uint64_t             ctx_addr = 0; +        br_stub_inode_ctx_t *ctx      = NULL; + +        fd = local->u.context.fd; + +        ret = br_stub_get_inode_ctx (this, fd->inode, &ctx_addr); +        if (ret < 0) +                goto error_return; + +        ctx = (br_stub_inode_ctx_t *) (long) ctx_addr; + +        LOCK (&fd->inode->lock); +        { +                __br_stub_set_inode_modified (ctx); +        } +        UNLOCK (&fd->inode->lock); + +        return 0; + + error_return: +        return -1; +} +  /**   * callback for inode/fd versioning   */ @@ -379,7 +499,6 @@ br_stub_fd_versioning (xlator_t *this, call_frame_t *frame,                              fd->inode, fd->inode->gfid,                              versioningtype, memversion); -        frame->local = local;          STACK_WIND (frame, callback,                      FIRST_CHILD (this), FIRST_CHILD (this)->fops->fsetxattr,                      fd, dict, flags, xdata); @@ -409,7 +528,6 @@ br_stub_perform_incversioning (xlator_t *this,          writeback_version = __br_stub_writeback_version (ctx); -        /* inode requires writeback to disk */          op_errno = ENOMEM;          dict = dict_new ();          if (!dict) @@ -518,54 +636,160 @@ br_stub_prepare_signature (xlator_t *this, dict_t *dict,          return -1;  } -int -br_stub_fsetxattr (call_frame_t *frame, xlator_t *this, -                   fd_t *fd, dict_t *dict, int flags, dict_t *xdata) +static void +br_stub_handle_object_signature (call_frame_t *frame, +                                 xlator_t *this, fd_t *fd, dict_t *dict, +                                 br_isignature_t *sign, dict_t *xdata)  { -        int32_t          ret  = 0; -        br_isignature_t *sign = NULL; -        gf_boolean_t     xref = _gf_false; +        int32_t      ret  = -1; +        gf_boolean_t xref = _gf_false; -        if (!IA_ISREG (fd->inode->ia_type)) -                goto wind; -        ret = dict_get_bin (dict, GLUSTERFS_SET_OBJECT_SIGNATURE, -                            (void **) &sign); -        if (ret < 0) -                goto wind;          if (frame->root->pid != GF_CLIENT_PID_BITD) -                goto unwind; +                goto dofop;          ret = br_stub_prepare_signature (this, dict, fd->inode, sign);          if (ret) -                goto unwind; +                goto dofop;          dict_del (dict, GLUSTERFS_SET_OBJECT_SIGNATURE); +        ret = -1;          if (!xdata) {                  xdata = dict_new ();                  if (!xdata) -                        goto unwind; +                        goto dofop;          } else {                  dict_ref (xdata);          }          xref = _gf_true;          ret = dict_set_int32 (xdata, GLUSTERFS_DURABLE_OP, 0); + + dofop: +        if (ret) +                STACK_UNWIND_STRICT (fsetxattr, frame, -1, EINVAL, NULL); +        else { +                gf_log (this->name, GF_LOG_DEBUG, "SIGNED VERSION: %lu", +                        sign->signedversion); + +                STACK_WIND (frame, default_setxattr_cbk, FIRST_CHILD (this), +                            FIRST_CHILD (this)->fops->fsetxattr, fd, dict, 0, +                            xdata); +        } + +        if (xref) +                dict_unref (xdata); +} + +int32_t +br_stub_fsetxattr_resume (call_frame_t *frame, void *cookie, xlator_t *this, +                          int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ +        int32_t ret = -1; +        br_stub_local_t *local = NULL; + +        local = frame->local; +        frame->local = NULL; + +        ret = br_stub_mark_inode_modified (this, local); +        if (ret) { +                op_ret = -1; +                op_errno = EINVAL; +        } + +        STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno, xdata); + +        br_stub_cleanup_local (local); +        br_stub_dealloc_local (local); + +        return 0; +} + +static void +br_stub_handle_object_reopen (call_frame_t *frame, +                              xlator_t *this, fd_t *fd, uint32_t val) +{ +        int32_t              ret         = -1; +        int32_t              op_ret      = -1; +        int32_t              op_errno    = EINVAL; +        call_stub_t         *stub        = NULL; +        gf_boolean_t         inc_version = _gf_false; +        gf_boolean_t         modified    = _gf_false; +        br_stub_inode_ctx_t *ctx         = NULL; +        br_stub_local_t     *local       = NULL; + +        ret = br_stub_need_versioning (this, fd, &inc_version, &modified, &ctx);          if (ret)                  goto unwind; -        gf_log (this->name, GF_LOG_DEBUG, "SIGNED VERSION: %lu", -                sign->signedversion); +        LOCK (&fd->inode->lock); +        { +                (void) __br_stub_inode_sign_state (ctx, GF_FOP_FSETXATTR, fd); +        } +        UNLOCK (&fd->inode->lock); + +        if ((val == BR_OBJECT_RESIGN) || !inc_version) { +                op_ret = op_errno = 0; +                goto unwind; +        } + +        ret = br_stub_versioning_prep (frame, this, fd, ctx); +        if (ret) +                goto unwind; +        local = frame->local; + +        stub = fop_fsetxattr_cbk_stub (frame, br_stub_fsetxattr_resume, +                                       0, 0, NULL); +        if (!stub) { +                gf_log (this->name, GF_LOG_ERROR, "failed to allocate stub for " +                        "fsetxattr fop (gfid: %s), unwinding", +                        uuid_utoa (fd->inode->gfid)); +                goto cleanup_local; +        } + +        (void) br_stub_perform_incversioning (this, frame, stub, fd, ctx); +        return; + + cleanup_local: +        br_stub_cleanup_local (local); +        br_stub_dealloc_local (local); + + unwind: +        frame->local = NULL; +        STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno, NULL); +} + +int +br_stub_fsetxattr (call_frame_t *frame, xlator_t *this, +                   fd_t *fd, dict_t *dict, int flags, dict_t *xdata) +{ +        int32_t          ret  = 0; +        uint32_t val = 0; +        br_isignature_t *sign = NULL; + +        if (!IA_ISREG (fd->inode->ia_type)) +                goto wind; + +        /* object signature request */ +        ret = dict_get_bin (dict, GLUSTERFS_SET_OBJECT_SIGNATURE, +                            (void **) &sign); +        if (!ret) { +                br_stub_handle_object_signature (frame, this, +                                                 fd, dict, sign, xdata); +                goto done; +        } + +        /* object reopen request */ +        ret = dict_get_uint32 (dict, BR_REOPEN_SIGN_HINT_KEY, &val); +        if (!ret) { +                br_stub_handle_object_reopen (frame, this, fd, val); +                goto done; +        } +   wind:          STACK_WIND (frame, default_setxattr_cbk,                      FIRST_CHILD (this), FIRST_CHILD (this)->fops->fsetxattr, fd,                      dict, flags, xdata); -        goto done; - - unwind: -        STACK_UNWIND_STRICT (setxattr, frame, -1, EINVAL, NULL);   done: -        if (xref) -                dict_unref (xdata);          return 0;  } @@ -812,110 +1036,29 @@ br_stub_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                      int32_t op_ret, int32_t op_errno, struct iatt *prebuf,                      struct iatt *postbuf, dict_t *xdata)  { -        int32_t              ret         = 0; -        uint64_t             ctx_addr    = 0; -        br_stub_inode_ctx_t *ctx         = NULL; -        br_stub_local_t     *local       = NULL; +        int32_t          ret   = 0; +        br_stub_local_t *local = NULL; -        if (frame->local) { -                local = frame->local; -                frame->local = NULL; -        } +        local = frame->local; +        frame->local = NULL;          if (op_ret < 0)                  goto unwind; -        ret = br_stub_get_inode_ctx (this, local->u.context.fd->inode, -                                     &ctx_addr); -        if (ret < 0) -                goto unwind; - -        ctx = (br_stub_inode_ctx_t *) (long) ctx_addr; - -        /* Mark the flag to indicate the inode has been modified */ -        LOCK (&local->u.context.fd->inode->lock); -        { -                if (!__br_stub_is_inode_modified (ctx)) -                        __br_stub_set_inode_modified (ctx); +        ret = br_stub_mark_inode_modified (this, local); +        if (ret) { +                op_ret = -1; +                op_errno = EINVAL;          } -        UNLOCK (&local->u.context.fd->inode->lock); -  unwind: -        STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, prebuf, postbuf, -                             xdata); +        STACK_UNWIND_STRICT (writev, frame, +                             op_ret, op_errno, prebuf, postbuf, xdata); +          br_stub_cleanup_local (local);          br_stub_dealloc_local (local); -        return 0; -} - -/** - * Ongoing version is increased only for the first modify operation. - * First modify version means the first write or truncate call coming on the - * first fd in the list of inodes. - * For anonymous fds open would not have come, so check if its the first write - * by doing both inode dirty check and ensuring list of fds is empty - */ -static inline gf_boolean_t -br_stub_inc_version (xlator_t *this, fd_t *fd, br_stub_inode_ctx_t *ctx) -{ -        gf_boolean_t inc_version = _gf_false; - -        GF_VALIDATE_OR_GOTO (this->name, fd, out); -        GF_VALIDATE_OR_GOTO (this->name, ctx, out); - -        LOCK (&fd->inode->lock); -        { -                if (__br_stub_is_inode_dirty (ctx)) -                        inc_version = _gf_true; -        } -        UNLOCK (&fd->inode->lock); - -out: -        return inc_version; -} - -/** - * Since NFS does not do open, writes from NFS are sent over an anonymous - * fd. It means each write fop might come on a different anonymous fd and - * will lead to very large number of notifications being sent. It might - * affect the perfromance as, there will too many sign requests. - * To avoid that whenever the last fd released from an inode (logical release) - * is an anonymous fd the release notification is sent with a flag being set - * __br_stub_anon_release (ctx); - * BitD checks for the flag and if set, it will send a dummy write request - * (again on an anonymous fd) instead of triggering sign. - * Bit-rot-stub should identify such dummy writes and should send success to - * them instead of winding them downwards. - */ -gf_boolean_t -br_stub_dummy_write (call_frame_t *frame) -{ -        return (frame->root->pid == GF_CLIENT_PID_BITD) -                        ? _gf_true : _gf_false; -} - -int32_t -br_stub_anon_fd_ctx (xlator_t *this, fd_t *fd, br_stub_inode_ctx_t *ctx) -{ -        int32_t  ret = -1; -        br_stub_fd_t *br_stub_fd = NULL; -        br_stub_fd = br_stub_fd_ctx_get (this, fd); -        if (!br_stub_fd) { -                ret = br_stub_add_fd_to_inode (this, fd, ctx); -                if (ret) { -                        gf_log (this->name, GF_LOG_ERROR, "failed to " -                                "add fd to the inode (gfid: %s)", -                                uuid_utoa (fd->inode->gfid)); -                        goto out; -                } -        } - -        ret = 0; - -out: -        return ret; +        return 0;  }  int32_t @@ -923,107 +1066,71 @@ br_stub_writev_resume (call_frame_t *frame, xlator_t *this, fd_t *fd,                         struct iovec *vector, int32_t count, off_t offset,                         uint32_t flags, struct iobref *iobref, dict_t *xdata)  { -        if (frame->root->pid == GF_CLIENT_PID_BITD) -                br_stub_writev_cbk (frame, NULL, this, vector->iov_len, 0, -                                    NULL, NULL, NULL); -        else -                STACK_WIND (frame, br_stub_writev_cbk, FIRST_CHILD(this), -                            FIRST_CHILD(this)->fops->writev, fd, vector, count, -                            offset, flags, iobref, xdata); +        STACK_WIND (frame, br_stub_writev_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->writev, fd, vector, count, +                    offset, flags, iobref, xdata);          return 0;  }  /** -   TODO: If possible add pictorial represention of below comment. - -   Before sending writev on the ANONYMOUS FD, increase the ongoing -   version first. This brings anonymous fd write closer to the regular -   fd write by having the ongoing version increased before doing the -   write (In regular fd, after open the ongoing version is incremented). -   Do following steps to handle writes on anonymous fds: -   1) Increase the on-disk ongoing version -   2) Once versioning is successfully done send write operation. If versioning -      fails, then fail the write fop. -   3) In writev_cbk do below things: -      a) Increase in-memory version -      b) set the fd context (so that br_stub_release is invoked) -      c) add the fd to the list of fds maintained in the inode context of -         bitrot-stub. -      d) Mark inode as non dirty -      e) Mard inode as modified (in the inode context) -**/ + * This is probably the most crucial part about the whole versioning thing. + * There's absolutely no differentiation as such between an anonymous fd + * and a regular fd except the fd context initialization. Object versioning + * is perfomed when the inode is dirty. Parallel write operations are no + * special with each write performing object versioning followed by marking + * the inode as non-dirty (synced). This is followed by the actual operation + * (writev() in this case) which on a success marks the inode as modified. + * This prevents signing of objects that have not been modified. + */  int32_t  br_stub_writev (call_frame_t *frame, xlator_t *this, fd_t *fd,                  struct iovec *vector, int32_t count, off_t offset,                  uint32_t flags, struct iobref *iobref, dict_t *xdata)  { -        br_stub_local_t     *local       = NULL;          call_stub_t         *stub        = NULL;          int32_t              op_ret      = -1;          int32_t              op_errno    = EINVAL;          gf_boolean_t         inc_version = _gf_false; +        gf_boolean_t         modified    = _gf_false;          br_stub_inode_ctx_t *ctx         = NULL; -        uint64_t             ctx_addr    = 0;          int32_t              ret         = -1; +        fop_writev_cbk_t     cbk         = default_writev_cbk; +        br_stub_local_t     *local       = NULL;          GF_VALIDATE_OR_GOTO ("bit-rot-stub", this, unwind);          GF_VALIDATE_OR_GOTO (this->name, frame, unwind);          GF_VALIDATE_OR_GOTO (this->name, fd, unwind); -        local = br_stub_alloc_local (this); -        if (!local) { -                gf_log (this->name, GF_LOG_ERROR, "local allocation failed " -                        "(gfid: %s)", uuid_utoa (fd->inode->gfid)); -                op_ret = -1; -                op_errno = ENOMEM; -                goto unwind; -        } - -        local->u.context.fd = fd_ref (fd); -        frame->local = local; - -        ret = br_stub_get_inode_ctx (this, fd->inode, &ctx_addr); -        if (ret < 0) { -                gf_log (this->name, GF_LOG_ERROR, "failed to get the inode " -                        "context for the inode %s", -                        uuid_utoa (fd->inode->gfid)); +        ret = br_stub_need_versioning (this, fd, &inc_version, &modified, &ctx); +        if (ret)                  goto unwind; -        } -        ctx = (br_stub_inode_ctx_t *) (long) ctx_addr; -        if (fd_is_anonymous (fd)) { -                ret = br_stub_anon_fd_ctx (this, fd, ctx); -                if (ret) -                        goto unwind; -        } - -        /* TODO: Better to do a dummy fsetxattr instead of write. Keep write -           simple */ -        if (br_stub_dummy_write (frame)) { -                LOCK (&fd->inode->lock); -                { -                        (void) __br_stub_inode_sign_state -                                             (ctx, GF_FOP_WRITE, fd); -                } -                UNLOCK (&fd->inode->lock); - -                if (xdata && dict_get (xdata, "br-fd-reopen")) { -                        op_ret = vector->iov_len; -                        op_errno = 0; -                        goto unwind; -                } -        } +        /** +         * The inode is not dirty and also witnessed atleast one successful +         * modification operation. Therefore, subsequent operations need not +         * perform any special tracking. +         */ +        if (!inc_version && modified) +                goto wind;          /** -         * Check whether this is the first write on this inode since the last -         * sign notification has been sent. If so, do versioning. Otherwise -         * go ahead with the fop. +         * okay.. so, either the inode needs versioning or the modification +         * needs to be tracked. ->cbk is set to the appropriate callback +         * routine for this. +         * NOTE: ->local needs to be deallocated on failures from here on.           */ -        inc_version = br_stub_inc_version (this, fd, ctx); -        if (!inc_version) +        ret = br_stub_versioning_prep (frame, this, fd, ctx); +        if (ret) +                goto unwind; + +        local = frame->local; +        if (!inc_version) { +                br_stub_fill_local (local, NULL, fd, fd->inode, +                                    fd->inode->gfid, BR_STUB_NO_VERSIONING, 0); +                cbk = br_stub_writev_cbk;                  goto wind; +        } -        /* Create the stub for the write fop */          stub = fop_writev_stub (frame, br_stub_writev_resume, fd, vector, count,                                  offset, flags, iobref, xdata); @@ -1031,24 +1138,27 @@ br_stub_writev (call_frame_t *frame, xlator_t *this, fd_t *fd,                  gf_log (this->name, GF_LOG_ERROR, "failed to allocate stub for "                          "write fop (gfid: %s), unwinding",                          uuid_utoa (fd->inode->gfid)); -                goto unwind; +                goto cleanup_local;          }          /* Perform Versioning */          return br_stub_perform_incversioning (this, frame, stub, fd, ctx); -wind: -        STACK_WIND (frame, br_stub_writev_cbk, FIRST_CHILD(this), -                    FIRST_CHILD(this)->fops->writev, fd, vector, count, offset, -                    flags, iobref, xdata); + wind: +        STACK_WIND (frame, cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->writev, +                    fd, vector, count, offset, flags, iobref, xdata);          return 0; -unwind: + cleanup_local: +        br_stub_cleanup_local (local); +        br_stub_dealloc_local (local); + + unwind:          frame->local = NULL;          STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, NULL, NULL,                               NULL); -        br_stub_cleanup_local (local); -        br_stub_dealloc_local (local); +          return 0;  } @@ -1057,40 +1167,28 @@ br_stub_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                         int32_t op_ret, int32_t op_errno, struct iatt *prebuf,                         struct iatt *postbuf, dict_t *xdata)  { -        int32_t              ret         = 0; -        uint64_t             ctx_addr    = 0; -        br_stub_inode_ctx_t *ctx         = NULL; -        br_stub_local_t     *local       = NULL; +        int32_t          ret   = -1; +        br_stub_local_t *local = NULL; -        if (frame->local) { -                local = frame->local; -                frame->local = NULL; -        } +        local = frame->local; +        frame->local = NULL;          if (op_ret < 0)                  goto unwind; -        ret = br_stub_get_inode_ctx (this, local->u.context.fd->inode, -                                     &ctx_addr); -        if (ret < 0) -                goto unwind; - -        ctx = (br_stub_inode_ctx_t *) (long) ctx_addr; - -        /* Mark the flag to indicate the inode has been modified */ -        LOCK (&local->u.context.fd->inode->lock); -        { -                if (!__br_stub_is_inode_modified (ctx)) -                        __br_stub_set_inode_modified (ctx); +        ret = br_stub_mark_inode_modified (this, local); +        if (ret) { +                op_ret = -1; +                op_errno = EINVAL;          } -        UNLOCK (&local->u.context.fd->inode->lock); -  unwind: -        STACK_UNWIND_STRICT (ftruncate, frame, op_ret, op_errno, prebuf, postbuf, -                             xdata); +        STACK_UNWIND_STRICT (ftruncate, frame, +                             op_ret, op_errno, prebuf, postbuf, xdata); +          br_stub_cleanup_local (local);          br_stub_dealloc_local (local); +          return 0;  } @@ -1103,6 +1201,7 @@ br_stub_ftruncate_resume (call_frame_t *frame, xlator_t *this, fd_t *fd,          return 0;  } +/* c.f. br_stub_writev() for explanation */  int32_t  br_stub_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd,                     off_t offset, dict_t *xdata) @@ -1112,72 +1211,59 @@ br_stub_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd,          int32_t              op_ret      = -1;          int32_t              op_errno    = EINVAL;          gf_boolean_t         inc_version = _gf_false; +        gf_boolean_t         modified    = _gf_false;          br_stub_inode_ctx_t *ctx         = NULL; -        uint64_t             ctx_addr    = 0;          int32_t              ret         = -1; +        fop_ftruncate_cbk_t  cbk         = default_ftruncate_cbk;          GF_VALIDATE_OR_GOTO ("bit-rot-stub", this, unwind);          GF_VALIDATE_OR_GOTO (this->name, frame, unwind);          GF_VALIDATE_OR_GOTO (this->name, fd, unwind); -        local = br_stub_alloc_local (this); -        if (!local) { -                gf_log (this->name, GF_LOG_ERROR, "local allocation failed " -                        "(gfid: %s)", uuid_utoa (fd->inode->gfid)); -                op_ret = -1; -                op_errno = ENOMEM; +        ret = br_stub_need_versioning (this, fd, &inc_version, &modified, &ctx); +        if (ret)                  goto unwind; -        } -        local->u.context.fd = fd_ref (fd); -        frame->local = local; +        if (!inc_version && modified) +                goto wind; -        ret = br_stub_get_inode_ctx (this, fd->inode, &ctx_addr); -        if (ret < 0) { -                gf_log (this->name, GF_LOG_ERROR, "failed to get the inode " -                        "context for the inode %s", -                        uuid_utoa (fd->inode->gfid)); +        ret = br_stub_versioning_prep (frame, this, fd, ctx); +        if (ret)                  goto unwind; -        } -        ctx = (br_stub_inode_ctx_t *) (long) ctx_addr; -        if (fd_is_anonymous (fd)) { -                ret = br_stub_anon_fd_ctx (this, fd, ctx); -                if (ret) -                        goto unwind; -        } - -        /** -         * c.f. br_stub_writev() -         */ -        inc_version = br_stub_inc_version (this, fd, ctx); -        if (!inc_version) +        local = frame->local; +        if (!inc_version) { +                br_stub_fill_local (local, NULL, fd, fd->inode, +                                    fd->inode->gfid, BR_STUB_NO_VERSIONING, 0); +                cbk = br_stub_ftruncate_cbk;                  goto wind; +        } -        /* Create the stub for the ftruncate fop */          stub = fop_ftruncate_stub (frame, br_stub_ftruncate_resume, fd, offset,                                     xdata);          if (!stub) {                  gf_log (this->name, GF_LOG_ERROR, "failed to allocate stub for "                          "ftruncate fop (gfid: %s), unwinding",                          uuid_utoa (fd->inode->gfid)); -                goto unwind; +                goto cleanup_local;          } -        /* Perform Versioning */          return br_stub_perform_incversioning (this, frame, stub, fd, ctx); -wind: -        STACK_WIND (frame, br_stub_ftruncate_cbk, FIRST_CHILD(this), + wind: +        STACK_WIND (frame, cbk, FIRST_CHILD(this),                      FIRST_CHILD(this)->fops->ftruncate, fd, offset, xdata);          return 0; -unwind: + cleanup_local: +        br_stub_cleanup_local (local); +        br_stub_dealloc_local (local); + + unwind:          frame->local = NULL;          STACK_UNWIND_STRICT (ftruncate, frame, op_ret, op_errno, NULL, NULL,                               NULL); -        br_stub_cleanup_local (local); -        br_stub_dealloc_local (local); +          return 0;  } @@ -1186,34 +1272,20 @@ br_stub_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                        int32_t op_ret, int32_t op_errno, struct iatt *prebuf,                        struct iatt *postbuf, dict_t *xdata)  { -        int32_t              ret         = 0; -        uint64_t             ctx_addr    = 0; -        br_stub_inode_ctx_t *ctx         = NULL; -        br_stub_local_t     *local       = NULL; +        int32_t          ret   = 0; +        br_stub_local_t *local = NULL; -        if (frame->local) { -                local = frame->local; -                frame->local = NULL; -        } +        local = frame->local; +        frame->local = NULL;          if (op_ret < 0)                  goto unwind; -        ret = br_stub_get_inode_ctx (this, local->u.context.fd->inode, -                                     &ctx_addr); -        if (ret < 0) -                goto unwind; - -        ctx = (br_stub_inode_ctx_t *) (long) ctx_addr; - -        /* Mark the flag to indicate the inode has been modified */ -        LOCK (&local->u.context.fd->inode->lock); -        { -                if (!__br_stub_is_inode_modified (ctx)) -                        __br_stub_set_inode_modified (ctx); +        ret = br_stub_mark_inode_modified (this, local); +        if (ret) { +                op_ret = -1; +                op_errno = EINVAL;          } -        UNLOCK (&local->u.context.fd->inode->lock); -  unwind:          STACK_UNWIND_STRICT (truncate, frame, op_ret, op_errno, prebuf, postbuf, @@ -1243,6 +1315,8 @@ br_stub_truncate_resume (call_frame_t *frame, xlator_t *this, loc_t *loc,   * on an anonymous fd. The fd will be valid till the completion of the   * truncate call. It guarantees that release on this anonymous fd will happen   * after the truncate call and notification is sent after the truncate call. + * + * c.f. br_writev_cbk() for explanation   */  int32_t  br_stub_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, @@ -1253,10 +1327,11 @@ br_stub_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc,          int32_t              op_ret      = -1;          int32_t              op_errno    = EINVAL;          gf_boolean_t         inc_version = _gf_false; +        gf_boolean_t         modified    = _gf_false;          br_stub_inode_ctx_t *ctx         = NULL; -        uint64_t             ctx_addr    = 0;          int32_t              ret         = -1;          fd_t                *fd          = NULL; +        fop_truncate_cbk_t   cbk         = default_truncate_cbk;          GF_VALIDATE_OR_GOTO ("bit-rot-stub", this, unwind);          GF_VALIDATE_OR_GOTO (this->name, frame, unwind); @@ -1270,63 +1345,50 @@ br_stub_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc,                  goto unwind;          } -        local = br_stub_alloc_local (this); -        if (!local) { -                gf_log (this->name, GF_LOG_ERROR, "local allocation failed " -                        "(gfid: %s)", uuid_utoa (loc->inode->gfid)); -                op_ret = -1; -                op_errno = ENOMEM; +        ret = br_stub_need_versioning (this, fd, &inc_version, &modified, &ctx); +        if (ret)                  goto unwind; -        } - -        local->u.context.fd = fd; -        frame->local = local; -        ret = br_stub_get_inode_ctx (this, loc->inode, &ctx_addr); -        if (ret < 0) { -                gf_log (this->name, GF_LOG_ERROR, "failed to get the inode " -                        "context for the inode %s", -                        uuid_utoa (fd->inode->gfid)); -                goto unwind; -        } +        if (!inc_version && modified) +                goto wind; -        ctx = (br_stub_inode_ctx_t *) (long) ctx_addr; -        ret = br_stub_anon_fd_ctx (this, local->u.context.fd, ctx); +        ret = br_stub_versioning_prep (frame, this, fd, ctx);          if (ret)                  goto unwind; -        /** -         * c.f. br_stub_writev() -         */ -        inc_version = br_stub_inc_version (this, fd, ctx); -        if (!inc_version) +        local = frame->local; +        if (!inc_version) { +                br_stub_fill_local (local, NULL, fd, fd->inode, +                                    fd->inode->gfid, BR_STUB_NO_VERSIONING, 0); +                cbk = br_stub_truncate_cbk;                  goto wind; +        } -        /* Create the stub for the truncate fop */          stub = fop_truncate_stub (frame, br_stub_truncate_resume, loc, offset,                                    xdata);          if (!stub) {                  gf_log (this->name, GF_LOG_ERROR, "failed to allocate stub for "                          "truncate fop (gfid: %s), unwinding",                          uuid_utoa (fd->inode->gfid)); -                goto unwind; +                goto cleanup_local;          } -        /* Perform Versioning */ -        return br_stub_perform_incversioning (this, frame, stub, -                                              local->u.context.fd, ctx); +        return br_stub_perform_incversioning (this, frame, stub, fd, ctx); -wind: -        STACK_WIND (frame, br_stub_truncate_cbk, FIRST_CHILD(this), + wind: +        STACK_WIND (frame, cbk, FIRST_CHILD(this),                      FIRST_CHILD(this)->fops->truncate, loc, offset, xdata);          return 0; -unwind: + cleanup_local: +        br_stub_cleanup_local (local); +        br_stub_dealloc_local (local); + + unwind:          frame->local = NULL;          STACK_UNWIND_STRICT (truncate, frame, op_ret, op_errno, NULL, NULL,                               NULL); -        br_stub_cleanup_local (local); -        br_stub_dealloc_local (local); +          return 0;  } @@ -1810,7 +1872,7 @@ __br_stub_inode_sign_state (br_stub_inode_ctx_t *ctx,          switch (fop) { -        case GF_FOP_WRITE: +        case GF_FOP_FSETXATTR:                  sign_info = ctx->info_sign = BR_SIGN_QUICK;                  break; diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub.h b/xlators/features/bit-rot/src/stub/bit-rot-stub.h index 69e212bb81f..e1e7b383f42 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub.h +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub.h @@ -66,7 +66,8 @@ typedef struct br_stub_local {          } u;  } br_stub_local_t; -#define BR_STUB_INCREMENTAL_VERSIONING (1<<1) +#define BR_STUB_NO_VERSIONING (1 << 0) +#define BR_STUB_INCREMENTAL_VERSIONING (1 << 1)  typedef struct br_stub_private {          gf_boolean_t go;  | 
