linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [RFC:PATCH 000/008] Tail Packing in the the Page Cache
@ 2006-07-18  4:08 Dave Kleikamp
  2006-07-18  4:08 ` [RFC:PATCH 001/008] Changes to common header files Dave Kleikamp
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Dave Kleikamp @ 2006-07-18  4:08 UTC (permalink / raw)
  To: linux-mm; +Cc: Dave Kleikamp, Dave McCracken, Badari Pulavarty

These patches are still a bit rough, but I wanted to post something before
my OLS presentation on Friday.

The goal of these patches is to avoid excessive internal fragmentation in
the page cache when the base page size is large.  The new function is
enabled by the option, CONFIG_FILE_TAILS, which currently depends on
CONFIG_PPC_64K_PAGES, but should eventually be available on any 64-bit
architecture.

Instead of allocating an entire page to hold the data for a smaller file
tail, we allocate a buffer from the slab cache (using malloc) and anchor it
to the address space (inode->mapping->tail).  A dummy page structure is
used to represent the tail in the page cache and lru list.

Any time the size of the file is increased, or the tail of the file is
mmapped, the tail is unpacked into a regular page.

I'm still experiencing an occasional hang with these patches.  I don't
recommend running with them, unless you are really interested in debugging.

Note: I had originally attempted to perform I/O directly on the dummy page,
but I was unable to get it working before the OLS deadline, so I simplified
things a bit and pack the data into the tail after it is initially read into
a normal page.  I expect that I can improve these patches quite a bit before
they are ready for submission.

These patches are based on linux-2.6.17.

The title of my presentation is "Efficient Use of the Page Cache with 64K
Pages" and will be held in conference room B at 11:00 on Friday, July 21st.

-- 
David Kleikamp
IBM Linux Technology Center

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC:PATCH 001/008] Changes to common header files
  2006-07-18  4:08 [RFC:PATCH 000/008] Tail Packing in the the Page Cache Dave Kleikamp
@ 2006-07-18  4:08 ` Dave Kleikamp
  2006-07-18  4:08 ` [RFC:PATCH 002/008] Base file tail function Dave Kleikamp
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Dave Kleikamp @ 2006-07-18  4:08 UTC (permalink / raw)
  To: linux-mm; +Cc: Dave Kleikamp, Dave McCracken, Badari Pulavarty

Changes to common header files

Add tail to address space and define PG_tail page flag

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
---
diff -Nurp linux000/arch/powerpc/Kconfig linux001/arch/powerpc/Kconfig
--- linux000/arch/powerpc/Kconfig	2006-06-17 20:49:35.000000000 -0500
+++ linux001/arch/powerpc/Kconfig	2006-07-17 23:04:37.000000000 -0500
@@ -696,6 +696,15 @@ config PPC_64K_PAGES
           while on hardware with such support, it will be used to map
           normal application pages.
 
+config FILE_TAILS
+	bool "Store file tails in slab cache"
+	depends on PPC_64K_PAGES
+	help
+	  If the data at the end of a file, or the entire file, is small,
+	  the kernel will attempt to store that data in the slab cache,
+	  rather than allocate an entire page in the page cache.
+	  If unsure, say N here.
+
 config SCHED_SMT
 	bool "SMT (Hyperthreading) scheduler support"
 	depends on PPC64 && SMP
diff -Nurp linux000/include/linux/fs.h linux001/include/linux/fs.h
--- linux000/include/linux/fs.h	2006-06-17 20:49:35.000000000 -0500
+++ linux001/include/linux/fs.h	2006-07-17 23:04:37.000000000 -0500
@@ -398,6 +398,9 @@ struct address_space {
 	spinlock_t		private_lock;	/* for use by the address_space */
 	struct list_head	private_list;	/* ditto */
 	struct address_space	*assoc_mapping;	/* ditto */
+#ifdef CONFIG_FILE_TAILS
+	void			*tail;		/* efficiently stored tail */
+#endif
 } __attribute__((aligned(sizeof(long))));
 	/*
 	 * On most architectures that alignment is already the case; but
diff -Nurp linux000/include/linux/page-flags.h linux001/include/linux/page-flags.h
--- linux000/include/linux/page-flags.h	2006-06-17 20:49:35.000000000 -0500
+++ linux001/include/linux/page-flags.h	2006-07-17 23:04:37.000000000 -0500
@@ -89,6 +89,7 @@
 #define PG_buddy		19	/* Page is free, on buddy lists */
 
 #define PG_uncached		20	/* Page has been mapped as uncached */
+#define PG_tail			21	/* Pseudo-page representing tail */
 
 /*
  * Global page accounting.  One instance per CPU.  Only unsigned longs are
@@ -360,6 +361,10 @@ extern void __mod_page_state_offset(unsi
 #define SetPageUncached(page)	set_bit(PG_uncached, &(page)->flags)
 #define ClearPageUncached(page)	clear_bit(PG_uncached, &(page)->flags)
 
+#define PageTail(page)		test_bit(PG_tail, &(page)->flags)
+#define SetPageTail(page)	set_bit(PG_tail, &(page)->flags)
+#define ClearPageTail(page)	clear_bit(PG_tail, &(page)->flags)
+
 struct page;	/* forward declaration */
 
 int test_clear_page_dirty(struct page *page);

-- 
David Kleikamp
IBM Linux Technology Center

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC:PATCH 002/008] Base file tail function
  2006-07-18  4:08 [RFC:PATCH 000/008] Tail Packing in the the Page Cache Dave Kleikamp
  2006-07-18  4:08 ` [RFC:PATCH 001/008] Changes to common header files Dave Kleikamp
