aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-04-24 21:02:27 -0400
committerJeff Garzik <jeff@garzik.org>2006-04-24 21:02:27 -0400
commita7b45f1a8e9d1376490174ffb5230e30de3d92f2 (patch)
tree19349d6abe7769de11af8fd78b87cf2c94486547
parent77e168ddd08fa4289f133be3c29d9aa817ea67bb (diff)
downloaddbfs-a7b45f1a8e9d1376490174ffb5230e30de3d92f2.tar.gz
dbfs: start to libify dbfs. add mkdbfs program (just base db, for now).
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am9
-rw-r--r--dbfs-backend.c120
-rw-r--r--dbfs.c30
-rw-r--r--dbfs.h16
-rw-r--r--libdbfs.c147
-rw-r--r--mkdbfs.c125
7 files changed, 329 insertions, 119 deletions
diff --git a/.gitignore b/.gitignore
index 567f41c..3a97f51 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,7 @@ stamp-h1
# app-specific
ndbfs
+mkdbfs
dbfs
dbfs-config.h*
diff --git a/Makefile.am b/Makefile.am
index afbdb04..85fa9dc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,13 +4,16 @@
INCLUDES = @GNET_CFLAGS@ @FUSE_CFLAGS@
-sbin_PROGRAMS = ndbfs dbfs
+sbin_PROGRAMS = ndbfs dbfs mkdbfs
ndbfs_SOURCES = ndbfs.c
ndbfs_LDADD = @GNET_LIBS@ @FUSE_LIBS@
-dbfs_SOURCES = dbfs.c dbfs.h dbfs-backend.c
-dbfs_LDADD = @GNET_LIBS@ @FUSE_LIBS@ @DB_LIBS@
+dbfs_SOURCES = dbfs.c dbfs.h dbfs-backend.c libdbfs.c
+dbfs_LDADD = @GLIB_LIBS@ @FUSE_LIBS@ @DB_LIBS@
+
+mkdbfs_SOURCES = mkdbfs.c
+mkdbfs_LDADD = @DB_LIBS@
EXTRA_DIST = autogen.sh
diff --git a/dbfs-backend.c b/dbfs-backend.c
index 5cdb72e..87bb065 100644
--- a/dbfs-backend.c
+++ b/dbfs-backend.c
@@ -1,6 +1,4 @@
-#define FUSE_USE_VERSION 25
-
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
@@ -24,112 +22,6 @@ struct dbfs_dirscan_info {
void *end_ent;
};
-static DB_ENV *db_env;
-static DB *db_meta;
-
-void dbfs_init(void *userdata)
-{
- const char *db_home, *db_password;
- int rc;
- unsigned int flags = 0;
-
- /*
- * open DB environment
- */
-
- db_home = getenv("DB_HOME");
- if (!db_home) {
- fprintf(stderr, "DB_HOME not set\n");
- exit(1);
- }
-
- /* this isn't a very secure way to handle passwords */
- db_password = getenv("DB_PASSWORD");
-
- rc = db_env_create(&db_env, 0);
- if (rc) {
- fprintf(stderr, "db_env_create failed: %d\n", rc);
- exit(1);
- }
-
- /* stderr is wrong; should use syslog instead */
- db_env->set_errfile(db_env, stderr);
- db_env->set_errpfx(db_env, "dbfs");
-
- if (db_password) {
- flags |= DB_ENCRYPT;
- rc = db_env->set_encrypt(db_env, db_password, DB_ENCRYPT_AES);
- if (rc) {
- db_env->err(db_env, rc, "db_env->set_encrypt");
- goto err_out;
- }
-
- /* this isn't a very good way to shroud the password */
- if (putenv("DB_PASSWORD=X"))
- perror("putenv (SECURITY WARNING)");
- }
-
- /* init DB transactional environment, stored in directory db_home */
- rc = db_env->open(db_env, db_home,
- DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
- DB_INIT_TXN | DB_RECOVER | DB_CREATE | flags, 0666);
- if (rc) {
- db_env->err(db_env, rc, "db_env->open");
- goto err_out;
- }
-
- /*
- * Open metadata database
- */
-
- rc = db_create(&db_meta, db_env, 0);
- if (rc) {
- db_env->err(db_env, rc, "db_create");
- goto err_out;
- }
-
- rc = db_meta->open(db_meta, NULL, "metadata", NULL,
- DB_HASH, DB_AUTO_COMMIT | DB_CREATE | flags, 0666);
- if (rc) {
- db_meta->err(db_meta, rc, "db_meta->open");
- goto err_out_meta;
- }
-
- /* our data items are small, so use the smallest possible page
- * size. This is a guess, and should be verified by looking at
- * overflow pages and other DB statistics.
- */
- rc = db_meta->set_pagesize(db_meta, 512);
- if (rc) {
- db_meta->err(db_meta, rc, "db_meta->set_pagesize");
- goto err_out_meta;
- }
-
- /* fix everything as little endian */
- rc = db_meta->set_lorder(db_meta, 1234);
- if (rc) {
- db_meta->err(db_meta, rc, "db_meta->set_lorder");
- goto err_out_meta;
- }
-
- return;
-
-err_out_meta:
- db_meta->close(db_meta, 0);
-err_out:
- db_env->close(db_env, 0);
- exit(1);
-}
-
-void dbfs_exit(void *userdata)
-{
- db_meta->close(db_meta, 0);
- db_env->close(db_env, 0);
-
- db_env = NULL;
- db_meta = NULL;
-}
-
void dbfs_inode_free(struct dbfs_inode *ino)
{
free(ino->raw_inode);
@@ -145,7 +37,7 @@ static int dbmeta_del(const char *key_str)
key.size = strlen(key_str);
/* delete key 'key_str' from metadata database */
- rc = db_meta->del(db_meta, NULL, &key, 0);
+ rc = gfs->meta->del(gfs->meta, NULL, &key, 0);
if (rc == DB_NOTFOUND)
return -ENOENT;
if (rc)
@@ -213,7 +105,7 @@ static int dbfs_inode_write(struct dbfs_inode *ino)
raw_ino->version = GUINT64_TO_LE(
GUINT64_FROM_LE(raw_ino->version) + 1);
- return db_meta->get(db_meta, NULL, &key, &val, 0) ? -EIO : 0;
+ return gfs->meta->get(gfs->meta, NULL, &key, &val, 0) ? -EIO : 0;
}
static int dbfs_mode_type(guint32 mode, enum dbfs_inode_type *itype)
@@ -255,7 +147,7 @@ int dbfs_inode_read(guint64 ino_n, struct dbfs_inode **ino_out)
val.flags = DB_DBT_MALLOC;
- rc = db_meta->get(db_meta, NULL, &key, &val, 0);
+ rc = gfs->meta->get(gfs->meta, NULL, &key, &val, 0);
if (rc == DB_NOTFOUND)
return -ENOENT;
if (rc)
@@ -296,7 +188,7 @@ int dbfs_symlink_read(guint64 ino, DBT *val)
val->flags = DB_DBT_MALLOC;
- rc = db_meta->get(db_meta, NULL, &key, val, 0);
+ rc = gfs->meta->get(gfs->meta, NULL, &key, val, 0);
if (rc == DB_NOTFOUND)
return -EINVAL;
return rc ? -EIO : 0;
@@ -318,7 +210,7 @@ int dbfs_dir_read(guint64 ino, DBT *val)
val->flags = DB_DBT_MALLOC;
- rc = db_meta->get(db_meta, NULL, &key, val, 0);
+ rc = gfs->meta->get(gfs->meta, NULL, &key, val, 0);
if (rc == DB_NOTFOUND)
return -ENOTDIR;
return rc ? -EIO : 0;
@@ -336,7 +228,7 @@ static int dbfs_dir_write(guint64 ino, DBT *val)
key.data = key_str;
key.size = strlen(key_str);
- return db_meta->put(db_meta, NULL, &key, val, 0) ? -EIO : 0;
+ return gfs->meta->put(gfs->meta, NULL, &key, val, 0) ? -EIO : 0;
}
int dbfs_dir_foreach(void *dir, dbfs_dir_actor_t func, void *userdata)
diff --git a/dbfs.c b/dbfs.c
index 9c1f501..13c039a 100644
--- a/dbfs.c
+++ b/dbfs.c
@@ -10,6 +10,32 @@
#include <db.h>
#include "dbfs.h"
+static void dbfs_op_init(void *userdata)
+{
+ struct dbfs **fs_io = userdata;
+ struct dbfs *fs;
+ int rc;
+
+ fs = dbfs_new();
+
+ rc = dbfs_open(fs);
+ if (rc)
+ abort(); /* TODO: improve */
+
+ *fs_io = fs;
+}
+
+static void dbfs_op_destroy(void *userdata)
+{
+ struct dbfs **fs_io = userdata;
+ struct dbfs *fs = *fs_io;
+
+ dbfs_close(fs);
+ dbfs_free(fs);
+
+ *fs_io = NULL;
+}
+
static void dbfs_op_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
{
struct fuse_entry_param e;
@@ -311,8 +337,8 @@ static void dbfs_op_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
}
static struct fuse_lowlevel_ops dbfs_ops = {
- .init = dbfs_init,
- .destroy = dbfs_exit,
+ .init = dbfs_op_init,
+ .destroy = dbfs_op_destroy,
.lookup = dbfs_op_lookup,
.forget = NULL,
.getattr = dbfs_op_getattr,
diff --git a/dbfs.h b/dbfs.h
index 9f84cc6..591ad92 100644
--- a/dbfs.h
+++ b/dbfs.h
@@ -1,6 +1,8 @@
#ifndef __DBFS_H__
#define __DBFS_H__
+#include <glib.h>
+
enum {
DBFS_BLK_ID_LEN = 20,
@@ -61,6 +63,14 @@ struct dbfs_inode {
struct dbfs_raw_inode *raw_inode;
};
+struct dbfs {
+ const char *home;
+ const char *passwd;
+
+ DB_ENV *env;
+ DB *meta;
+};
+
typedef int (*dbfs_dir_actor_t) (struct dbfs_dirent *, void *);
@@ -77,4 +87,10 @@ extern int dbfs_mknod(guint64 parent, const char *name,
guint32 mode, guint64 rdev,
struct dbfs_inode **ino);
+extern int dbfs_open(struct dbfs *fs);
+extern void dbfs_close(struct dbfs *fs);
+extern struct dbfs *dbfs_new(void);
+extern void dbfs_free(struct dbfs *fs);
+extern struct dbfs *gfs;
+
#endif /* __DBFS_H__ */
diff --git a/libdbfs.c b/libdbfs.c
new file mode 100644
index 0000000..be36afc
--- /dev/null
+++ b/libdbfs.c
@@ -0,0 +1,147 @@
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <glib.h>
+#include <db.h>
+#include "dbfs.h"
+
+struct dbfs *gfs;
+
+int dbfs_open(struct dbfs *fs)
+{
+ const char *db_home, *db_password;
+ int rc;
+ unsigned int flags = 0;
+
+ /*
+ * open DB environment
+ */
+
+ db_home = fs->home;
+ if (!db_home) {
+ fprintf(stderr, "DB_HOME not set\n");
+ return -EINVAL;
+ }
+
+ /* this isn't a very secure way to handle passwords */
+ db_password = fs->passwd;
+
+ rc = db_env_create(&fs->env, 0);
+ if (rc) {
+ fprintf(stderr, "fs->env_create failed: %d\n", rc);
+ return rc;
+ }
+
+ /* stderr is wrong; should use syslog instead */
+ fs->env->set_errfile(fs->env, stderr);
+ fs->env->set_errpfx(fs->env, "dbfs");
+
+ if (db_password) {
+ flags |= DB_ENCRYPT;
+ rc = fs->env->set_encrypt(fs->env, db_password, DB_ENCRYPT_AES);
+ if (rc) {
+ fs->env->err(fs->env, rc, "fs->env->set_encrypt");
+ goto err_out;
+ }
+
+ /* this isn't a very good way to shroud the password */
+ if (putenv("DB_PASSWORD=X"))
+ perror("putenv (SECURITY WARNING)");
+ }
+
+ /* init DB transactional environment, stored in directory db_home */
+ rc = fs->env->open(fs->env, db_home,
+ DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
+ DB_INIT_TXN | DB_RECOVER | DB_CREATE | flags, 0666);
+ if (rc) {
+ fs->env->err(fs->env, rc, "fs->env->open");
+ goto err_out;
+ }
+
+ /*
+ * Open metadata database
+ */
+
+ rc = db_create(&fs->meta, fs->env, 0);
+ if (rc) {
+ fs->env->err(fs->env, rc, "db_create");
+ goto err_out;
+ }
+
+ rc = fs->meta->open(fs->meta, NULL, "metadata", NULL,
+ DB_HASH, DB_AUTO_COMMIT | flags, 0666);
+ if (rc) {
+ fs->meta->err(fs->meta, rc, "fs->meta->open");
+ goto err_out_meta;
+ }
+
+ /* our data items are small, so use the smallest possible page
+ * size. This is a guess, and should be verified by looking at
+ * overflow pages and other DB statistics.
+ */
+ rc = fs->meta->set_pagesize(fs->meta, 512);
+ if (rc) {
+ fs->meta->err(fs->meta, rc, "fs->meta->set_pagesize");
+ goto err_out_meta;
+ }
+
+ /* fix everything as little endian */
+ rc = fs->meta->set_lorder(fs->meta, 1234);
+ if (rc) {
+ fs->meta->err(fs->meta, rc, "fs->meta->set_lorder");
+ goto err_out_meta;
+ }
+
+ gfs = fs;
+ return 0;
+
+err_out_meta:
+ fs->meta->close(fs->meta, 0);
+err_out:
+ fs->env->close(fs->env, 0);
+ return rc;
+}
+
+void dbfs_close(struct dbfs *fs)
+{
+ fs->meta->close(fs->meta, 0);
+ fs->env->close(fs->env, 0);
+
+ fs->env = NULL;
+ fs->meta = NULL;
+}
+
+struct dbfs *dbfs_new(void)
+{
+ struct dbfs *fs;
+ char *passwd;
+
+ fs = g_new0(struct dbfs, 1);
+ if (!fs)
+ return NULL;
+
+ fs->home = getenv("DB_HOME");
+ if (!fs->home)
+ goto err_out;
+
+ passwd = getenv("DB_PASSWORD");
+ if (passwd) {
+ fs->passwd = strdup(passwd);
+ if (putenv("DB_PASSWORD=X"))
+ perror("putenv DB_PASSWORD (SECURITY WARNING)");
+ }
+
+ return fs;
+
+err_out:
+ g_free(fs);
+ return NULL;
+}
+
+void dbfs_free(struct dbfs *fs)
+{
+ g_free(fs);
+}
+
diff --git a/mkdbfs.c b/mkdbfs.c
new file mode 100644
index 0000000..2269e0b
--- /dev/null
+++ b/mkdbfs.c
@@ -0,0 +1,125 @@
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <glib.h>
+#include <db.h>
+#include "dbfs.h"
+
+static DB_ENV *db_env;
+static DB *db_meta;
+
+void dbfs_init(void *userdata)
+{
+ const char *db_home, *db_password;
+ int rc;
+ unsigned int flags = 0;
+
+ /*
+ * open DB environment
+ */
+
+ db_home = getenv("DB_HOME");
+ if (!db_home) {
+ fprintf(stderr, "DB_HOME not set\n");
+ exit(1);
+ }
+
+ /* this isn't a very secure way to handle passwords */
+ db_password = getenv("DB_PASSWORD");
+
+ rc = db_env_create(&db_env, 0);
+ if (rc) {
+ fprintf(stderr, "db_env_create failed: %d\n", rc);
+ exit(1);
+ }
+
+ db_env->set_errfile(db_env, stderr);
+ db_env->set_errpfx(db_env, "dbfs");
+
+ if (db_password) {
+ flags |= DB_ENCRYPT;
+ rc = db_env->set_encrypt(db_env, db_password, DB_ENCRYPT_AES);
+ if (rc) {
+ db_env->err(db_env, rc, "db_env->set_encrypt");
+ goto err_out;
+ }
+
+ /* this isn't a very good way to shroud the password */
+ if (putenv("DB_PASSWORD=X"))
+ perror("putenv (SECURITY WARNING)");
+ }
+
+ /* init DB transactional environment, stored in directory db_home */
+ rc = db_env->open(db_env, db_home,
+ DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
+ DB_INIT_TXN | DB_CREATE | flags, 0666);
+ if (rc) {
+ db_env->err(db_env, rc, "db_env->open");
+ goto err_out;
+ }
+
+ /*
+ * Open metadata database
+ */
+
+ rc = db_create(&db_meta, db_env, 0);
+ if (rc) {
+ db_env->err(db_env, rc, "db_create");
+ goto err_out;
+ }
+
+ rc = db_meta->open(db_meta, NULL, "metadata", NULL,
+ DB_HASH,
+ DB_AUTO_COMMIT | DB_CREATE | DB_TRUNCATE | flags,
+ 0666);
+ if (rc) {
+ db_meta->err(db_meta, rc, "db_meta->open");
+ goto err_out_meta;
+ }
+
+ /* our data items are small, so use the smallest possible page
+ * size. This is a guess, and should be verified by looking at
+ * overflow pages and other DB statistics.
+ */
+ rc = db_meta->set_pagesize(db_meta, 512);
+ if (rc) {
+ db_meta->err(db_meta, rc, "db_meta->set_pagesize");
+ goto err_out_meta;
+ }
+
+ /* fix everything as little endian */
+ rc = db_meta->set_lorder(db_meta, 1234);
+ if (rc) {
+ db_meta->err(db_meta, rc, "db_meta->set_lorder");
+ goto err_out_meta;
+ }
+
+ return;
+
+err_out_meta:
+ db_meta->close(db_meta, 0);
+err_out:
+ db_env->close(db_env, 0);
+ exit(1);
+}
+
+void dbfs_exit(void *userdata)
+{
+ db_meta->close(db_meta, 0);
+ db_env->close(db_env, 0);
+
+ db_env = NULL;
+ db_meta = NULL;
+}
+
+int main (int argc, char *argv[])
+{
+ dbfs_init(NULL);
+ dbfs_exit(NULL);
+ return 0;
+}
+