[patch] Re: 2.4.3-pre6: agpart.o causes arch/i386/mm/ioremap.c hang

2001-03-23 Thread Andrew Morton

"Adam J. Richter" wrote:
> 
>  In case anyone is interested, the conflicting lock of
> init_mm.page_table_lock was acquired in line 1318 of mm/memory.c,
> in pte_alloc.

You can sorta blame me for that.  I reviewed the locking in
the mmap_sem patch and said it was correct :(

I only checked that the new locking was correct, rather than
checking that the new locking *rules* were being complied
with kernel-wide.

pmd_alloc() has the same problem.  It requires ->page_table_lock,
and we have bugs there. Fixed in this patch.

Linus, this patch includes the mm->rss locking stuff which
I sent yesterday.

Also, is the comment over remap_page_range true?  Should the caller
be doing a down_write(mmap_sem)?  If so, then there are
about thirty callers who don't.  I've looked at each one,
and it is safe to do the down_write() *within* remap_page_range().



--- linux-2.4.3-pre6/fs/exec.c  Thu Mar 22 18:52:52 2001
+++ linux-akpm/fs/exec.cFri Mar 23 22:08:48 2001
@@ -252,6 +252,8 @@
 /*
  * This routine is used to map in a page into an address space: needed by
  * execve() for the initial stack and environment pages.
+ *
+ * tsk->mmap_sem is held for writing.
  */
 void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long 
address)
 {
@@ -291,6 +293,7 @@
unsigned long stack_base;
struct vm_area_struct *mpnt;
int i;
+   unsigned long rss_increment = 0;
 
stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
 
@@ -322,11 +325,14 @@
struct page *page = bprm->page[i];
if (page) {
bprm->page[i] = NULL;
-   current->mm->rss++;
+   rss_increment++;
put_dirty_page(current,page,stack_base);
}
stack_base += PAGE_SIZE;
}
+   spin_lock(>mm->page_table_lock);
+   current->mm->rss += rss_increment;
+   spin_unlock(>mm->page_table_lock);
up_write(>mm->mmap_sem);

return 0;
--- linux-2.4.3-pre6/include/linux/mm.h Thu Mar 22 18:52:52 2001
+++ linux-akpm/include/linux/mm.h   Fri Mar 23 23:32:00 2001
@@ -407,6 +407,8 @@
  * On a two-level page table, this ends up being trivial. Thus the
  * inlining and the symmetry break with pte_alloc() that does all
  * of this out-of-line.
+ *
+ * __pmd_alloc() requires that mm->page_table_lock be held, so we do too.
  */
 static inline pmd_t *pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long 
address)
 {
--- linux-2.4.3-pre6/include/linux/sched.h  Thu Mar 22 18:52:52 2001
+++ linux-akpm/include/linux/sched.hFri Mar 23 22:08:48 2001
@@ -209,9 +209,12 @@
atomic_t mm_count;  /* How many references to "struct 
mm_struct" (users count as 1) */
int map_count;  /* number of VMAs */
struct rw_semaphore mmap_sem;
-   spinlock_t page_table_lock;
+   spinlock_t page_table_lock; /* Protects task page tables and 
+mm->rss */
 
-   struct list_head mmlist;/* List of all active mm's */
+   struct list_head mmlist;/* List of all active mm's.  These are 
+globally strung
+* together off init_mm.mmlist, and 
+are protected
+* by mmlist_lock
+*/
 
unsigned long start_code, end_code, start_data, end_data;
unsigned long start_brk, brk, start_stack;
--- linux-2.4.3-pre6/mm/memory.cFri Mar 23 22:16:55 2001
+++ linux-akpm/mm/memory.c  Fri Mar 23 23:32:05 2001
@@ -374,7 +374,6 @@
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
} while (address && (address < end));
-   spin_unlock(>page_table_lock);
/*
 * Update rss for the mm_struct (not necessarily current->mm)
 * Notice that rss is an unsigned long.
@@ -383,6 +382,7 @@
mm->rss -= freed;
else
mm->rss = 0;
+   spin_unlock(>page_table_lock);
 }
 
 
@@ -655,6 +655,7 @@
} while (address && (address < end));
 }
 
+/* mm->page_table_lock must be held */
 static inline int zeromap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long 
address,
 unsigned long size, pgprot_t prot)
 {
@@ -734,6 +735,7 @@
} while (address && (address < end));
 }
 
+/* mm->page_table_lock must be held */
 static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long 
