This way we create a set of methods that can be used by self-check to list existing objects. Signed-off-by: Pete Zaitcev <zaitcev@xxxxxxxxxx> --- server/be-fs.c | 361 +++++++++++++++++++++++++++++----------------- server/chunkd.h | 16 ++ 2 files changed, 244 insertions(+), 133 deletions(-) commit cbc71b0262fa3594be940d8a758873f746c410e7 Author: Master <zaitcev@xxxxxxxxxxxxxxxxxx> Date: Sun Dec 27 15:35:13 2009 -0700 Add methods with which a self-check can list objects later. diff --git a/server/be-fs.c b/server/be-fs.c index 89635f8..1f8f1a5 100644 --- a/server/be-fs.c +++ b/server/be-fs.c @@ -689,168 +689,263 @@ err_out: return false; } -GList *fs_list_objs(uint32_t table_id, const char *user) +int fs_list_objs_open(struct fs_obj_lister *t, + const char *root_path, uint32_t table_id) { - GList *res = NULL; - struct dirent *de, *root_de; - DIR *d, *root; - char *sub, *table_path = NULL; + int err; - sub = alloca(strlen(chunkd_srv.vol_path) + 1 + 16 + 4 + 1); + if (asprintf(&t->table_path, MDB_TPATH_FMT, root_path, table_id) < 0) + return -ENOMEM; + t->root = opendir(t->table_path); + if (!t->root) { + err = errno; + free(t->table_path); + return -err; + } + return 0; +} - if (asprintf(&table_path, MDB_TPATH_FMT, - chunkd_srv.vol_path, table_id) < 0) - return NULL; +/* + * Get next filename. + * Return: + * -1 - error + * 0 - EOF + * 1 - ok + */ +int fs_list_objs_next(struct fs_obj_lister *t, char **fnp) +{ + struct dirent *de; - root = opendir(table_path); - if (!root) { - syslogerr(table_path); - free(table_path); - return NULL; - } +again: + if (!t->sub) { + if ((de = readdir(t->root)) == NULL) + return 0; - /* iterate through each dir */ - while ((root_de = readdir(root)) != NULL) { + if (de->d_name[0] == '.') + goto again; + if (strlen(de->d_name) != 4) + goto again; - if (root_de->d_name[0] == '.') - continue; - if (strlen(root_de->d_name) != 4) - continue; + if (asprintf(&t->sub, "%s/%s", t->table_path, de->d_name) < 0) + return -1; + } - sprintf(sub, "%s/%s", table_path, root_de->d_name); - d = opendir(sub); - if (!d) { - syslogerr(sub); - break; + if (!t->d) { + t->d = opendir(t->sub); + if (!t->d) { + syslogerr(t->sub); + free(t->sub); + t->sub = NULL; + goto again; } + } - while ((de = readdir(d)) != NULL) { - int fd; - char *fn; - ssize_t rrc; - struct be_fs_obj_hdr hdr; - struct stat st; - struct volume_entry *ve; - void *p; - size_t alloc_len; - void *key_in; - uint32_t key_len_in; - - if (de->d_name[0] == '.') - continue; - - if (asprintf(&fn, "%s/%s", sub, de->d_name) < 0) - break; - - fd = open(fn, O_RDONLY); - if (fd < 0) { - syslogerr(fn); - free(fn); - break; - } + if ((de = readdir(t->d)) == NULL) { + closedir(t->d); + t->d = NULL; + free(t->sub); + t->sub = NULL; + goto again; + } - if (fstat(fd, &st) < 0) { - syslogerr(fn); - close(fd); - free(fn); - break; - } + if (de->d_name[0] == '.') + goto again; - rrc = read(fd, &hdr, sizeof(hdr)); - if (rrc != sizeof(hdr)) { - if (rrc < 0) - syslogerr(fn); - else - applog(LOG_ERR, "%s hdr read failed", fn); - close(fd); - free(fn); - break; - } + if (asprintf(fnp, "%s/%s", t->sub, de->d_name) < 0) + return -1; - key_len_in = GUINT32_FROM_LE(hdr.key_len); - if (key_len_in < 1 || key_len_in > CHD_KEY_SZ) { - applog(LOG_ERR, "%s hdr key len invalid", fn); - close(fd); - free(fn); - break; - } + return 1; +} - key_in = malloc(key_len_in); - if (!key_in) { - close(fd); - free(fn); - break; - } +void fs_list_objs_close(struct fs_obj_lister *t) +{ + closedir(t->root); + free(t->table_path); - rrc = read(fd, key_in, key_len_in); - if (rrc != key_len_in) { - if (rrc < 0) - syslogerr(fn); - else - applog(LOG_ERR, "%s hdr read failed", fn); - close(fd); - free(fn); - free(key_in); - break; - } + if (t->d) + closedir(t->d); + free(t->sub); +} - if (close(fd) < 0) - syslogerr(fn); +GList *fs_list_objs(uint32_t table_id, const char *user) +{ + struct fs_obj_lister lister; + GList *res = NULL; + char *fn; + int rc; + + memset(&lister, 0, sizeof(struct fs_obj_lister)); + rc = fs_list_objs_open(&lister, chunkd_srv.vol_path, table_id); + if (rc) { + applog(LOG_WARNING, "Cannot open table %u: %s", table_id, + strerror(-rc)); + return NULL; + } + while (fs_list_objs_next(&lister, &fn) > 0) { + char *owner; + char *csum; + unsigned long long size; + time_t mtime; + struct volume_entry *ve; + void *p; + size_t alloc_len; + void *key_in; + size_t klen_in; + + rc = fs_obj_hdr_read(fn, &owner, &csum, &key_in, &klen_in, + &size, &mtime); + if (rc < 0) { free(fn); + break; + } + free(fn); + + /* filter out results that do not match + * the authenticated user + */ + if (strcmp(user, owner)) { + free(owner); + free(csum); + free(key_in); + continue; + } - /* filter out results that do not match - * the authenticated user - */ - if (strcmp(user, hdr.owner)) { - free(key_in); - continue; - } + /* one alloc, for fixed + var length struct */ + alloc_len = sizeof(*ve) + strlen(csum) + 1 + strlen(owner) + 1; - /* one alloc, for fixed + var length struct */ - alloc_len = sizeof(*ve) + - strlen(hdr.checksum) + 1 + - strlen(hdr.owner) + 1; + ve = malloc(alloc_len); + if (!ve) { + free(owner); + free(csum); + free(key_in); + applog(LOG_ERR, "OOM"); + break; + } - ve = malloc(alloc_len); - if (!ve) { - free(key_in); - applog(LOG_ERR, "OOM"); - break; - } + /* store fixed-length portion of struct */ + ve->size = size; + ve->mtime = mtime; + ve->key = key_in; + ve->key_len = klen_in; - /* store fixed-length portion of struct */ - st.st_size -= sizeof(struct be_fs_obj_hdr); - st.st_size -= key_len_in; + /* + * store variable-length portion of struct: + * checksum, owner strings + */ - ve->size = st.st_size; - ve->mtime = st.st_mtime; - ve->key = key_in; - ve->key_len = key_len_in; + p = (ve + 1); + ve->hash = p; + strcpy(ve->hash, csum); - /* - * store variable-length portion of struct: - * checksum, owner strings - */ + p += strlen(ve->hash) + 1; + ve->owner = p; + strcpy(ve->owner, owner); - p = (ve + 1); - ve->hash = p; - strcpy(ve->hash, hdr.checksum); + /* add entry to result list */ + res = g_list_append(res, ve); - p += strlen(ve->hash) + 1; - ve->owner = p; - strcpy(ve->owner, hdr.owner); + free(owner); + free(csum); + } - /* add entry to result list */ - res = g_list_append(res, ve); - } + fs_list_objs_close(&lister); + return res; +} + +/* + * Read an object by filename. + * TODO - possibly factor out some code from fs_obj_open and fs_obj_delete. + */ +int fs_obj_hdr_read(const char *fn, char **owner, char **csum, + void **keyp, size_t *klenp, + unsigned long long *size, time_t *mtime) +{ + struct be_fs_obj_hdr hdr; + struct stat st; + int fd; + ssize_t rrc; + void *key_in; + size_t klen_in; + unsigned long long sz; - closedir(d); + fd = open(fn, O_RDONLY); + if (fd < 0) { + syslogerr(fn); + goto err_open; } - closedir(root); + if (fstat(fd, &st) < 0) { + syslogerr(fn); + goto err_stat; + } - free(table_path); - return res; + rrc = read(fd, &hdr, sizeof(hdr)); + if (rrc != sizeof(hdr)) { + if (rrc < 0) + syslogerr(fn); + else + applog(LOG_WARNING, "%s hdr read failed", fn); + goto err_fix; + } + + klen_in = GUINT32_FROM_LE(hdr.key_len); + if (klen_in < 1 || klen_in > CHD_KEY_SZ) { + applog(LOG_WARNING, "%s hdr key len (0x%x) invalid", + fn, (unsigned int)klen_in); + goto err_fix; + } + + key_in = malloc(klen_in); + if (!key_in) { + applog(LOG_WARNING, "NO CORE"); + goto err_fix; + } + + rrc = read(fd, key_in, klen_in); + if (rrc != klen_in) { + if (rrc < 0) + syslogerr(fn); + else + applog(LOG_ERR, "%s hdr short read (%lu)", + fn, (unsigned long)rrc); + goto err_var; + } + + *owner = strndup(hdr.owner, sizeof(hdr.owner)); + if (!*owner) { + applog(LOG_WARNING, "NO CORE"); + goto err_owner; + } + *csum = strndup(hdr.checksum, sizeof(hdr.checksum)); + if (!*csum) { + applog(LOG_WARNING, "NO CORE"); + goto err_csum; + } + + *keyp = key_in; + *klenp = klen_in; + + sz = st.st_size; + if (sz < klen_in + sizeof(struct be_fs_obj_hdr)) + sz = 0; + else + sz = st.st_size - (sizeof(struct be_fs_obj_hdr) + klen_in); + *size = sz; + *mtime = st.st_mtime; + + close(fd); + return 0; + + err_csum: + free(*owner); + err_owner: + err_var: + free(key_in); + err_fix: + err_stat: + close(fd); + err_open: + return -1; } diff --git a/server/chunkd.h b/server/chunkd.h index 57726fd..a97088d 100644 --- a/server/chunkd.h +++ b/server/chunkd.h @@ -217,6 +217,15 @@ struct server { extern struct hail_log cldu_hail_log; /* be-fs.c */ +#include <dirent.h> +struct fs_obj_lister { + DIR *root; + char *table_path; + + DIR *d; + char *sub; +}; + extern int fs_open(void); extern void fs_close(void); extern void fs_free(void); @@ -234,6 +243,13 @@ extern bool fs_obj_delete(uint32_t table_id, const char *user, const void *kbuf, size_t klen, enum chunk_errcode *err_code); extern ssize_t fs_obj_sendfile(struct backend_obj *bo, int out_fd, size_t len); +extern int fs_list_objs_open(struct fs_obj_lister *t, + const char *root_path, uint32_t table_id); +extern int fs_list_objs_next(struct fs_obj_lister *t, char **fnp); +extern void fs_list_objs_close(struct fs_obj_lister *t); +extern int fs_obj_hdr_read(const char *fn, char **owner, char **checksum, + void **keyp, size_t *klenp, + unsigned long long *size, time_t *mtime); extern GList *fs_list_objs(uint32_t table_id, const char *user); extern bool fs_table_open(const char *user, const void *kbuf, size_t klen, bool tbl_creat, bool excl_creat, uint32_t *table_id, -- To unsubscribe from this list: send the line "unsubscribe hail-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html