summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiffin Tony Thottan <jthottan@redhat.com>2015-03-25 15:04:19 +0530
committerVijay Bellur <vbellur@redhat.com>2015-04-24 11:07:25 -0700
commitb72bc58ecc108a2fddbdb6f606cd86a57ca5a68f (patch)
treefbc1af361c628aa9cead9a2a979fbe2faadcf6d0
parent4973d0ea608147ff186f13ab51090f59986f1c9f (diff)
features/trash : Notify CTR translator if an unlink happens to a file
This implementation is same as the posix_unlink_cbk() where CTR sends a request during a unlink to send the number of links to the inode and posix obliges sending it using the unwind xdata dict. For Trash xlator a unlink is stat + mkdir(if parent is not present) + rename. And hence this is handled in trash_unlink_rename_cbk(). Change-Id: I402e83567b88e3c9fe171379693c82937af567f9 BUG: 1205545 Signed-off-by: Jiffin Tony Thottan <jthottan@redhat.com> Signed-off-by: Joseph Fernandes <josferna@redhat.com> Signed-off-by: Anoop C S <achiraya@redhat.com> Reviewed-on: http://review.gluster.org/9989 Tested-by: NetBSD Build System Tested-by: Joseph Fernandes Reviewed-by: Joseph Fernandes Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Niels de Vos <ndevos@redhat.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-rw-r--r--tests/bugs/tier/bug-1205545-CTR-and-trash-integration.t71
-rw-r--r--xlators/features/changetimerecorder/src/changetimerecorder.c22
-rw-r--r--xlators/features/trash/src/trash.c66
-rw-r--r--xlators/features/trash/src/trash.h1
-rw-r--r--xlators/storage/posix/src/posix-helpers.c3
-rw-r--r--xlators/storage/posix/src/posix.c12
6 files changed, 159 insertions, 16 deletions
diff --git a/tests/bugs/tier/bug-1205545-CTR-and-trash-integration.t b/tests/bugs/tier/bug-1205545-CTR-and-trash-integration.t
new file mode 100644
index 00000000000..979c3e8c83a
--- /dev/null
+++ b/tests/bugs/tier/bug-1205545-CTR-and-trash-integration.t
@@ -0,0 +1,71 @@
+#!/bin/bash
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+
+LAST_BRICK=3
+CACHE_BRICK_FIRST=4
+CACHE_BRICK_LAST=5
+
+cleanup
+
+# Start glusterd [1-2]
+TEST glusterd
+TEST pidof glusterd
+
+# Set-up tier cluster [3-4]
+TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0..$LAST_BRICK}
+TEST $CLI volume attach-tier $V0 replica 2 $H0:$B0/${V0}$CACHE_BRICK_FIRST $H0:$B0/${V0}$CACHE_BRICK_LAST
+
+# Start and mount the volume after enabling CTR and trash [5-8]
+TEST $CLI volume set $V0 features.ctr-enabled on
+TEST $CLI volume set $V0 features.trash on
+TEST $CLI volume start $V0
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0;
+
+# Create an empty file
+touch $M0/foo
+
+# gf_file_tb and gf_flink_tb should contain one entry each [9]
+ENTRY_COUNT=$(echo "select * from gf_file_tb; select * from gf_flink_tb;" | \
+ sqlite3 $B0/${V0}5/.glusterfs/${V0}5.db | wc -l )
+TEST [ $ENTRY_COUNT -eq 2 ]
+
+# Create two hard links
+ln $M0/foo $M0/lnk1
+ln $M0/foo $M0/lnk2
+
+# Now gf_flink_tb should contain 3 entries [10]
+ENTRY_COUNT=$(echo "select * from gf_flink_tb;" | \
+ sqlite3 $B0/${V0}5/.glusterfs/${V0}5.db | wc -l )
+TEST [ $ENTRY_COUNT -eq 3 ]
+
+# Delete the hard link
+rm -rf $M0/lnk1
+
+# Corresponding hard link entry must be removed from gf_flink_tb
+# but gf_file_tb should still contain the file entry [11]
+ENTRY_COUNT=$(echo "select * from gf_file_tb; select * from gf_flink_tb;" | \
+ sqlite3 $B0/${V0}5/.glusterfs/${V0}5.db | wc -l )
+TEST [ $ENTRY_COUNT -eq 3 ]
+
+# Remove the file
+rm -rf $M0/foo
+
+# Another hardlink removed [12]
+ENTRY_COUNT=$(echo "select * from gf_file_tb; select * from gf_flink_tb;" | \
+ sqlite3 $B0/${V0}5/.glusterfs/${V0}5.db | wc -l )
+TEST [ $ENTRY_COUNT -eq 2 ]
+
+# Remove the last hardlink
+rm -rf $M0/lnk2
+
+# All entried must be removed from gf_flink_tb and gf_file_tb [13]
+ENTRY_COUNT=$(echo "select * from gf_file_tb; select * from gf_flink_tb;" | \
+ sqlite3 $B0/${V0}5/.glusterfs/${V0}5.db | wc -l )
+TEST [ $ENTRY_COUNT -eq 0 ]
+
+cleanup
+
+
+
diff --git a/xlators/features/changetimerecorder/src/changetimerecorder.c b/xlators/features/changetimerecorder/src/changetimerecorder.c
index 80deefbd4b2..42470a92ef9 100644
--- a/xlators/features/changetimerecorder/src/changetimerecorder.c
+++ b/xlators/features/changetimerecorder/src/changetimerecorder.c
@@ -451,11 +451,6 @@ ctr_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
remaining_links = -1;
}
- /*As the xdata is no more required by CTR Xlator.*/
- if (xdata) {
- dict_unref (xdata);
- }
-
/*This is not the only link*/
if (remaining_links != 1) {
@@ -476,8 +471,6 @@ ctr_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
}
}
-
-
out:
STACK_UNWIND_STRICT (unlink, frame, op_ret, op_errno, preparent,
postparent, NULL);
@@ -494,6 +487,7 @@ ctr_unlink (call_frame_t *frame, xlator_t *this,
gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx;
gf_ctr_link_context_t ctr_link_cx;
gf_ctr_link_context_t *_link_cx = &ctr_link_cx;
+ gf_boolean_t is_xdata_created = _gf_false;
GF_ASSERT (frame);
@@ -517,8 +511,6 @@ ctr_unlink (call_frame_t *frame, xlator_t *this,
"Failed inserting unlink wind");
}
-
-
/*
*
* Sending CTR_REQUEST_LINK_COUNT_XDATA
@@ -526,8 +518,10 @@ ctr_unlink (call_frame_t *frame, xlator_t *this,
*
* */
/*create xdata if NULL*/
- if (!xdata)
+ if (!xdata) {
xdata = dict_new();
+ is_xdata_created = (xdata) ? _gf_true : _gf_false;
+ }
if (!xdata) {
gf_log (this->name, GF_LOG_ERROR,
"xdata is NULL :"
@@ -540,18 +534,20 @@ ctr_unlink (call_frame_t *frame, xlator_t *this,
if (ret) {
gf_log (this->name, GF_LOG_ERROR,
"Failed setting CTR_REQUEST_LINK_COUNT_XDATA");
- if (xdata) {
+ if (is_xdata_created) {
dict_unref (xdata);
}
goto out;
}
-
-
out:
STACK_WIND (frame, ctr_unlink_cbk, FIRST_CHILD (this),
FIRST_CHILD (this)->fops->unlink,
loc, xflag, xdata);
+
+ if (is_xdata_created)
+ dict_unref (xdata);
+
return 0;
}
diff --git a/xlators/features/trash/src/trash.c b/xlators/features/trash/src/trash.c
index 5cc051004b4..b2dd94ab161 100644
--- a/xlators/features/trash/src/trash.c
+++ b/xlators/features/trash/src/trash.c
@@ -750,6 +750,7 @@ trash_unlink_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
char *dir_name = NULL;
char *tmp_cookie = NULL;
loc_t tmp_loc = {0,};
+ dict_t *new_xdata = NULL;
char *tmp_stat = NULL;
char real_path[PATH_MAX] = {0,};
int ret = 0;
@@ -829,14 +830,69 @@ trash_unlink_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
goto out;
}
+ /**********************************************************************
+ *
+ * CTR Xlator message handling done here!
+ *
+ **********************************************************************/
+ /**
+ * If unlink is handled by trash translator, it should inform the
+ * CTR Xlator. And trash translator only handles the unlink for
+ * the last hardlink.
+ *
+ * Check if there is a CTR_REQUEST_LINK_COUNT_XDATA from CTR Xlator
+ *
+ */
+
+ if (local->ctr_link_count_req) {
+
+ /* Sending back inode link count to ctr_unlink
+ * (changetimerecoder xlator) via
+ * "CTR_RESPONSE_LINK_COUNT_XDATA" key using xdata.
+ * */
+ if (xdata) {
+ ret = dict_set_uint32 (xdata,
+ CTR_RESPONSE_LINK_COUNT_XDATA,
+ 1);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "Failed to set"
+ " CTR_RESPONSE_LINK_COUNT_XDATA");
+ }
+ } else {
+ new_xdata = dict_new ();
+ if (!new_xdata) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "Memory allocation failure while "
+ "creating new_xdata");
+ goto ctr_out;
+ }
+ ret = dict_set_uint32 (new_xdata,
+ CTR_RESPONSE_LINK_COUNT_XDATA,
+ 1);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "Failed to set"
+ " CTR_RESPONSE_LINK_COUNT_XDATA");
+ }
+ctr_out:
+ TRASH_STACK_UNWIND (unlink, frame, 0, op_errno,
+ &local->preparent,
+ &local->postparent, new_xdata);
+ goto out;
+ }
+ }
/* All other cases, unlink should return success */
TRASH_STACK_UNWIND (unlink, frame, 0, op_errno, &local->preparent,
&local->postparent, xdata);
out:
+
if (tmp_str)
GF_FREE (tmp_str);
if (tmp_cookie)
GF_FREE (tmp_cookie);
+ if (new_xdata)
+ dict_unref (new_xdata);
return ret;
}
@@ -938,6 +994,7 @@ trash_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflags,
trash_private_t *priv = NULL;
trash_local_t *local = NULL;/* files inside trash */
int32_t match = 0;
+ int32_t ctr_link_req = 0;
char *pathbuf = NULL;
int ret = 0;
@@ -1034,6 +1091,15 @@ trash_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflags,
goto out;
}
+ /* To know whether CTR xlator requested for the link count */
+ ret = dict_get_int32 (xdata, CTR_REQUEST_LINK_COUNT_XDATA,
+ &ctr_link_req);
+ if (ret) {
+ local->ctr_link_count_req = _gf_false;
+ ret = 0;
+ } else
+ local->ctr_link_count_req = _gf_true;
+
LOCK_INIT (&frame->lock);
STACK_WIND (frame, trash_unlink_stat_cbk,
diff --git a/xlators/features/trash/src/trash.h b/xlators/features/trash/src/trash.h
index 3e03edf5474..37d8f7b3d85 100644
--- a/xlators/features/trash/src/trash.h
+++ b/xlators/features/trash/src/trash.h
@@ -50,6 +50,7 @@ struct trash_struct {
int32_t loop_count;
struct iatt preparent;
struct iatt postparent;
+ gf_boolean_t ctr_link_count_req;
};
typedef struct trash_struct trash_local_t;
diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c
index f3d6d6c3da7..e1bd5b127fd 100644
--- a/xlators/storage/posix/src/posix-helpers.c
+++ b/xlators/storage/posix/src/posix-helpers.c
@@ -409,6 +409,9 @@ _posix_xattr_get_set (dict_t *xattr_req, char *key, data_t *data,
} else if (fnmatch (marker_contri_key, key, 0) == 0) {
ret = _posix_get_marker_quota_contributions (filler, key);
+ } else if (strcmp(key, CTR_REQUEST_LINK_COUNT_XDATA) == 0) {
+ ret = dict_set (filler->xattr,
+ CTR_REQUEST_LINK_COUNT_XDATA, data);
} else {
ret = _posix_xattr_get_set_from_backend (filler, key);
}
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index 337f9b95fa2..8cbe2c5a02e 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -1652,11 +1652,12 @@ posix_unlink (call_frame_t *frame, xlator_t *this,
if (!unwind_dict) {
op_ret = 0;
gf_log (this->name, GF_LOG_WARNING,
- "Failed to creating unwind_dict");
+ "Memory allocation failure while "
+ "creating unwind_dict");
goto out;
}
- /* Even if unwind_dict fails to set CTR_RESPONSE_LINK_COUNT_XDATA we will
- * not mark the FOP unsuccessful
+ /* Even if unwind_dict fails to set CTR_RESPONSE_LINK_COUNT_XDATA we
+ * will not mark the FOP unsuccessful
* because this dict is only used by CTR Xlator to clear
* all records if link count == 0*/
op_ret = dict_set_uint32 (unwind_dict, CTR_RESPONSE_LINK_COUNT_XDATA,
@@ -1678,6 +1679,11 @@ out:
close (fd);
}
+ /* unref unwind_dict*/
+ if (unwind_dict) {
+ dict_unref (unwind_dict);
+ }
+
return 0;
}