All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH, RFC] xip: use i_mutex for xip_file_fault
@ 2011-09-10 15:31 Marco Stornelli
  2011-09-10 15:56 ` Al Viro
  0 siblings, 1 reply; 6+ messages in thread
From: Marco Stornelli @ 2011-09-10 15:31 UTC (permalink / raw)
  To: Linux FS Devel; +Cc: Linux Kernel

From: Marco Stornelli <marco.stornelli@gmail.com>

There aren't sufficient sync points for a fs for xip operations. In 
particular for the mmap case. It can be not sufficient to lock/unlock 
to do some operation inside get_xip_mem callback. For xip_file_read 
it's really easy to write a fs specific wrapper, xip_file_write hold 
i_mutex so no problem. With this patch we can avoid concurrent truncate 
operation and xip mmap.

Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
---

--- filemap_xip.c.orig	2011-09-10 17:16:56.000000000 +0200
+++ filemap_xip.c	2011-09-10 17:19:25.000000000 +0200
@@ -230,6 +230,7 @@ static int xip_file_fault(struct vm_area
 	int error;
 
 	/* XXX: are VM_FAULT_ codes OK? */
+	mutex_lock(&inode->i_mutex);
 again:
 	size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	if (vmf->pgoff >= size)
@@ -239,8 +240,10 @@ again:
 						&xip_mem, &xip_pfn);
 	if (likely(!error))
 		goto found;
-	if (error != -ENODATA)
+	if (error != -ENODATA) {
+		mutex_unlock(&inode->i_mutex);
 		return VM_FAULT_OOM;
+	}
 
 	/* sparse block */
 	if ((vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) &&
@@ -253,17 +256,22 @@ again:
 		error = mapping->a_ops->get_xip_mem(mapping, vmf->pgoff, 1,
 							&xip_mem, &xip_pfn);
 		mutex_unlock(&xip_sparse_mutex);
-		if (error)
+		if (error) {
+			mutex_unlock(&inode->i_mutex);
 			return VM_FAULT_SIGBUS;
+		}
 		/* unmap sparse mappings at pgoff from all other vmas */
 		__xip_unmap(mapping, vmf->pgoff);
 
 found:
 		err = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address,
 							xip_pfn);
-		if (err == -ENOMEM)
+		if (err == -ENOMEM) {
+			mutex_unlock(&inode->i_mutex);
 			return VM_FAULT_OOM;
+		}
 		BUG_ON(err);
+		mutex_unlock(&inode->i_mutex);
 		return VM_FAULT_NOPAGE;
 	} else {
 		int err, ret = VM_FAULT_OOM;
@@ -292,6 +300,7 @@ found:
 out:
 		write_seqcount_end(&xip_sparse_seq);
 		mutex_unlock(&xip_sparse_mutex);
+		mutex_unlock(&inode->i_mutex);
 
 		return ret;
 	}

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

* Re: [PATCH, RFC] xip: use i_mutex for xip_file_fault
  2011-09-10 15:31 [PATCH, RFC] xip: use i_mutex for xip_file_fault Marco Stornelli
@ 2011-09-10 15:56 ` Al Viro
  2011-09-11  8:25   ` Marco Stornelli
  0 siblings, 1 reply; 6+ messages in thread
From: Al Viro @ 2011-09-10 15:56 UTC (permalink / raw)
  To: Marco Stornelli; +Cc: Linux FS Devel, Linux Kernel

On Sat, Sep 10, 2011 at 05:31:39PM +0200, Marco Stornelli wrote:
> From: Marco Stornelli <marco.stornelli@gmail.com>
> 
> There aren't sufficient sync points for a fs for xip operations. In 
> particular for the mmap case. It can be not sufficient to lock/unlock 
> to do some operation inside get_xip_mem callback. For xip_file_read 
> it's really easy to write a fs specific wrapper, xip_file_write hold 
> i_mutex so no problem. With this patch we can avoid concurrent truncate 
> operation and xip mmap.

Umm...  I really don't like that; what's going to happen if you have a file
mmapped and do write() to that file from address in that mapping?

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

* Re: [PATCH, RFC] xip: use i_mutex for xip_file_fault
  2011-09-10 15:56 ` Al Viro
@ 2011-09-11  8:25   ` Marco Stornelli
  2011-09-11 11:15     ` Al Viro
  0 siblings, 1 reply; 6+ messages in thread
From: Marco Stornelli @ 2011-09-11  8:25 UTC (permalink / raw)
  To: Al Viro; +Cc: Linux FS Devel, Linux Kernel

Il 10/09/2011 17:56, Al Viro ha scritto:
> On Sat, Sep 10, 2011 at 05:31:39PM +0200, Marco Stornelli wrote:
>> From: Marco Stornelli<marco.stornelli@gmail.com>
>>
>> There aren't sufficient sync points for a fs for xip operations. In
>> particular for the mmap case. It can be not sufficient to lock/unlock
>> to do some operation inside get_xip_mem callback. For xip_file_read
>> it's really easy to write a fs specific wrapper, xip_file_write hold
>> i_mutex so no problem. With this patch we can avoid concurrent truncate
>> operation and xip mmap.
>
> Umm...  I really don't like that; what's going to happen if you have a file
> mmapped and do write() to that file from address in that mapping?
>

Nothing strange. There is a serialization of the operations. Maybe I 
don't understand the point here.

Marco

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

