<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux.git/fs/fscache/cookie.c, branch v4.2</title>
<subtitle>Linux kernel source tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/'/>
<entry>
<title>FS-Cache: The operation cancellation method needs calling in more places</title>
<updated>2015-04-02T13:28:53+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2015-02-24T10:05:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=d3b97ca4a99e4e6c78f5a21c968eadf5c8ba9971'/>
<id>d3b97ca4a99e4e6c78f5a21c968eadf5c8ba9971</id>
<content type='text'>
Any time an incomplete operation is cancelled, the operation cancellation
function needs to be called to clean up.  This is currently being passed
directly to some of the functions that might want to call it, but not all.

Instead, pass the cancellation method pointer to the fscache_operation_init()
and have that cache it in the operation struct.  Further, plug in a dummy
cancellation handler if the caller declines to set one as this allows us to
call the function unconditionally (the extra overhead isn't worth bothering
about as we don't expect to be calling this typically).

The cancellation method must thence be called everywhere the CANCELLED state
is set.  Note that we call it *before* setting the CANCELLED state such that
the method can use the old state value to guide its operation.

fscache_do_cancel_retrieval() needs moving higher up in the sources so that
the init function can use it now.

Without this, the following oops may be seen:

	FS-Cache: Assertion failed
	FS-Cache: 3 == 0 is false
	------------[ cut here ]------------
	kernel BUG at ../fs/fscache/page.c:261!
	...
	RIP: 0010:[&lt;ffffffffa0089c1b&gt;]  fscache_release_retrieval_op+0x77/0x100
	 [&lt;ffffffffa008853d&gt;] fscache_put_operation+0x114/0x2da
	 [&lt;ffffffffa008b8c2&gt;] __fscache_read_or_alloc_pages+0x358/0x3b3
	 [&lt;ffffffffa00b761f&gt;] __nfs_readpages_from_fscache+0x59/0xbf [nfs]
	 [&lt;ffffffffa00b06c5&gt;] nfs_readpages+0x10c/0x185 [nfs]
	 [&lt;ffffffff81124925&gt;] ? alloc_pages_current+0x119/0x13e
	 [&lt;ffffffff810ee5fd&gt;] ? __page_cache_alloc+0xfb/0x10a
	 [&lt;ffffffff810f87f8&gt;] __do_page_cache_readahead+0x188/0x22c
	 [&lt;ffffffff810f8b3a&gt;] ondemand_readahead+0x29e/0x2af
	 [&lt;ffffffff810f8c92&gt;] page_cache_sync_readahead+0x38/0x3a
	 [&lt;ffffffff810ef337&gt;] generic_file_read_iter+0x1a2/0x55a
	 [&lt;ffffffffa00a9dff&gt;] ? nfs_revalidate_mapping+0xd6/0x288 [nfs]
	 [&lt;ffffffffa00a6a23&gt;] nfs_file_read+0x49/0x70 [nfs]
	 [&lt;ffffffff811363be&gt;] new_sync_read+0x78/0x9c
	 [&lt;ffffffff81137164&gt;] __vfs_read+0x13/0x38
	 [&lt;ffffffff8113721e&gt;] vfs_read+0x95/0x121
	 [&lt;ffffffff811372f6&gt;] SyS_read+0x4c/0x8a
	 [&lt;ffffffff81557a52&gt;] system_call_fastpath+0x12/0x17

The assertion is showing that the remaining number of pages (n_pages) is not 0
when the operation is being released.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Reviewed-by: Steve Dickson &lt;steved@redhat.com&gt;
Acked-by: Jeff Layton &lt;jeff.layton@primarydata.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Any time an incomplete operation is cancelled, the operation cancellation
function needs to be called to clean up.  This is currently being passed
directly to some of the functions that might want to call it, but not all.

Instead, pass the cancellation method pointer to the fscache_operation_init()
and have that cache it in the operation struct.  Further, plug in a dummy
cancellation handler if the caller declines to set one as this allows us to
call the function unconditionally (the extra overhead isn't worth bothering
about as we don't expect to be calling this typically).

The cancellation method must thence be called everywhere the CANCELLED state
is set.  Note that we call it *before* setting the CANCELLED state such that
the method can use the old state value to guide its operation.

fscache_do_cancel_retrieval() needs moving higher up in the sources so that
the init function can use it now.

Without this, the following oops may be seen:

	FS-Cache: Assertion failed
	FS-Cache: 3 == 0 is false
	------------[ cut here ]------------
	kernel BUG at ../fs/fscache/page.c:261!
	...
	RIP: 0010:[&lt;ffffffffa0089c1b&gt;]  fscache_release_retrieval_op+0x77/0x100
	 [&lt;ffffffffa008853d&gt;] fscache_put_operation+0x114/0x2da
	 [&lt;ffffffffa008b8c2&gt;] __fscache_read_or_alloc_pages+0x358/0x3b3
	 [&lt;ffffffffa00b761f&gt;] __nfs_readpages_from_fscache+0x59/0xbf [nfs]
	 [&lt;ffffffffa00b06c5&gt;] nfs_readpages+0x10c/0x185 [nfs]
	 [&lt;ffffffff81124925&gt;] ? alloc_pages_current+0x119/0x13e
	 [&lt;ffffffff810ee5fd&gt;] ? __page_cache_alloc+0xfb/0x10a
	 [&lt;ffffffff810f87f8&gt;] __do_page_cache_readahead+0x188/0x22c
	 [&lt;ffffffff810f8b3a&gt;] ondemand_readahead+0x29e/0x2af
	 [&lt;ffffffff810f8c92&gt;] page_cache_sync_readahead+0x38/0x3a
	 [&lt;ffffffff810ef337&gt;] generic_file_read_iter+0x1a2/0x55a
	 [&lt;ffffffffa00a9dff&gt;] ? nfs_revalidate_mapping+0xd6/0x288 [nfs]
	 [&lt;ffffffffa00a6a23&gt;] nfs_file_read+0x49/0x70 [nfs]
	 [&lt;ffffffff811363be&gt;] new_sync_read+0x78/0x9c
	 [&lt;ffffffff81137164&gt;] __vfs_read+0x13/0x38
	 [&lt;ffffffff8113721e&gt;] vfs_read+0x95/0x121
	 [&lt;ffffffff811372f6&gt;] SyS_read+0x4c/0x8a
	 [&lt;ffffffff81557a52&gt;] system_call_fastpath+0x12/0x17

The assertion is showing that the remaining number of pages (n_pages) is not 0
when the operation is being released.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Reviewed-by: Steve Dickson &lt;steved@redhat.com&gt;
Acked-by: Jeff Layton &lt;jeff.layton@primarydata.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>FS-Cache: fscache_object_is_dead() has wrong logic, kill it</title>
<updated>2015-04-02T13:28:53+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2015-02-24T10:52:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=87021526300f1a292dd966e141e183630ac95317'/>
<id>87021526300f1a292dd966e141e183630ac95317</id>
<content type='text'>
fscache_object_is_dead() returns true only if the object is marked dead and
the cache got an I/O error.  This should be a logical OR instead.  Since two
of the callers got split up into handling for separate subcases, expand the
other callers and kill the function.  This is probably the right thing to do
anyway since one of the subcases isn't about the object at all, but rather
about the cache.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Reviewed-by: Steve Dickson &lt;steved@redhat.com&gt;
Acked-by: Jeff Layton &lt;jeff.layton@primarydata.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
fscache_object_is_dead() returns true only if the object is marked dead and
the cache got an I/O error.  This should be a logical OR instead.  Since two
of the callers got split up into handling for separate subcases, expand the
other callers and kill the function.  This is probably the right thing to do
anyway since one of the subcases isn't about the object at all, but rather
about the cache.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Reviewed-by: Steve Dickson &lt;steved@redhat.com&gt;
Acked-by: Jeff Layton &lt;jeff.layton@primarydata.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>sched: Remove proliferation of wait_on_bit() action functions</title>
<updated>2014-07-16T13:10:39+00:00</updated>
<author>
<name>NeilBrown</name>
<email>neilb@suse.de</email>
</author>
<published>2014-07-07T05:16:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=743162013d40ca612b4cb53d3a200dff2d9ab26e'/>
<id>743162013d40ca612b4cb53d3a200dff2d9ab26e</id>
<content type='text'>
The current "wait_on_bit" interface requires an 'action'
function to be provided which does the actual waiting.
There are over 20 such functions, many of them identical.
Most cases can be satisfied by one of just two functions, one
which uses io_schedule() and one which just uses schedule().

So:
 Rename wait_on_bit and        wait_on_bit_lock to
        wait_on_bit_action and wait_on_bit_lock_action
 to make it explicit that they need an action function.

 Introduce new wait_on_bit{,_lock} and wait_on_bit{,_lock}_io
 which are *not* given an action function but implicitly use
 a standard one.
 The decision to error-out if a signal is pending is now made
 based on the 'mode' argument rather than being encoded in the action
 function.

 All instances of the old wait_on_bit and wait_on_bit_lock which
 can use the new version have been changed accordingly and their
 action functions have been discarded.
 wait_on_bit{_lock} does not return any specific error code in the
 event of a signal so the caller must check for non-zero and
 interpolate their own error code as appropriate.

The wait_on_bit() call in __fscache_wait_on_invalidate() was
ambiguous as it specified TASK_UNINTERRUPTIBLE but used
fscache_wait_bit_interruptible as an action function.
David Howells confirms this should be uniformly
"uninterruptible"

The main remaining user of wait_on_bit{,_lock}_action is NFS
which needs to use a freezer-aware schedule() call.

A comment in fs/gfs2/glock.c notes that having multiple 'action'
functions is useful as they display differently in the 'wchan'
field of 'ps'. (and /proc/$PID/wchan).
As the new bit_wait{,_io} functions are tagged "__sched", they
will not show up at all, but something higher in the stack.  So
the distinction will still be visible, only with different
function names (gds2_glock_wait versus gfs2_glock_dq_wait in the
gfs2/glock.c case).

Since first version of this patch (against 3.15) two new action
functions appeared, on in NFS and one in CIFS.  CIFS also now
uses an action function that makes the same freezer aware
schedule call as NFS.

Signed-off-by: NeilBrown &lt;neilb@suse.de&gt;
Acked-by: David Howells &lt;dhowells@redhat.com&gt; (fscache, keys)
Acked-by: Steven Whitehouse &lt;swhiteho@redhat.com&gt; (gfs2)
Acked-by: Peter Zijlstra &lt;peterz@infradead.org&gt;
Cc: Oleg Nesterov &lt;oleg@redhat.com&gt;
Cc: Steve French &lt;sfrench@samba.org&gt;
Cc: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Link: http://lkml.kernel.org/r/20140707051603.28027.72349.stgit@notabene.brown
Signed-off-by: Ingo Molnar &lt;mingo@kernel.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The current "wait_on_bit" interface requires an 'action'
function to be provided which does the actual waiting.
There are over 20 such functions, many of them identical.
Most cases can be satisfied by one of just two functions, one
which uses io_schedule() and one which just uses schedule().

So:
 Rename wait_on_bit and        wait_on_bit_lock to
        wait_on_bit_action and wait_on_bit_lock_action
 to make it explicit that they need an action function.

 Introduce new wait_on_bit{,_lock} and wait_on_bit{,_lock}_io
 which are *not* given an action function but implicitly use
 a standard one.
 The decision to error-out if a signal is pending is now made
 based on the 'mode' argument rather than being encoded in the action
 function.

 All instances of the old wait_on_bit and wait_on_bit_lock which
 can use the new version have been changed accordingly and their
 action functions have been discarded.
 wait_on_bit{_lock} does not return any specific error code in the
 event of a signal so the caller must check for non-zero and
 interpolate their own error code as appropriate.

The wait_on_bit() call in __fscache_wait_on_invalidate() was
ambiguous as it specified TASK_UNINTERRUPTIBLE but used
fscache_wait_bit_interruptible as an action function.
David Howells confirms this should be uniformly
"uninterruptible"

The main remaining user of wait_on_bit{,_lock}_action is NFS
which needs to use a freezer-aware schedule() call.

A comment in fs/gfs2/glock.c notes that having multiple 'action'
functions is useful as they display differently in the 'wchan'
field of 'ps'. (and /proc/$PID/wchan).
As the new bit_wait{,_io} functions are tagged "__sched", they
will not show up at all, but something higher in the stack.  So
the distinction will still be visible, only with different
function names (gds2_glock_wait versus gfs2_glock_dq_wait in the
gfs2/glock.c case).

Since first version of this patch (against 3.15) two new action
functions appeared, on in NFS and one in CIFS.  CIFS also now
uses an action function that makes the same freezer aware
schedule call as NFS.

Signed-off-by: NeilBrown &lt;neilb@suse.de&gt;
Acked-by: David Howells &lt;dhowells@redhat.com&gt; (fscache, keys)
Acked-by: Steven Whitehouse &lt;swhiteho@redhat.com&gt; (gfs2)
Acked-by: Peter Zijlstra &lt;peterz@infradead.org&gt;
Cc: Oleg Nesterov &lt;oleg@redhat.com&gt;
Cc: Steve French &lt;sfrench@samba.org&gt;
Cc: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Link: http://lkml.kernel.org/r/20140707051603.28027.72349.stgit@notabene.brown
Signed-off-by: Ingo Molnar &lt;mingo@kernel.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fs/fscache: convert printk to pr_foo()</title>
<updated>2014-06-04T23:53:51+00:00</updated>
<author>
<name>Fabian Frederick</name>
<email>fabf@skynet.be</email>
</author>
<published>2014-06-04T23:05:38+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=36dfd116edd48fa6174d5694c143f1d4bd81aba8'/>
<id>36dfd116edd48fa6174d5694c143f1d4bd81aba8</id>
<content type='text'>
All printk converted to pr_foo() except internal.h: printk(KERN_DEBUG

Coalesce formats.

Add pr_fmt

Signed-off-by: Fabian Frederick &lt;fabf@skynet.be&gt;
Cc: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
All printk converted to pr_foo() except internal.h: printk(KERN_DEBUG

Coalesce formats.

Add pr_fmt

Signed-off-by: Fabian Frederick &lt;fabf@skynet.be&gt;
Cc: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>FS-Cache: Provide the ability to enable/disable cookies</title>
<updated>2013-09-27T17:40:25+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2013-09-20T23:09:31+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=94d30ae90a00cafe686c1057be57f4885f963abf'/>
<id>94d30ae90a00cafe686c1057be57f4885f963abf</id>
<content type='text'>
Provide the ability to enable and disable fscache cookies.  A disabled cookie
will reject or ignore further requests to:

	Acquire a child cookie
	Invalidate and update backing objects
	Check the consistency of a backing object
	Allocate storage for backing page
	Read backing pages
	Write to backing pages

but still allows:

	Checks/waits on the completion of already in-progress objects
	Uncaching of pages
	Relinquishment of cookies

Two new operations are provided:

 (1) Disable a cookie:

	void fscache_disable_cookie(struct fscache_cookie *cookie,
				    bool invalidate);

     If the cookie is not already disabled, this locks the cookie against other
     dis/enablement ops, marks the cookie as being disabled, discards or
     invalidates any backing objects and waits for cessation of activity on any
     associated object.

     This is a wrapper around a chunk split out of fscache_relinquish_cookie(),
     but it reinitialises the cookie such that it can be reenabled.

     All possible failures are handled internally.  The caller should consider
     calling fscache_uncache_all_inode_pages() afterwards to make sure all page
     markings are cleared up.

 (2) Enable a cookie:

	void fscache_enable_cookie(struct fscache_cookie *cookie,
				   bool (*can_enable)(void *data),
				   void *data)

     If the cookie is not already enabled, this locks the cookie against other
     dis/enablement ops, invokes can_enable() and, if the cookie is not an
     index cookie, will begin the procedure of acquiring backing objects.

     The optional can_enable() function is passed the data argument and returns
     a ruling as to whether or not enablement should actually be permitted to
     begin.

     All possible failures are handled internally.  The cookie will only be
     marked as enabled if provisional backing objects are allocated.

A later patch will introduce these to NFS.  Cookie enablement during nfs_open()
is then contingent on i_writecount &lt;= 0.  can_enable() checks for a race
between open(O_RDONLY) and open(O_WRONLY/O_RDWR).  This simplifies NFS's cookie
handling and allows us to get rid of open(O_RDONLY) accidentally introducing
caching to an inode that's open for writing already.

One operation has its API modified:

 (3) Acquire a cookie.

	struct fscache_cookie *fscache_acquire_cookie(
		struct fscache_cookie *parent,
		const struct fscache_cookie_def *def,
		void *netfs_data,
		bool enable);

     This now has an additional argument that indicates whether the requested
     cookie should be enabled by default.  It doesn't need the can_enable()
     function because the caller must prevent multiple calls for the same netfs
     object and it doesn't need to take the enablement lock because no one else
     can get at the cookie before this returns.

Signed-off-by: David Howells &lt;dhowells@redhat.com
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Provide the ability to enable and disable fscache cookies.  A disabled cookie
will reject or ignore further requests to:

	Acquire a child cookie
	Invalidate and update backing objects
	Check the consistency of a backing object
	Allocate storage for backing page
	Read backing pages
	Write to backing pages

but still allows:

	Checks/waits on the completion of already in-progress objects
	Uncaching of pages
	Relinquishment of cookies

Two new operations are provided:

 (1) Disable a cookie:

	void fscache_disable_cookie(struct fscache_cookie *cookie,
				    bool invalidate);

     If the cookie is not already disabled, this locks the cookie against other
     dis/enablement ops, marks the cookie as being disabled, discards or
     invalidates any backing objects and waits for cessation of activity on any
     associated object.

     This is a wrapper around a chunk split out of fscache_relinquish_cookie(),
     but it reinitialises the cookie such that it can be reenabled.

     All possible failures are handled internally.  The caller should consider
     calling fscache_uncache_all_inode_pages() afterwards to make sure all page
     markings are cleared up.

 (2) Enable a cookie:

	void fscache_enable_cookie(struct fscache_cookie *cookie,
				   bool (*can_enable)(void *data),
				   void *data)

     If the cookie is not already enabled, this locks the cookie against other
     dis/enablement ops, invokes can_enable() and, if the cookie is not an
     index cookie, will begin the procedure of acquiring backing objects.

     The optional can_enable() function is passed the data argument and returns
     a ruling as to whether or not enablement should actually be permitted to
     begin.

     All possible failures are handled internally.  The cookie will only be
     marked as enabled if provisional backing objects are allocated.

A later patch will introduce these to NFS.  Cookie enablement during nfs_open()
is then contingent on i_writecount &lt;= 0.  can_enable() checks for a race
between open(O_RDONLY) and open(O_WRONLY/O_RDWR).  This simplifies NFS's cookie
handling and allows us to get rid of open(O_RDONLY) accidentally introducing
caching to an inode that's open for writing already.

One operation has its API modified:

 (3) Acquire a cookie.

	struct fscache_cookie *fscache_acquire_cookie(
		struct fscache_cookie *parent,
		const struct fscache_cookie_def *def,
		void *netfs_data,
		bool enable);

     This now has an additional argument that indicates whether the requested
     cookie should be enabled by default.  It doesn't need the can_enable()
     function because the caller must prevent multiple calls for the same netfs
     object and it doesn't need to take the enablement lock because no one else
     can get at the cookie before this returns.

Signed-off-by: David Howells &lt;dhowells@redhat.com
</pre>
</div>
</content>
</entry>
<entry>
<title>FS-Cache: Add use/unuse/wake cookie wrappers</title>
<updated>2013-09-27T17:40:25+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2013-09-20T23:09:31+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=8fb883f3e30065529e4f35d4b4f355193dcdb7a2'/>
<id>8fb883f3e30065529e4f35d4b4f355193dcdb7a2</id>
<content type='text'>
Add wrapper functions for dealing with cookie-&gt;n_active:

 (*) __fscache_use_cookie() to increment it.

 (*) __fscache_unuse_cookie() to decrement and test against zero.

 (*) __fscache_wake_unused_cookie() to wake up anyone waiting for it to reach
     zero.

The second and third are split so that the third can be done after cookie-&gt;lock
has been released in case the waiter wakes up whilst we're still holding it and
tries to get it.

We will need to wake-on-zero once the cookie disablement patch is applied
because it will then be possible to see n_active become zero without the cookie
being relinquished.

Also move the cookie usement out of fscache_attr_changed_op() and into
fscache_attr_changed() and the operation struct so that cookie disablement
will be able to track it.

Whilst we're at it, only increment n_active if we're about to do
fscache_submit_op() so that we don't have to deal with undoing it if anything
earlier fails.  Possibly this should be moved into fscache_submit_op() which
could look at FSCACHE_OP_UNUSE_COOKIE.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Add wrapper functions for dealing with cookie-&gt;n_active:

 (*) __fscache_use_cookie() to increment it.

 (*) __fscache_unuse_cookie() to decrement and test against zero.

 (*) __fscache_wake_unused_cookie() to wake up anyone waiting for it to reach
     zero.

The second and third are split so that the third can be done after cookie-&gt;lock
has been released in case the waiter wakes up whilst we're still holding it and
tries to get it.

We will need to wake-on-zero once the cookie disablement patch is applied
because it will then be possible to see n_active become zero without the cookie
being relinquished.

Also move the cookie usement out of fscache_attr_changed_op() and into
fscache_attr_changed() and the operation struct so that cookie disablement
will be able to track it.

Whilst we're at it, only increment n_active if we're about to do
fscache_submit_op() so that we don't have to deal with undoing it if anything
earlier fails.  Possibly this should be moved into fscache_submit_op() which
could look at FSCACHE_OP_UNUSE_COOKIE.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fscache: check consistency does not decrement refcount</title>
<updated>2013-09-10T16:04:46+00:00</updated>
<author>
<name>Milosz Tanski</name>
<email>milosz@adfin.com</email>
</author>
<published>2013-09-09T18:28:57+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=9c89d62948c4740e379a7e0085dd8d7c1561f53f'/>
<id>9c89d62948c4740e379a7e0085dd8d7c1561f53f</id>
<content type='text'>
__fscache_check_consistency() does not decrement the count of operations
active after it finishes in the success case. This leads to a hung tasks on
cookie de-registration (commonly in inode eviction).

INFO: task kworker/1:2:4214 blocked for more than 120 seconds.
kworker/1:2     D ffff880443513fc0     0  4214      2 0x00000000
Workqueue: ceph-msgr con_work [libceph]
  ...
Call Trace:
 [&lt;ffffffff81569fc6&gt;] ? _raw_spin_unlock_irqrestore+0x16/0x20
 [&lt;ffffffffa0016570&gt;] ? fscache_wait_bit_interruptible+0x30/0x30 [fscache]
 [&lt;ffffffff81568d09&gt;] schedule+0x29/0x70
 [&lt;ffffffffa001657e&gt;] fscache_wait_atomic_t+0xe/0x20 [fscache]
 [&lt;ffffffff815665cf&gt;] out_of_line_wait_on_atomic_t+0x9f/0xe0
 [&lt;ffffffff81083560&gt;] ? autoremove_wake_function+0x40/0x40
 [&lt;ffffffffa0015a9c&gt;] __fscache_relinquish_cookie+0x15c/0x310 [fscache]
 [&lt;ffffffffa00a4fae&gt;] ceph_fscache_unregister_inode_cookie+0x3e/0x50 [ceph]
 [&lt;ffffffffa007e373&gt;] ceph_destroy_inode+0x33/0x200 [ceph]
 [&lt;ffffffff811c13ae&gt;] ? __fsnotify_inode_delete+0xe/0x10
 [&lt;ffffffff8119ba1c&gt;] destroy_inode+0x3c/0x70
 [&lt;ffffffff8119bb69&gt;] evict+0x119/0x1b0

Signed-off-by: Milosz Tanski &lt;milosz@adfin.com&gt;
Acked-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: Sage Weil &lt;sage@inktank.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
__fscache_check_consistency() does not decrement the count of operations
active after it finishes in the success case. This leads to a hung tasks on
cookie de-registration (commonly in inode eviction).

INFO: task kworker/1:2:4214 blocked for more than 120 seconds.
kworker/1:2     D ffff880443513fc0     0  4214      2 0x00000000
Workqueue: ceph-msgr con_work [libceph]
  ...
Call Trace:
 [&lt;ffffffff81569fc6&gt;] ? _raw_spin_unlock_irqrestore+0x16/0x20
 [&lt;ffffffffa0016570&gt;] ? fscache_wait_bit_interruptible+0x30/0x30 [fscache]
 [&lt;ffffffff81568d09&gt;] schedule+0x29/0x70
 [&lt;ffffffffa001657e&gt;] fscache_wait_atomic_t+0xe/0x20 [fscache]
 [&lt;ffffffff815665cf&gt;] out_of_line_wait_on_atomic_t+0x9f/0xe0
 [&lt;ffffffff81083560&gt;] ? autoremove_wake_function+0x40/0x40
 [&lt;ffffffffa0015a9c&gt;] __fscache_relinquish_cookie+0x15c/0x310 [fscache]
 [&lt;ffffffffa00a4fae&gt;] ceph_fscache_unregister_inode_cookie+0x3e/0x50 [ceph]
 [&lt;ffffffffa007e373&gt;] ceph_destroy_inode+0x33/0x200 [ceph]
 [&lt;ffffffff811c13ae&gt;] ? __fsnotify_inode_delete+0xe/0x10
 [&lt;ffffffff8119ba1c&gt;] destroy_inode+0x3c/0x70
 [&lt;ffffffff8119bb69&gt;] evict+0x119/0x1b0

Signed-off-by: Milosz Tanski &lt;milosz@adfin.com&gt;
Acked-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: Sage Weil &lt;sage@inktank.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>FS-Cache: Add interface to check consistency of a cached object</title>
<updated>2013-09-06T08:17:30+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2013-08-21T21:29:38+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=da9803bc8812f5bd3b26baaa90e515b843c65ff7'/>
<id>da9803bc8812f5bd3b26baaa90e515b843c65ff7</id>
<content type='text'>
Extend the fscache netfs API so that the netfs can ask as to whether a cache
object is up to date with respect to its corresponding netfs object:

	int fscache_check_consistency(struct fscache_cookie *cookie)

This will call back to the netfs to check whether the auxiliary data associated
with a cookie is correct.  It returns 0 if it is and -ESTALE if it isn't; it
may also return -ENOMEM and -ERESTARTSYS.

The backends now have to implement a mandatory operation pointer:

	int (*check_consistency)(struct fscache_object *object)

that corresponds to the above API call.  FS-Cache takes care of pinning the
object and the cookie in memory and managing this call with respect to the
object state.

Original-author: Hongyi Jia &lt;jiayisuse@gmail.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
cc: Hongyi Jia &lt;jiayisuse@gmail.com&gt;
cc: Milosz Tanski &lt;milosz@adfin.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Extend the fscache netfs API so that the netfs can ask as to whether a cache
object is up to date with respect to its corresponding netfs object:

	int fscache_check_consistency(struct fscache_cookie *cookie)

This will call back to the netfs to check whether the auxiliary data associated
with a cookie is correct.  It returns 0 if it is and -ESTALE if it isn't; it
may also return -ENOMEM and -ERESTARTSYS.

The backends now have to implement a mandatory operation pointer:

	int (*check_consistency)(struct fscache_object *object)

that corresponds to the above API call.  FS-Cache takes care of pinning the
object and the cookie in memory and managing this call with respect to the
object state.

Original-author: Hongyi Jia &lt;jiayisuse@gmail.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
cc: Hongyi Jia &lt;jiayisuse@gmail.com&gt;
cc: Milosz Tanski &lt;milosz@adfin.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>FS-Cache: Simplify cookie retention for fscache_objects, fixing oops</title>
<updated>2013-06-19T13:16:47+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2013-05-10T18:50:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=1362729b169b7903c7e739dbe7904994b0d8c47f'/>
<id>1362729b169b7903c7e739dbe7904994b0d8c47f</id>
<content type='text'>
Simplify the way fscache cache objects retain their cookie.  The way I
implemented the cookie storage handling made synchronisation a pain (ie. the
object state machine can't rely on the cookie actually still being there).

Instead of the the object being detached from the cookie and the cookie being
freed in __fscache_relinquish_cookie(), we defer both operations:

 (*) The detachment of the object from the list in the cookie now takes place
     in fscache_drop_object() and is thus governed by the object state machine
     (fscache_detach_from_cookie() has been removed).

 (*) The release of the cookie is now in fscache_object_destroy() - which is
     called by the cache backend just before it frees the object.

This means that the fscache_cookie struct is now available to the cache all the
way through from -&gt;alloc_object() to -&gt;drop_object() and -&gt;put_object() -
meaning that it's no longer necessary to take object-&gt;lock to guarantee access.

However, __fscache_relinquish_cookie() doesn't wait for the object to go all
the way through to destruction before letting the netfs proceed.  That would
massively slow down the netfs.  Since __fscache_relinquish_cookie() leaves the
cookie around, in must therefore break all attachments to the netfs - which
includes -&gt;def, -&gt;netfs_data and any outstanding page read/writes.

To handle this, struct fscache_cookie now has an n_active counter:

 (1) This starts off initialised to 1.

 (2) Any time the cache needs to get at the netfs data, it calls
     fscache_use_cookie() to increment it - if it is not zero.  If it was zero,
     then access is not permitted.

 (3) When the cache has finished with the data, it calls fscache_unuse_cookie()
     to decrement it.  This does a wake-up on it if it reaches 0.

 (4) __fscache_relinquish_cookie() decrements n_active and then waits for it to
     reach 0.  The initialisation to 1 in step (1) ensures that we only get
     wake ups when we're trying to get rid of the cookie.

This leaves __fscache_relinquish_cookie() a lot simpler.


***
This fixes a problem in the current code whereby if fscache_invalidate() is
followed sufficiently quickly by fscache_relinquish_cookie() then it is
possible for __fscache_relinquish_cookie() to have detached the cookie from the
object and cleared the pointer before a thread is dispatched to process the
invalidation state in the object state machine.

Since the pending write clearance was deferred to the invalidation state to
make it asynchronous, we need to either wait in relinquishment for the stores
tree to be cleared in the invalidation state or we need to handle the clearance
in relinquishment.

Further, if the relinquishment code does clear the tree, then the invalidation
state need to make the clearance contingent on still having the cookie to hand
(since that's where the tree is rooted) and we have to prevent the cookie from
disappearing for the duration.

This can lead to an oops like the following:

BUG: unable to handle kernel NULL pointer dereference at 000000000000000c
...
RIP: 0010:[&lt;ffffffff8151023e&gt;] _spin_lock+0xe/0x30
...
CR2: 000000000000000c ...
...
Process kslowd002 (...)
....
Call Trace:
 [&lt;ffffffffa01c3278&gt;] fscache_invalidate_writes+0x38/0xd0 [fscache]
 [&lt;ffffffff810096f0&gt;] ? __switch_to+0xd0/0x320
 [&lt;ffffffff8105e759&gt;] ? find_busiest_queue+0x69/0x150
 [&lt;ffffffff8110ddd4&gt;] ? slow_work_enqueue+0x104/0x180
 [&lt;ffffffffa01c1303&gt;] fscache_object_slow_work_execute+0x5e3/0x9d0 [fscache]
 [&lt;ffffffff81096b67&gt;] ? bit_waitqueue+0x17/0xd0
 [&lt;ffffffff8110e233&gt;] slow_work_execute+0x233/0x310
 [&lt;ffffffff8110e515&gt;] slow_work_thread+0x205/0x360
 [&lt;ffffffff81096ca0&gt;] ? autoremove_wake_function+0x0/0x40
 [&lt;ffffffff8110e310&gt;] ? slow_work_thread+0x0/0x360
 [&lt;ffffffff81096936&gt;] kthread+0x96/0xa0
 [&lt;ffffffff8100c0ca&gt;] child_rip+0xa/0x20
 [&lt;ffffffff810968a0&gt;] ? kthread+0x0/0xa0
 [&lt;ffffffff8100c0c0&gt;] ? child_rip+0x0/0x20

The parameter to fscache_invalidate_writes() was object-&gt;cookie which is NULL.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Tested-By: Milosz Tanski &lt;milosz@adfin.com&gt;
Acked-by: Jeff Layton &lt;jlayton@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Simplify the way fscache cache objects retain their cookie.  The way I
implemented the cookie storage handling made synchronisation a pain (ie. the
object state machine can't rely on the cookie actually still being there).

Instead of the the object being detached from the cookie and the cookie being
freed in __fscache_relinquish_cookie(), we defer both operations:

 (*) The detachment of the object from the list in the cookie now takes place
     in fscache_drop_object() and is thus governed by the object state machine
     (fscache_detach_from_cookie() has been removed).

 (*) The release of the cookie is now in fscache_object_destroy() - which is
     called by the cache backend just before it frees the object.

This means that the fscache_cookie struct is now available to the cache all the
way through from -&gt;alloc_object() to -&gt;drop_object() and -&gt;put_object() -
meaning that it's no longer necessary to take object-&gt;lock to guarantee access.

However, __fscache_relinquish_cookie() doesn't wait for the object to go all
the way through to destruction before letting the netfs proceed.  That would
massively slow down the netfs.  Since __fscache_relinquish_cookie() leaves the
cookie around, in must therefore break all attachments to the netfs - which
includes -&gt;def, -&gt;netfs_data and any outstanding page read/writes.

To handle this, struct fscache_cookie now has an n_active counter:

 (1) This starts off initialised to 1.

 (2) Any time the cache needs to get at the netfs data, it calls
     fscache_use_cookie() to increment it - if it is not zero.  If it was zero,
     then access is not permitted.

 (3) When the cache has finished with the data, it calls fscache_unuse_cookie()
     to decrement it.  This does a wake-up on it if it reaches 0.

 (4) __fscache_relinquish_cookie() decrements n_active and then waits for it to
     reach 0.  The initialisation to 1 in step (1) ensures that we only get
     wake ups when we're trying to get rid of the cookie.

This leaves __fscache_relinquish_cookie() a lot simpler.


***
This fixes a problem in the current code whereby if fscache_invalidate() is
followed sufficiently quickly by fscache_relinquish_cookie() then it is
possible for __fscache_relinquish_cookie() to have detached the cookie from the
object and cleared the pointer before a thread is dispatched to process the
invalidation state in the object state machine.

Since the pending write clearance was deferred to the invalidation state to
make it asynchronous, we need to either wait in relinquishment for the stores
tree to be cleared in the invalidation state or we need to handle the clearance
in relinquishment.

Further, if the relinquishment code does clear the tree, then the invalidation
state need to make the clearance contingent on still having the cookie to hand
(since that's where the tree is rooted) and we have to prevent the cookie from
disappearing for the duration.

This can lead to an oops like the following:

BUG: unable to handle kernel NULL pointer dereference at 000000000000000c
...
RIP: 0010:[&lt;ffffffff8151023e&gt;] _spin_lock+0xe/0x30
...
CR2: 000000000000000c ...
...
Process kslowd002 (...)
....
Call Trace:
 [&lt;ffffffffa01c3278&gt;] fscache_invalidate_writes+0x38/0xd0 [fscache]
 [&lt;ffffffff810096f0&gt;] ? __switch_to+0xd0/0x320
 [&lt;ffffffff8105e759&gt;] ? find_busiest_queue+0x69/0x150
 [&lt;ffffffff8110ddd4&gt;] ? slow_work_enqueue+0x104/0x180
 [&lt;ffffffffa01c1303&gt;] fscache_object_slow_work_execute+0x5e3/0x9d0 [fscache]
 [&lt;ffffffff81096b67&gt;] ? bit_waitqueue+0x17/0xd0
 [&lt;ffffffff8110e233&gt;] slow_work_execute+0x233/0x310
 [&lt;ffffffff8110e515&gt;] slow_work_thread+0x205/0x360
 [&lt;ffffffff81096ca0&gt;] ? autoremove_wake_function+0x0/0x40
 [&lt;ffffffff8110e310&gt;] ? slow_work_thread+0x0/0x360
 [&lt;ffffffff81096936&gt;] kthread+0x96/0xa0
 [&lt;ffffffff8100c0ca&gt;] child_rip+0xa/0x20
 [&lt;ffffffff810968a0&gt;] ? kthread+0x0/0xa0
 [&lt;ffffffff8100c0c0&gt;] ? child_rip+0x0/0x20

The parameter to fscache_invalidate_writes() was object-&gt;cookie which is NULL.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Tested-By: Milosz Tanski &lt;milosz@adfin.com&gt;
Acked-by: Jeff Layton &lt;jlayton@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>FS-Cache: Fix object state machine to have separate work and wait states</title>
<updated>2013-06-19T13:16:47+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2013-05-10T18:50:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=caaef6900befb45689b1d1831ce3c7e7fb5b504f'/>
<id>caaef6900befb45689b1d1831ce3c7e7fb5b504f</id>
<content type='text'>
Fix object state machine to have separate work and wait states as that makes
it easier to envision.

There are now three kinds of state:

 (1) Work state.  This is an execution state.  No event processing is performed
     by a work state.  The function attached to a work state returns a pointer
     indicating the next state to which the OSM should transition.  Returning
     NO_TRANSIT repeats the current state, but goes back to the scheduler
     first.

 (2) Wait state.  This is an event processing state.  No execution is
     performed by a wait state.  Wait states are just tables of "if event X
     occurs, clear it and transition to state Y".  The dispatcher returns to
     the scheduler if none of the events in which the wait state has an
     interest are currently pending.

 (3) Out-of-band state.  This is a special work state.  Transitions to normal
     states can be overridden when an unexpected event occurs (eg. I/O error).
     Instead the dispatcher disables and clears the OOB event and transits to
     the specified work state.  This then acts as an ordinary work state,
     though object-&gt;state points to the overridden destination.  Returning
     NO_TRANSIT resumes the overridden transition.

In addition, the states have names in their definitions, so there's no need for
tables of state names.  Further, the EV_REQUEUE event is no longer necessary as
that is automatic for work states.

Since the states are now separate structs rather than values in an enum, it's
not possible to use comparisons other than (non-)equality between them, so use
some object-&gt;flags to indicate what phase an object is in.

The EV_RELEASE, EV_RETIRE and EV_WITHDRAW events have been squished into one
(EV_KILL).  An object flag now carries the information about retirement.

Similarly, the RELEASING, RECYCLING and WITHDRAWING states have been merged
into an KILL_OBJECT state and additional states have been added for handling
waiting dependent objects (JUMPSTART_DEPS and KILL_DEPENDENTS).

A state has also been added for synchronising with parent object initialisation
(WAIT_FOR_PARENT) and another for initiating look up (PARENT_READY).

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Tested-By: Milosz Tanski &lt;milosz@adfin.com&gt;
Acked-by: Jeff Layton &lt;jlayton@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Fix object state machine to have separate work and wait states as that makes
it easier to envision.

There are now three kinds of state:

 (1) Work state.  This is an execution state.  No event processing is performed
     by a work state.  The function attached to a work state returns a pointer
     indicating the next state to which the OSM should transition.  Returning
     NO_TRANSIT repeats the current state, but goes back to the scheduler
     first.

 (2) Wait state.  This is an event processing state.  No execution is
     performed by a wait state.  Wait states are just tables of "if event X
     occurs, clear it and transition to state Y".  The dispatcher returns to
     the scheduler if none of the events in which the wait state has an
     interest are currently pending.

 (3) Out-of-band state.  This is a special work state.  Transitions to normal
     states can be overridden when an unexpected event occurs (eg. I/O error).
     Instead the dispatcher disables and clears the OOB event and transits to
     the specified work state.  This then acts as an ordinary work state,
     though object-&gt;state points to the overridden destination.  Returning
     NO_TRANSIT resumes the overridden transition.

In addition, the states have names in their definitions, so there's no need for
tables of state names.  Further, the EV_REQUEUE event is no longer necessary as
that is automatic for work states.

Since the states are now separate structs rather than values in an enum, it's
not possible to use comparisons other than (non-)equality between them, so use
some object-&gt;flags to indicate what phase an object is in.

The EV_RELEASE, EV_RETIRE and EV_WITHDRAW events have been squished into one
(EV_KILL).  An object flag now carries the information about retirement.

Similarly, the RELEASING, RECYCLING and WITHDRAWING states have been merged
into an KILL_OBJECT state and additional states have been added for handling
waiting dependent objects (JUMPSTART_DEPS and KILL_DEPENDENTS).

A state has also been added for synchronising with parent object initialisation
(WAIT_FOR_PARENT) and another for initiating look up (PARENT_READY).

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Tested-By: Milosz Tanski &lt;milosz@adfin.com&gt;
Acked-by: Jeff Layton &lt;jlayton@redhat.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
