All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pete Zaitcev <zaitcev@redhat.com>
To: Jeff Garzik <jeff@garzik.org>
Cc: Project Hail List <hail-devel@vger.kernel.org>
Subject: [Patch 1/1] chunkd: split up fs_list_objs
Date: Sun, 27 Dec 2009 16:58:55 -0700	[thread overview]
Message-ID: <20091227165855.3fce6e15@redhat.com> (raw)

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@redhat.com>

---
 server/be-fs.c  |  361 +++++++++++++++++++++++++++++-----------------
 server/chunkd.h |   16 ++
 2 files changed, 244 insertions(+), 133 deletions(-)

commit cbc71b0262fa3594be940d8a758873f746c410e7
Author: Master <zaitcev@lembas.zaitcev.lan>
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,

             reply	other threads:[~2009-12-27 23:58 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-27 23:58 Pete Zaitcev [this message]
2009-12-28  0:32 ` [Patch 1/1] chunkd: split up fs_list_objs Jeff Garzik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20091227165855.3fce6e15@redhat.com \
    --to=zaitcev@redhat.com \
    --cc=hail-devel@vger.kernel.org \
    --cc=jeff@garzik.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.