From c444b19c469d152057126c6484cec54b6d52d7d6 Mon Sep 17 00:00:00 2001 From: shadow Date: Fri, 20 Mar 2009 07:38:44 +0000 Subject: [PATCH] resolve race between llap_shrinker and umount. Branch b1_8 b=18773 i=jay i=tappro --- lustre/ChangeLog | 7 +++++++ lustre/llite/llite_lib.c | 10 +++++++--- lustre/llite/rw.c | 5 +++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lustre/ChangeLog b/lustre/ChangeLog index f872eee..ff8aca4 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -185,6 +185,13 @@ Details : Do not put cancelled locks into replay list, hold references on information, please refer to bugzilla 17630. Severity : normal +Frequency : rare, at shutdown +Bugzilla : 18773 +Descriptoin: panic at umount +Details : llap_shrinker can be raced with killing super block from list and + this produce panic with access to already freeded pointer + +Severity : normal Frequency : rare Bugzilla : 18154 Descriptoin: don't lose wakeup for imp_recovery_waitq diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index db80b2e..eb4cb3b 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -66,7 +66,7 @@ extern struct address_space_operations ll_dir_aops; #define log2(n) ffz(~(n)) #endif -static inline void ll_pglist_fini(struct ll_sb_info *sbi) +static void ll_pglist_fini(struct ll_sb_info *sbi) { struct page *page; int i; @@ -86,7 +86,7 @@ static inline void ll_pglist_fini(struct ll_sb_info *sbi) sbi->ll_pglist = NULL; } -static inline int ll_pglist_init(struct ll_sb_info *sbi) +static int ll_pglist_init(struct ll_sb_info *sbi) { struct ll_pglist_data *pd; unsigned long budget; @@ -226,10 +226,11 @@ void ll_free_sbi(struct super_block *sb) ENTRY; if (sbi != NULL) { - ll_pglist_fini(sbi); spin_lock(&ll_sb_lock); list_del(&sbi->ll_list); spin_unlock(&ll_sb_lock); + /* dont allow find cache via sb list first */ + ll_pglist_fini(sbi); lcounter_destroy(&sbi->ll_async_page_count); OBD_FREE(sbi->ll_async_page_sample, sizeof(long) * num_possible_cpus()); @@ -1296,8 +1297,11 @@ ll_shrink_cache(int priority, unsigned int gfp_mask) struct ll_sb_info *sbi; int count = 0; + /* don't race with umount */ + spin_lock(&ll_sb_lock); list_for_each_entry(sbi, &ll_super_blocks, ll_list) count += llap_shrink_cache(sbi, priority); + spin_unlock(&ll_sb_lock); #if defined(HAVE_CACHE_RETURN_INT) return count; diff --git a/lustre/llite/rw.c b/lustre/llite/rw.c index c2e84de..b8498d2 100644 --- a/lustre/llite/rw.c +++ b/lustre/llite/rw.c @@ -555,9 +555,10 @@ static inline int llap_shrink_cache_internal(struct ll_sb_info *sbi, int keep; if (unlikely(need_resched())) { + list_del(&dummy_llap.llap_pglist_item); ll_pglist_cpu_unlock(sbi, cpu); - cond_resched(); - ll_pglist_cpu_lock(sbi, cpu); + /* vmscan::shrink_slab() have own schedule() */ + return count; } llap = llite_pglist_next_llap(head, -- 1.8.3.1