summaryrefslogtreecommitdiffstats
path: root/xlators/mgmt/glusterd/src/glusterd-quota.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-quota.c')
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-quota.c184
1 files changed, 153 insertions, 31 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-quota.c b/xlators/mgmt/glusterd/src/glusterd-quota.c
index 24bd41ad..e67208cf 100644
--- a/xlators/mgmt/glusterd/src/glusterd-quota.c
+++ b/xlators/mgmt/glusterd/src/glusterd-quota.c
@@ -580,6 +580,8 @@ glusterd_quota_disable (glusterd_volinfo_t *volinfo, char **op_errstr)
if (ret)
goto out;
+ (void) glusterd_clean_up_quota_store (volinfo);
+
ret = 0;
out:
if (ret && op_errstr && !*op_errstr)
@@ -671,6 +673,47 @@ out:
return ret;
}
+#define QUOTA_CONF_HEADER \
+ "GlusterFS Quota conf | version: v%d.%d\n"
+
+static int
+glusterd_store_quota_conf_skip_header (xlator_t *this, int fd)
+{
+ char buf[PATH_MAX] = {0,};
+
+ snprintf (buf, sizeof(buf)-1, QUOTA_CONF_HEADER, 1, 1);
+ return gf_skip_header_section (fd, strlen (buf));
+}
+
+static int
+glusterd_store_quota_conf_stamp_header (xlator_t *this, int fd)
+{
+ char buf[PATH_MAX] = {0,};
+ int buf_len = 0;
+ ssize_t ret = -1;
+ ssize_t written = 0;
+
+ snprintf (buf, sizeof(buf)-1, QUOTA_CONF_HEADER, 1, 1);
+ buf_len = strlen (buf);
+ for (written = 0; written != buf_len; written += ret) {
+ ret = write (fd, buf + written, buf_len - written);
+ if (ret == -1) {
+ goto out;
+ }
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+static int
+glusterd_update_quota_conf_version (glusterd_volinfo_t *volinfo)
+{
+ volinfo->quota_conf_version++;
+ return 0;
+}
+
static int
glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path,
char *gfid_str, int opcode, char **op_errstr)
@@ -679,13 +722,13 @@ glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path,
int count = 0;
xlator_t *this = NULL;
glusterd_conf_t *conf = NULL;
- char buf[256] = {0,};
+ unsigned char buf[16] = {0,};
int fd = -1;
- FILE *conf_filep = NULL;
- FILE *tmp_filep = NULL;
+ int conf_fd = -1;
+ size_t entry_sz = 16;
uuid_t gfid = {0,};
- uuid_t gfid_iter = {0,};
gf_boolean_t found = _gf_false;
+ gf_boolean_t modified = _gf_false;
this = THIS;
@@ -702,23 +745,67 @@ glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path,
ret = -1;
goto out;
}
- tmp_filep = fdopen (fd, "r+");
- conf_filep = fopen (volinfo->quota_conf_shandle->path, "r");
- if (conf_filep == NULL) {
+ conf_fd = open (volinfo->quota_conf_shandle->path, O_RDONLY);
+ if (conf_fd == -1) {
ret = -1;
goto out;
}
- while (fscanf (conf_filep, "%s", buf) != EOF) {
- count++;
- uuid_parse (buf, gfid_iter);
+ ret = glusterd_store_quota_conf_skip_header (this, conf_fd);
+ if (ret) {
+ goto out;
+ }
- if (uuid_compare (gfid, gfid_iter))
- fprintf (tmp_filep, "%s\n", buf);
- else
+ ret = glusterd_store_quota_conf_stamp_header (this, fd);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to add header to tmp "
+ "file.");
+ goto out;
+ }
+ //gfid is stored as 16 bytes of 'raw' data
+ entry_sz = 16;
+ for (;;) {
+ ret = read (conf_fd, (void*)&buf, entry_sz) ;
+ if (ret <= 0) {
+ //Finished reading all entries in the conf file
+ break;
+ }
+ if (ret != 16) {
+ //This should never happen. We must have a multiple of
+ //entry_sz bytes in our configuration file.
+ gf_log (this->name, GF_LOG_CRITICAL, "Quota "
+ "configuration store may be corrupt.");
+ ret = -1;
+ goto out;
+ }
+ count++;
+ if (uuid_compare (gfid, buf)) {
+ /*If the gfids don't match, write @buf into tmp file. */
+ ret = write (fd, (void*) buf, entry_sz);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "write %s into quota configuration.",
+ uuid_utoa (buf));
+ goto out;
+ }
+ } else {
+ /*If a match is found, write @buf into tmp file for
+ * limit-usage only.
+ */
+ if (opcode == GF_QUOTA_OPTION_TYPE_LIMIT_USAGE) {
+ ret = write (fd, (void *) buf, entry_sz);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to write %s into quota "
+ "configuration.",
+ uuid_utoa (buf));
+ goto out;
+ }
+ }
found = _gf_true;
+ }
}
switch (opcode) {
@@ -727,15 +814,24 @@ glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path,
* count = 0 implies that the conf file is empty.
* In this case, we directly go ahead and write gfid_str
* into the tmp file.
- * If count is non-zero and found is false, then we
- * append gfid_str to the end of the file.
- * If count is non-zero and found is true, then again
+ * If count is non-zero and found is false, limit is
+ * being set on a gfid for the first time. So
* append gfid_str to the end of the file.
- *
- * In short, in all of the above cases, append gfid_str
- * to the end of the file.
*/
- fprintf (tmp_filep, "%s\n", gfid_str);
+ if ((count == 0) ||
+ ((count > 0) && (found == _gf_false))) {
+ memcpy (buf, gfid, 16);
+ ret = write (fd, (void *) buf, entry_sz);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to write %s into quota "
+ "configuration.",
+ uuid_utoa (buf));
+ goto out;
+ }
+ modified = _gf_true;
+ }
+
break;
case GF_QUOTA_OPTION_TYPE_REMOVE:
@@ -757,12 +853,15 @@ glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path,
goto out;
} else {
if (!found) {
- gf_asprintf (op_errstr, "Error. gfid %s for "
- "path %s not found in store",
- gfid_str, path);
- ret = -1;
- goto out;
+ gf_asprintf (op_errstr, "Error. gfid %s"
+ " for path %s not found in"
+ " store", gfid_str, path);
+ ret = -1;
+ goto out;
+ } else {
+ modified = _gf_true;
}
+
}
break;
@@ -771,17 +870,40 @@ glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path,
break;
}
+ if (modified)
+ glusterd_update_quota_conf_version (volinfo);
+
ret = 0;
out:
- if (conf_filep)
- fclose (conf_filep);
- if (tmp_filep)
- fclose (tmp_filep);
+ if (conf_fd != -1) {
+ close (conf_fd);
+ }
+
+ if (fd != -1) {
+ close (fd);
+ }
- if (ret && (fd > 0))
+ if (ret && (fd > 0)) {
gf_store_unlink_tmppath (volinfo->quota_conf_shandle);
- else if (!ret)
+ } else if (!ret) {
ret = gf_store_rename_tmppath (volinfo->quota_conf_shandle);
+ if (modified) {
+ ret = glusterd_compute_cksum (volinfo, _gf_true);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "compute cksum for quota conf file");
+ goto out;
+ }
+
+ ret = glusterd_store_save_quota_version_and_cksum
+ (volinfo);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "store quota version and cksum");
+ goto out;
+ }
+ }
+ }
return ret;
}