diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-04-24 21:02:27 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-04-24 21:02:27 -0400 |
commit | a7b45f1a8e9d1376490174ffb5230e30de3d92f2 (patch) | |
tree | 19349d6abe7769de11af8fd78b87cf2c94486547 | |
parent | 77e168ddd08fa4289f133be3c29d9aa817ea67bb (diff) | |
download | dbfs-a7b45f1a8e9d1376490174ffb5230e30de3d92f2.tar.gz |
dbfs: start to libify dbfs. add mkdbfs program (just base db, for now).
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.am | 9 | ||||
-rw-r--r-- | dbfs-backend.c | 120 | ||||
-rw-r--r-- | dbfs.c | 30 | ||||
-rw-r--r-- | dbfs.h | 16 | ||||
-rw-r--r-- | libdbfs.c | 147 | ||||
-rw-r--r-- | mkdbfs.c | 125 |
7 files changed, 329 insertions, 119 deletions
@@ -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) @@ -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, @@ -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; +} + |