public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/1] mips: fault.c: Port OOM changes to do_page_fault
@ 2011-12-23 11:22 Kautuk Consul
  2011-12-23 11:42 ` Kautuk Consul
  2012-01-16 15:47 ` Ralf Baechle
  0 siblings, 2 replies; 4+ messages in thread
From: Kautuk Consul @ 2011-12-23 11:22 UTC (permalink / raw)
  To: Ralf Baechle, Ingo Molnar, Peter Zijlstra
  Cc: linux-mips, linux-kernel, Mohd. Faris, Kautuk Consul

From: Kautuk Consul <consul.kautuk@gmail.com>

Commit d065bd810b6deb67d4897a14bfe21f8eb526ba99
(mm: retry page fault when blocking on disk transfer) and
commit 37b23e0525d393d48a7d59f870b3bc061a30ccdb
(x86,mm: make pagefault killable)

The above commits introduced changes into the x86 pagefault handler
for making the page fault handler retryable as well as killable.

These changes reduce the mmap_sem hold time, which is crucial
during OOM killer invocation.

Port these changes to MIPS.

Without these changes, my MIPS board encounters many hang and livelock
scenarios.
After applying this patch, OOM feature performance improves according to
my testing.

Signed-off-by: Mohd. Faris <mohdfarisq2010@gmail.com>
Signed-off-by: Kautuk Consul <consul.kautuk@gmail.com>
---
 arch/mips/mm/fault.c |   36 +++++++++++++++++++++++++++++-------
 1 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 937cf33..aae2cb3 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -42,6 +42,8 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ
 	const int field = sizeof(unsigned long) * 2;
 	siginfo_t info;
 	int fault;
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+						 (write ? FAULT_FLAG_WRITE : 0);
 
 #if 0
 	printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", raw_smp_processor_id(),
@@ -91,6 +93,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ
 	if (in_atomic() || !mm)
 		goto bad_area_nosemaphore;
 
+retry:
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
 	if (!vma)
@@ -144,7 +147,11 @@ good_area:
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault.
 	 */
-	fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
+	fault = handle_mm_fault(mm, vma, address, flags);
+
+	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+		return;
+
 	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
@@ -153,12 +160,27 @@ good_area:
 			goto do_sigbus;
 		BUG();
 	}
-	if (fault & VM_FAULT_MAJOR) {
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
-		tsk->maj_flt++;
-	} else {
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
-		tsk->min_flt++;
+	if (flags & FAULT_FLAG_ALLOW_RETRY) {
+		if (fault & VM_FAULT_MAJOR) {
+			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
+						  regs, address);
+			tsk->maj_flt++;
+		} else {
+			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
+						  regs, address);
+			tsk->min_flt++;
+		}
+		if (fault & VM_FAULT_RETRY) {
+			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+			/*
+			 * No need to up_read(&mm->mmap_sem) as we would
+			 * have already released it in __lock_page_or_retry
+			 * in mm/filemap.c.
+			 */
+
+			goto retry;
+		}
 	}
 
 	up_read(&mm->mmap_sem);
-- 
1.7.6


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

* Re: [PATCH 1/1] mips: fault.c: Port OOM changes to do_page_fault
  2011-12-23 11:22 [PATCH 1/1] mips: fault.c: Port OOM changes to do_page_fault Kautuk Consul
