diff options
Diffstat (limited to 'xlators/storage/posix/src')
| -rw-r--r-- | xlators/storage/posix/src/posix-messages.h | 10 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.c | 116 | 
2 files changed, 113 insertions, 13 deletions
diff --git a/xlators/storage/posix/src/posix-messages.h b/xlators/storage/posix/src/posix-messages.h index 0c0eb059270..b5472aded91 100644 --- a/xlators/storage/posix/src/posix-messages.h +++ b/xlators/storage/posix/src/posix-messages.h @@ -918,6 +918,16 @@   */  #define P_MSG_INODE_RESOLVE_FAILED              (POSIX_COMP_BASE + 108) + +/*! + * @messageid + * @diagnosis + * @recommendedaction + * + */ + +#define P_MSG_PREOP_CHECK_FAILED              (POSIX_COMP_BASE + 109) +  /*!   * @messageid   * @diagnosis diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 3a2fc13d2b1..4f286fda333 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -1393,18 +1393,22 @@ int  posix_mkdir (call_frame_t *frame, xlator_t *this,               loc_t *loc, mode_t mode, mode_t umask, dict_t *xdata)  { -        int32_t               op_ret        = -1; -        int32_t               op_errno      = 0; -        char                 *real_path     = NULL, *gfid_path = NULL; -        char                 *par_path      = NULL; -        struct iatt           stbuf         = {0, }; -        struct posix_private *priv          = NULL; -        gid_t                 gid           = 0; -        struct iatt           preparent     = {0,}; -        struct iatt           postparent    = {0,}; -        gf_boolean_t          entry_created = _gf_false, gfid_set = _gf_false; -        void                 *uuid_req      = NULL; -        ssize_t               size          = 0; +        int32_t               op_ret          = -1; +        int32_t               op_errno        = 0; +        char                 *real_path       = NULL, *gfid_path = NULL; +        char                 *par_path        = NULL, *xattr_name = NULL; +        struct iatt           stbuf           = {0, }; +        struct posix_private *priv            = NULL; +        gid_t                 gid             = 0; +        struct iatt           preparent       = {0,}; +        struct iatt           postparent      = {0,}; +        gf_boolean_t          entry_created   = _gf_false, gfid_set = _gf_false; +        void                 *uuid_req        = NULL; +        ssize_t               size            = 0; +        dict_t               *xdata_rsp       = NULL; +        void                 *disk_xattr      = NULL, *arg_xattr = NULL; +        data_t               *arg_data        = NULL; +        char          pgfid[GF_UUID_BUF_SIZE] = {0};          DECLARE_OLD_FS_ID_VAR; @@ -1434,6 +1438,11 @@ posix_mkdir (call_frame_t *frame, xlator_t *this,                  goto out;          } +        if (loc->parent) +                gf_uuid_unparse (loc->parent->gfid, pgfid); +        else +                gf_uuid_unparse (loc->pargfid, pgfid); +          gid = frame->root->gid;          op_ret = posix_pstat (this, NULL, real_path, &stbuf); @@ -1477,6 +1486,84 @@ posix_mkdir (call_frame_t *frame, xlator_t *this,                  mode |= S_ISGID;          } +        op_ret = dict_get_str (xdata, GF_PREOP_PARENT_KEY, &xattr_name); +        if (xattr_name != NULL) { +                arg_data = dict_get (xdata, xattr_name); +                if (arg_data) { +                        size = sys_lgetxattr (par_path, xattr_name, NULL, 0); +                        if (size < 0) { +                                op_ret = -1; +                                op_errno = errno; +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_PREOP_CHECK_FAILED, +                                        "mkdir (%s/%s): getxattr on key (%s)" +                                        " path (%s) failed ", pgfid, +                                        loc->name, xattr_name, +                                        par_path); +                                goto out; +                        } + +                        disk_xattr = alloca (size); +                        if (disk_xattr == NULL) { +                                op_ret = -1; +                                op_errno = errno; +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_PREOP_CHECK_FAILED, +                                        "mkdir (%s/%s): alloca failed during" +                                        " preop of mkdir (%s)", pgfid, +                                        loc->name, real_path); +                                goto out; +                        } + +                        size = sys_lgetxattr (par_path, xattr_name, +                                              disk_xattr, size); +                        if (size < 0) { +                                op_errno = errno; +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_PREOP_CHECK_FAILED, +                                        "mkdir (%s/%s): getxattr on key (%s)" +                                        " path (%s) failed (%s)", pgfid, +                                        loc->name, xattr_name, +                                        par_path, strerror (errno)); +                                goto out; +                        } + +                        if ((arg_data->len != size) +                            || (memcmp (arg_data->data, disk_xattr, size))) { +                                int ret = 0; +                                gf_msg (this->name, GF_LOG_INFO, EIO, +                                        P_MSG_PREOP_CHECK_FAILED, +                                        "mkdir (%s/%s): failing preop of " +                                        "mkdir (%s) as on-disk" +                                        " xattr value differs from argument " +                                        "value for key %s", pgfid, loc->name, +                                        real_path, xattr_name); +                                op_ret = -1; +                                op_errno = EIO; + +                                xdata_rsp = dict_new (); +                                if (xdata_rsp == NULL) { +                                        gf_msg (this->name, GF_LOG_ERROR, +                                                ENOMEM, +                                                P_MSG_PREOP_CHECK_FAILED, +                                                "mkdir (%s/%s):  " +                                                "dict allocation failed", pgfid, +                                                loc->name); +                                        op_errno = ENOMEM; +                                        goto out; +                                } + +                                ret = dict_set_int8 (xdata_rsp, +                                                     GF_PREOP_CHECK_FAILED, 1); +                                goto out; +                        } + +                        dict_del (xdata, xattr_name); +                } + +                dict_del (xdata, GF_PREOP_PARENT_KEY); +        } +          op_ret = sys_mkdir (real_path, mode);          if (op_ret == -1) {                  op_errno = errno; @@ -1540,7 +1627,7 @@ out:          STACK_UNWIND_STRICT (mkdir, frame, op_ret, op_errno,                               (loc)?loc->inode:NULL, &stbuf, &preparent, -                             &postparent, NULL); +                             &postparent, xdata_rsp);          if (op_ret < 0) {                  if (entry_created) @@ -1550,6 +1637,9 @@ out:                          posix_gfid_unset (this, xdata);          } +        if (xdata_rsp) +                dict_unref (xdata_rsp); +          return 0;  }  | 
