diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-08-05 16:51:18 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-08-05 16:51:18 -0400 |
commit | 89419915ba7b438d6631e086cdf95fee9b23060f (patch) | |
tree | f713aba8af40752180a518ee9475a83f3f4a89c9 | |
parent | e78673577ce02c308b1a8df11da8bd7914ac9920 (diff) | |
download | dbfs-89419915ba7b438d6631e086cdf95fee9b23060f.tar.gz |
Special case the reading and writing of all-zero data blocks.
-rw-r--r-- | dbfs-backend.c | 70 | ||||
-rw-r--r-- | dbfs.h | 2 |
2 files changed, 55 insertions, 17 deletions
diff --git a/dbfs-backend.c b/dbfs-backend.c index 5722e6b..ae575a6 100644 --- a/dbfs-backend.c +++ b/dbfs-backend.c @@ -682,6 +682,30 @@ err_out: return rc; } +static const char zero_block[DBFS_ZERO_CMP_BLK_SZ]; + +static gboolean is_zero_buf(const void *buf, size_t buflen) +{ + while (buflen > 0) { + size_t cmp_size; + int rc; + + cmp_size = MIN(buflen, DBFS_ZERO_CMP_BLK_SZ); + rc = memcmp(buf, zero_block, cmp_size); + if (rc) + return FALSE; + + buflen -= cmp_size; + } + + return TRUE; +} + +static gboolean is_null_id(dbfs_blk_id_t *id) +{ + return is_zero_buf(id, DBFS_BLK_ID_LEN); +} + static int dbfs_ext_read(dbfs_blk_id_t *id, void **buf, size_t *buflen) { DBT key, val; @@ -733,27 +757,32 @@ int dbfs_read(guint64 ino_n, guint64 off, size_t read_req_size, tmp = ext_list; while (tmp) { struct dbfs_extent *ext; - void *frag; - size_t fraglen; ext = tmp->data; - rc = dbfs_ext_read(&ext->id, &frag, &fraglen); - if (rc) { - free(buf); - buf = NULL; - goto out_list; - } - if ((ext->off + ext->len) > fraglen) { + if (is_null_id(&ext->id)) { + memset(buf + pos, 0, ext->len); + } else { + void *frag; + size_t fraglen; + + rc = dbfs_ext_read(&ext->id, &frag, &fraglen); + if (rc) { + free(buf); + buf = NULL; + goto out_list; + } + if ((ext->off + ext->len) > fraglen) { + free(frag); + free(buf); + buf = NULL; + rc = -EINVAL; + goto out_list; + } + + memcpy(buf + pos, frag + ext->off, ext->len); free(frag); - free(buf); - buf = NULL; - rc = -EINVAL; - goto out_list; } - memcpy(buf + pos, frag + ext->off, ext->len); - free(frag); - pos += ext->len; tmp = tmp->next; @@ -810,8 +839,12 @@ static int dbfs_write_buf(const void *buf, size_t buflen, if (buflen == 0 || buflen > DBFS_MAX_EXT_LEN) return -EINVAL; - ext->off = 0; + memset(ext, 0, sizeof(*ext)); ext->len = buflen; + + if (is_zero_buf(buf, buflen)) + return 0; + SHA1(buf, buflen, (unsigned char *) &ext->id); memset(&key, 0, sizeof(key)); @@ -846,6 +879,9 @@ static int dbfs_data_unref(dbfs_blk_id_t *id) DBT key, val; int rc, rc2; + if (is_null_id(id)) + return 0; + memset(&key, 0, sizeof(key)); key.data = id; key.size = DBFS_BLK_ID_LEN; @@ -49,6 +49,8 @@ enum { DBFS_PGSZ_DATA = 2048, DBFS_MAX_EXT_LEN = (4 * 1024 * 1024), /* max extent len */ + + DBFS_ZERO_CMP_BLK_SZ = 8192, }; enum { |