@ 2011-12-23 11:42 ` Kautuk Consul
  2012-01-04  4:52   ` Kautuk Consul
  2012-01-16 15:47 ` Ralf Baechle
  1 sibling, 1 reply; 4+ messages in thread
From: Kautuk Consul @ 2011-12-23 11:42 UTC (permalink / raw)
  To: Ralf Baechle, Ingo Molnar, Peter Zijlstra
  Cc: linux-mips, linux-kernel, Mohd. Faris, Kautuk Consul

[-- Attachment #1: Type: text/plain, Size: 755 bytes --]

>
> Without these changes, my MIPS board encounters many hang and livelock
> scenarios.
> After applying this patch, OOM feature performance improves according to
> my testing.
>

Just to clarify the hang scenario I am talking about, the test case I
used to reproduce
this problem is attached to this email.
Running this a few times hangs my console and then even Ctrl-C signals
do not get handled
and I also do not get back the command prompt.

After applying this patch things seem to improve, but there are still
some hangs which I
encounter which I am further trying to debug.

However, since the generic part of the kernel(mm/filemap.c) now
supports killable and
retryable page fault handling, I thought that this change would be
valid for MIPS too.

[-- Attachment #2: stress_32k.c --]
[-- Type: text/x-csrc, Size: 3897 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

#define ALLOC_BYTE 512*1024
#define COUNT 50

void *alloc_function_one( void *ptr );
void *alloc_function_two( void *ptr );
void *alloc_function_three( void *ptr );
void *alloc_function_four( void *ptr );
void *alloc_function_five( void *ptr );
void *enable_function( void *ptr );


int main(int argc, char *argv[])
{
	pthread_t thread1, thread2, thread3, thread4, thread5;
	char *message1 = "Thread 1";
	char *message2 = "Thread 2";
	char *message3 = "Thread 3";
	char *message4 = "Thread 4";
	char *message5 = "Thread 5";
	int iret1 = -1;
	int iret2 = -1;
	int iret3 = -1;
	int iret4 = -1;
	int iret5 = -1;
	fork();
	iret1 = pthread_create( &thread1, NULL, alloc_function_one, (void*) message1);
	iret2 = pthread_create( &thread2, NULL, alloc_function_two, (void*) message2);
	iret2 = pthread_create( &thread3, NULL, alloc_function_three, (void*) message2);
	iret2 = pthread_create( &thread4, NULL, alloc_function_four, (void*) message2);
	iret2 = pthread_create( &thread5, NULL, alloc_function_five, (void*) message2);

	pthread_join( thread1, NULL);
	pthread_join( thread2, NULL);
	pthread_join( thread3, NULL);
	pthread_join( thread4, NULL);
	pthread_join( thread5, NULL);

	printf("Thread 1 returns: %d\n",iret1);
	printf("Thread 2 returns: %d\n",iret2);
	printf("Thread 3 returns: %d\n",iret3);
	printf("Thread 4 returns: %d\n",iret4);
	printf("Thread 5 returns: %d\n",iret5);
	exit(0);
}

void *alloc_function_two( void *ptr )
{
	char *message;
	message = (char *) ptr;
	void *myblock[COUNT];
	int i= 0,j=0;
	int freed=0;
	printf("message_alloc  \n");
	while(1)
	{
		memset(myblock,0,sizeof(myblock));
		printf("message_alloc %s \n",message);
		for(i=0;i< COUNT ;i++)
		{
			myblock[i] = (void *) malloc(ALLOC_BYTE);
			memset(myblock[i],1, ALLOC_BYTE);
		}
	}
}


void *alloc_function_one( void *ptr )
{
	char *message;
	message = (char *) ptr;
	void *myblock[COUNT];
	int i= 0,j=0;
	int freed=0;
	printf("message_alloc  \n");
	while(1)
	{
		memset(myblock,0,sizeof(myblock));
		printf("message_alloc %s \n",message);
		for(i=0;i< COUNT ;i++)
		{
			myblock[i] = (void *) malloc(ALLOC_BYTE);
			memset(myblock[i],1, ALLOC_BYTE);
		}
	}
}

void *alloc_function_three( void *ptr )
{
       char *message;
        message = (char *) ptr;
        void *myblock[COUNT];
        int i= 0,j=0;
        int freed=0;
        printf("message_alloc  \n");
        while(1)
        {
                memset(myblock,0,sizeof(myblock));
                printf("message_alloc %s \n",message);
                for(i=0;i< COUNT ;i++)
                {
                        myblock[i] = (void *) malloc(ALLOC_BYTE);
                        memset(myblock[i],1, ALLOC_BYTE);
                }
        }
}
void *alloc_function_four( void *ptr )
{
       char *message;
        message = (char *) ptr;
        void *myblock[COUNT];
        int i= 0,j=0;
        int freed=0;
        printf("message_alloc  \n");
        while(1)
        {
                memset(myblock,0,sizeof(myblock));
                printf("message_alloc %s \n",message);
                for(i=0;i< COUNT ;i++)
                {
                        myblock[i] = (void *) malloc(ALLOC_BYTE);
                        memset(myblock[i],1, ALLOC_BYTE);
                }
        }
}
void *alloc_function_five( void *ptr )
{
       char *message;
        message = (char *) ptr;
        void *myblock[COUNT];
        int i= 0,j=0;
        int freed=0;
        printf("message_alloc  \n");
        while(1)
        {
                memset(myblock,0,sizeof(myblock));
                printf("message_alloc %s \n",message);
                for(i=0;i< COUNT ;i++)
                {
                        myblock[i] = (void *) malloc(ALLOC_BYTE);
                        memset(myblock[i],1, ALLOC_BYTE);
                }
        }
}

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

* Re: [PATCH 1/1] mips: fault.c: Port OOM changes to do_page_fault
  2011-12-23 11:42 ` Kautuk Consul
@ 2012-01-04  4:52   ` Kautuk Consul
  0 siblings, 0 replies; 4+ messages in thread
From: Kautuk Consul @ 2012-01-04  4:52 UTC (permalink / raw)
  To: Ralf Baechle, Ingo Molnar, Peter Zijlstra
  Cc: linux-mips, linux-kernel, Mohd. Faris, Kautuk Consul

>
> However, since the generic part of the kernel(mm/filemap.c) now
> supports killable and
> retryable page fault handling, I thought that this change would be
> valid for MIPS too.


Did anyone get a chance to review this patch?

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

* Re: [PATCH 1/1] mips: fault.c: Port OOM changes to do_page_fault
  2011-12-23 11:22 [PATCH 1/1] mips: fault.c: Port OOM changes to do_page_fault Kautuk Consul
  2011-12-23 11:42 ` Kautuk Consul
@ 2012-01-16 15:47 ` Ralf Baechle
  1 sibling, 0 replies; 4+ messages in thread
From: Ralf Baechle @ 2012-01-16 15:47 UTC (permalink / raw)
  To: Kautuk Consul
  Cc: Ingo Molnar, Peter Zijlstra, linux-mips, linux-kernel,
	Mohd. Faris

On Fri, Dec 23, 2011 at 04:52:42PM +0530, Kautuk Consul wrote:

Applied.  Thanks Kautuk!

  Ralf

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

end of thread, other threads:[~2012-01-16 15:47 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-23 11:22 [PATCH 1/1] mips: fault.c: Port OOM changes to do_page_fault Kautuk Consul
2011-12-23 11:42 ` Kautuk Consul
2012-01-04  4:52   ` Kautuk Consul
2012-01-16 15:47 ` Ralf Baechle

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