@ 2006-07-18  4:08 ` Dave Kleikamp
  2006-07-18  4:08 ` [RFC:PATCH 003/008] Handle tail pages in kmap & kmap_atomic Dave Kleikamp
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Dave Kleikamp @ 2006-07-18  4:08 UTC (permalink / raw)
  To: linux-mm; +Cc: Dave Kleikamp, Dave McCracken, Badari Pulavarty

Base file tail function

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
---
diff -Nurp linux001/include/linux/file_tail.h linux002/include/linux/file_tail.h
--- linux001/include/linux/file_tail.h	1969-12-31 18:00:00.000000000 -0600
+++ linux002/include/linux/file_tail.h	2006-07-17 23:04:37.000000000 -0500
@@ -0,0 +1,48 @@
+#ifndef FILE_TAIL_H
+#define FILE_TAIL_H
+
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+
+/*
+ * This file deals with storing tails of files in buffers smaller than a page
+ */
+
+#ifdef CONFIG_FILE_TAILS
+
+#define FILE_TAIL_INDEX(mapping) \
+	(i_size_read((mapping)->host) >> PAGE_CACHE_SHIFT)
+#define FILE_TAIL_LENGTH(mapping) \
+	(i_size_read((mapping)->host) & (PAGE_CACHE_SIZE - 1))
+
+static inline int page_data_size(struct page *page)
+{
+	if (PageTail(page))
+		return FILE_TAIL_LENGTH(page->mapping);
+	else
+		return PAGE_CACHE_SIZE;
+}
+
+extern struct page *page_cache_alloc_tail(struct address_space *);
+void page_cache_free_tail(struct page *);
+void pack_file_tail(struct page *);
+/*
+ * Called holding write_lock_irq(&mapping->tree_lock)
+ */
+extern void __unpack_file_tail(struct address_space *);
+
+static inline void unpack_file_tail(struct address_space *mapping)
+{
+	write_lock_irq(&mapping->tree_lock);
+	__unpack_file_tail(mapping);
+	write_unlock_irq(&mapping->tree_lock);
+}
+
+#else /* !CONFIG_FILE_TAILS */
+
+#define page_data_size(page) PAGE_CACHE_SIZE
+#define unpack_file_tail(mapping) do {} while (0)
+
+#endif /* CONFIG_FILE_TAILS */
+
+#endif	/* FILE_TAIL_H */
diff -Nurp linux001/mm/Makefile linux002/mm/Makefile
--- linux001/mm/Makefile	2006-06-17 20:49:35.000000000 -0500
+++ linux002/mm/Makefile	2006-07-17 23:04:37.000000000 -0500
@@ -23,4 +23,5 @@ obj-$(CONFIG_SLAB) += slab.o
 obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
 obj-$(CONFIG_FS_XIP) += filemap_xip.o
 obj-$(CONFIG_MIGRATION) += migrate.o
