diff options
| -rwxr-xr-x | tests/bugs/quota/bug-1288474.t | 5 | ||||
| -rw-r--r-- | tests/bugs/unclassified/bug-1357397.t | 3 | ||||
| -rw-r--r-- | xlators/features/trash/src/trash.c | 870 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 19 | 
4 files changed, 496 insertions, 401 deletions
diff --git a/tests/bugs/quota/bug-1288474.t b/tests/bugs/quota/bug-1288474.t index bd64df9e45c..ea6bca6cb07 100755 --- a/tests/bugs/quota/bug-1288474.t +++ b/tests/bugs/quota/bug-1288474.t @@ -22,6 +22,9 @@ TEST glusterd  #Create and start a tiered volume  create_dist_tier_vol $NUM_BRICKS +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 +touch $M0/foobar +  TEST $CLI volume quota $V0 enable  TEST $CLI volume quota $V0 limit-usage / 10MB @@ -39,5 +42,7 @@ mkdir $B0/hot  TEST $CLI volume tier $V0 attach $H0:$B0/hot/${V0}{0..$1}  EXPECT_WITHIN $MARKER_UPDATE_TIMEOUT "10.0MB" quota_list_field "/" 5 +TEST umount $M0 +  cleanup; diff --git a/tests/bugs/unclassified/bug-1357397.t b/tests/bugs/unclassified/bug-1357397.t index dc76787b505..129a208e278 100644 --- a/tests/bugs/unclassified/bug-1357397.t +++ b/tests/bugs/unclassified/bug-1357397.t @@ -12,6 +12,9 @@ TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2}  TEST $CLI volume start $V0 +TEST $CLI volume set $V0 features.trash on +TEST $CLI volume set $V0 features.trash-internal-op on +  TEST [ -e $B0/${V0}1/.trashcan ]  TEST [ -e $B0/${V0}1/.trashcan/internal_op ] diff --git a/xlators/features/trash/src/trash.c b/xlators/features/trash/src/trash.c index 02302c2c5d9..3f1b4c5dd1a 100644 --- a/xlators/features/trash/src/trash.c +++ b/xlators/features/trash/src/trash.c @@ -125,30 +125,6 @@ remove_trash_path (const char *path, gf_boolean_t internal, char **rem_path)                  *rem_path =  strchr (*rem_path + 1, '/');  } -/** - * Check whether the path includes trash directory or internal op directory - * inside trash. This check is used to make sure that we avoid deletion, - * rename and creation operations from trash directory. - */ -int -check_whether_trash_directory (const char *path, -                               const char *trash_directory_path) -{ -        char                    tmp_path[PATH_MAX]              = {0,}; -        char                    internal_op_path[PATH_MAX]      = {0,}; -        int                     ret                             = 0; - -        if (path[strlen(path)-1] == '/') -                sprintf (tmp_path, "%s", path); -        else -                sprintf (tmp_path, "%s/", path); - -        copy_trash_path (trash_directory_path, _gf_true, internal_op_path); -        ret = strcmp (tmp_path, trash_directory_path) && -              strcmp (tmp_path, internal_op_path); - -        return ret; -}  /**   * Checks whether the given path reside under the specified eliminate path @@ -236,6 +212,24 @@ append_time_stamp (char *name)          strcat (name, timestr);  } +/* * + * Check whether delete/rename operation is permitted on + * trash directory + */ + +gf_boolean_t +check_whether_op_permitted (trash_private_t *priv, loc_t *loc) +{ +        if ((priv->state && +            (gf_uuid_compare(loc->inode->gfid, trash_gfid) == 0))) +                return _gf_false; +        if (priv->internal && +           (gf_uuid_compare(loc->inode->gfid, internal_op_gfid) == 0)) +                return _gf_false; + +        return _gf_true; +} +  /**   * Wipe the memory used by trash location variable   */ @@ -280,69 +274,355 @@ wipe_eliminate_path (trash_elim_path **trav)  }  /** + * This is the call back of rename fop initated using STACK_WIND in + * reconfigure/notify function which is used to rename trash directory + * in the brick when it is required either in volume start or set. + * This frame  must destroyed from this function itself since it was + * created by trash xlator + */ +int32_t +trash_dir_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                      int32_t op_ret, int32_t op_errno, struct iatt *buf, +                      struct iatt *preoldparent, struct iatt *postoldparent, +                      struct iatt *prenewparent, struct iatt *postnewparent, +                      dict_t *xdata) +{ +        trash_private_t       *priv      = NULL; +        trash_local_t         *local     = NULL; + +        priv = this->private; + +        local = frame->local; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "rename trash directory " +                                "failed: %s", strerror (op_errno)); +                goto out; +        } + +        GF_FREE (priv->oldtrash_dir); + +        priv->oldtrash_dir = gf_strdup(priv->newtrash_dir); +        if (!priv->oldtrash_dir) { +                op_ret = ENOMEM; +                gf_log (this->name, GF_LOG_DEBUG, +                                "out of memory"); +        } + +out: +        frame->local = NULL; +        STACK_DESTROY (frame->root); +        trash_local_wipe (local); +        return op_ret; +} + +int +rename_trash_directory (xlator_t *this) +{ +        trash_private_t       *priv      = NULL; +        int                   ret        = 0; +        loc_t                 loc        = {0, }; +        loc_t                 old_loc    = {0, }; +        call_frame_t          *frame     = NULL; +        trash_local_t         *local     = NULL; + +        priv = this->private; + +        frame = create_frame (this, this->ctx->pool); +        if (frame == NULL) { +                gf_log (this->name, GF_LOG_ERROR, +                                "failed to create frame"); +                ret = ENOMEM; +                goto out; +        } + +        local = mem_get0 (this->local_pool); +        if (!local) { +                gf_log (this->name, GF_LOG_DEBUG, "out of memory"); +                ret = ENOMEM; +                goto out; +        } +        frame->local = local; + +        /* assign new location values to new_loc members */ +        gf_uuid_copy (loc.gfid, trash_gfid); +        gf_uuid_copy (loc.pargfid, root_gfid); +        ret = extract_trash_directory (priv->newtrash_dir, +                                                &loc.name); +        if (ret) { +                gf_log (this->name, GF_LOG_DEBUG, +                                "out of memory"); +                goto out; +        } +        loc.path = gf_strdup (priv->newtrash_dir); +        if (!loc.path) { +                ret = ENOMEM; +                gf_log (this->name, GF_LOG_DEBUG, +                                "out of memory"); +                goto out; +        } + +        /* assign old location values to old_loc members */ +        gf_uuid_copy (old_loc.gfid, trash_gfid); +        gf_uuid_copy (old_loc.pargfid, root_gfid); +        ret = extract_trash_directory (priv->oldtrash_dir, +                                                &old_loc.name); +        if (ret) { +                gf_log (this->name, GF_LOG_DEBUG, +                                "out of memory"); +                goto out; +        } +        old_loc.path = gf_strdup (priv->oldtrash_dir); +        if (!old_loc.path) { +                ret = ENOMEM; +                gf_log (this->name, GF_LOG_DEBUG, +                                "out of memory"); +                goto out; +        } + +        old_loc.inode = inode_ref (priv->trash_inode); +        gf_uuid_copy(old_loc.inode->gfid, old_loc.gfid); + +        loc_copy (&local->loc, &old_loc); +        loc_copy (&local->newloc, &loc); + +        STACK_WIND (frame, trash_dir_rename_cbk, +                    FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->rename, +                    &old_loc, &loc, NULL); +        return 0; + +out: +        frame->local = NULL; +        STACK_DESTROY (frame->root); +        trash_local_wipe (local); + +        return ret; +} + +int32_t +trash_internal_op_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                        int32_t op_ret, int32_t op_errno, inode_t *inode, +                        struct iatt *buf, struct iatt *preparent, +                        struct iatt *postparent, dict_t *xdata) +{ +       trash_local_t          *local   = NULL; +       local = frame->local; + +        if (op_ret != 0 && !(op_errno == EEXIST)) +                gf_log (this->name, GF_LOG_ERROR, "mkdir failed for " +                        "internal op directory : %s", strerror (op_errno)); + +        frame->local = NULL; +        STACK_DESTROY (frame->root); +        trash_local_wipe (local); +        return op_ret; +} + +/** + * This is the call back of mkdir fop initated using STACK_WIND in + * notify/reconfigure function which is used to create trash directory + * in the brick when "trash" is on. The frame of the mkdir must + * destroyed from this function itself since it was created by trash xlator + */ + +int32_t +trash_dir_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                     int32_t op_ret, int32_t op_errno, inode_t *inode, +                     struct iatt *buf, struct iatt *preparent, +                     struct iatt *postparent, dict_t *xdata) +{ +        trash_private_t        *priv    = NULL; +        trash_local_t          *local   = NULL; + +        priv = this->private; + +        local = frame->local; + +        if (op_ret == 0) { +                priv->oldtrash_dir = gf_strdup (priv->newtrash_dir); +                if (!priv->oldtrash_dir) { +                        gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                        op_ret = ENOMEM; +                } +        } else if (op_ret != 0 && errno != EEXIST) +                gf_log (this->name, GF_LOG_ERROR, "mkdir failed for trash" +                                " directory : %s", strerror (op_errno)); + +        frame->local = NULL; +        STACK_DESTROY (frame->root); +        trash_local_wipe (local); +        return op_ret; +} + +/**   * This getxattr calls returns existing trash directory path in   * the dictionary   */  int32_t -trash_notify_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +trash_dir_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                        int32_t op_ret, int32_t op_errno, dict_t *dict,                        dict_t *xdata)  {          data_t                 *data                  = NULL;          trash_private_t        *priv                  = NULL;          int                    ret                    = 0; +        trash_local_t          *local                 = NULL;          priv = this->private;          GF_VALIDATE_OR_GOTO ("trash", priv, out); +        local = frame->local; +          data = dict_get (dict, GET_ANCESTRY_PATH_KEY);          if (!data) { -                gf_log (this->name, GF_LOG_DEBUG, -                                "oldtrash-directory doesnot exists"); -                priv->oldtrash_dir = gf_strdup (priv->newtrash_dir); -                if (!priv->oldtrash_dir) { -                        gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto out; +        } +        priv->oldtrash_dir = GF_CALLOC (1, PATH_MAX, +                                        gf_common_mt_char); +        if (!priv->oldtrash_dir) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                 ret = ENOMEM; +                 goto out; +        } +        /* appending '/' if it is not present */ +        sprintf (priv->oldtrash_dir, "%s%c", data->data, +                 data->data[strlen(data->data) - 1] != '/' ? '/' : '\0' +                 ); +        gf_log (this->name, GF_LOG_DEBUG, "old trash directory path " +                                          "is %s", priv->oldtrash_dir); +        if (strcmp(priv->newtrash_dir, priv->oldtrash_dir) != 0) { + +                /* When user set a new name for trash directory, trash +                * xlator will perform a rename operation on old trash +                * directory to the new one using a STACK_WIND from here. +                * This option can be configured only when volume is in +                * started state +                */ +                ret = rename_trash_directory (this); +        } + +out: +        frame->local = NULL; +        STACK_DESTROY (frame->root); +        trash_local_wipe (local); +        return ret; +} +/** + * This is a nameless look up for internal op directory + * The lookup is based on gfid, because internal op directory + * has fixed gfid. + */ +int32_t +trash_internalop_dir_lookup_cbk (call_frame_t *frame, void *cookie, +                                 xlator_t *this, int32_t op_ret, +                                 int32_t op_errno, inode_t *inode, +                                 struct iatt *buf, dict_t *xdata, +                                 struct iatt *postparent) +{ +        trash_private_t       *priv      = NULL; +        int                   ret        = 0; +        uuid_t                *gfid_ptr  = NULL; +        loc_t                 loc        = {0, }; +        char                  internal_op_path[PATH_MAX]        = {0,}; +        dict_t                *dict      = NULL; +        trash_local_t          *local    = NULL; + +        priv = this->private; +        GF_VALIDATE_OR_GOTO ("trash", priv, out); + +        local = frame->local; +        if (op_ret != 0 && op_errno == ENOENT) { +                loc_wipe (&local->loc); +                gfid_ptr = GF_CALLOC (1, sizeof(uuid_t), +                                   gf_common_mt_uuid_t); +                if (!gfid_ptr) {                          ret = ENOMEM;                          goto out;                  } -        } else { -                priv->oldtrash_dir = GF_CALLOC (1, PATH_MAX, -                                                gf_common_mt_char); -                if (!priv->oldtrash_dir) { -                        gf_log (this->name, GF_LOG_ERROR, "out of memory"); -                         ret = ENOMEM; -                         goto out; + +                gf_uuid_copy (*gfid_ptr, internal_op_gfid); + +                dict = dict_new (); +                if (!dict) { +                        ret = ENOMEM; +                        goto out; +                } +                ret = dict_set_dynptr (dict, "gfid-req", gfid_ptr, +                               sizeof (uuid_t)); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, +                                "setting key gfid-req failed"); +                        goto out;                  } -                /* appending '/' if it is not present */ -                sprintf (priv->oldtrash_dir, "%s%c", data->data, -                         data->data[strlen(data->data) - 1] != '/' ? '/' : '\0' -                         ); -                gf_log (this->name, GF_LOG_DEBUG, "old trash directory path " -                                                  "is %s", priv->oldtrash_dir); +                gf_uuid_copy (loc.gfid, internal_op_gfid); +                gf_uuid_copy (loc.pargfid, trash_gfid); + +                loc.inode = inode_new (priv->trash_itable); + +                /* The mkdir call for creating internal op directory */ +                loc.name = gf_strdup ("internal_op"); +                if (!loc.name) { +                        gf_log (this->name, GF_LOG_DEBUG, +                                 "out of memory"); +                        ret = ENOMEM; +                        goto out; +                } +                sprintf (internal_op_path, "%s%s/", +                         priv->newtrash_dir, loc.name); + +                loc.path = gf_strdup (internal_op_path); +                if (!loc.path) { +                        gf_log (this->name, GF_LOG_DEBUG, +                                 "out of memory"); +                        ret = ENOMEM; +                        goto out; +                } + +                loc_copy (&local->loc, &loc); +                STACK_WIND (frame, trash_internal_op_mkdir_cbk, +                            FIRST_CHILD(this), +                            FIRST_CHILD(this)->fops->mkdir, +                            &loc, 0755, 0022, dict); +                return 0;          }  out: -          return ret; +        if (ret && gfid_ptr) +                GF_FREE (gfid_ptr); +        if (dict) +                dict_unref (dict); +        frame->local = NULL; +        STACK_DESTROY (frame->root); +        trash_local_wipe (local); +        return op_ret;  } +  /**   * This is a nameless look up for old trash directory   * The lookup is based on gfid, because trash directory   * has fixed gfid.   */  int32_t -trash_notify_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, -                         int32_t op_ret, int32_t op_errno, inode_t *inode, -                         struct iatt *buf, dict_t *xdata, -                         struct iatt *postparent) +trash_dir_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                      int32_t op_ret, int32_t op_errno, inode_t *inode, +                      struct iatt *buf, dict_t *xdata, +                      struct iatt *postparent)  {          trash_private_t         *priv                  = NULL;          loc_t                   loc                    = {0,};          int                     ret                    = 0; +        uuid_t                  *gfid_ptr              = NULL; +        dict_t                  *dict                  = NULL; +        trash_local_t           *local                 = NULL;          priv = this->private;          GF_VALIDATE_OR_GOTO ("trash", priv, out); +        local = frame->local; + +        loc_wipe (&local->loc);          if (op_ret == 0) {                  gf_log (this->name, GF_LOG_DEBUG, "inode found with gfid %s", @@ -354,174 +634,167 @@ trash_notify_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  priv->trash_inode = inode_link (inode, NULL, NULL, buf);                  loc.inode = inode_ref (priv->trash_inode); +                loc_copy (&local->loc, &loc);                  /*Used to find path of old trash directory*/ -                STACK_WIND (frame, trash_notify_getxattr_cbk, FIRST_CHILD(this), +                STACK_WIND (frame, trash_dir_getxattr_cbk, FIRST_CHILD(this),                              FIRST_CHILD(this)->fops->getxattr, &loc,                              GET_ANCESTRY_PATH_KEY, xdata); +                return 0;          }          /* If there is no old trash directory we set its value to new one,           * which is the valid condition for trash directory creation           */          else { -                priv->oldtrash_dir = gf_strdup (priv->newtrash_dir); -                if (!priv->oldtrash_dir) { -                        gf_log (this->name, GF_LOG_ERROR, "out of memory"); -                        goto out; -                } -        } - -out: -        loc_wipe (&loc); -        return ret; -} - -int32_t -trash_internal_op_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, -                        int32_t op_ret, int32_t op_errno, inode_t *inode, -                        struct iatt *buf, struct iatt *preparent, -                        struct iatt *postparent, dict_t *xdata) -{ -        if (op_ret != 0 && !(op_errno == EEXIST)) -                gf_log (this->name, GF_LOG_ERROR, "mkdir failed for " -                        "internal op directory : %s", strerror (op_errno)); -        return op_ret; -} - -/** - * This is the call back of mkdir fop initated using STACK_WIND in - * notify function which is used to create trash directory in the brick - * when a volume starts.The frame of the mkdir must destroyed from - * this function itself since it was created by trash xlator - */ -int32_t -trash_notify_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, -                        int32_t op_ret, int32_t op_errno, inode_t *inode, -                        struct iatt *buf, struct iatt *preparent, -                        struct iatt *postparent, dict_t *xdata) -{ -        uuid_t                *gfid_ptr                         = NULL; -        loc_t                 loc                               = {0, }; -        int                   ret                               = 0; -        dict_t                *dict                             = NULL; -        char                  internal_op_path[PATH_MAX]        = {0,}; -        trash_private_t       *priv       = NULL; +                gf_log (this->name, GF_LOG_DEBUG, "Creating trash " +                                   "directory %s ", +                                   priv->newtrash_dir); -        priv = this->private; -        GF_VALIDATE_OR_GOTO ("trash", priv, out); - -        dict = dict_new (); -        if (!dict) { -                ret = -1; -                goto out; -        } -        if ((op_ret == 0) || (op_ret == -1 && op_errno == EEXIST)) {                  gfid_ptr = GF_CALLOC (1, sizeof(uuid_t), -                                           gf_common_mt_uuid_t); +                                          gf_common_mt_uuid_t);                  if (!gfid_ptr) {                          ret = ENOMEM;                          goto out;                  } -                gf_uuid_copy (*gfid_ptr, internal_op_gfid); - -                gf_uuid_copy (loc.gfid, internal_op_gfid); -                gf_uuid_copy (loc.pargfid, trash_gfid); -                loc.name = gf_strdup ("internal_op"); +                gf_uuid_copy (*gfid_ptr, trash_gfid); -                if (!loc.name) { +                gf_uuid_copy (loc.gfid, trash_gfid); +                gf_uuid_copy (loc.pargfid, root_gfid); +                ret = extract_trash_directory (priv->newtrash_dir, +                                               &loc.name); +                if (ret) {                          gf_log (this->name, GF_LOG_DEBUG, -                                         "out of memory"); -                        ret = ENOMEM; +                                        "out of memory");                          goto out;                  } -                sprintf (internal_op_path, "%s%s", -                                priv->newtrash_dir, loc.name); - -                loc.path = gf_strdup (internal_op_path); - +                loc.path = gf_strdup (priv->newtrash_dir);                  if (!loc.path) {                          gf_log (this->name, GF_LOG_DEBUG, -                                         "out of memory"); +                                        "out of memory");                          ret = ENOMEM;                          goto out;                  } -                loc.inode = inode_new (priv->trash_itable); -                loc.inode->ia_type = IA_IFDIR; +                priv->trash_inode = inode_new (priv->trash_itable); +                priv->trash_inode->ia_type = IA_IFDIR; +                loc.inode = inode_ref (priv->trash_inode); +                dict = dict_new (); +                if (!dict) { +                        ret = ENOMEM; +                        goto out; +                }                  /* Fixed gfid is set for trash directory with                   * this function                   */                  ret = dict_set_dynptr (dict, "gfid-req", gfid_ptr, -                                       sizeof (uuid_t)); +                                      sizeof (uuid_t));                  if (ret) {                          gf_log (this->name, GF_LOG_ERROR, -                                 "setting key gfid-req failed"); +                                "setting key gfid-req failed");                          goto out;                  } +                loc_copy (&local->loc, &loc);                  /* The mkdir call for creating trash directory */ -                STACK_WIND (frame, trash_internal_op_mkdir_cbk, +                STACK_WIND (frame, trash_dir_mkdir_cbk,                              FIRST_CHILD(this),                              FIRST_CHILD(this)->fops->mkdir, &loc, 0755,                              0022, dict); -                /* After creating we must call other notify functions */ -                default_notify (this, GF_EVENT_CHILD_UP, NULL); -        } else { -                gf_log (this->name, GF_LOG_ERROR, "mkdir failed for trash" -                                " directory : %s", strerror (op_errno)); +                return 0;          } - -        STACK_DESTROY (frame->root);  out:          if (ret && gfid_ptr)                  GF_FREE (gfid_ptr);          if (dict)                  dict_unref (dict); -        return 0; +        frame->local = NULL; +        STACK_DESTROY (frame->root); +        trash_local_wipe (local); +        return ret;  } -int32_t -trash_notify_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, -                    int32_t op_ret, int32_t op_errno, struct iatt *buf, -                    struct iatt *preoldparent, struct iatt *postoldparent, -                    struct iatt *prenewparent, struct iatt *postnewparent, -                    dict_t *xdata) +int +create_or_rename_trash_directory (xlator_t *this)  { -        if ((op_ret == 0) || (op_ret == -1 && op_errno == EEXIST)) { -                /* After creating we must call other notify functions */ -                default_notify (this, GF_EVENT_CHILD_UP, NULL); -        } else { -                gf_log (this->name, GF_LOG_ERROR, "rename failed: %s", -                        strerror (op_errno)); +        trash_private_t       *priv      = NULL; +        int                   ret        = 0; +        loc_t                 loc        = {0, }; +        call_frame_t          *frame     = NULL; +        trash_local_t         *local     = NULL; + +        priv = this->private; + + +        frame = create_frame (this, this->ctx->pool); +        if (frame == NULL) { +                gf_log (this->name, GF_LOG_ERROR, +                                "failed to create frame"); +                ret = ENOMEM; +                goto out;          } -        STACK_DESTROY (frame->root); -        return op_ret; +        local = mem_get0 (this->local_pool); +        if (!local) { +                gf_log (this->name, GF_LOG_DEBUG, "out of memory"); +                ret = ENOMEM; +                goto out; +        } +        frame->local = local; + +        loc.inode = inode_new (priv->trash_itable); +        gf_uuid_copy (loc.gfid, trash_gfid); +        loc_copy (&local->loc, &loc); +        gf_log (this->name, GF_LOG_DEBUG, "nameless lookup for" +                           "old trash directory"); +        STACK_WIND (frame, trash_dir_lookup_cbk, +                    FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->lookup, +                    &loc, NULL); +out: +        return ret;  } -/** - * This is the call back of rename fop initated using STACK_WIND in - * reconfigure function which is used to rename trash directory in - * the brick when we perform volume set.This frame  must destroyed - * from this function itself since it was created by trash xlator - */ -int32_t -trash_reconf_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, -                         int32_t op_ret, int32_t op_errno, struct iatt *buf, -                         struct iatt *preoldparent, struct iatt *postoldparent, -                         struct iatt *prenewparent, struct iatt *postnewparent, -                         dict_t *xdata) +int +create_internalop_directory (xlator_t *this)  { -        if (op_ret == -1 && op_errno == EEXIST) { +        trash_private_t       *priv      = NULL; +        int                   ret        = 0; +        loc_t                 loc        = {0, }; +        call_frame_t          *frame     = NULL; +        trash_local_t         *local     = NULL; -                gf_log (this->name, GF_LOG_ERROR, "rename failed: %s", -                        strerror (op_errno)); +        priv = this->private; + +        frame = create_frame (this, this->ctx->pool); +        if (frame == NULL) { +                gf_log (this->name, GF_LOG_ERROR, +                                "failed to create frame"); +                ret = ENOMEM; +                goto out;          } -        STACK_DESTROY (frame->root); +        local = mem_get0 (this->local_pool); +        if (!local) { +                gf_log (this->name, GF_LOG_DEBUG, "out of memory"); +                ret = ENOMEM; +                goto out; +        } +        frame->local = local; -        return op_ret; +        gf_uuid_copy (loc.gfid, internal_op_gfid); +        gf_uuid_copy (loc.pargfid, trash_gfid); +        loc.inode = inode_new (priv->trash_itable); +        loc.inode->ia_type = IA_IFDIR; + +        loc_copy (&local->loc, &loc); +        STACK_WIND (frame, trash_internalop_dir_lookup_cbk, +                    FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->lookup, +                    &loc, NULL); +out: + +        return ret;  }  int32_t @@ -1900,7 +2173,7 @@ trash_mkdir (call_frame_t *frame, xlator_t *this,          priv = this->private;          GF_VALIDATE_OR_GOTO ("trash", priv, out); -        if (!check_whether_trash_directory (loc->path, priv->newtrash_dir)) { +        if (!check_whether_op_permitted (priv, loc)) {                  gf_log (this->name, GF_LOG_WARNING,                          "mkdir issued on %s, which is not permitted",                          priv->newtrash_dir); @@ -1913,6 +2186,7 @@ trash_mkdir (call_frame_t *frame, xlator_t *this,                  STACK_WIND (frame, trash_common_mkdir_cbk, FIRST_CHILD(this),                      FIRST_CHILD(this)->fops->mkdir, loc, mode, umask, xdata);          } +  out:          return 0;  } @@ -1932,7 +2206,7 @@ trash_rename (call_frame_t *frame, xlator_t *this,          priv = this->private;          GF_VALIDATE_OR_GOTO ("trash", priv, out); -        if (!check_whether_trash_directory (oldloc->path, priv->newtrash_dir)) { +        if (!check_whether_op_permitted (priv, oldloc)) {                  gf_log (this->name, GF_LOG_WARNING,                          "rename issued on %s, which is not permitted",                          priv->newtrash_dir); @@ -1945,8 +2219,9 @@ trash_rename (call_frame_t *frame, xlator_t *this,                  STACK_WIND (frame, trash_common_rename_cbk, FIRST_CHILD(this),                      FIRST_CHILD(this)->fops->rename, oldloc, newloc, xdata);          } +  out: -        return 0; +       return 0;  }  /** @@ -1964,7 +2239,7 @@ trash_rmdir (call_frame_t *frame, xlator_t *this,          priv = this->private;          GF_VALIDATE_OR_GOTO ("trash", priv, out); -        if (!check_whether_trash_directory (loc->path, priv->newtrash_dir)) { +        if (!check_whether_op_permitted (priv, loc)) {                  gf_log (this->name, GF_LOG_WARNING,                          "rmdir issued on %s, which is not permitted",                          priv->newtrash_dir); @@ -1977,8 +2252,9 @@ trash_rmdir (call_frame_t *frame, xlator_t *this,                  STACK_WIND (frame, trash_common_rmdir_cbk, FIRST_CHILD(this),                      FIRST_CHILD(this)->fops->rmdir, loc, flags, xdata);          } +  out: -        return 0; +       return 0;  }  /** @@ -1989,24 +2265,31 @@ out:  int  reconfigure (xlator_t *this, dict_t *options)  { -        uint64_t              max_fsize           = 0; -        int                   ret                 = 0; -        char                  *tmp                = NULL; -        char                  *tmp_str            = NULL; -        trash_private_t       *priv               = NULL; -        loc_t                 old_loc             = {0, }; -        loc_t                 new_loc             = {0, }; -        call_frame_t          *frame              = NULL; -        char                  trash_dir[PATH_MAX] = {0,}; +        uint64_t              max_fsize                         = 0; +        int                   ret                               = 0; +        char                  *tmp                              = NULL; +        char                  *tmp_str                          = NULL; +        trash_private_t       *priv                             = NULL; +        char                  trash_dir[PATH_MAX]               = {0,};          priv = this->private; +          GF_VALIDATE_OR_GOTO ("trash", priv, out); +        GF_OPTION_RECONF ("trash-internal-op", priv->internal, options, +                                               bool, out); +        GF_OPTION_RECONF ("trash-dir", tmp, options, str, out); +          GF_OPTION_RECONF ("trash", priv->state, options, bool, out); -        GF_OPTION_RECONF ("trash-dir", tmp, options, str, out); -        if (tmp) { -                sprintf(trash_dir, "/%s/", tmp); +        if (priv->state) { +                ret = create_or_rename_trash_directory (this); + +                if (tmp) +                        sprintf(trash_dir, "/%s/", tmp); +                else +                        sprintf(trash_dir, "%s", priv->oldtrash_dir); +                  if (strcmp(priv->newtrash_dir, trash_dir) != 0) {                          /* When user set a new name for trash directory, trash @@ -2035,73 +2318,17 @@ reconfigure (xlator_t *this, dict_t *options)                                  ret = ENOMEM;                                  goto out;                          } -                        frame = create_frame (this, this->ctx->pool); -                        if (frame == NULL) { -                                gf_log (this->name, GF_LOG_ERROR, -                                                "failed to create frame"); -                                ret = ENOMEM; -                                goto out; -                        } - -                        /* assign new location values to new_loc members */ -                        gf_uuid_copy (new_loc.gfid, trash_gfid); -                        gf_uuid_copy (new_loc.pargfid, root_gfid); -                        ret = extract_trash_directory (priv->newtrash_dir, -                                                                &new_loc.name); -                        if (ret) { -                                gf_log (this->name, GF_LOG_DEBUG, -                                                "out of memory"); -                                goto out; -                        } -                        new_loc.path = gf_strdup (priv->newtrash_dir); -                        if (!new_loc.path) { -                                ret = ENOMEM; -                                gf_log (this->name, GF_LOG_DEBUG, -                                                "out of memory"); -                                goto out; -                        } +                        ret = rename_trash_directory (this); -                        /* assign old location values to old_loc members */ -                        gf_uuid_copy (old_loc.gfid, trash_gfid); -                        gf_uuid_copy (old_loc.pargfid, root_gfid); -                        ret = extract_trash_directory (priv->oldtrash_dir, -                                                                &old_loc.name); -                        if (ret) { -                                gf_log (this->name, GF_LOG_DEBUG, -                                                "out of memory"); -                                goto out; -                        } -                        old_loc.path = gf_strdup (priv->oldtrash_dir); -                        if (!old_loc.path) { -                                ret = ENOMEM; -                                gf_log (this->name, GF_LOG_DEBUG, -                                                "out of memory"); -                                goto out; -                        } +                } -                        old_loc.inode = inode_ref (priv->trash_inode); -                        gf_uuid_copy(old_loc.inode->gfid, old_loc.gfid); +                if (priv->internal) { +                        ret = create_internalop_directory (this); -                        STACK_WIND (frame, trash_reconf_rename_cbk, -                                    FIRST_CHILD(this), -                                    FIRST_CHILD(this)->fops->rename, -                                    &old_loc, &new_loc, options); -                        GF_FREE (priv->oldtrash_dir); - -                        priv->oldtrash_dir = gf_strdup(priv->newtrash_dir); -                        if (!priv->oldtrash_dir) { -                                ret = ENOMEM; -                                gf_log (this->name, GF_LOG_DEBUG, -                                                "out of memory"); -                                goto out; -                        }                  }          }          tmp = NULL; -        GF_OPTION_RECONF ("trash-internal-op", priv->internal, options, -                                               bool, out); -          GF_OPTION_RECONF ("trash-max-filesize", max_fsize, options,                                                  size_uint64, out);          if (max_fsize) { @@ -2128,10 +2355,6 @@ reconfigure (xlator_t *this, dict_t *options)          }  out: -        if (tmp_str) -                GF_FREE (tmp_str); -        loc_wipe (&new_loc); -        loc_wipe (&old_loc);          return ret;  } @@ -2144,32 +2367,19 @@ int  notify (xlator_t *this, int event, void *data, ...)  {          trash_private_t       *priv      = NULL; -        dict_t                *dict      = NULL;          int                   ret        = 0; -        uuid_t                *tgfid_ptr = NULL; -        loc_t                 loc        = {0, }; -        loc_t                 old_loc    = {0, }; -        call_frame_t          *frame     = NULL;          priv = this->private;          GF_VALIDATE_OR_GOTO ("trash", priv, out); -        /* Check whether posix is up not */ +       /* Check whether posix is up not */          if (event == GF_EVENT_CHILD_UP) { -                frame = create_frame(this, this->ctx->pool); -                if (frame == NULL) { -                        gf_log (this->name, GF_LOG_ERROR, -                                        "failed to create frame"); -                        ret = ENOMEM; -                        goto out; -                } -                dict = dict_new (); -                if (!dict) { -                        ret = ENOMEM; +                priv->trash_itable = inode_table_new (0, this); +                if (!priv->state) { +                        gf_log (this->name, GF_LOG_DEBUG, "trash xlator is off");                          goto out;                  } -                priv->trash_itable = inode_table_new (0, this);                  /* Here there is two possiblities ,if trash directory already                   * exist ,then we need to perform a rename operation on the @@ -2178,146 +2388,22 @@ notify (xlator_t *this, int event, void *data, ...)                   * and a frame for calling STACK_WIND.The location variable                   * requires name,path,gfid and inode                   */ -                if (!priv->oldtrash_dir) { -                        loc.inode = inode_new (priv->trash_itable); -                        gf_uuid_copy (loc.gfid, trash_gfid); - -                        gf_log (this->name, GF_LOG_DEBUG, "nameless lookup for" -                                           "old trash directory"); -                        STACK_WIND (frame, trash_notify_lookup_cbk, -                                    FIRST_CHILD(this), -                                    FIRST_CHILD(this)->fops->lookup, -                                    &loc, dict); -                        gf_log (this->name, GF_LOG_DEBUG, "old_trash_dir %s", -                                        priv->oldtrash_dir); -                        loc_wipe (&loc); -                } - -                if (priv->oldtrash_dir == NULL) { -                        ret = EINVAL; +                if (!priv->oldtrash_dir) +                        ret = create_or_rename_trash_directory (this); +                else if (strcmp(priv->newtrash_dir, priv->oldtrash_dir) != 0) +                        ret = rename_trash_directory (this); +                if (ret)                          goto out; -                } -                if (strcmp (priv->oldtrash_dir, priv->newtrash_dir) == 0) { -                        gf_log (this->name, GF_LOG_DEBUG, "Creating trash " -                                           "directory %s from notify", -                                           priv->newtrash_dir); - -                        tgfid_ptr = GF_CALLOC (1, sizeof(uuid_t), -                                                  gf_common_mt_uuid_t); -                        if (!tgfid_ptr) { -                                ret = ENOMEM; -                                goto out; -                        } -                        gf_uuid_copy (*tgfid_ptr, trash_gfid); - -                        gf_uuid_copy (loc.gfid, trash_gfid); -                        gf_uuid_copy (loc.pargfid, root_gfid); -                        ret = extract_trash_directory (priv->newtrash_dir, -                                                                &loc.name); -                        if (ret) { -                                gf_log (this->name, GF_LOG_DEBUG, -                                                "out of memory"); -                                goto out; -                        } -                        loc.path = gf_strdup (priv->newtrash_dir); -                        if (!loc.path) { -                                gf_log (this->name, GF_LOG_DEBUG, -                                                "out of memory"); -                                ret = ENOMEM; -                                goto out; -                        } - -                        priv->trash_inode = inode_new (priv->trash_itable); -                        priv->trash_inode->ia_type = IA_IFDIR; -                        loc.inode = inode_ref (priv->trash_inode); - -                        /* Fixed gfid is set for trash directory with -                         * this function -                         */ -                        ret = dict_set_dynptr (dict, "gfid-req", tgfid_ptr, -                                              sizeof (uuid_t)); -                        if (ret) { -                                gf_log (this->name, GF_LOG_ERROR, -                                        "setting key gfid-req failed"); -                                goto out; -                        } - -                        /* The mkdir call for creating trash directory */ -                        STACK_WIND (frame, trash_notify_mkdir_cbk, -                                    FIRST_CHILD(this), -                                    FIRST_CHILD(this)->fops->mkdir, &loc, 0755, -                                    0022, dict); -                } else { -                        /* assign new location values to new_loc members */ -                        gf_log (this->name, GF_LOG_DEBUG, "Renaming %s -> %s" -                                        " from notify", priv->oldtrash_dir, -                                        priv->newtrash_dir); -                        gf_uuid_copy (loc.gfid, trash_gfid); -                        gf_uuid_copy (loc.pargfid, root_gfid); -                        ret = extract_trash_directory (priv->newtrash_dir, -                                                                &loc.name); -                        if (ret) { -                                gf_log (this->name, GF_LOG_DEBUG, -                                                "out of memory"); -                                goto out; -                        } -                        loc.path = gf_strdup (priv->newtrash_dir); -                        if (!loc.path) { -                                gf_log (this->name, GF_LOG_DEBUG, -                                                "out of memory"); -                                ret = ENOMEM; -                                goto out; -                        } -                        /* assign old location values to old_loc members */ -                        gf_uuid_copy (old_loc.gfid, trash_gfid); -                        gf_uuid_copy (old_loc.pargfid, root_gfid); -                        ret = extract_trash_directory (priv->oldtrash_dir, -                                                                &old_loc.name); -                        if (ret) { -                                gf_log (this->name, GF_LOG_DEBUG, -                                                "out of memory"); -                                goto out; -                        } -                        old_loc.path = gf_strdup (priv->oldtrash_dir); -                        if (!old_loc.path) { -                                gf_log (this->name, GF_LOG_DEBUG, -                                                "out of memory"); -                                ret = ENOMEM; -                                goto out; -                        } -                        old_loc.inode = inode_ref (priv->trash_inode); -                        gf_uuid_copy(old_loc.inode->gfid, old_loc.gfid); +                if (priv->internal) +                        ret = create_internalop_directory (this); -                        STACK_WIND (frame, trash_notify_rename_cbk, -                                    FIRST_CHILD(this), -                                    FIRST_CHILD(this)->fops->rename, -                                    &old_loc, &loc, dict); -                        GF_FREE (priv->oldtrash_dir); - -                        priv->oldtrash_dir = gf_strdup(priv->newtrash_dir); -                        if (!priv->oldtrash_dir) { -                                gf_log (this->name, GF_LOG_DEBUG, -                                                "out of memory"); -                                ret = ENOMEM; -                                goto out; -                        } -                } -        } else { -                ret = default_notify (this, event, data); -                if (ret) -                        gf_log (this->name, GF_LOG_INFO, -                                "default notify event failed");          } -  out: -        if (ret && tgfid_ptr) -                GF_FREE (tgfid_ptr); -        if (dict) -                dict_unref (dict); -        loc_wipe (&loc); -        loc_wipe (&old_loc); - +        ret = default_notify (this, event, data); +        if (ret) +                gf_log (this->name, GF_LOG_INFO, +                        "default notify event failed");          return ret;  } diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 5650bb2e7be..d3e8875306f 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -1234,6 +1234,16 @@ glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr)                  if (glusterd_check_globaloption (key))                          global_opt = _gf_true; +                ret = glusterd_validate_shared_storage (key, value, errstr); +                if (ret) { +                        gf_msg (this->name, GF_LOG_ERROR, 0, +                                GD_MSG_SHARED_STRG_VOL_OPT_VALIDATE_FAIL, +                                "Failed to validate shared " +                                "storage volume options"); +                        goto out; +                } + +                  if (volinfo) {                          ret = glusterd_volinfo_get (volinfo,                                                  VKEY_FEATURES_TRASH, &val_dup); @@ -1245,15 +1255,6 @@ glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr)                          }                  } -                ret = glusterd_validate_shared_storage (key, value, errstr); -                if (ret) { -                        gf_msg (this->name, GF_LOG_ERROR, 0, -                                GD_MSG_SHARED_STRG_VOL_OPT_VALIDATE_FAIL, -                                "Failed to validate shared " -                                "storage volume options"); -                        goto out; -                } -                  if (!strcmp(key, "features.trash-dir") && trash_enabled) {                          if (strchr (value, '/')) {                                  snprintf (errstr, sizeof (errstr),  | 
