diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-08-05 07:18:01 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-08-05 07:18:01 -0400 |
commit | 7a96bdc61f66c9c465ec35fb99082e357f9b9054 (patch) | |
tree | 8b6c283e1b5252716baa3c1ee03263b351a679b0 | |
parent | cdac8a5c4ad0cbcc3a610bbbe768dbe06936bae1 (diff) | |
download | dbfs-7a96bdc61f66c9c465ec35fb99082e357f9b9054.tar.gz |
Create hashref database, add data write/delete support routines.
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | README | 7 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | dbfs-backend.c | 115 | ||||
-rw-r--r-- | dbfs.h | 7 | ||||
-rw-r--r-- | libdbfs.c | 8 |
6 files changed, 139 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am index b9b3f32..4c5c52b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,7 +11,7 @@ sbin_PROGRAMS = dbfs mkdbfs dbfsck libdbfs_a_SOURCES = libdbfs.c dbfs_SOURCES = dbfs.c dbfs.h dbfs-backend.c xattr.c -dbfs_LDADD = @GLIB_LIBS@ @FUSE_LIBS@ @DB_LIBS@ libdbfs.a +dbfs_LDADD = @GLIB_LIBS@ @FUSE_LIBS@ @DB_LIBS@ @CRYPTO_LIBS@ libdbfs.a mkdbfs_SOURCES = mkdbfs.c mkdbfs_LDADD = @GLIB_LIBS@ @DB_LIBS@ libdbfs.a @@ -5,3 +5,10 @@ git://git.kernel.org/pub/scm/fs/fuse/dbfs.git Software home: http://www.kernel.org/pub/linux/kernel/people/jgarzik/fs/ + +Build (and probably runtime) dependencies: +* GLib 2.x +* DB 4.x +* FUSE +* OpenSSL, or compatible libcrypto (for SHA1) + diff --git a/configure.ac b/configure.ac index 79667b3..f7d3088 100644 --- a/configure.ac +++ b/configure.ac @@ -43,6 +43,7 @@ dnl ----------------------------- dnl Checks for required libraries dnl ----------------------------- AC_CHECK_LIB(db-4.3, db_create, DB_LIBS=-ldb-4.3, exit 1) +AC_CHECK_LIB(crypto, SHA1_Update, CRYPTO_LIBS=-lcrypto, exit 1) dnl ------------------------------------- dnl Checks for optional library functions @@ -60,6 +61,7 @@ AM_PATH_GLIB_2_0(2.0.0) PKG_CHECK_MODULES([FUSE], fuse) AC_SUBST(DB_LIBS) +AC_SUBST(CRYPTO_LIBS) AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/dbfs-backend.c b/dbfs-backend.c index a75670a..0f10e71 100644 --- a/dbfs-backend.c +++ b/dbfs-backend.c @@ -8,6 +8,7 @@ #include <time.h> #include <glib.h> #include <db.h> +#include <openssl/sha.h> #include "dbfs.h" struct dbfs_lookup_info { @@ -749,3 +750,117 @@ out: return rc < 0 ? rc : buflen; } +#if 0 +static int dbfs_write_unique_buf(DBT *key, const void *buf, size_t buflen) +{ + struct dbfs_hashref ref; + DBT val; + int rc; + + ref.refs = GUINT32_TO_LE(1); + + memset(&val, 0, sizeof(val)); + val.data = &ref; + val.size = sizeof(ref); + + rc = gfs->hashref->put(gfs->hashref, NULL, key, &val, 0); + if (rc) + return -EIO; + + memset(&val, 0, sizeof(val)); + val.data = (void *) buf; + val.size = buflen; + + rc = gfs->data->put(gfs->data, NULL, key, &val, DB_NOOVERWRITE); + if (rc) { + memset(&val, 0, sizeof(val)); + val.data = &ref; + val.size = sizeof(ref); + gfs->hashref->del(gfs->hashref, NULL, key, 0); + + return -EIO; + } +} + +static int dbfs_write_buf(const void *buf, size_t buflen, + struct dbfs_extent *ext) +{ + struct dbfs_hashref *ref; + DBT key, val; + int rc; + + if (buflen == 0 || buflen > DBFS_MAX_EXT_LEN) + return -EINVAL; + + ext->off = 0; + ext->len = buflen; + SHA1(buf, buflen, (unsigned char *) &ext->id); + + memset(&key, 0, sizeof(key)); + key.data = &ext->id; + key.size = DBFS_BLK_ID_LEN; + + memset(&val, 0, sizeof(val)); + val.flags = DB_DBT_MALLOC; + + rc = gfs->hashref->get(gfs->hashref, NULL, &key, &val, 0); + if (rc && (rc != DB_NOTFOUND)) + return -EIO; + + if (rc == DB_NOTFOUND) + return dbfs_write_unique_buf(&key, buf, buflen); + + ref = val.data; + g_assert(val.size == sizeof(*ref)); + + ref->refs = GUINT32_TO_LE(GUINT32_FROM_LE(ref->refs) + 1); + + rc = gfs->hashref->put(gfs->hashref, NULL, &key, &val, 0); + free(val.data); + + return rc ? -EIO : 0; +} + +static int dbfs_data_unref(dbfs_blk_id_t *id) +{ + struct dbfs_hashref *ref; + guint32 refs; + DBT key, val; + int rc, rc2; + + memset(&key, 0, sizeof(key)); + key.data = id; + key.size = DBFS_BLK_ID_LEN; + + memset(&val, 0, sizeof(val)); + val.flags = DB_DBT_MALLOC; + + rc = gfs->hashref->get(gfs->hashref, NULL, &key, &val, 0); + if (rc == DB_NOTFOUND) + return -ENOENT; + if (rc) + return -EIO; + + ref = val.data; + g_assert(val.size == sizeof(*ref)); + refs = GUINT32_FROM_LE(ref->refs); + + if (refs > 1) { + refs--; + ref->refs = GUINT32_TO_LE(refs); + + rc = gfs->hashref->put(gfs->hashref, NULL, &key, &val, 0); + free(val.data); + + return rc ? -EIO : 0; + } + + free(val.data); + + rc = gfs->hashref->del(gfs->hashref, NULL, &key, 0); + rc2 = gfs->data->del(gfs->data, NULL, &key, 0); + + return (rc || rc2) ? -EIO : 0; +} + +#endif @@ -29,6 +29,8 @@ enum { * as well as large ones */ DBFS_PGSZ_DATA = 2048, + + DBFS_MAX_EXT_LEN = (4 * 1024 * 1024), }; enum { @@ -67,6 +69,10 @@ struct dbfs_extent { dbfs_blk_id_t id; /* block id */ } __attribute__ ((packed)); +struct dbfs_hashref { + guint32 refs; +} __attribute__ ((packed)); + struct dbfs_raw_inode { guint64 ino; guint64 version; @@ -96,6 +102,7 @@ struct dbfs { DB_ENV *env; DB *meta; DB *data; + DB *hashref; guint64 next_inode; }; @@ -103,7 +103,11 @@ int dbfs_open(struct dbfs *fs, unsigned int env_flags, unsigned int flags, rc = open_db(fs->env, &fs->meta, "metadata", DBFS_PGSZ_METADATA, flags); if (rc) - goto err_out_meta; + goto err_out; + + rc = open_db(fs->env, &fs->hashref, "hash", DBFS_PGSZ_METADATA, flags); + if (rc) + goto err_out; rc = open_db(fs->env, &fs->data, "data", DBFS_PGSZ_DATA, flags); if (rc) @@ -120,6 +124,8 @@ err_out: void dbfs_close(struct dbfs *fs) { + fs->data->close(fs->data, 0); + fs->hashref->close(fs->hashref, 0); fs->meta->close(fs->meta, 0); fs->env->close(fs->env, 0); |