summaryrefslogtreecommitdiffstats
path: root/xlators/features
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/features')
-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;
}