int ghostfs_sync(struct ghostfs *gfs) { struct cluster *c; int ret, i; ret = cluster_get(gfs, 0, &c); if (ret < 0) return ret; ret = write_header(gfs, c); if (ret < 0) return ret; if (!gfs->clusters) // nothing more to sync return 0; for (i = 1; i < gfs->hdr.cluster_count; i++) { c = gfs->clusters[i]; if (!c || !cluster_dirty(c)) continue; ret = write_cluster(gfs, c, i); if (ret < 0) return ret; } return 0; }
static int cluster_get_next(struct ghostfs *gfs, struct cluster **pcluster) { if ((*pcluster)->hdr.next == 0) { warnx("fs: cluster missing, bad filesystem"); return -EIO; } return cluster_get(gfs, (*pcluster)->hdr.next, pcluster); }
int check_vcenter_hv_discovery(AGENT_REQUEST *request, const char *username, const char *password, AGENT_RESULT *result) { struct zbx_json json_data; int i, ret = SYSINFO_RET_FAIL; char *url, *name; zbx_vmware_service_t *service; if (1 != request->nparam) return SYSINFO_RET_FAIL; url = get_rparam(request, 0); zbx_vmware_lock(); if (NULL == (service = get_vmware_service(url, username, password, result, &ret))) goto unlock; zbx_json_init(&json_data, ZBX_JSON_STAT_BUF_LEN); zbx_json_addarray(&json_data, ZBX_PROTO_TAG_DATA); for (i = 0; i < service->data->hvs.values_num; i++) { zbx_vmware_cluster_t *cluster = NULL; zbx_vmware_hv_t *hv = (zbx_vmware_hv_t *)service->data->hvs.values[i]; if (NULL == (name = zbx_xml_read_value(hv->details, ZBX_XPATH_LN2("config", "name")))) continue; if (NULL != hv->clusterid) cluster = cluster_get(&service->data->clusters, hv->clusterid); zbx_json_addobject(&json_data, NULL); zbx_json_addstring(&json_data, "{#HV.UUID}", hv->uuid, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json_data, "{#HV.ID}", hv->id, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json_data, "{#HV.NAME}", name, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json_data, "{#CLUSTER.NAME}", (NULL != cluster ? cluster->name : ""), ZBX_JSON_TYPE_STRING); zbx_json_close(&json_data); zbx_free(name); } zbx_json_close(&json_data); SET_STR_RESULT(result, zbx_strdup(NULL, json_data.buffer)); zbx_json_free(&json_data); ret = SYSINFO_RET_OK; unlock: zbx_vmware_unlock(); return ret; }
static int dir_iter_init(struct ghostfs *gfs, struct dir_iter *it, int cluster_nr) { int ret; ret = cluster_get(gfs, cluster_nr, &it->cluster); if (ret < 0) return ret; it->gfs = gfs; it->entry = (struct dir_entry *)it->cluster->data; it->entry_nr = 0; return 0; }
int ghostfs_mount(struct ghostfs **pgfs, struct stegger *stegger) { struct ghostfs *gfs; int i, ret; gfs = calloc(1, sizeof(*gfs)); if (!gfs) return -ENOMEM; gfs->stegger = stegger; gfs->root_entry.size = 0x80000000; ret = ghostfs_check(gfs); if (ret < 0) { ghostfs_free(gfs); return ret; } gfs->clusters = calloc(1, sizeof(struct cluster *) * gfs->hdr.cluster_count); if (!gfs->clusters) { ghostfs_free(gfs); return -ENOMEM; } gfs->uid = getuid(); gfs->gid = getgid(); time(&gfs->mount_time); // check free clusters for (i = 1; i < gfs->hdr.cluster_count; i++) { struct cluster *c; ret = cluster_get(gfs, i, &c); if (ret < 0) { ghostfs_free(gfs); return ret; } if (!c->hdr.used) gfs->free_clusters++; } *pgfs = gfs; return 0; }
int check_vcenter_vm_cluster_name(AGENT_REQUEST *request, const char *username, const char *password, AGENT_RESULT *result) { int i, ret = SYSINFO_RET_FAIL; char *url, *uuid; zbx_vmware_service_t *service; zbx_vmware_cluster_t *cluster = NULL; if (2 != request->nparam) return SYSINFO_RET_FAIL; url = get_rparam(request, 0); uuid = get_rparam(request, 1); if ('\0' == *uuid) return SYSINFO_RET_FAIL; zbx_vmware_lock(); if (NULL == (service = get_vmware_service(url, username, password, result, &ret))) goto unlock; for (i = 0; i < service->data->hvs.values_num; i++) { zbx_vmware_hv_t *hv = service->data->hvs.values[i]; zbx_vmware_vm_t *vm; if (NULL != (vm = vm_get(&hv->vms, uuid))) { if (NULL != hv->clusterid) cluster = cluster_get(&service->data->clusters, hv->clusterid); break; } } SET_STR_RESULT(result, zbx_strdup(NULL, NULL != cluster ? cluster->name : "")); ret = SYSINFO_RET_OK; unlock: zbx_vmware_unlock(); return ret; }
// cluster_at returns the cluster at the given index starting from cluster nr static int cluster_at(struct ghostfs *gfs, int nr, int index, struct cluster **pcluster) { struct cluster *c = NULL; int ret, i; for (i = 0; i <= index; i++) { if (!nr) { warnx("fs: cluster missing, bad filesystem"); return -EIO; } ret = cluster_get(gfs, nr, &c); if (ret < 0) return ret; nr = c->hdr.next; } *pcluster = c; return 0; }
static int free_clusters(struct ghostfs *gfs, struct cluster *c) { int ret; for (;;) { c->hdr.used = 0; cluster_set_dirty(c, true); gfs->free_clusters++; if (!c->hdr.next) break; ret = cluster_get(gfs, c->hdr.next, &c); if (ret < 0) { errno = -ret; warn("failed to free cluster"); return ret; } } return 0; }
int check_vcenter_hv_cluster_name(AGENT_REQUEST *request, const char *username, const char *password, AGENT_RESULT *result) { char *url, *uuid; zbx_vmware_hv_t *hv; zbx_vmware_service_t *service; int ret = SYSINFO_RET_FAIL; zbx_vmware_cluster_t *cluster = NULL; if (2 != request->nparam) return SYSINFO_RET_FAIL; url = get_rparam(request, 0); uuid = get_rparam(request, 1); if ('\0' == *uuid) return SYSINFO_RET_FAIL; zbx_vmware_lock(); if (NULL == (service = get_vmware_service(url, username, password, result, &ret))) goto unlock; if (NULL == (hv = hv_get(&service->data->hvs, uuid))) goto unlock; if (NULL != hv->clusterid) cluster = cluster_get(&service->data->clusters, hv->clusterid); SET_STR_RESULT(result, zbx_strdup(NULL, NULL != cluster ? cluster->name : "")); ret = SYSINFO_RET_OK; unlock: zbx_vmware_unlock(); return ret; }
static int do_truncate(struct ghostfs *gfs, struct dir_iter *it, off_t new_size) { int ret; int count; int next; struct cluster *c = NULL; if (new_size < 0) return -EINVAL; if (new_size > FILESIZE_MAX) return -EFBIG; if (dir_entry_is_directory(it->entry)) return -EISDIR; next = it->entry->cluster; count = size_to_clusters(min(it->entry->size, new_size)); if (count) { ret = cluster_at(gfs, next, count - 1, &c); if (ret < 0) return ret; next = c->hdr.next; } if (new_size > it->entry->size) { int alloc; long used = it->entry->size % CLUSTER_DATA; // zero remaining cluster space if (used) { memset(c->data + used, 0, CLUSTER_DATA - used); cluster_set_dirty(c, true); } alloc = size_to_clusters(new_size) - count; if (alloc) { ret = alloc_clusters(gfs, alloc, NULL, true); if (ret < 0) return ret; if (c) { c->hdr.next = ret; cluster_set_dirty(c, true); } else { it->entry->cluster = ret; } } } else if (new_size < it->entry->size) { if (next) { if (c) { c->hdr.next = 0; cluster_set_dirty(c, true); } ret = cluster_get(gfs, next, &c); if (ret < 0) return ret; free_clusters(gfs, c); } } dir_entry_set_size(it->entry, new_size, false); cluster_set_dirty(it->cluster, true); return 0; }
// allocates a list of clusters static int alloc_clusters(struct ghostfs *gfs, int count, struct cluster **pfirst, bool zero) { struct cluster *prev = NULL; struct cluster *c; int first = 0; int pos = 1; int alloc = 0; int ret; while (alloc < count) { for (;;) { if (pos >= gfs->hdr.cluster_count) { ret = -ENOSPC; goto undo; } ret = cluster_get(gfs, pos, &c); if (ret < 0) goto undo; if (!c->hdr.used) { if (zero) memset(c->data, 0, sizeof(c->data)); c->hdr.used = 1; cluster_set_dirty(c, true); gfs->free_clusters--; if (!first) { first = pos; if (pfirst) *pfirst = c; } else { prev->hdr.next = pos; } prev = c; pos++; break; } pos++; } alloc++; } prev->hdr.next = 0; return first; undo: pos = first; while (alloc > 0) { int r = cluster_get(gfs, pos, &c); if (r < 0) return r; c->hdr.used = 0; cluster_set_dirty(c, true); gfs->free_clusters++; pos = c->hdr.next; alloc--; } return ret; }