<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux.git/fs/fuse/file.c, branch v3.13</title>
<subtitle>Linux kernel source tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/'/>
<entry>
<title>fuse: writepages: protect secondary requests from fuse file release</title>
<updated>2013-11-05T09:11:29+00:00</updated>
<author>
<name>Maxim Patlasov</name>
<email>MPatlasov@parallels.com</email>
</author>
<published>2013-10-02T17:38:54+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=ce128de6260f86a990ed44a697f26d0859684f28'/>
<id>ce128de6260f86a990ed44a697f26d0859684f28</id>
<content type='text'>
All async fuse requests must be supplied with extra reference to a fuse
file.  This is necessary to ensure that the fuse file is not released until
all in-flight requests are completed.  Fuse secondary writeback requests
must obey this rule as well.

Signed-off-by: Maxim Patlasov &lt;MPatlasov@parallels.com&gt;
Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
All async fuse requests must be supplied with extra reference to a fuse
file.  This is necessary to ensure that the fuse file is not released until
all in-flight requests are completed.  Fuse secondary writeback requests
must obey this rule as well.

Signed-off-by: Maxim Patlasov &lt;MPatlasov@parallels.com&gt;
Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fuse: writepages: update bdi writeout when deleting secondary request</title>
<updated>2013-11-05T09:11:28+00:00</updated>
<author>
<name>Maxim Patlasov</name>
<email>MPatlasov@parallels.com</email>
</author>
<published>2013-10-02T17:38:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=41b6e41fc609753a9386d24295f7ed03b28c4601'/>
<id>41b6e41fc609753a9386d24295f7ed03b28c4601</id>
<content type='text'>
BDI_WRITTEN counter is used to estimate bdi bandwidth.  It must be
incremented every time as bdi ends page writeback.  No matter whether it
was fulfilled by actual write or by discarding the request (e.g. due to
shrunk i_size).

Note that even before writepages patches, the case "Got truncated off
completely" was handled in fuse_send_writepage() by calling
fuse_writepage_finish() which updated BDI_WRITTEN unconditionally.

Signed-off-by: Maxim Patlasov &lt;MPatlasov@parallels.com&gt;
Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
BDI_WRITTEN counter is used to estimate bdi bandwidth.  It must be
incremented every time as bdi ends page writeback.  No matter whether it
was fulfilled by actual write or by discarding the request (e.g. due to
shrunk i_size).

Note that even before writepages patches, the case "Got truncated off
completely" was handled in fuse_send_writepage() by calling
fuse_writepage_finish() which updated BDI_WRITTEN unconditionally.

Signed-off-by: Maxim Patlasov &lt;MPatlasov@parallels.com&gt;
Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fuse: writepages: crop secondary requests</title>
<updated>2013-11-05T09:11:27+00:00</updated>
<author>
<name>Maxim Patlasov</name>
<email>MPatlasov@parallels.com</email>
</author>
<published>2013-10-02T17:38:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=6eaf4782eb09e28dbd13d23b9ce0fb7646daf37e'/>
<id>6eaf4782eb09e28dbd13d23b9ce0fb7646daf37e</id>
<content type='text'>
If writeback happens while fuse is in FUSE_NOWRITE condition, the request
will be queued but not processed immediately (see fuse_flush_writepages()).
Until FUSE_NOWRITE becomes relaxed, more writebacks can happen.  They will
be queued as "secondary" requests to that first ("primary") request.

Existing implementation crops only primary request.  This is not correct
because a subsequent extending write(2) may increase i_size and then
secondary requests won't be cropped properly.  The result would be stale
data written to the server to a file offset where zeros must be.

Similar problem may happen if secondary requests are attached to an
in-flight request that was already cropped.

The patch solves the issue by cropping all secondary requests in
fuse_writepage_end().  Thanks to Miklos for idea.

Signed-off-by: Maxim Patlasov &lt;MPatlasov@parallels.com&gt;
Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
If writeback happens while fuse is in FUSE_NOWRITE condition, the request
will be queued but not processed immediately (see fuse_flush_writepages()).
Until FUSE_NOWRITE becomes relaxed, more writebacks can happen.  They will
be queued as "secondary" requests to that first ("primary") request.

Existing implementation crops only primary request.  This is not correct
because a subsequent extending write(2) may increase i_size and then
secondary requests won't be cropped properly.  The result would be stale
data written to the server to a file offset where zeros must be.

Similar problem may happen if secondary requests are attached to an
in-flight request that was already cropped.

The patch solves the issue by cropping all secondary requests in
fuse_writepage_end().  Thanks to Miklos for idea.

