From 6418d8ac85f25251bf661c3e96a87d8f8301e18d Mon Sep 17 00:00:00 2001 From: shadow Date: Fri, 4 Jul 2008 07:38:07 +0000 Subject: [PATCH] add recount protection for osc callbacks, so avoid panic on shutdown Branch b1_6 b=15210 i=green i=umka --- lustre/ChangeLog | 4 ++++ lustre/include/lustre_cache.h | 2 ++ lustre/osc/cache.c | 41 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 219203e..1b7771f 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -29,6 +29,10 @@ Bugzilla : 16189 Description: Update to RHEL4 kernel-2.6.9-67.0.20. Severity : normal +Bugzilla : 15210 +Description: add recount protection for osc callbacks, so avoid panic on shutdown + +Severity : normal Bugzilla : 12653 Description: sanity test 65a fails if stripecount of -1 is set Details : handle -1 striping on filesystem in ll_dirstripe_verify diff --git a/lustre/include/lustre_cache.h b/lustre/include/lustre_cache.h index 291d882..d5a5337 100644 --- a/lustre/include/lustre_cache.h +++ b/lustre/include/lustre_cache.h @@ -13,6 +13,7 @@ struct osc_async_page; struct page_removal_cb_element { struct list_head prce_list; obd_page_removal_cb_t prce_callback; + atomic_t prce_refcnt; }; typedef int (*cache_iterate_extents_cb_t)(struct lustre_cache *, @@ -27,6 +28,7 @@ struct lustre_cache { struct list_head lc_locks_list; spinlock_t lc_locks_list_lock; struct list_head lc_page_removal_callback_list; + rwlock_t lc_page_removal_cb_lock; /* iterate vs modify list */ struct obd_device *lc_obd; obd_pin_extent_cb lc_pin_extent_cb; }; diff --git a/lustre/osc/cache.c b/lustre/osc/cache.c index c144d96..4f4ddd9 100644 --- a/lustre/osc/cache.c +++ b/lustre/osc/cache.c @@ -137,16 +137,39 @@ int cache_add_extent(struct lustre_cache *cache, struct ldlm_res_id *res, RETURN(0); } +static void cache_extent_removal_get(struct page_removal_cb_element *element) +{ + atomic_inc(&element->prce_refcnt); +} + +static void cache_extent_removal_put(struct page_removal_cb_element *element) +{ + if(atomic_dec_and_test(&element->prce_refcnt)) + OBD_FREE_PTR(element); +} + static int cache_extent_removal_event(struct lustre_cache *cache, void *data, int discard) { struct page *page = data; + struct list_head *iter; struct page_removal_cb_element *element; - list_for_each_entry(element, &cache->lc_page_removal_callback_list, - prce_list) { + read_lock(&cache->lc_page_removal_cb_lock); + iter = cache->lc_page_removal_callback_list.next; + while(iter != &cache->lc_page_removal_callback_list) { + element = list_entry(iter, struct page_removal_cb_element, prce_list); + cache_extent_removal_get(element); + read_unlock(&cache->lc_page_removal_cb_lock); + element->prce_callback(page, discard); + + read_lock(&cache->lc_page_removal_cb_lock); + iter = iter->next; + cache_extent_removal_put(element); } + read_unlock(&cache->lc_page_removal_cb_lock); + return 0; } @@ -166,12 +189,17 @@ int cache_add_extent_removal_cb(struct lustre_cache *cache, if (!func_cb) return 0; - OBD_ALLOC(element, sizeof(*element)); + + OBD_ALLOC_PTR(element); if (!element) return -ENOMEM; element->prce_callback = func_cb; + atomic_set(&element->prce_refcnt, 1); + + write_lock(&cache->lc_page_removal_cb_lock); list_add_tail(&element->prce_list, &cache->lc_page_removal_callback_list); + write_unlock(&cache->lc_page_removal_cb_lock); cache->lc_pin_extent_cb = pin_cb; return 0; @@ -187,17 +215,21 @@ int cache_del_extent_removal_cb(struct lustre_cache *cache, int found = 0; struct page_removal_cb_element *element, *t; + write_lock(&cache->lc_page_removal_cb_lock); list_for_each_entry_safe(element, t, &cache->lc_page_removal_callback_list, prce_list) { if (element->prce_callback == func_cb) { list_del(&element->prce_list); - OBD_FREE(element, sizeof(*element)); + write_unlock(&cache->lc_page_removal_cb_lock); found = 1; + cache_extent_removal_put(element); + write_lock(&cache->lc_page_removal_cb_lock); /* We continue iterating the list in case this function was registered more than once */ } } + write_unlock(&cache->lc_page_removal_cb_lock); if (list_empty(&cache->lc_page_removal_callback_list)) cache->lc_pin_extent_cb = NULL; @@ -357,6 +389,7 @@ struct lustre_cache *cache_create(struct obd_device *obd) spin_lock_init(&cache->lc_locks_list_lock); CFS_INIT_LIST_HEAD(&cache->lc_locks_list); CFS_INIT_LIST_HEAD(&cache->lc_page_removal_callback_list); + rwlock_init(&cache->lc_page_removal_cb_lock); cache->lc_obd = obd; out: -- 1.8.3.1