Details
-
Bug
-
Resolution: Fixed
-
Minor
-
Upstream
-
None
-
3
-
9223372036854775807
Description
cfs_hash_rehash(struct cfs_hash *hs, int do_rehash) { ... hs->hs_rehash_bits = rc; if (!do_rehash) { /* launch and return */ queue_work(cfs_rehash_wq, &hs->hs_rehash_work); cfs_hash_unlock(hs, 1); return; } cfs_hash_rehash_cancel(struct cfs_hash *hs) { LASSERT(cfs_hash_with_rehash(hs)); cancel_work_sync(&hs->hs_rehash_work); } cfs_hash_for_each_enter(struct cfs_hash *hs) { ... if (cfs_hash_is_rehashing(hs)) cfs_hash_rehash_cancel(hs); }
if we enter iteration (cfs_hash_for_each_enter()) and find rehashing scheduled or in progress (hs_rehash_bits != 0), then we want to cancel that work using cancel_work_sync().
but if the work hasn't started yet then who would reset hs_rehash_bits back to 0?
a trivial test demonstrates this:
static struct workqueue_struct *test_rehash_wq; struct work_struct test_rehash_work; static volatile int test_var = 0; static void test_worker(struct work_struct *work) { test_var = 0; } void work_test(void) { test_rehash_wq = alloc_workqueue("test", WQ_SYSFS, 4); INIT_WORK(&test_rehash_work, test_worker); test_var = 1; queue_work(test_rehash_wq, &test_rehash_work); cancel_work_sync(&test_rehash_work); LASSERT(test_var == 0); destroy_workqueue(test_rehash_wq); }
"Oleg Drokin <green@whamcloud.com>" merged in patch https://review.whamcloud.com/c/fs/lustre-release/+/53283/
Subject:
LU-15207libcfs: reset hs_rehash_bitsProject: fs/lustre-release
Branch: b2_15
Current Patch Set:
Commit: e063351ab068a795dadbefaa5514d5bf7b7c4eb2