aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-08-05 07:18:01 -0400
committerJeff Garzik <jeff@garzik.org>2006-08-05 07:18:01 -0400
commit7a96bdc61f66c9c465ec35fb99082e357f9b9054 (patch)
tree8b6c283e1b5252716baa3c1ee03263b351a679b0
parentcdac8a5c4ad0cbcc3a610bbbe768dbe06936bae1 (diff)
downloaddbfs-7a96bdc61f66c9c465ec35fb99082e357f9b9054.tar.gz
Create hashref database, add data write/delete support routines.
-rw-r--r--Makefile.am2
-rw-r--r--README7
-rw-r--r--configure.ac2
-rw-r--r--dbfs-backend.c115
-rw-r--r--dbfs.h7
-rw-r--r--libdbfs.c8
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
diff --git a/README b/README
index 69ff9f6..e7d1890 100644
--- a/README
+++ b/README
@@ -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
diff --git a/dbfs.h b/dbfs.h
index 02b002c..1bb578e 100644
--- a/dbfs.h
+++ b/dbfs.h
@@ -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;
};
diff --git a/libdbfs.c b/libdbfs.c
index 7335846..36e5ead 100644
--- a/libdbfs.c
+++ b/libdbfs.c
@@ -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);