From ab75b15af49a45f0fc7131766cda628e830bec50 Mon Sep 17 00:00:00 2001 From: Xavier Hernandez Date: Tue, 28 Oct 2014 14:00:29 +0100 Subject: ec: Correctly handle quota xattrs This is a backport of http://review.gluster.org/8990/ Change-Id: I35e11d83c318210d44b918e847cf13db35b01510 BUG: 1158088 Signed-off-by: Xavier Hernandez Reviewed-on: http://review.gluster.org/8992 Tested-by: Gluster Build System Reviewed-by: Dan Lambright --- tests/basic/ec/quota.t | 58 +++++++++++++++++++++++++++++++++++++ xlators/cluster/ec/src/ec-combine.c | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100755 tests/basic/ec/quota.t diff --git a/tests/basic/ec/quota.t b/tests/basic/ec/quota.t new file mode 100755 index 00000000000..ad92d50ad91 --- /dev/null +++ b/tests/basic/ec/quota.t @@ -0,0 +1,58 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +function hard_limit() +{ + local QUOTA_PATH=$1; + $CLI volume quota $V0 list $QUOTA_PATH | grep "$QUOTA_PATH" | awk '{print $2}' +} + +function soft_limit() +{ + local QUOTA_PATH=$1; + $CLI volume quota $V0 list $QUOTA_PATH | grep "$QUOTA_PATH" | awk '{print $3}' +} + +function usage() +{ + local QUOTA_PATH=$1; + $CLI volume quota $V0 list $QUOTA_PATH | grep "$QUOTA_PATH" | awk '{print $4}' +} + +cleanup + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse $H0:$B0/${V0}{0..2} +EXPECT 'Created' volinfo_field $V0 'Status' +TEST $CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'Started' volinfo_field $V0 'Status' +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 --volfile-id=/$V0 --volfile-server=$H0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "$DISPERSE" ec_child_up_count $V0 0 + +TEST mkdir -p $M0/test + +TEST $CLI volume quota $V0 enable + +TEST $CLI volume quota $V0 limit-usage /test 10MB + +EXPECT "10.0MB" hard_limit "/test"; +EXPECT "80%" soft_limit "/test"; + +TEST $CLI volume quota $V0 soft-timeout 0 +TEST $CLI volume quota $V0 hard-timeout 0 + +TEST ! dd if=/dev/urandom of=$M0/test/file1.txt bs=1024k count=12 +TEST rm $M0/test/file1.txt + +EXPECT_WITHIN $MARKER_UPDATE_TIMEOUT "0Bytes" usage "/test" + +TEST dd if=/dev/urandom of=$M0/test/file2.txt bs=1024k count=8 +EXPECT_WITHIN $MARKER_UPDATE_TIMEOUT "8.0MB" usage "/test" + +TEST rm $M0/test/file2.txt +EXPECT_WITHIN $MARKER_UPDATE_TIMEOUT "0Bytes" usage "/test" + +cleanup; diff --git a/xlators/cluster/ec/src/ec-combine.c b/xlators/cluster/ec/src/ec-combine.c index 5468777f432..540e155556c 100644 --- a/xlators/cluster/ec/src/ec-combine.c +++ b/xlators/cluster/ec/src/ec-combine.c @@ -21,12 +21,15 @@ #include #include "libxlator.h" +#include "byte-order.h" #include "ec-data.h" #include "ec-helpers.h" #include "ec-common.h" #include "ec-combine.h" +#define EC_QUOTA_PREFIX "trusted.glusterfs.quota." + struct _ec_dict_info; typedef struct _ec_dict_info ec_dict_info_t; @@ -140,6 +143,7 @@ int32_t ec_dict_data_compare(dict_t * dict, char * key, data_t * value, (strcmp(key, GF_XATTR_LOCKINFO_KEY) == 0) || (strcmp(key, GF_XATTR_CLRLK_CMD) == 0) || (strcmp(key, GLUSTERFS_OPEN_FD_COUNT) == 0) || + (strncmp(key, EC_QUOTA_PREFIX, strlen(EC_QUOTA_PREFIX)) == 0) || (fnmatch(GF_XATTR_STIME_PATTERN, key, 0) == 0) || (fnmatch(MARKER_XATTR_PREFIX ".*." XTIME, key, 0) == 0) || (XATTR_IS_NODE_UUID(key))) @@ -531,6 +535,47 @@ int32_t ec_dict_data_max64(ec_cbk_data_t *cbk, int32_t which, char *key) return 0; } +int32_t ec_dict_data_quota(ec_cbk_data_t *cbk, int32_t which, char *key) +{ + data_t *data[cbk->count]; + dict_t *dict; + ec_t *ec; + int32_t i, num; + uint64_t max, tmp; + + num = cbk->count; + if (!ec_dict_list(data, &num, cbk, which, key)) { + return -1; + } + + if (num == 0) { + return 0; + } + + /* Quota size xattr is managed outside of the control of the ec xlator. + * This means that it might not be updated at the same time on all + * bricks and we can receive slightly different values. If that's the + * case, we take the maximum of all received values. + */ + max = ntoh64(*(uint64_t *)data_to_ptr(data[0])); + for (i = 1; i < num; i++) { + tmp = ntoh64(*(uint64_t *)data_to_ptr(data[i])); + if (max < tmp) { + max = tmp; + } + } + + ec = cbk->fop->xl->private; + max *= ec->fragments; + + dict = (which == EC_COMBINE_XDATA) ? cbk->xdata : cbk->dict; + if (ec_dict_set_number(dict, key, max) != 0) { + return -1; + } + + return 0; +} + int32_t ec_dict_data_stime(ec_cbk_data_t * cbk, int32_t which, char * key) { data_t * data[cbk->count]; @@ -586,6 +631,14 @@ int32_t ec_dict_data_combine(dict_t * dict, char * key, data_t * value, return ec_dict_data_max32(data->cbk, data->which, key); } + if (strcmp(key, QUOTA_SIZE_KEY) == 0) { + return ec_dict_data_quota(data->cbk, data->which, key); + } + /* Ignore all other quota attributes */ + if (strncmp(key, EC_QUOTA_PREFIX, strlen(EC_QUOTA_PREFIX)) == 0) { + return 0; + } + if (XATTR_IS_NODE_UUID(key)) { return ec_dict_data_uuid(data->cbk, data->which, key); -- cgit