| Summary: | contigfree() doesn't | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Andrew Gallatin <gallatin> |
| Component: | kern | Assignee: | freebsd-bugs (Nobody) <bugs> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 4.4-RELEASE | ||
| Hardware: | Any | ||
| OS: | Any | ||
State Changed From-To: open->feedback Is this still a problem? State Changed From-To: feedback->closed Appears to be fixed by dillon's vm_contig v1.3 and MFC'ed to vm_page.c 1.147.2.9. |
When debugging an apparent memory leak in a 3rd party device driver, I found what appears to be a serious problem with contigfree() -- it doesn't appear to actually free the pages. Fix: unknown How-To-Repeat: I modified the syscall example kld to contigmalloc 1024 pages on load & free them on unload. Prior to the contigmalloc() it prints out the number of wired pages, as well as the size of the free and cache queues. It prints this same information after the contigfree at unload time. As you can see from the following output, the pages remain wired & are never freed: load: wired: 3710, cache 8, free 119993 unload: wired: 4735, cache 8, free 118954 load: wired: 4738, cache 8, free 118950 unload: wired: 5762, cache 8, free 117924 load: wired: 5762, cache 8, free 117926 unload: wired: 6786, cache 8, free 116900 load: wired: 6786, cache 8, free 116902 unload: wired: 7810, cache 8, free 115876 I've appended a modified version of the syscall module: --- /usr/share/examples/kld/syscall/module/syscall.c Wed Aug 15 14:40:49 2001 +++ syscall.c Mon Sep 24 15:21:42 2001 @@ -33,6 +33,8 @@ #include <sys/sysent.h> #include <sys/kernel.h> #include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/vmmeter.h> /* * The function for implementing the syscall. @@ -64,6 +66,9 @@ * The function called at load/unload. */ +void *contigmem; +unsigned long size = PAGE_SIZE * 1024; + static int load (struct module *module, int cmd, void *arg) { @@ -71,10 +76,15 @@ switch (cmd) { case MOD_LOAD : - printf ("syscall loaded at %d\n", offset); + printf("load: wired: %d, cache %d, free %d\n", + cnt.v_wire_count, cnt.v_cache_count, cnt.v_free_count); + contigmem = contigmalloc (size, M_DEVBUF, M_NOWAIT, + 0x100000, 0xffffffff, PAGE_SIZE, 0); break; case MOD_UNLOAD : - printf ("syscall unloaded from %d\n", offset); + contigfree(contigmem, size, M_DEVBUF); + printf("unload: wired: %d, cache %d, free %d\n", + cnt.v_wire_count, cnt.v_cache_count, cnt.v_free_count); break; default : error = EINVAL;