Release CacheFS search records lest they return to haunt us
PATCH 1/1 Release CacheFS search records lest they return to haunt us
The attached patch causes CacheFS to free cached search records when it destroys a cookie. These were coming back to haunt us because the list isn't re-initialised when the cookie is re-allocated (the slab allocator func initialises it in the first place).
Signed-off-by David Howells <[email protected]>
---
interface.c | 34 ++++++++++++++++++++++++++-------- 1 files changed, 26 insertions(+), 8 deletions(-)
fs/cachefs/interface.c +26 -8
@@ -114,7 +114,8 @@up_write (&cachefs_addremove_sem);if (ret <0 ) { -kmem_cache_free (cachefs_cookie_jar, netfs->primary_index); + netfs->primary_index->iparent =NULL ; +__cachefs_cookie_put (netfs->primary_index); netfs->primary_index =NULL ; }
@@ -275,8 +276,9 @@struct cachefs_search_result *srch;struct cachefs_cookie *cookie, *xcookie =NULL ; -_enter ("{ino=%lu cnt=%u}" , - inode->vfs_inode.i_ino,atomic_read (&inode->vfs_inode.i_count)); +_enter ("{ino=%lu cnt=%u ck=%p}" , + inode->vfs_inode.i_ino,atomic_read (&inode->vfs_inode.i_count), + inode->cookie);/* first of all we have to break the links between the inode and the * cookie
@@ -305,9 +307,11 @@* cookie's list */ list_for_each_entry (srch, &cookie->search_results, link) {if (srch->super == inode->vfs_inode.i_sb->s_fs_info) -break ; + goto found_record; } +BUG (); + found_record:list_del (&srch->link);dbgfree (srch);kfree (srch);
@@ -773,9 +777,8 @@ error:printk ("CacheFS: error from cache fs: %d\n" , ret);if (cookie) { -kmem_cache_free (cachefs_cookie_jar, cookie); +__cachefs_cookie_put (cookie); cookie =CACHEFS_NEGATIVE_COOKIE ; -atomic_dec (&iparent->usage);atomic_dec (&iparent->children); }
@@ -800,7 +803,8 @@ {struct cachefs_inode *inode; -_enter ("{%s},%d" , +_enter ("%p{%s},%d" , + cookie, cookie && cookie->idef ? (char *) cookie->idef->name :"<file>" , retire);
@@ -955,11 +959,25 @@*/ static void __cachefs_cookie_put (struct cachefs_cookie *cookie) { -_enter ("" ); +struct cachefs_search_result *srch; + +_enter ("%p" , cookie);if (cookie->iparent)cachefs_cookie_put (cookie->iparent); +/* dispose of any cached search results */ +while (!list_empty (&cookie->search_results)) { + srch =list_entry (cookie->search_results.next, + struct cachefs_search_result, + link); + +list_del (&srch->link); +kfree (srch); + } + +BUG_ON (!list_empty (&cookie->search_results)); +BUG_ON (!list_empty (&cookie->backing_inodes));kmem_cache_free (cachefs_cookie_jar, cookie);_leave ("" );