Skip to content

Commit

Permalink
FS-Cache: Handle removal of unadded object to the fscache_object_list…
Browse files Browse the repository at this point in the history
… rb tree

When FS-Cache allocates an object, the following sequence of events can
occur:

 -->fscache_alloc_object()
    -->cachefiles_alloc_object() [via cache->ops->alloc_object]
    <--[returns new object]
    -->fscache_attach_object()
    <--[failed]
    -->cachefiles_put_object() [via cache->ops->put_object]
       -->fscache_object_destroy()
          -->fscache_objlist_remove()
             -->rb_erase() to remove the object from fscache_object_list.

resulting in a crash in the rbtree code.

The problem is that the object is only added to fscache_object_list on
the success path of fscache_attach_object() where it calls
fscache_objlist_add().

So if fscache_attach_object() fails, the object won't have been added to
the objlist rbtree.  We do, however, unconditionally try to remove the
object from the tree.

Thanks to NeilBrown for finding this and suggesting this solution.

Reported-by: NeilBrown <neilb@suse.de>
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: (a customer of) NeilBrown <neilb@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
dhowells authored and torvalds committed Feb 17, 2014
1 parent 416e2ab commit 7026f19
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 0 deletions.
5 changes: 5 additions & 0 deletions fs/fscache/object-list.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ void fscache_objlist_add(struct fscache_object *obj)
struct fscache_object *xobj; struct fscache_object *xobj;
struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL; struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL;


ASSERT(RB_EMPTY_NODE(&obj->objlist_link));

write_lock(&fscache_object_list_lock); write_lock(&fscache_object_list_lock);


while (*p) { while (*p) {
Expand All @@ -75,6 +77,9 @@ void fscache_objlist_add(struct fscache_object *obj)
*/ */
void fscache_objlist_remove(struct fscache_object *obj) void fscache_objlist_remove(struct fscache_object *obj)
{ {
if (RB_EMPTY_NODE(&obj->objlist_link))
return;

write_lock(&fscache_object_list_lock); write_lock(&fscache_object_list_lock);


BUG_ON(RB_EMPTY_ROOT(&fscache_object_list)); BUG_ON(RB_EMPTY_ROOT(&fscache_object_list));
Expand Down
3 changes: 3 additions & 0 deletions fs/fscache/object.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -314,6 +314,9 @@ void fscache_object_init(struct fscache_object *object,
object->cache = cache; object->cache = cache;
object->cookie = cookie; object->cookie = cookie;
object->parent = NULL; object->parent = NULL;
#ifdef CONFIG_FSCACHE_OBJECT_LIST
RB_CLEAR_NODE(&object->objlist_link);
#endif


object->oob_event_mask = 0; object->oob_event_mask = 0;
for (t = object->oob_table; t->events; t++) for (t = object->oob_table; t->events; t++)
Expand Down

0 comments on commit 7026f19

Please sign in to comment.