+obj-$(CONFIG_FILE_TAILS) += file_tail.o
 
diff -Nurp linux001/mm/file_tail.c linux002/mm/file_tail.c
--- linux001/mm/file_tail.c	1969-12-31 18:00:00.000000000 -0600
+++ linux002/mm/file_tail.c	2006-07-17 23:04:37.000000000 -0500
@@ -0,0 +1,305 @@
+/*
+ *	linux/mm/file_tail.c
+ *
+ * Copyright (C) International Business Machines  Corp., 2006
+ */
+
+/*
+ * This file deals with storing tails of files in buffers smaller than a page
+ */
+
+#include <linux/file_tail.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/buffer_head.h>
+#include <linux/swap.h>
+#include <linux/mm_inline.h>
+#include "internal.h"
+
+static struct kmem_cache *tail_page_cachep;
+
+/*
+ * Maybe this could become more generic, but for now, I need it here
+ */
+static void lru_cache_delete(struct page *page)
+{
+	if (PageLRU(page)) {
+		unsigned long flags;
+		struct zone *zone = page_zone(page);
+
+		spin_lock_irqsave(&zone->lru_lock, flags);
+		BUG_ON(!PageLRU(page));
+		__ClearPageLRU(page);
+		del_page_from_lru(zone, page);
+		spin_unlock_irqrestore(&zone->lru_lock, flags);
+	}
+}
+
+/*
+ * Caller must hold write lock on mapping->tree_lock
+ */
+void __unpack_file_tail(struct address_space *mapping)
+{
+	int error;
+	unsigned long index;
+	char *kaddr;
+	struct page *full_page = NULL, *short_page;
+	char *tail;
+	int tail_length;
+
+	while(mapping->tail) {
+		index = FILE_TAIL_INDEX(mapping);
+		write_unlock_irq(&mapping->tree_lock);
+
+		/* Allocate full page */
+		if (!full_page)
+			full_page = page_cache_alloc(mapping);
+		BUG_ON(!full_page);	
+
+		/* Get & lock short page */
+		short_page = find_lock_page(mapping, index);
+		if (!short_page || !PageTail(short_page)) {
+			if (short_page) {
+				unlock_page(short_page);
+				page_cache_release(short_page);
+			}
+			/* anything can happen since we released the lock */
+			write_lock_irq(&mapping->tree_lock);
+			continue;
+		}
+		/* We have the tail page locked, so this shouldn't go away */
+		BUG_ON(!mapping->tail);
+
+		BUG_ON(page_has_buffers(short_page) || PageDirty(short_page));
+
+		/* This is the equivalent of remove_from_page_cache and
+		 * add_to_page_cache_lru, without dropping tree_lock
+		 */
+		error = radix_tree_preload(mapping_gfp_mask(mapping));
+		BUG_ON(error);
+		write_lock_irq(&mapping->tree_lock);
+		lru_cache_delete(short_page);
+		radix_tree_delete(&mapping->page_tree, index);
+		short_page->mapping = NULL;
+		tail = mapping->tail;
+		mapping->tail = NULL;
+
+		error = radix_tree_insert(&mapping->page_tree, index,
+					  full_page);
+		BUG_ON(error);
+		page_cache_get(full_page);
+		SetPageLocked(full_page);
+		full_page->mapping = mapping;
+		full_page->index = index;
+
+		write_unlock_irq(&mapping->tree_lock);
+		radix_tree_preload_end();
+		page_cache_release(short_page); /* page cache ref */
+
+		/*
+		 * Now that the short page has been replaced by the full
+		 * page in the radix tree, we need to wait until all of
+		 * the references on the short page are gone.
+		 */
+		unlock_page(short_page);
+
+		/*
+		 * This still needs work.  We occasionally get caught in 
+		 * this loop.
+		 */
+		while (page_count(short_page) > 1)
+			schedule();
+		/*
+		 * ToDo: Figure out where this is getting added back to
+		 * lru
+		 */
+		lru_cache_delete(short_page);
+
+		/* Copy data from tail to full page */
+		if (PageUptodate(short_page)) {
+			kaddr = kmap_atomic(full_page, KM_USER0);
+			tail_length = FILE_TAIL_LENGTH(mapping);
+			memcpy(kaddr, tail, tail_length);
+			memset(kaddr+tail_length, 0,
+			       PAGE_CACHE_SIZE - tail_length);
+			kunmap_atomic(kaddr, KM_USER0);
+			SetPageUptodate(full_page);
+		}
+		kfree(tail);
+
+		/* finalize full_page */
+		lru_cache_add(full_page);
+		unlock_page(full_page);
+		page_cache_release(full_page);
+		full_page = NULL;
+
+		/* free short_page */
+		WARN_ON(PageLRU(short_page));
+		kmem_cache_free(tail_page_cachep, short_page);
+
+		/* 
+		 * unlikely, but check to see if there was no tail added
+		 * back.  We need to return with tree_lock held.
+		 */
+		write_lock_irq(&mapping->tree_lock);
+
+	}
+	if (full_page)
+		page_cache_release(full_page);
+	return;
+}
+EXPORT_SYMBOL(__unpack_file_tail);
+
+void i_size_write(struct inode *inode, loff_t i_size)
+{
+	struct address_space *mapping = inode->i_mapping;
+
+	write_lock_irq(&mapping->tree_lock);
+	if (mapping->tail && (i_size > i_size_read(inode)))
+		__unpack_file_tail(mapping);
+	_i_size_write(inode, i_size);
+	write_unlock_irq(&mapping->tree_lock);
+}
+EXPORT_SYMBOL(i_size_write);
+
+static void init_once(void *ptr, kmem_cache_t *cachep, unsigned long flags)
+{
+	struct page *page = (struct page *)ptr;
+
+	if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR) {
+		memset(page, 0, sizeof(struct page));
+		reset_page_mapcount(page);
+		INIT_LIST_HEAD(&page->lru);
+		SetPageTail(page);
+	}
+}
+
+static __init int file_tail_init(void)
+{
+	tail_page_cachep = kmem_cache_create("tail_page_cache",
+					     sizeof(struct page), 0, 0,
+					     init_once, NULL);
+	if (tail_page_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+__initcall(file_tail_init);
+
+/*
+ * If the page is clean, in use by no one else, and the data is sufficiently
+ * small, allocate a tail page, copy it's data, and replace the page with
+ * the tail page in the page cache.
+ *
+ * Caller must hold reference on the page.
+ */
+void pack_file_tail(struct page *full_page)
+{
+	int error;
+	pgoff_t index;
+	void *kaddr;
+	struct address_space *mapping = full_page->mapping;
+	struct page *short_page;
+	int size;
+	void *tail;
+
+	if (!mapping)
+		return;
+
+	if (TestSetPageLocked(full_page))
+		return;
+
+	size = FILE_TAIL_LENGTH(mapping);
+	index = FILE_TAIL_INDEX(mapping);
+
+	if ((size > PAGE_CACHE_SIZE / 2) || PageDirty(full_page) ||
+	    !PageUptodate(full_page) || mapping_mapped(mapping) ||
+	    (page_count(full_page) > 2) || page_has_buffers(full_page) ||
+	    PageWriteback(full_page)) {
+		unlock_page(full_page);
+		return;
+	}
+
+	short_page = kmem_cache_alloc(tail_page_cachep, SLAB_KERNEL);
+	if (!short_page) {
+		unlock_page(full_page);
+		return;
+	}
+
+	tail = kmalloc(size, SLAB_KERNEL);
+
+	if (!tail) {
+		kmem_cache_free(tail_page_cachep, short_page);
+		unlock_page(full_page);
+		return;
+	}
+	set_page_count(short_page, 1);
+	short_page->flags = 0;
+	SetPageTail(short_page);
+
+	/* Copy the data into the tail */
+	kaddr = kmap_atomic(full_page, KM_USER0);
+	memcpy(tail, kaddr, size);
+	kunmap_atomic(kaddr,KM_USER0);
+	SetPageUptodate(short_page);
+
+	error = radix_tree_preload(mapping_gfp_mask(mapping));
+	if (error) {
+		kfree(tail);
+		kmem_cache_free(tail_page_cachep, short_page);
+		unlock_page(full_page);
+		return;
+	}
+	/*
+	 * Take tree lock.  Recheck that nobody else is using full_page,
+	 * remove it from the page cache and add short page, all while holding
+	 * the lock
+	 */
+	write_lock_irq(&mapping->tree_lock);
+	/*
+	 * Make sure the file size didn't change
+	 */
+	if (mapping->tail || (full_page->index != FILE_TAIL_INDEX(mapping)) ||
+	    (size != FILE_TAIL_LENGTH(mapping)) || mapping_mapped(mapping) ||
+	    page_count(full_page) > 2) {
+		write_unlock_irq(&mapping->tree_lock);
+		radix_tree_preload_end();
+		kfree(tail);
+		kmem_cache_free(tail_page_cachep, short_page);
+		unlock_page(full_page);
+		return;
+	}
+	/* out with the old */
+	lru_cache_delete(full_page);
+	radix_tree_delete(&mapping->page_tree, index);
+	full_page->mapping = NULL;
+
+	/* in with the new */
+	mapping->tail = tail;
+	error = radix_tree_insert(&mapping->page_tree, index, short_page);
+	BUG_ON(error);
+	page_cache_get(short_page);
+	SetPageLocked(short_page);
+	short_page->mapping = mapping;
+	short_page->index = index;
+
+	write_unlock_irq(&mapping->tree_lock);
+	radix_tree_preload_end();
+
+	unlock_page(full_page);
+	page_cache_release(full_page); /* page cache reference */
+
+	/* We're done with this now */
+	lru_cache_add(short_page);
+	unlock_page(short_page);
+	page_cache_release(short_page);
+
+	return;
+}
+
+void page_cache_free_tail(struct page *page)
+{
+	kmem_cache_free(tail_page_cachep, page);
+}

-- 
David Kleikamp
IBM Linux Technology Center

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC:PATCH 003/008] Handle tail pages in kmap & kmap_atomic
  2006-07-18  4:08 [RFC:PATCH 000/008] Tail Packing in the the Page Cache Dave Kleikamp
  2006-07-18  4:08 ` [RFC:PATCH 001/008] Changes to common header files Dave Kleikamp
  2006-07-18  4:08 ` [RFC:PATCH 002/008] Base file tail function Dave Kleikamp
@ 2006-07-18  4:08 ` Dave Kleikamp
  2006-07-18  4:08 ` [RFC:PATCH 004/008] Wrap i_size_write Dave Kleikamp
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Dave Kleikamp @ 2006-07-18  4:08 UTC (permalink / raw)
  To: linux-mm; +Cc: Dave Kleikamp, Dave McCracken, Badari Pulavarty

Handle tail pages in kmap & kmap_atomic

TODO: possibly move to mm.h: lowmem_page_address()

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
---
diff -Nurp linux002/include/asm-powerpc/io.h linux003/include/asm-powerpc/io.h
--- linux002/include/asm-powerpc/io.h	2006-06-17 20:49:35.000000000 -0500
+++ linux003/include/asm-powerpc/io.h	2006-07-17 23:04:38.000000000 -0500
@@ -250,7 +250,9 @@ static inline void * phys_to_virt(unsign
 /*
  * Change "struct page" to physical address.
  */
-#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
+#define page_to_phys(page)	(PageTail(page) ?			\
+				__pa((page)->mapping->tail) :		\
+				page_to_pfn(page) << PAGE_SHIFT)
 
 /* We do NOT want virtual merging, it would put too much pressure on
  * our iommu allocator. Instead, we want drivers to be smart enough
diff -Nurp linux002/include/linux/highmem.h linux003/include/linux/highmem.h
--- linux002/include/linux/highmem.h	2006-06-17 20:49:35.000000000 -0500
+++ linux003/include/linux/highmem.h	2006-07-17 23:04:38.000000000 -0500
@@ -33,12 +33,21 @@ static inline unsigned int nr_free_highp
 static inline void *kmap(struct page *page)
 {
 	might_sleep();
+#ifdef CONFIG_FILE_TAILS
+	return PageTail(page) ? page->mapping->tail : page_address(page);
+#else
 	return page_address(page);
+#endif
 }
 
 #define kunmap(page) do { (void) (page); } while (0)
 
+#ifdef CONFIG_FILE_TAILS
+#define kmap_atomic(page, idx) \
+       	(PageTail(page) ? (page)->mapping->tail : page_address(page))
+#else
 #define kmap_atomic(page, idx)		page_address(page)
+#endif
 #define kunmap_atomic(addr, idx)	do { } while (0)
 #define kmap_atomic_pfn(pfn, idx)	page_address(pfn_to_page(pfn))
 #define kmap_atomic_to_page(ptr)	virt_to_page(ptr)

-- 
David Kleikamp
IBM Linux Technology Center

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC:PATCH 004/008] Wrap i_size_write
  2006-07-18  4:08 [RFC:PATCH 000/008] Tail Packing in the the Page Cache Dave Kleikamp
                   ` (2 preceding siblings ...)
  2006-07-18  4:08 ` [RFC:PATCH 003/008] Handle tail pages in kmap & kmap_atomic Dave Kleikamp
@ 2006-07-18  4:08 ` Dave Kleikamp
  2006-07-18  4:08 ` [RFC:PATCH 005/008] unpack tail page to avoid memory mapping Dave Kleikamp
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Dave Kleikamp @ 2006-07-18  4:08 UTC (permalink / raw)
  To: linux-mm; +Cc: Dave Kleikamp, Dave McCracken, Badari Pulavarty

Wrap i_size_write

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
---
diff -Nurp linux003/include/linux/fs.h linux004/include/linux/fs.h
--- linux003/include/linux/fs.h	2006-07-17 23:04:37.000000000 -0500
+++ linux004/include/linux/fs.h	2006-07-17 23:04:38.000000000 -0500
@@ -578,8 +578,13 @@ static inline loff_t i_size_read(struct 
 #endif
 }
 
+#ifdef CONFIG_FILE_TAILS
+extern void i_size_write(struct inode *, loff_t); /* defined in file_tail.c */
 
+static inline void _i_size_write(struct inode *inode, loff_t i_size)
+#else
 static inline void i_size_write(struct inode *inode, loff_t i_size)
+#endif
 {
 #if BITS_PER_LONG==32 && defined(CONFIG_SMP)
 	write_seqcount_begin(&inode->i_size_seqcount);

-- 
David Kleikamp
IBM Linux Technology Center

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC:PATCH 005/008] unpack tail page to avoid memory mapping
  2006-07-18  4:08 [RFC:PATCH 000/008] Tail Packing in the the Page Cache Dave Kleikamp
                   ` (3 preceding siblings ...)
  2006-07-18  4:08 ` [RFC:PATCH 004/008] Wrap i_size_write Dave Kleikamp
@ 2006-07-18  4:08 ` Dave Kleikamp
  2006-07-18  4:08 ` [RFC:PATCH 006/008] Don't need to zero past end-of-file in file tail Dave Kleikamp
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Dave Kleikamp @ 2006-07-18  4:08 UTC (permalink / raw)
  To: linux-mm; +Cc: Dave Kleikamp, Dave McCracken, Badari Pulavarty

unpack tail page to avoid memory mapping

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
---
diff -Nurp linux004/mm/memory.c linux005/mm/memory.c
--- linux004/mm/memory.c	2006-06-17 20:49:35.000000000 -0500
+++ linux005/mm/memory.c	2006-07-17 23:04:38.000000000 -0500
@@ -48,6 +48,7 @@
 #include <linux/rmap.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/file_tail.h>
 
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
@@ -2071,6 +2072,15 @@ retry:
 	if (new_page == NOPAGE_OOM)
 		return VM_FAULT_OOM;
 
+#ifdef CONFIG_FILE_TAILS
+	if (PageTail(new_page)) {
+		/* Can new_page->mapping be different from mapping? */
+		struct address_space *mapping2 = new_page->mapping;
+		page_cache_release(new_page);
+		unpack_file_tail(mapping2);
+		goto retry;
+	}
+#endif
 	/*
 	 * Should we do an early C-O-W break?
 	 */

-- 
David Kleikamp
IBM Linux Technology Center

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC:PATCH 006/008] Don't need to zero past end-of-file in file tail
  2006-07-18  4:08 [RFC:PATCH 000/008] Tail Packing in the the Page Cache Dave Kleikamp
                   ` (4 preceding siblings ...)
  2006-07-18  4:08 ` [RFC:PATCH 005/008] unpack tail page to avoid memory mapping Dave Kleikamp
