X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fosc%2Fosc_page.c;h=df51fc5a86204625c6c2b339e204b47e1ac5bc94;hb=98060d83459ba10409f295898f0ec917f938b4d3;hp=126256f7d86f851858ab5e101516ba815614240a;hpb=72e1ce04a8b8f6887ff3df620f20755be0d244d8;p=fs%2Flustre-release.git diff --git a/lustre/osc/osc_page.c b/lustre/osc/osc_page.c index 126256f..df51fc5 100644 --- a/lustre/osc/osc_page.c +++ b/lustre/osc/osc_page.c @@ -27,7 +27,7 @@ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, Whamcloud, Inc. + * Copyright (c) 2011, 2013, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -126,7 +126,7 @@ static int osc_page_protected(const struct lu_env *env, descr->cld_mode = mode; descr->cld_start = page->cp_index; descr->cld_end = page->cp_index; - cfs_spin_lock(&hdr->coh_lock_guard); + spin_lock(&hdr->coh_lock_guard); cfs_list_for_each_entry(scan, &hdr->coh_locks, cll_linkage) { /* * Lock-less sub-lock has to be either in HELD state @@ -144,7 +144,7 @@ static int osc_page_protected(const struct lu_env *env, break; } } - cfs_spin_unlock(&hdr->coh_lock_guard); + spin_unlock(&hdr->coh_lock_guard); } return result; } @@ -168,7 +168,6 @@ static void osc_page_fini(const struct lu_env *env, struct osc_page *opg = cl2osc_page(slice); CDEBUG(D_TRACE, "%p\n", opg); LASSERT(opg->ops_lock == NULL); - OBD_SLAB_FREE_PTR(opg, osc_page_kmem); } static void osc_page_transfer_get(struct osc_page *opg, const char *label) @@ -207,10 +206,10 @@ static void osc_page_transfer_add(const struct lu_env *env, * first and then use it as inflight. */ osc_lru_del(osc_cli(obj), opg, false); - cfs_spin_lock(&obj->oo_seatbelt); - cfs_list_add(&opg->ops_inflight, &obj->oo_inflight[crt]); - opg->ops_submitter = cfs_current(); - cfs_spin_unlock(&obj->oo_seatbelt); + spin_lock(&obj->oo_seatbelt); + cfs_list_add(&opg->ops_inflight, &obj->oo_inflight[crt]); + opg->ops_submitter = cfs_current(); + spin_unlock(&obj->oo_seatbelt); } static int osc_page_cache_add(const struct lu_env *env, @@ -432,13 +431,13 @@ static void osc_page_delete(const struct lu_env *env, LASSERT(0); } - cfs_spin_lock(&obj->oo_seatbelt); + spin_lock(&obj->oo_seatbelt); if (opg->ops_submitter != NULL) { LASSERT(!cfs_list_empty(&opg->ops_inflight)); cfs_list_del_init(&opg->ops_inflight); opg->ops_submitter = NULL; } - cfs_spin_unlock(&obj->oo_seatbelt); + spin_unlock(&obj->oo_seatbelt); osc_lru_del(osc_cli(obj), opg, true); EXIT; @@ -454,9 +453,9 @@ void osc_page_clip(const struct lu_env *env, const struct cl_page_slice *slice, opg->ops_from = from; opg->ops_to = to; - cfs_spin_lock(&oap->oap_lock); - oap->oap_async_flags |= ASYNC_COUNT_STABLE; - cfs_spin_unlock(&oap->oap_lock); + spin_lock(&oap->oap_lock); + oap->oap_async_flags |= ASYNC_COUNT_STABLE; + spin_unlock(&oap->oap_lock); } static int osc_page_cancel(const struct lu_env *env, @@ -508,46 +507,41 @@ static const struct cl_page_operations osc_page_ops = { .cpo_flush = osc_page_flush }; -struct cl_page *osc_page_init(const struct lu_env *env, - struct cl_object *obj, - struct cl_page *page, cfs_page_t *vmpage) +int osc_page_init(const struct lu_env *env, struct cl_object *obj, + struct cl_page *page, cfs_page_t *vmpage) { - struct osc_object *osc = cl2osc(obj); - struct osc_page *opg; - int result; + struct osc_object *osc = cl2osc(obj); + struct osc_page *opg = cl_object_page_slice(obj, page); + int result; - OBD_SLAB_ALLOC_PTR_GFP(opg, osc_page_kmem, CFS_ALLOC_IO); - if (opg != NULL) { - opg->ops_from = 0; - opg->ops_to = CFS_PAGE_SIZE; - - result = osc_prep_async_page(osc, opg, vmpage, - cl_offset(obj, page->cp_index)); - if (result == 0) { - struct osc_io *oio = osc_env_io(env); - opg->ops_srvlock = osc_io_srvlock(oio); - cl_page_slice_add(page, &opg->ops_cl, obj, - &osc_page_ops); - } - /* - * Cannot assert osc_page_protected() here as read-ahead - * creates temporary pages outside of a lock. - */ + opg->ops_from = 0; + opg->ops_to = CFS_PAGE_SIZE; + + result = osc_prep_async_page(osc, opg, vmpage, + cl_offset(obj, page->cp_index)); + if (result == 0) { + struct osc_io *oio = osc_env_io(env); + opg->ops_srvlock = osc_io_srvlock(oio); + cl_page_slice_add(page, &opg->ops_cl, obj, + &osc_page_ops); + } + /* + * Cannot assert osc_page_protected() here as read-ahead + * creates temporary pages outside of a lock. + */ #ifdef INVARIANT_CHECK - opg->ops_temp = !osc_page_protected(env, opg, CLM_READ, 1); + opg->ops_temp = !osc_page_protected(env, opg, CLM_READ, 1); #endif - /* ops_inflight and ops_lru are the same field, but it doesn't - * hurt to initialize it twice :-) */ - CFS_INIT_LIST_HEAD(&opg->ops_inflight); - CFS_INIT_LIST_HEAD(&opg->ops_lru); - } else - result = -ENOMEM; + /* ops_inflight and ops_lru are the same field, but it doesn't + * hurt to initialize it twice :-) */ + CFS_INIT_LIST_HEAD(&opg->ops_inflight); + CFS_INIT_LIST_HEAD(&opg->ops_lru); /* reserve an LRU space for this page */ if (page->cp_type == CPT_CACHEABLE && result == 0) result = osc_lru_reserve(env, osc, opg); - return ERR_PTR(result); + return result; } /** @@ -647,7 +641,7 @@ static int discard_pagevec(const struct lu_env *env, struct cl_io *io, * This check is necessary to avoid freeing the pages * having already been removed from LRU and pinned * for IO. */ - if (cfs_atomic_read(&page->cp_ref) == 1) { + if (!cl_page_in_use(page)) { cl_page_unmap(env, io, page); cl_page_discard(env, io, page); ++count; @@ -700,8 +694,7 @@ int osc_lru_shrink(struct client_obd *cli, int target) opg = cfs_list_entry(cli->cl_lru_list.next, struct osc_page, ops_lru); page = cl_page_top(opg->ops_cl.cpl_page); - if (page->cp_state == CPS_FREEING || - cfs_atomic_read(&page->cp_ref) > 0) { + if (cl_page_in_use_noref(page)) { cfs_list_move_tail(&opg->ops_lru, &cli->cl_lru_list); continue; } @@ -724,12 +717,15 @@ int osc_lru_shrink(struct client_obd *cli, int target) clobj = tmp; io->ci_obj = clobj; + io->ci_ignore_layout = 1; rc = cl_io_init(env, io, CIT_MISC, clobj); + + client_obd_list_lock(&cli->cl_lru_list_lock); + if (rc != 0) break; ++maxscan; - client_obd_list_lock(&cli->cl_lru_list_lock); continue; } @@ -783,8 +779,10 @@ static void osc_lru_add(struct client_obd *cli, struct osc_page *opg) } client_obd_list_unlock(&cli->cl_lru_list_lock); - if (wakeup) + if (wakeup) { + osc_lru_shrink(cli, osc_cache_too_much(cli)); cfs_waitq_broadcast(&osc_lru_waitq); + } } /* delete page from LRUlist. The page can be deleted from LRUlist for two @@ -820,18 +818,22 @@ static void osc_lru_del(struct client_obd *cli, struct osc_page *opg, bool del) } } +static inline int max_to_shrink(struct client_obd *cli) +{ + return min(cfs_atomic_read(&cli->cl_lru_in_list) >> 1, lru_shrink_max); +} + static int osc_lru_reclaim(struct client_obd *cli) { struct cl_client_cache *cache = cli->cl_cache; - struct client_obd *victim; - struct client_obd *tmp; + int max_scans; int rc; LASSERT(cache != NULL); LASSERT(!cfs_list_empty(&cache->ccc_lru)); rc = osc_lru_shrink(cli, lru_shrink_min); - if (rc > 0) { + if (rc != 0) { CDEBUG(D_CACHE, "%s: Free %d pages from own LRU: %p.\n", cli->cl_import->imp_obd->obd_name, rc, cli); return rc; @@ -844,36 +846,34 @@ static int osc_lru_reclaim(struct client_obd *cli) /* Reclaim LRU slots from other client_obd as it can't free enough * from its own. This should rarely happen. */ - cfs_spin_lock(&cache->ccc_lru_lock); + spin_lock(&cache->ccc_lru_lock); cache->ccc_lru_shrinkers++; cfs_list_move_tail(&cli->cl_lru_osc, &cache->ccc_lru); - cfs_list_for_each_entry_safe(victim, tmp, &cache->ccc_lru, cl_lru_osc) { - if (victim == cli) - break; - CDEBUG(D_CACHE, "%s: cli %p LRU pages: %d, busy: %d.\n", - victim->cl_import->imp_obd->obd_name, victim, - cfs_atomic_read(&victim->cl_lru_in_list), - cfs_atomic_read(&victim->cl_lru_busy)); + max_scans = cfs_atomic_read(&cache->ccc_users); + while (--max_scans > 0 && !cfs_list_empty(&cache->ccc_lru)) { + cli = cfs_list_entry(cache->ccc_lru.next, struct client_obd, + cl_lru_osc); - cfs_list_move_tail(&victim->cl_lru_osc, &cache->ccc_lru); - if (cfs_atomic_read(&victim->cl_lru_in_list) > 0) - break; - } - cfs_spin_unlock(&cache->ccc_lru_lock); - if (victim == cli) { - CDEBUG(D_CACHE, "%s: can't get any free LRU slots.\n", - cli->cl_import->imp_obd->obd_name); - return 0; - } + CDEBUG(D_CACHE, "%s: cli %p LRU pages: %d, busy: %d.\n", + cli->cl_import->imp_obd->obd_name, cli, + cfs_atomic_read(&cli->cl_lru_in_list), + cfs_atomic_read(&cli->cl_lru_busy)); - rc = osc_lru_shrink(victim, - min(cfs_atomic_read(&victim->cl_lru_in_list) >> 1, - lru_shrink_max)); + cfs_list_move_tail(&cli->cl_lru_osc, &cache->ccc_lru); + if (cfs_atomic_read(&cli->cl_lru_in_list) > 0) { + spin_unlock(&cache->ccc_lru_lock); - CDEBUG(D_CACHE, "%s: Free %d pages from other cli: %p.\n", - cli->cl_import->imp_obd->obd_name, rc, victim); + rc = osc_lru_shrink(cli, max_to_shrink(cli)); + spin_lock(&cache->ccc_lru_lock); + if (rc != 0) + break; + } + } + spin_unlock(&cache->ccc_lru_lock); + CDEBUG(D_CACHE, "%s: cli %p freed %d pages.\n", + cli->cl_import->imp_obd->obd_name, cli, rc); return rc; }