[patch] truncate_inode_pages

Andrew Morton (andrewm@uow.edu.au)
Sun, 10 Jun 2001 01:51:47 +1000


The ftruncate() in this program:

#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

int clean = 64 * 1024 * 1024;
int dirty = 64 * 1024 * 1024;

main()
{
int fd = open("foo", O_RDWR|O_TRUNC|O_CREAT, 0666);
void *mem;

ftruncate(fd, clean + dirty);
mem = mmap(0, clean + dirty, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
memset(mem, 0, clean + dirty);
msync(mem, clean, MS_SYNC);
ftruncate(fd, clean);
}

takes 45 seconds CPU time due to the O(clean * dirty) algorithm in
truncate_inode_pages(). The machine is locked up for the duration.
The patch reduces this to 20 milliseconds via an O(clean + dirty)
algorithm.

--- linux-2.4.5/mm/filemap.c Mon May 28 13:31:49 2001
+++ linux-akpm/mm/filemap.c Sun Jun 10 01:27:09 2001
@@ -273,15 +273,24 @@
{
unsigned long start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
unsigned partial = lstart & (PAGE_CACHE_SIZE - 1);
+ int complete;

-repeat:
spin_lock(&pagecache_lock);
- if (truncate_list_pages(&mapping->clean_pages, start, &partial))
- goto repeat;
- if (truncate_list_pages(&mapping->dirty_pages, start, &partial))
- goto repeat;
- if (truncate_list_pages(&mapping->locked_pages, start, &partial))
- goto repeat;
+ do {
+ complete = 1;
+ while (truncate_list_pages(&mapping->clean_pages, start, &partial)) {
+ spin_lock(&pagecache_lock);
+ complete = 0;
+ }
+ while (truncate_list_pages(&mapping->dirty_pages, start, &partial)) {
+ spin_lock(&pagecache_lock);
+ complete = 0;
+ }
+ while (truncate_list_pages(&mapping->locked_pages, start, &partial)) {
+ spin_lock(&pagecache_lock);
+ complete = 0;
+ }
+ } while (!complete);
spin_unlock(&pagecache_lock);
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/