@ 2006-07-18  4:08 ` Dave Kleikamp
  2006-07-18  4:09 ` [RFC:PATCH 007/008] Make sure tail page is freed correctly Dave Kleikamp
  2006-07-18  4:09 ` [RFC:PATCH 008/008] Handle file tails in mm/filemap.c Dave Kleikamp
  7 siblings, 0 replies; 9+ messages in thread
From: Dave Kleikamp @ 2006-07-18  4:08 UTC (permalink / raw)
  To: linux-mm; +Cc: Dave Kleikamp, Dave McCracken, Badari Pulavarty

Don't need to zero past end-of-file in file tail

It will always be unpacked if the file is later grown

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
---
diff -Nurp linux005/mm/truncate.c linux006/mm/truncate.c
--- linux005/mm/truncate.c	2006-06-17 20:49:35.000000000 -0500
+++ linux006/mm/truncate.c	2006-07-17 23:04:38.000000000 -0500
@@ -14,11 +14,16 @@
 #include <linux/pagevec.h>
 #include <linux/buffer_head.h>	/* grr. try_to_release_page,
 				   do_invalidatepage */
+#include <linux/file_tail.h>
 
 
 static inline void truncate_partial_page(struct page *page, unsigned partial)
 {
-	memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
+#ifdef CONFIG_FILE_TAILS
+	if (PageTail(page))
+		return;
+#endif
+	memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE - partial);
 	if (PagePrivate(page))
 		do_invalidatepage(page, partial);
 }

-- 
David Kleikamp
IBM Linux Technology Center

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC:PATCH 007/008] Make sure tail page is freed correctly
  2006-07-18  4:08 [RFC:PATCH 000/008] Tail Packing in the the Page Cache Dave Kleikamp
                   ` (5 preceding siblings ...)
  2006-07-18  4:08 ` [RFC:PATCH 006/008] Don't need to zero past end-of-file in file tail Dave Kleikamp
@ 2006-07-18  4:09 ` Dave Kleikamp
  2006-07-18  4:09 ` [RFC:PATCH 008/008] Handle file tails in mm/filemap.c Dave Kleikamp
  7 siblings, 0 replies; 9+ messages in thread
From: Dave Kleikamp @ 2006-07-18  4:09 UTC (permalink / raw)
  To: linux-mm; +Cc: Dave Kleikamp, Dave McCracken, Badari Pulavarty

Make sure tail page is freed correctly

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
---
diff -Nurp linux006/mm/page_alloc.c linux007/mm/page_alloc.c
--- linux006/mm/page_alloc.c	2006-06-17 20:49:35.000000000 -0500
+++ linux007/mm/page_alloc.c	2006-07-17 23:04:38.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/nodemask.h>
 #include <linux/vmalloc.h>
 #include <linux/mempolicy.h>
+#include <linux/file_tail.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -733,6 +734,13 @@ static void fastcall free_hot_cold_page(
 	struct per_cpu_pages *pcp;
 	unsigned long flags;
 
+#ifdef CONFIG_FILE_TAILS
+	if (PageTail(page)) {
+		/* Not a real page */
+		page_cache_free_tail(page);
+		return;
+	}
+#endif
 	arch_free_page(page, 0);
 
 	if (PageAnon(page))

-- 
David Kleikamp
IBM Linux Technology Center

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC:PATCH 008/008] Handle file tails in mm/filemap.c
  2006-07-18  4:08 [RFC:PATCH 000/008] Tail Packing in the the Page Cache Dave Kleikamp
                   ` (6 preceding siblings ...)
  2006-07-18  4:09 ` [RFC:PATCH 007/008] Make sure tail page is freed correctly Dave Kleikamp
@ 2006-07-18  4:09 ` Dave Kleikamp
  7 siblings, 0 replies; 9+ messages in thread
