Re: [PATCH] ramfs: fix memleak on no-mmu arch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi, Andrew

cc'd some folks working on nommu.

On Tue, Mar 29, 2011 at 8:02 AM, Andrew Morton
<akpm@xxxxxxxxxxxxxxxxxxxx> wrote:
> On Mon, 28 Mar 2011 13:32:35 +0800
> Bob Liu <lliubbo@xxxxxxxxx> wrote:
>
>> On no-mmu arch, there is a memleak duirng shmem test.
>> The cause of this memleak is ramfs_nommu_expand_for_mapping() added page
>> refcount to 2 which makes iput() can't free that pages.
>>
>> The simple test file is like this:
>> int main(void)
>> {
>> Â Â Â int i;
>> Â Â Â key_t k = ftok("/etc", 42);
>>
>> Â Â Â for ( i=0; i<100; ++i) {
>> Â Â Â Â Â Â Â int id = shmget(k, 10000, 0644|IPC_CREAT);
>> Â Â Â Â Â Â Â if (id == -1) {
>> Â Â Â Â Â Â Â Â Â Â Â printf("shmget error\n");
>> Â Â Â Â Â Â Â }
>> Â Â Â Â Â Â Â if(shmctl(id, IPC_RMID, NULL ) == -1) {
>> Â Â Â Â Â Â Â Â Â Â Â printf("shm Ârm error\n");
>> Â Â Â Â Â Â Â Â Â Â Â return -1;
>> Â Â Â Â Â Â Â }
>> Â Â Â }
>> Â Â Â printf("run ok...\n");
>> Â Â Â return 0;
>> }
>>
>> ...
>>
>> diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
>> index 9eead2c..fbb0b47 100644
>> --- a/fs/ramfs/file-nommu.c
>> +++ b/fs/ramfs/file-nommu.c
>> @@ -112,6 +112,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
>> Â Â Â Â Â Â Â SetPageDirty(page);
>>
>> Â Â Â Â Â Â Â unlock_page(page);
>> + Â Â Â Â Â Â put_page(page);
>> Â Â Â }
>>
>> Â Â Â return 0;
>
> Something is still wrong here.
>
> A live, in-use page should have a refcount of three. ÂOne for the
> existence of the page, one for its presence on the page LRU and one for
> its existence in the pagecache radix tree.
>
> So allocation should do:
>
> Â Â Â Âalloc_pages()
> Â Â Â Âadd_to_page_cache()
> Â Â Â Âadd_to_lru()
>
> and deallocation should do
>
> Â Â Â Âremove_from_lru()
> Â Â Â Âremove_from_page_cache()
> Â Â Â Âput_page()
>
> If this protocol is followed correctly, there is no need to do a
> put_page() during the allocation/setup phase!
>
> I suspect that the problem in nommu really lies in the
> deallocation/teardown phase.
>

What about below patch ?

BTW: It seems that in MMU cases shmem pages are freed during memory reclaim,
since I didn't find the direct free place.
I am not sure maybe I got something wrong ?

Signed-off-by: Bob Liu <lliubbo@xxxxxxxxx>
---
 fs/ramfs/file-nommu.c |    1 +
 fs/ramfs/inode.c      |   22 ++++++++++++++++++++++
 2 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index fbb0b47..11f48eb 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -114,6 +114,7 @@ int ramfs_nommu_expand_for_mapping(struct inode
*inode, size_t newsize)
 		unlock_page(page);
 		put_page(page);
 	}
+	inode->i_private = pages;

 	return 0;

diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index eacb166..e446d9f 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -151,9 +151,31 @@ static const struct inode_operations
ramfs_dir_inode_operations = {
 	.rename		= simple_rename,
 };

+#ifndef CONFIG_MMU
+static void ramfs_evict_inode(struct inode *inode)
+{
+	int i;
+	struct page *free_pages = (struct page *)inode->i_private;
+
+	/*
+	 * for nommu arch, need an extra put_page so that pages gotten
+	 * by ramfs_nommu_expand_for_mapping() can be freed
+	 */
+	for (i = 0; i < inode->i_data.nrpages; i++)
+		put_page(free_pages + i);
+
+	if (inode->i_data.nrpages)
+		truncate_inode_pages(&inode->i_data, 0);
+	end_writeback(inode);
+}
+#endif
+
 static const struct super_operations ramfs_ops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= generic_delete_inode,
+#ifndef CONFIG_MMU
+	.evict_inode    = ramfs_evict_inode,
+#endif
 	.show_options	= generic_show_options,
 };

-- 
1.6.3.3

-- 
Regards,
--Bob

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@xxxxxxxxxx  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]