summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Hernandez <xhernandez@datalab.es>2014-10-28 14:00:29 +0100
committerVijay Bellur <vbellur@redhat.com>2014-11-15 10:01:14 -0800
commitab75b15af49a45f0fc7131766cda628e830bec50 (patch)
tree761680187e9936eb88d2d99b908ff24d33110972
parent7fd6c51d7595e433f25859394d13d161d8884c9e (diff)
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 <xhernandez@datalab.es> Reviewed-on: http://review.gluster.org/8992 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Dan Lambright <dlambrig@redhat.com>
-rwxr-xr-xtests/basic/ec/quota.t58
-rw-r--r--xlators/cluster/ec/src/ec-combine.c53
2 files changed, 111 insertions, 0 deletions
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 <fnmatch.h>
#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);