summaryrefslogtreecommitdiffstats
path: root/xlators/features/trash/src/trash.c
diff options
context:
space:
mode:
authorJiffin Tony Thottan <jthottan@redhat.com>2015-09-28 17:20:19 +0530
committerJeff Darcy <jdarcy@redhat.com>2017-01-20 04:12:20 -0800
commit07b9853ad0c92b341be33a6cd632013c416221c8 (patch)
treedfeb01dff68e7de49fd082cc99f5a7425f9e0147 /xlators/features/trash/src/trash.c
parent71913a3058cdf2978fc948304a361748dc8fdbc0 (diff)
features/trash: Create trash directory only when it is enabled
Previously trash directory was being created as part of volume start operation. And also the user/admin could not delete this directory from volume even if it is not needed. This patch will fix the same. From now onwards creation and enforcement on trash directory will come into pictrure only when trash translator is enabled. Similarly exact same behaviour is reflected on internal-op directory inside trash directory. Change-Id: I3e58316a7b299a691885e458c960438bec2220fb BUG: 1264849 Signed-off-by: Jiffin Tony Thottan <jthottan@redhat.com> Reviewed-on: http://review.gluster.org/12256 Smoke: Gluster Build System <jenkins@build.gluster.org> Tested-by: Anoop C S <anoopcs@redhat.com> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.org> Reviewed-by: Anoop C S <anoopcs@redhat.com> Reviewed-by: Jeff Darcy <jdarcy@redhat.com>
Diffstat (limited to 'xlators/features/trash/src/trash.c')
-rw-r--r--xlators/features/trash/src/trash.c870
1 files changed, 478 insertions, 392 deletions
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;
}