|
|
| version 1.1, 2007/07/09 06:12:03 | version 1.2, 2007/08/02 15:55:15 |
|---|---|
| Line 206 _xfs_mru_cache_list_insert( | Line 206 _xfs_mru_cache_list_insert( |
| */ | */ |
| if (!_xfs_mru_cache_migrate(mru, now)) { | if (!_xfs_mru_cache_migrate(mru, now)) { |
| mru->time_zero = now; | mru->time_zero = now; |
| if (!mru->next_reap) | if (!mru->queued) { |
| mru->next_reap = mru->grp_count * mru->grp_time; | mru->queued = 1; |
| queue_delayed_work(xfs_mru_reap_wq, &mru->work, | |
| mru->grp_count * mru->grp_time); | |
| } | |
| } else { | } else { |
| grp = (now - mru->time_zero) / mru->grp_time; | grp = (now - mru->time_zero) / mru->grp_time; |
| grp = (mru->lru_grp + grp) % mru->grp_count; | grp = (mru->lru_grp + grp) % mru->grp_count; |
| Line 271 _xfs_mru_cache_reap( | Line 274 _xfs_mru_cache_reap( |
| struct work_struct *work) | struct work_struct *work) |
| { | { |
| xfs_mru_cache_t *mru = container_of(work, xfs_mru_cache_t, work.work); | xfs_mru_cache_t *mru = container_of(work, xfs_mru_cache_t, work.work); |
| unsigned long now; | unsigned long now, next; |
| ASSERT(mru && mru->lists); | ASSERT(mru && mru->lists); |
| if (!mru || !mru->lists) | if (!mru || !mru->lists) |
| return; | return; |
| mutex_spinlock(&mru->lock); | mutex_spinlock(&mru->lock); |
| now = jiffies; | next = _xfs_mru_cache_migrate(mru, jiffies); |
| if (mru->reap_all || | _xfs_mru_cache_clear_reap_list(mru); |
| (mru->next_reap && time_after(now, mru->next_reap))) { | |
| if (mru->reap_all) | mru->queued = next; |
| now += mru->grp_count * mru->grp_time * 2; | if ((mru->queued > 0)) { |
| mru->next_reap = _xfs_mru_cache_migrate(mru, now); | now = jiffies; |
| _xfs_mru_cache_clear_reap_list(mru); | if (next <= now) |
| next = 0; | |
| else | |
| next -= now; | |
| queue_delayed_work(xfs_mru_reap_wq, &mru->work, next); | |
| } | } |
| /* | |
| * the process that triggered the reap_all is responsible | |
| * for restating the periodic reap if it is required. | |
| */ | |
| if (!mru->reap_all) | |
| queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time); | |
| mru->reap_all = 0; | |
| mutex_spinunlock(&mru->lock, 0); | mutex_spinunlock(&mru->lock, 0); |
| } | } |
| Line 352 xfs_mru_cache_create( | Line 352 xfs_mru_cache_create( |
| /* An extra list is needed to avoid reaping up to a grp_time early. */ | /* An extra list is needed to avoid reaping up to a grp_time early. */ |
| mru->grp_count = grp_count + 1; | mru->grp_count = grp_count + 1; |
| mru->lists = kmem_alloc(mru->grp_count * sizeof(*mru->lists), KM_SLEEP); | mru->lists = kmem_zalloc(mru->grp_count * sizeof(*mru->lists), KM_SLEEP); |
| if (!mru->lists) { | if (!mru->lists) { |
| err = ENOMEM; | err = ENOMEM; |
| Line 374 xfs_mru_cache_create( | Line 374 xfs_mru_cache_create( |
| mru->grp_time = grp_time; | mru->grp_time = grp_time; |
| mru->free_func = free_func; | mru->free_func = free_func; |
| /* start up the reaper event */ | |
| mru->next_reap = 0; | |
| mru->reap_all = 0; | |
| queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time); | |
| *mrup = mru; | *mrup = mru; |
| exit: | exit: |
| Line 394 exit: | Line 389 exit: |
| * Call xfs_mru_cache_flush() to flush out all cached entries, calling their | * Call xfs_mru_cache_flush() to flush out all cached entries, calling their |
| * free functions as they're deleted. When this function returns, the caller is | * free functions as they're deleted. When this function returns, the caller is |
| * guaranteed that all the free functions for all the elements have finished | * guaranteed that all the free functions for all the elements have finished |
| * executing. | * executing and the reaper is not running. |
| * | |
| * While we are flushing, we stop the periodic reaper event from triggering. | |
| * Normally, we want to restart this periodic event, but if we are shutting | |
| * down the cache we do not want it restarted. hence the restart parameter | |
| * where 0 = do not restart reaper and 1 = restart reaper. | |
| */ | */ |
| void | void |
| xfs_mru_cache_flush( | xfs_mru_cache_flush( |
| xfs_mru_cache_t *mru, | xfs_mru_cache_t *mru) |
| int restart) | |
| { | { |
| if (!mru || !mru->lists) | if (!mru || !mru->lists) |
| return; | return; |
| cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work); | |
| mutex_spinlock(&mru->lock); | mutex_spinlock(&mru->lock); |
| mru->reap_all = 1; | if (mru->queued) { |
| mutex_spinunlock(&mru->lock, 0); | mutex_spinunlock(&mru->lock, 0); |
| cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work); | |
| mutex_spinlock(&mru->lock); | |
| } | |
| queue_work(xfs_mru_reap_wq, &mru->work.work); | _xfs_mru_cache_migrate(mru, jiffies + mru->grp_count * mru->grp_time); |
| flush_workqueue(xfs_mru_reap_wq); | _xfs_mru_cache_clear_reap_list(mru); |
| mutex_spinlock(&mru->lock); | |
| WARN_ON_ONCE(mru->reap_all != 0); | |
| mru->reap_all = 0; | |
| if (restart) | |
| queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time); | |
| mutex_spinunlock(&mru->lock, 0); | mutex_spinunlock(&mru->lock, 0); |
| } | } |
| Line 433 xfs_mru_cache_destroy( | Line 418 xfs_mru_cache_destroy( |
| if (!mru || !mru->lists) | if (!mru || !mru->lists) |
| return; | return; |
| /* we don't want the reaper to restart here */ | xfs_mru_cache_flush(mru); |
| xfs_mru_cache_flush(mru, 0); | |
| kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists)); | kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists)); |
| kmem_free(mru, sizeof(*mru)); | kmem_free(mru, sizeof(*mru)); |