[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b

acab (none) acab at 1337ness.
Sun Apr 4 01:04:42 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit 5a078ca98c4df284c002b557e96f1139f872aea5
Author: acab <acab at 1337ness.(none)>
Date:   Thu Sep 10 03:20:02 2009 +0200

    fuck mmap_sem!

diff --git a/libclamav/fmap.c b/libclamav/fmap.c
index a267e67..0105028 100644
--- a/libclamav/fmap.c
+++ b/libclamav/fmap.c
@@ -37,6 +37,9 @@
 #endif
 #endif
 
+#include <pthread.h>
+
+
 #include "others.h"
 #include "cltypes.h"
 
@@ -54,9 +57,14 @@
 /* FIXME: tune this stuff */
 #define UNPAGE_THRSHLD_LO 4*1024*1024
 #define UNPAGE_THRSHLD_HI 8*1024*1024
-#define DUMB_SIZE 1*1024*1024
+#define READAHEAD_PAGES 8
+
+/* FIXME: remove the malloc fallback, it only makes thing slower */
+#define DUMB_SIZE 0
+
+/* DON'T ASK ME */
+pthread_mutex_t fmap_mutex = PTHREAD_MUTEX_INITIALIZER;
 
-#define READAHEAD_PAGES 4
 
 static unsigned int fmap_align_items(unsigned int sz, unsigned int al) {
     return sz / al + (sz % al != 0);
@@ -99,10 +107,15 @@ struct F_MAP *fmap(int fd, off_t offset, size_t len) {
     mapsz = pages * pgsz + hdrsz;
 #if HAVE_MMAP
     if(mapsz >= DUMB_SIZE) {
-	if ((m = (struct F_MAP *)mmap(NULL, mapsz, PROT_READ | PROT_WRITE, MAP_PRIVATE|ANONYMOUS_MAP, -1, 0)) == MAP_FAILED)
+	pthread_mutex_lock(&fmap_mutex);
+	if ((m = (struct F_MAP *)mmap(NULL, mapsz, PROT_READ | PROT_WRITE, MAP_PRIVATE|/*FIXME: MAP_POPULATE is ~8% faster but more memory intensive */ANONYMOUS_MAP, -1, 0)) == MAP_FAILED)
 	    m = NULL;
-	else
+	else {
 	    dumb = 0;
+	    madvise(m, mapsz, MADV_RANDOM|MADV_DONTFORK);
+	    madvise(m, hdrsz, MADV_WILLNEED);
+	}
+	pthread_mutex_unlock(&fmap_mutex);
     } else
 #endif
 	m = (struct F_MAP *)cli_malloc(mapsz);
@@ -120,7 +133,13 @@ struct F_MAP *fmap(int fd, off_t offset, size_t len) {
     m->pgsz = pgsz;
     m->paged = 0;
     memset(m->bitmap, 0, sizeof(uint32_t) * pages);
-//    cli_errmsg("FMAPDBG: created %p - len %u pages %u hdrsz %u\n", m, len, pages, hdrsz);
+#ifdef FMAPDEBUG
+    m->page_needs = 0;
+    m->page_reads = 0;
+    m->page_locks = 0;
+    m->page_unlocks = 0;
+    m->page_unmaps = 0;
+#endif
     return m;
 }
 
@@ -179,8 +198,13 @@ static void fmap_aging(struct F_MAP *m) {
 		m->bitmap[freeme[i]] = FM_MASK_SEEN;
 		m->paged--;
 		/* and we mmap the page over so the kernel knows there's nothing good in there */
+		pthread_mutex_lock(&fmap_mutex);
 		if(mmap(pptr, m->pgsz, PROT_READ | PROT_WRITE, MAP_FIXED|MAP_PRIVATE|ANONYMOUS_MAP, -1, 0) == MAP_FAILED)
 		    cli_warnmsg("fmap_aging: kernel hates you\n");
+		pthread_mutex_unlock(&fmap_mutex);
+#ifdef FMAPDEBUG
+		m->page_unmaps++;
+#endif
 	    }
 	}
 	free(freeme);
@@ -192,9 +216,16 @@ static void fmap_aging(struct F_MAP *m) {
 static int fmap_readpage(struct F_MAP *m, unsigned int first_page, unsigned int count, unsigned int lock_count) {
     size_t readsz = 0, got;
     char *pptr = NULL;
-    uint32_t s;
+    volatile uint32_t s;
     unsigned int i, page = first_page, force_read = 0;
 
+    for(i=0; i<count; i++) { /* REAL MEN DON'T MADVISE: seriously, it sucks! */
+	volatile char faultme = ((char *)m)[(first_page+i) * m->pgsz + m->hdrsz];
+    }
+#ifdef FMAPDEBUG
+    m->page_needs += count;
+    m->page_locks += lock_count;
+#endif
     for(i=0; i<=count; i++, page++) {
 	int lock;
 	if(lock_count) {
@@ -254,6 +285,9 @@ static int fmap_readpage(struct F_MAP *m, unsigned int first_page, unsigned int
 		cli_warnmsg("pread fail: page %u pages %u map-offset %lu - asked for %lu bytes, got %lu\n", first_page, m->pages, (long unsigned int)m->offset, (long unsigned int)readsz, (long unsigned int)got);
 		return 1;
 	    }
+#ifdef FMAPDEBUG
+	    m->page_reads += count;
+#endif
 	    pptr = NULL;
 	    force_read = 0;
 	    readsz = 0;
@@ -285,12 +319,12 @@ static void *fmap_need(struct F_MAP *m, size_t at, size_t len, int lock) {
     char *ret;
 
     if(!len) {
-	cli_warnmsg("fmap: attempted void need\n");
+//	cli_warnmsg("fmap: attempted void need\n");
 	return NULL;
     }
 
     if(!CLI_ISCONTAINED(0, m->len, at, len)) {
-	cli_warnmsg("fmap: attempted oof need\n");
+      //	cli_warnmsg("fmap: attempted oof need\n");
 	return NULL;
     }
 
@@ -304,8 +338,6 @@ static void *fmap_need(struct F_MAP *m, size_t at, size_t len, int lock) {
     if(last_page >= m->pages) last_page = m->pages - 1;
 #endif
 
-//    cli_errmsg("FMAPDBG: +++ map %p - len %u lock: %d (page %u to %u)\n", m, len, lock, first_page, last_page);
-
     if(fmap_readpage(m, first_page, last_page-first_page+1, lock_count))
 	return NULL;
 
@@ -315,19 +347,15 @@ static void *fmap_need(struct F_MAP *m, size_t at, size_t len, int lock) {
 }
 
 void *fmap_need_off(struct F_MAP *m, size_t at, size_t len) {
-//    cli_errmsg("FMAPDBG: need_off map %p at %u len %u\n", m, at, len);
     return fmap_need(m, at, len, 1);
 }
 void *fmap_need_off_once(struct F_MAP *m, size_t at, size_t len) {
-//    cli_errmsg("FMAPDBG: need_off_once map %p at %u len %u\n", m, at, len);
     return fmap_need(m, at, len, 0);
 }
 void *fmap_need_ptr(struct F_MAP *m, void *ptr, size_t len) {
-//    cli_errmsg("FMAPDBG: need_ptr map %p at %p len %u\n", m, ptr, len);
     return fmap_need_off(m, (char *)ptr - (char *)m - m->hdrsz, len);
 }
 void *fmap_need_ptr_once(struct F_MAP *m, void *ptr, size_t len) {
-//    cli_errmsg("FMAPDBG: need_ptr_once map %p at %p len %u\n", m, ptr, len);
     return fmap_need_off_once(m, (char *)ptr - (char *)m - m->hdrsz, len);
 }
 
@@ -339,11 +367,12 @@ void *fmap_need_str(struct F_MAP *m, void *ptr, size_t len_hint) {
 static void fmap_unneed_page(struct F_MAP *m, unsigned int page) {
     uint32_t s = m->bitmap[page];
 
-//    cli_errmsg("FMAPDBG: --- map %p - page %u status %u count %u\n", m, page, s>>30, s & FM_MASK_COUNT);
-
     if((s & (FM_MASK_PAGED | FM_MASK_LOCKED)) == (FM_MASK_PAGED | FM_MASK_LOCKED)) {
 	/* page is paged and locked: check lock count */
 	s &= FM_MASK_COUNT;
+#ifdef FMAPDEBUG
+	m->page_unlocks ++;
+#endif
 	if(s > 1) /* locked more than once: dec lock count */
 	    m->bitmap[page]--;
 	else if (s == 1) /* only one lock left: unlock and begin aging */
@@ -399,10 +428,16 @@ int fmap_readn(struct F_MAP *m, void *dst, size_t at, size_t len) {
 }
 
 void fmunmap(struct F_MAP *m) {
+#ifdef FMAPDEBUG
+  cli_errmsg("FMAPDEBUG: Needs:%u reads:%u locks:%u unlocks:%u unmaps:%u\n", m->page_needs, m->page_reads, m->page_locks, m->page_unlocks, m->page_unmaps);
+#endif
+
 #if HAVE_MMAP
     if(!m->dumb) {
 	size_t len = m->pages * m->pgsz + m->hdrsz;
+	pthread_mutex_lock(&fmap_mutex);
 	munmap((void *)m, len);
+	pthread_mutex_unlock(&fmap_mutex);
     } else
 #endif
 	free((void *)m);
@@ -416,7 +451,7 @@ void *fmap_need_offstr(struct F_MAP *m, size_t at, size_t len_hint) {
 	len_hint = m->len - at;
 
     if(!CLI_ISCONTAINED(0, m->len, at, len_hint)) {
-	cli_warnmsg("fmap: attempted oof need_str\n");
+      //	cli_warnmsg("fmap: attempted oof need_str\n");
 	return NULL;
     }
 
@@ -435,11 +470,12 @@ void *fmap_need_offstr(struct F_MAP *m, size_t at, size_t len_hint) {
 	}
 	if(i == first_page) {
 	    scanat = at % m->pgsz;
-	    scansz = m->pgsz - scanat;
+	    scansz = MIN(len_hint, m->pgsz - scanat);
 	} else {
 	    scanat = 0;
-	    scansz = m->pgsz;
+	    scansz = MIN(len_hint, m->pgsz);
 	}
+	len_hint -= scansz;
 	if(memchr(&thispage[scanat], 0, scansz))
 	    return ptr;
     }
@@ -447,3 +483,52 @@ void *fmap_need_offstr(struct F_MAP *m, size_t at, size_t len_hint) {
 	fmap_unneed_page(m, i);
     return NULL;
 }
+
+
+void *fmap_gets(struct F_MAP *m, char *dst, size_t *at, size_t max_len) {
+    unsigned int i, first_page, last_page;
+    char *src = (void *)((char *)m + m->hdrsz + *at), *endptr = NULL;
+    size_t len = MIN(max_len-1, m->len - *at), fullen = len;
+
+    if(!len || !CLI_ISCONTAINED(0, m->len, *at, len)) {
+        //cli_warnmsg("fmap: attempted oof need_str\n");
+	return NULL;
+    }
+
+    fmap_aging(m);
+
+    first_page = fmap_which_page(m, *at);
+    last_page = fmap_which_page(m, *at + len - 1);
+
+    for(i=first_page; i<=last_page; i++) {
+	char *thispage = (char *)m + m->hdrsz + i * m->pgsz;
+	unsigned int scanat, scansz;
+
+	if(fmap_readpage(m, i, 1, 0))
+	    return NULL;
+
+	if(i == first_page) {
+	    scanat = *at % m->pgsz;
+	    scansz = MIN(len, m->pgsz - scanat);
+	} else {
+	    scanat = 0;
+	    scansz = MIN(len, m->pgsz);
+	}
+	len -= scansz;
+
+	if((endptr = memchr(&thispage[scanat], '\n', scansz))) {
+	    endptr++;
+	    break;
+	}
+    }
+    if(endptr) {
+	memcpy(dst, src, endptr - src);
+	dst[endptr - src] = '\0';
+	*at += endptr - src;
+    } else {
+	memcpy(dst, src, fullen);
+	dst[fullen] = '\0';
+	*at += fullen;
+    }
+    return dst;
+}

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list