[Linux-cachefs] locking/refcount problems in cachefiles.

NeilBrown neilb at suse.de
Thu Feb 6 00:45:10 UTC 2014


On Wed, 05 Feb 2014 16:09:51 +0000 David Howells <dhowells at redhat.com> wrote:

> NeilBrown <neilb at suse.de> wrote:
> 
> > fscache_alloc_object() calls fscache_attach_object() and if that fails it
> > calls cache->ops->put_object(), which is cachefiles_put_object() which calls
> > fscache_object_destroy(), which calls fscache_objlist_remove() which calls
> > rb_erase() to remove the object from fscache_object_list.
> > 
> > However the object isn't added to fscache_object_list except on the success
> > path of fscache_attach_object() where it calls fscache_objlist_add().
> > 
> > So if fscache_attach_object() fails, then the object wasn't added to the
> > objlist rbtree, but is removed from it.  This causes a crash.
> > 
> > One approach would be to rb_init_node(&object->objlist_link) in
> > fscache_object_init, and the test !RB_EMPTY_NODE(&obj->objlist_link) before
> > calling rb_erase().
> > 
> > Does that make sense?  Is the suggested fix best or is there a better way?
> 
> Sounds very reasonable.  Something like the attached patch?

Yes, that looks just right. Thanks.
I'll let you know when the customer confirms it fixes their problem.

NeilBrown

> 
> David
> ---
> commit fe02fb3ec10932ce07406b1581e28326181fc9d8
> Author: David Howells <dhowells at redhat.com>
> Date:   Wed Feb 5 15:14:40 2014 +0000
> 
>     FS-Cache: Handle removal of unadded object to the fscache_object_list 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 at suse.de>
>     Signed-off-by: David Howells <dhowells at redhat.com>
> 
> diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c
> index e1959efad64f..b5ebc2d7d80d 100644
> --- a/fs/fscache/object-list.c
> +++ b/fs/fscache/object-list.c
> @@ -50,6 +50,8 @@ void fscache_objlist_add(struct fscache_object *obj)
>  	struct fscache_object *xobj;
>  	struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL;
>  
> +	ASSERT(RB_EMPTY_NODE(&obj->objlist_link));
> +
>  	write_lock(&fscache_object_list_lock);
>  
>  	while (*p) {
> @@ -75,6 +77,9 @@ void fscache_objlist_add(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);
>  
>  	BUG_ON(RB_EMPTY_ROOT(&fscache_object_list));
> diff --git a/fs/fscache/object.c b/fs/fscache/object.c
> index 53d35c504240..d3b4539f1651 100644
> --- a/fs/fscache/object.c
> +++ b/fs/fscache/object.c
> @@ -314,6 +314,9 @@ void fscache_object_init(struct fscache_object *object,
>  	object->cache = cache;
>  	object->cookie = cookie;
>  	object->parent = NULL;
> +#ifdef CONFIG_FSCACHE_OBJECT_LIST
> +	RB_CLEAR_NODE(&object->objlist_link);
> +#endif
>  
>  	object->oob_event_mask = 0;
>  	for (t = object->oob_table; t->events; t++)

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 828 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/linux-cachefs/attachments/20140206/98b165b5/attachment.sig>


More information about the Linux-cachefs mailing list