Signed-off-by: Maxim Patlasov &lt;MPatlasov@parallels.com&gt;
Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fuse: writepages: roll back changes if request not found</title>
<updated>2013-11-05T09:11:26+00:00</updated>
<author>
<name>Maxim Patlasov</name>
<email>MPatlasov@parallels.com</email>
</author>
<published>2013-10-02T11:01:07+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=f6011081f5e290756bd90fe96f1e86d3eac76f77'/>
<id>f6011081f5e290756bd90fe96f1e86d3eac76f77</id>
<content type='text'>
fuse_writepage_in_flight() returns false if it fails to find request with
given index in fi-&gt;writepages.  Then the caller proceeds with populating
data-&gt;orig_pages[] and incrementing req-&gt;num_pages.  Hence,
fuse_writepage_in_flight() must revert changes it made in request before
returning false.

Signed-off-by: Maxim Patlasov &lt;MPatlasov@parallels.com&gt;
Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
fuse_writepage_in_flight() returns false if it fails to find request with
given index in fi-&gt;writepages.  Then the caller proceeds with populating
data-&gt;orig_pages[] and incrementing req-&gt;num_pages.  Hence,
fuse_writepage_in_flight() must revert changes it made in request before
returning false.

Signed-off-by: Maxim Patlasov &lt;MPatlasov@parallels.com&gt;
Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fuse: writepage: skip already in flight</title>
<updated>2013-10-01T14:44:53+00:00</updated>
<author>
<name>Miklos Szeredi</name>
<email>mszeredi@suse.cz</email>
</author>
<published>2013-10-01T14:44:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=ff17be0864777fe0dfb0a477868a8cb95c1ff90e'/>
<id>ff17be0864777fe0dfb0a477868a8cb95c1ff90e</id>
<content type='text'>
If -&gt;writepage() tries to write back a page whose copy is still in flight,
then just skip by calling redirty_page_for_writepage().

This is OK, since now -&gt;writepage() should never be called for data
integrity sync.

Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
If -&gt;writepage() tries to write back a page whose copy is still in flight,
then just skip by calling redirty_page_for_writepage().

This is OK, since now -&gt;writepage() should never be called for data
integrity sync.

Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fuse: writepages: handle same page rewrites</title>
<updated>2013-10-01T14:44:53+00:00</updated>
<author>
<name>Miklos Szeredi</name>
<email>mszeredi@suse.cz</email>
</author>
<published>2013-10-01T14:44:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=8b284dc47291daf72fe300e1138a2e7ed56f38ab'/>
<id>8b284dc47291daf72fe300e1138a2e7ed56f38ab</id>
<content type='text'>
As Maxim Patlasov pointed out, it's possible to get a dirty page while it's
copy is still under writeback, despite fuse_page_mkwrite() doing its thing
(direct IO).

This could result in two concurrent write request for the same offset, with
data corruption if they get mixed up.

To prevent this, fuse needs to check and delay such writes.  This
implementation does this by:

 1. check if page is still under writeout, if so create a new, single page
    secondary request for it

 2. chain this secondary request onto the in-flight request

 2/a. if a seconday request for the same offset was already chained to the
    in-flight request, then just copy the contents of the page and discard
    the new secondary request.  This makes sure that for each page will
    have at most two requests associated with it

 3. when the in-flight request finished, send off all secondary requests
    chained onto it

Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
As Maxim Patlasov pointed out, it's possible to get a dirty page while it's
copy is still under writeback, despite fuse_page_mkwrite() doing its thing
(direct IO).

This could result in two concurrent write request for the same offset, with
data corruption if they get mixed up.

To prevent this, fuse needs to check and delay such writes.  This
implementation does this by:

 1. check if page is still under writeout, if so create a new, single page
    secondary request for it

 2. chain this secondary request onto the in-flight request

 2/a. if a seconday request for the same offset was already chained to the
    in-flight request, then just copy the contents of the page and discard
    the new secondary request.  This makes sure that for each page will
    have at most two requests associated with it

 3. when the in-flight request finished, send off all secondary requests
    chained onto it

Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fuse: writepages: fix aggregation</title>
<updated>2013-10-01T14:44:53+00:00</updated>
<author>
<name>Miklos Szeredi</name>
<email>mszeredi@suse.cz</email>
</author>
<published>2013-10-01T14:44:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=1e112a484e58cd13e6c90a3dfd9e54ea5859b795'/>
<id>1e112a484e58cd13e6c90a3dfd9e54ea5859b795</id>
<content type='text'>
Checking against tmp-page indexes is not very useful, and results in one
(or rarely two) page requests.  Which is not much of an improvement...

Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Checking against tmp-page indexes is not very useful, and results in one
(or rarely two) page requests.  Which is not much of an improvement...

Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fuse: fix race in fuse_writepages()</title>
<updated>2013-10-01T14:44:53+00:00</updated>
<author>
<name>Maxim Patlasov</name>
<email>MPatlasov@parallels.com</email>
</author>
<published>2013-08-16T11:51:41+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=2d033eaa0073d276ee6c324dd0ade0c5074a5542'/>
<id>2d033eaa0073d276ee6c324dd0ade0c5074a5542</id>
<content type='text'>
The patch fixes a race between ftruncate(2), mmap-ed write and write(2):