From: Dave Kleikamp @ 2006-07-18  4:09 UTC (permalink / raw)
  To: linux-mm; +Cc: Dave Kleikamp, Dave McCracken, Badari Pulavarty

Handle file tails in mm/filemap.c

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
---
diff -Nurp linux007/mm/filemap.c linux008/mm/filemap.c
--- linux007/mm/filemap.c	2006-06-17 20:49:35.000000000 -0500
+++ linux008/mm/filemap.c	2006-07-17 23:04:38.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/cpuset.h>
+#include <linux/file_tail.h>
 #include "filemap.h"
 #include "internal.h"
 
@@ -117,6 +118,12 @@ void __remove_from_page_cache(struct pag
 {
 	struct address_space *mapping = page->mapping;
 
+#ifdef CONFIG_FILE_TAILS
+	if (PageTail(page)) {
+		kfree(mapping->tail);
+		mapping->tail = NULL;
+	}
+#endif
 	radix_tree_delete(&mapping->page_tree, page->index);
 	page->mapping = NULL;
 	mapping->nrpages--;
@@ -885,6 +892,11 @@ page_ok:
 		index += offset >> PAGE_CACHE_SHIFT;
 		offset &= ~PAGE_CACHE_MASK;
 
+#ifdef CONFIG_FILE_TAILS
+		if (!mapping->tail && page->index == FILE_TAIL_INDEX(mapping) &&
+		    !PageDirty(page))
+			pack_file_tail(page);
+#endif
 		page_cache_release(page);
 		if (ret == nr && desc->count)
 			continue;
@@ -2030,6 +2042,16 @@ generic_file_buffered_write(struct kiocb
 			break;
 		}
 
+#ifdef CONFIG_FILE_TAILS
+		if (PageTail(page)) {
+			/* Can't unpack the tail while holding the tail page */
+			unlock_page(page);
+			page_cache_release(page);
+			unpack_file_tail(mapping);
+			continue;
+		}
+#endif
+
 		status = a_ops->prepare_write(file, page, offset, offset+bytes);
 		if (unlikely(status)) {
 			loff_t isize = i_size_read(inode);

-- 
David Kleikamp
IBM Linux Technology Center

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2006-07-18  4:09 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-07-18  4:08 [RFC:PATCH 000/008] Tail Packing in the the Page Cache Dave Kleikamp
2006-07-18  4:08 ` [RFC:PATCH 001/008] Changes to common header files Dave Kleikamp
2006-07-18  4:08 ` [RFC:PATCH 002/008] Base file tail function Dave Kleikamp
2006-07-18  4:08 ` [RFC:PATCH 003/008] Handle tail pages in kmap & kmap_atomic Dave Kleikamp
2006-07-18  4:08 ` [RFC:PATCH 004/008] Wrap i_size_write Dave Kleikamp
2006-07-18  4:08 ` [RFC:PATCH 005/008] unpack tail page to avoid memory mapping Dave Kleikamp
2006-07-18  4:08 ` [RFC:PATCH 006/008] Don't need to zero past end-of-file in file tail Dave Kleikamp
2006-07-18  4:09 ` [RFC:PATCH 007/008] Make sure tail page is freed correctly Dave Kleikamp
2006-07-18  4:09 ` [RFC:PATCH 008/008] Handle file tails in mm/filemap.c Dave Kleikamp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox