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), |