2 * Copyright (c) 2016 Maxim Sobolev <sobomax@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <sys/types.h>
39 #if defined(MKUZ_DEBUG)
43 #include "mkuz_blockcache.h"
45 struct mkuz_blkcache {
46 struct mkuz_blkcache_hit hit;
48 unsigned char digest[16];
49 struct mkuz_blkcache *next;
52 static struct mkuz_blkcache blkcache;
55 verify_match(int fd, off_t data_offset, void *data, ssize_t len,
56 struct mkuz_blkcache *bcep)
67 if (lseek(fd, bcep->data_offset, SEEK_SET) < 0) {
70 rlen = read(fd, vbuf, len);
74 rval = (memcmp(data, vbuf, len) == 0) ? 1 : 0;
76 lseek(fd, data_offset, SEEK_SET);
83 struct mkuz_blkcache_hit *
84 mkuz_blkcache_regblock(int fd, uint32_t blkno, off_t offset, ssize_t len,
87 struct mkuz_blkcache *bcep;
90 unsigned char mdigest[16];
93 data_offset = lseek(fd, 0, SEEK_CUR);
94 if (data_offset < 0) {
98 MD5Update(&mcontext, data, len);
99 MD5Final(mdigest, &mcontext);
100 if (blkcache.hit.len == 0) {
103 for (bcep = &blkcache; bcep != NULL; bcep = bcep->next) {
104 if (bcep->hit.len != len)
106 if (memcmp(mdigest, bcep->digest, sizeof(mdigest)) == 0) {
111 rval = verify_match(fd, data_offset, data, len, bcep);
113 #if defined(MKUZ_DEBUG)
114 fprintf(stderr, "cache hit %d, %d, %d\n",
115 (int)bcep->hit.offset, (int)data_offset, (int)len);
120 #if defined(MKUZ_DEBUG)
121 fprintf(stderr, "block MD5 collision, you should try lottery, "
126 warn("verify_match");
129 bcep = malloc(sizeof(struct mkuz_blkcache));
132 memset(bcep, '\0', sizeof(struct mkuz_blkcache));
133 bcep->next = blkcache.next;
134 blkcache.next = bcep;
136 memcpy(bcep->digest, mdigest, sizeof(mdigest));
137 bcep->data_offset = data_offset;
138 bcep->hit.offset = offset;
140 bcep->hit.blkno = blkno;