address, unsigned long size,
unsigned long phys_addr, pgprot_t prot)
 {
@@ -792,6 +794,8 @@
  *  - flush the old one
  *  - update the page tables
  *  - inform the TLB about the new one
+ *
+ * We hold the mm semaphore for reading and vma->vm_mm->page_table_lock
  */
 static inline void establish_pte(struct vm_area_struct * vma, unsigned long address, 
pte_t 

Re: 2.4.3-pre6: agpart.o causes arch/i386/mm/ioremap.c hang

2001-03-23 Thread Adam J. Richter

I wrote:

>   Under linux-2.4.3-pre6 compiled for SMP, loading agpgart.o
>hangs the system in remap_area_pages (arch/i386/mm/ioremap.c) at
>the call to spin_lock(_mm.page_table_lock), which is not in 2.4.2.
[...]
>   agp_backend_initialize
>   agp_generic_create_gatt_table
>   io_remap_nocache
>   __ioremap
>   remap_area_pages
[...]


>   I'm rebuilding the kernel now with a modified spin_lock()
>routine that should tell me who acquired the lock previously [...]

 In case anyone is interested, the conflicting lock of
init_mm.page_table_lock was acquired in line 1318 of mm/memory.c,
in pte_alloc.

One way that this might be happening is that it looks like
no page_table_lock is every acquired by vmalloc, which results in
the following call graph:

vmalloc
__vmalloc
vmalloc_area_pages
alloc_area_pmd
pte_alloc ...which assumes (here incorrectly) that
mm->page_table_lock is held, and sometimes releases
and reacquires mm->page_table_lock.

I will attempt to analyze this further tomorrow if nobody
beats me to it.

Adam J. Richter __ __   4880 Stevens Creek Blvd, Suite 104
[EMAIL PROTECTED] \ /  San Jose, California 95129-1034
+1 408 261-6630 | g g d r a s i l   United States of America
fax +1 408 261-6631  "Free Software For The Rest Of Us."
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/



2.4.3-pre6: agpart.o causes arch/i386/mm/ioremap.c hang

2001-03-23 Thread Adam J. Richter

Under linux-2.4.3-pre6 compiled for SMP, loading agpgart.o
hangs the system in remap_area_pages (arch/i386/mm/ioremap.c) at
the call to spin_lock(_mm.page_table_lock), which is not in 2.4.2.

When I load agpgart.o, I get the following messages:

Linux agpgart interface v0.99 (c) Jeff Hartmann
agpgart: Maximum main memory to use for agp memory: 690M
agpgart: Detected Via Apollo Pro chipset

After that, the console keys (RightAlt ScrollLock, Alt-F2, etc.)
but there is not other response to my keystrokes and the system is no
longer pingable.  The call graphic is basically:

agp_backend_initialize
agp_generic_create_gatt_table
io_remap_nocache
__ioremap
remap_area_pages

I've made a cursory search through the kernel sources for what
else might be holding this lock, but I have not yet found anything.

I'm rebuilding the kernel now with a modified spin_lock()
routine that should tell me who acquired the lock previously; however,
I really do not understand this part of the kernel enough to know
what the changes were intended to do in the first place.  So, knowing
where else the lock was acquired will not necessarily be enough for
me to be able to generate a patch.  Anyhow, I imagine that this
lock is being held by some code that can block.  We'll see.

Adam J. Richter __ __   4880 Stevens Creek Blvd, Suite 104
[EMAIL PROTECTED] \ /  San Jose, California 95129-1034
+1 408 261-6630 | g g d r a s i l   United States of America
fax +1 408 261-6631  "Free Software For The Rest Of Us."
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/



2.4.3-pre6: agpart.o causes arch/i386/mm/ioremap.c hang

2001-03-23 Thread Adam J. Richter

Under linux-2.4.3-pre6 compiled for SMP, loading agpgart.o
hangs the system in remap_area_pages (arch/i386/mm/ioremap.c) at
the call to spin_lock(init_mm.page_table_lock), which is not in 2.4.2.

When I load agpgart.o, I get the following messages:

Linux agpgart interface v0.99 (c) Jeff Hartmann
agpgart: Maximum main memory to use for agp memory: 690M
agpgart: Detected Via Apollo Pro chipset

After that, the console keys (RightAlt ScrollLock, Alt-F2, etc.)
but there is not other response to my keystrokes and the system is no
longer pingable.  The call graphic is basically:

agp_backend_initialize
agp_generic_create_gatt_table
io_remap_nocache
__ioremap
remap_area_pages

I've made a cursory search through the kernel sources for what
else might be holding this lock, but I have not yet found anything.

I'm rebuilding the kernel now with a modified spin_lock()
routine that should tell me who acquired the lock previously; however,
I really do not understand this part of the kernel enough to know
what the changes were intended to do in the first place.  So, knowing
where else the lock was acquired will not necessarily be enough for
me to be able to generate a patch.  Anyhow, I imagine that this
lock is being held by some code that can block.  We'll see.

Adam J. Richter __ __   4880 Stevens Creek Blvd, Suite 104
[EMAIL PROTECTED] \ /  San Jose, California 95129-1034
+1 408 261-6630 | g g d r a s i l   United States of America
fax +1 408 261-6631  "Free Software For The Rest Of Us."
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/



Re: 2.4.3-pre6: agpart.o causes arch/i386/mm/ioremap.c hang

2001-03-23 Thread Adam J. Richter

I wrote:

   Under linux-2.4.3-pre6 compiled for SMP, loading agpgart.o
hangs the system in remap_area_pages (arch/i386/mm/ioremap.c) at
the call to spin_lock(init_mm.page_table_lock), which is not in 2.4.2.
[...]
   agp_backend_initialize
   agp_generic_create_gatt_table
   io_remap_nocache
   __ioremap
   remap_area_pages
[...]


   I'm rebuilding the kernel now with a modified spin_lock()
routine that should tell me who acquired the lock previously [...]

 In case anyone is interested, the conflicting lock of
init_mm.page_table_lock was acquired in line 1318 of mm/memory.c,
in pte_alloc.

One way that this might be happening is that it looks like
no page_table_lock is every acquired by vmalloc, which results in
the following call graph:

vmalloc
__vmalloc
vmalloc_area_pages
alloc_area_pmd
pte_alloc ...which assumes (here incorrectly) that
mm-page_table_lock is held, and sometimes releases
and reacquires mm-page_table_lock.

I will attempt to analyze this further tomorrow if nobody
beats me to it.

Adam J. Richter __ __   4880 Stevens Creek Blvd, Suite 104
[EMAIL PROTECTED] \ /  San Jose, California 95129-1034
+1 408 261-6630 | g g d r a s i l   United States of America
fax +1 408 261-6631  "Free Software For The Rest Of Us."
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/