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>
This commit is contained in:
parent
4973d0ea60
commit
b72bc58ecc
71
tests/bugs/tier/bug-1205545-CTR-and-trash-integration.t
Normal file
71
tests/bugs/tier/bug-1205545-CTR-and-trash-integration.t
Normal file
@ -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
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user