From ed14dd4d80ae32635cee501a0e2f33bffe1872ab Mon Sep 17 00:00:00 2001 From: shadow <shadow> Date: Fri, 4 Jul 2008 07:42:10 +0000 Subject: [PATCH] add recount protection for osc callbacks, so avoid panic on shutdown Branch HEAD 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 d281ffde65..02d8d73086 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -12,6 +12,10 @@ tbd Sun Microsystems, Inc. * RHEL 4 and RHEL 5/SLES 10 clients behaves differently on 'cd' to a removed cwd "./" (refer to Bugzilla 14399). +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 diff --git a/lustre/include/lustre_cache.h b/lustre/include/lustre_cache.h index 291d882936..d5a5337bd2 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 3dc93fb72f..25869743c0 100644 --- a/lustre/osc/cache.c +++ b/lustre/osc/cache.c @@ -138,16 +138,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; } @@ -167,12 +190,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; @@ -188,17 +216,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; @@ -358,6 +390,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: -- GitLab