1) An user makes a page dirty via mmap-ed write.
2) The user performs shrinking truncate(2) intended to purge the page.
3) Before fuse_do_setattr calls truncate_pagecache, the page goes to
   writeback. fuse_writepages_fill attaches a new page to FUSE_WRITE request,
   then releases the original page by end_page_writeback and unlock it.
4) fuse_do_setattr completes and successfully returns. Since now, i_mutex
   is free.
5) Ordinary write(2) extends i_size back to cover the page. Note that
   fuse_send_write_pages do wait for fuse writeback, but for another
   page-&gt;index.
6) fuse_writepages_fill attaches more pages to the request (if any), then
   fuse_writepages_send is eventually called. It is supposed to crop
   inarg-&gt;size of the request, but it doesn't because i_size has already been
   extended back.

Moving end_page_writeback behind fuse_writepages_send guarantees that
__fuse_release_nowrite (called from fuse_do_setattr) will crop inarg-&gt;size
of the request before write(2) gets the chance to extend i_size.

Signed-off-by: Maxim Patlasov &lt;mpatlasov@parallels.com&gt;
Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The patch fixes a race between ftruncate(2), mmap-ed write and write(2):

1) An user makes a page dirty via mmap-ed write.
2) The user performs shrinking truncate(2) intended to purge the page.
3) Before fuse_do_setattr calls truncate_pagecache, the page goes to
   writeback. fuse_writepages_fill attaches a new page to FUSE_WRITE request,
   then releases the original page by end_page_writeback and unlock it.
4) fuse_do_setattr completes and successfully returns. Since now, i_mutex
   is free.
5) Ordinary write(2) extends i_size back to cover the page. Note that
   fuse_send_write_pages do wait for fuse writeback, but for another
   page-&gt;index.
6) fuse_writepages_fill attaches more pages to the request (if any), then
   fuse_writepages_send is eventually called. It is supposed to crop
   inarg-&gt;size of the request, but it doesn't because i_size has already been
   extended back.

Moving end_page_writeback behind fuse_writepages_send guarantees that
__fuse_release_nowrite (called from fuse_do_setattr) will crop inarg-&gt;size
of the request before write(2) gets the chance to extend i_size.

Signed-off-by: Maxim Patlasov &lt;mpatlasov@parallels.com&gt;
Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fuse: Implement writepages callback</title>
<updated>2013-10-01T14:44:52+00:00</updated>
<author>
<name>Pavel Emelyanov</name>
<email>xemul@openvz.org</email>
</author>
<published>2013-06-29T17:45:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=26d614df1da9d7d255686af5d6d4508f77853c01'/>
<id>26d614df1da9d7d255686af5d6d4508f77853c01</id>
<content type='text'>
The .writepages one is required to make each writeback request carry more than
one page on it. The patch enables optimized behaviour unconditionally,
i.e. mmap-ed writes will benefit from the patch even if fc-&gt;writeback_cache=0.

[SzM: simplify, add comments]

Signed-off-by: Maxim Patlasov &lt;MPatlasov@parallels.com&gt;
Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The .writepages one is required to make each writeback request carry more than
one page on it. The patch enables optimized behaviour unconditionally,
i.e. mmap-ed writes will benefit from the patch even if fc-&gt;writeback_cache=0.

[SzM: simplify, add comments]

Signed-off-by: Maxim Patlasov &lt;MPatlasov@parallels.com&gt;
Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fuse: don't BUG on no write file</title>
<updated>2013-10-01T14:44:52+00:00</updated>
<author>
<name>Miklos Szeredi</name>
<email>mszeredi@suse.cz</email>
</author>
<published>2013-10-01T14:44:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=72523425fb434e81c0c9f611bd880ce339c4e06b'/>
<id>72523425fb434e81c0c9f611bd880ce339c4e06b</id>
<content type='text'>
Don't bug if there's no writable files found for page writeback.  If ever
this is triggered, a WARN_ON helps debugging it much better then a BUG_ON.

Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Don't bug if there's no writable files found for page writeback.  If ever
this is triggered, a WARN_ON helps debugging it much better then a BUG_ON.

Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
</pre>
</div>
</content>
</entry>
</feed>