* Re: [PATCH, RFC] xip: use i_mutex for xip_file_fault
  2011-09-11  8:25   ` Marco Stornelli
@ 2011-09-11 11:15     ` Al Viro
  2011-09-11 11:25       ` Al Viro
  0 siblings, 1 reply; 6+ messages in thread
From: Al Viro @ 2011-09-11 11:15 UTC (permalink / raw)
  To: Marco Stornelli; +Cc: Linux FS Devel, Linux Kernel

On Sun, Sep 11, 2011 at 10:25:03AM +0200, Marco Stornelli wrote:
> Il 10/09/2011 17:56, Al Viro ha scritto:
> >On Sat, Sep 10, 2011 at 05:31:39PM +0200, Marco Stornelli wrote:
> >>From: Marco Stornelli<marco.stornelli@gmail.com>
> >>
> >>There aren't sufficient sync points for a fs for xip operations. In
> >>particular for the mmap case. It can be not sufficient to lock/unlock
> >>to do some operation inside get_xip_mem callback. For xip_file_read
> >>it's really easy to write a fs specific wrapper, xip_file_write hold
> >>i_mutex so no problem. With this patch we can avoid concurrent truncate
> >>operation and xip mmap.
> >
> >Umm...  I really don't like that; what's going to happen if you have a file
> >mmapped and do write() to that file from address in that mapping?
> >
> 
> Nothing strange. There is a serialization of the operations. Maybe I
> don't understand the point here.

write() grabs ->i_mutex on the file it's going to write to.  It uses
copy_from_user() while holding ->i_mutex; that can end up calling ->fault().
If your data comes from the same file mmapped in your address space, you
have xip_write_fault() called while you are in xip_file_write() and *already*
are holding ->i_mutex on the same inode.  With your patch it will, AFAICS,
cheerfully deadlock.


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

* Re: [PATCH, RFC] xip: use i_mutex for xip_file_fault
  2011-09-11 11:15     ` Al Viro
@ 2011-09-11 11:25       ` Al Viro
  2011-09-11 15:57         ` Marco Stornelli
  0 siblings, 1 reply; 6+ messages in thread
From: Al Viro @ 2011-09-11 11:25 UTC (permalink / raw)
  To: Marco Stornelli; +Cc: Linux FS Devel, Linux Kernel

On Sun, Sep 11, 2011 at 12:15:04PM +0100, Al Viro wrote:

> write() grabs ->i_mutex on the file it's going to write to.  It uses
> copy_from_user() while holding ->i_mutex; that can end up calling ->fault().
> If your data comes from the same file mmapped in your address space, you
> have xip_write_fault() called while you are in xip_file_write() and *already*
> are holding ->i_mutex on the same inode.  With your patch it will, AFAICS,
> cheerfully deadlock.

Oh, wait...  You are only doing that to write side of pagefault?  That's
better, but not much:

thread 1: mmap the file, modify mapping
thread 2: write() to file

The former will do xip_write_fault() while holding ->mmap_sem.
The latter will do copy_from_user() from xip_file_write(), getting
pagefaults while holding ->i_mutex.

Note that we are grabbing ->mmap_sem and ->i_mutex in opposite orders.
I.e. that will deadlock on you - all you need is threads sharing the
address space.

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

* Re: [PATCH, RFC] xip: use i_mutex for xip_file_fault
  2011-09-11 11:25       ` Al Viro
@ 2011-09-11 15:57         ` Marco Stornelli
  0 siblings, 0 replies; 6+ messages in thread
From: Marco Stornelli @ 2011-09-11 15:57 UTC (permalink / raw)
  To: Al Viro; +Cc: Linux FS Devel, Linux Kernel



Il 11/09/2011 13:25, Al Viro ha scritto:
> On Sun, Sep 11, 2011 at 12:15:04PM +0100, Al Viro wrote:
>
>> write() grabs ->i_mutex on the file it's going to write to.  It uses
>> copy_from_user() while holding ->i_mutex; that can end up calling ->fault().
>> If your data comes from the same file mmapped in your address space, you
>> have xip_write_fault() called while you are in xip_file_write() and *already*
>> are holding ->i_mutex on the same inode.  With your patch it will, AFAICS,
>> cheerfully deadlock.
>
> Oh, wait...  You are only doing that to write side of pagefault?  That's
> better, but not much:
>
> thread 1: mmap the file, modify mapping
> thread 2: write() to file
>
> The former will do xip_write_fault() while holding ->mmap_sem.
> The latter will do copy_from_user() from xip_file_write(), getting
> pagefaults while holding ->i_mutex.
>
> Note that we are grabbing ->mmap_sem and ->i_mutex in opposite orders.
> I.e. that will deadlock on you - all you need is threads sharing the
> address space.
>

Ok, thank you very much for the on-line debug :) So i_mutex is not a 
good lock to use in this situation. It was a common sync point, but it 
has some collateral effect on the write path that we must avoid. At this 
point, what can be a good strategy? Any opinion is welcome.

Marco

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

end of thread, other threads:[~2011-09-11 16:03 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-10 15:31 [PATCH, RFC] xip: use i_mutex for xip_file_fault Marco Stornelli
2011-09-10 15:56 ` Al Viro
2011-09-11  8:25   ` Marco Stornelli
2011-09-11 11:15     ` Al Viro
2011-09-11 11:25       ` Al Viro
2011-09-11 15:57         ` Marco Stornelli

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.