X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fosc%2Fosc_cache.c;h=11a5e0e4ed416d47c7282e5a5eaac293933432b1;hb=0b2f943a317083a117d6f5f4a22e1d8233a7da77;hp=060224201abaadcc93245ba9e4213f07667e1418;hpb=f7a81d4797933d179f9955bb0821779d3ac9a8fe;p=fs%2Flustre-release.git diff --git a/lustre/osc/osc_cache.c b/lustre/osc/osc_cache.c index 0602242..11a5e0e 100644 --- a/lustre/osc/osc_cache.c +++ b/lustre/osc/osc_cache.c @@ -309,7 +309,7 @@ static struct osc_extent *osc_extent_alloc(struct osc_object *obj) { struct osc_extent *ext; - OBD_SLAB_ALLOC_PTR_GFP(ext, osc_extent_kmem, CFS_ALLOC_STD); + OBD_SLAB_ALLOC_PTR_GFP(ext, osc_extent_kmem, GFP_IOFS); if (ext == NULL) return NULL; @@ -505,7 +505,7 @@ static int osc_extent_merge(const struct lu_env *env, struct osc_extent *cur, return -ERANGE; LASSERT(cur->oe_osclock == victim->oe_osclock); - ppc_bits = osc_cli(obj)->cl_chunkbits - CFS_PAGE_SHIFT; + ppc_bits = osc_cli(obj)->cl_chunkbits - PAGE_CACHE_SHIFT; chunk_start = cur->oe_start >> ppc_bits; chunk_end = cur->oe_end >> ppc_bits; if (chunk_start != (victim->oe_end >> ppc_bits) + 1 && @@ -612,8 +612,8 @@ struct osc_extent *osc_extent_find(const struct lu_env *env, LASSERT(lock != NULL); LASSERT(lock->cll_descr.cld_mode >= CLM_WRITE); - LASSERT(cli->cl_chunkbits >= CFS_PAGE_SHIFT); - ppc_bits = cli->cl_chunkbits - CFS_PAGE_SHIFT; + LASSERT(cli->cl_chunkbits >= PAGE_CACHE_SHIFT); + ppc_bits = cli->cl_chunkbits - PAGE_CACHE_SHIFT; chunk_mask = ~((1 << ppc_bits) - 1); chunksize = 1 << cli->cl_chunkbits; chunk = index >> ppc_bits; @@ -827,8 +827,8 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext, if (!sent) { lost_grant = ext->oe_grants; - } else if (blocksize < CFS_PAGE_SIZE && - last_count != CFS_PAGE_SIZE) { + } else if (blocksize < PAGE_CACHE_SIZE && + last_count != PAGE_CACHE_SIZE) { /* For short writes we shouldn't count parts of pages that * span a whole chunk on the OST side, or our accounting goes * wrong. Should match the code in filter_grant_check. */ @@ -838,7 +838,7 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext, if (end) count += blocksize - end; - lost_grant = CFS_PAGE_SIZE - count; + lost_grant = PAGE_CACHE_SIZE - count; } if (ext->oe_grants > 0) osc_free_grant(cli, nr_pages, lost_grant); @@ -920,7 +920,8 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index, struct osc_async_page *oap; struct osc_async_page *tmp; int pages_in_chunk = 0; - int ppc_bits = cli->cl_chunkbits - CFS_PAGE_SHIFT; + int ppc_bits = cli->cl_chunkbits - + PAGE_CACHE_SHIFT; __u64 trunc_chunk = trunc_index >> ppc_bits; int grants = 0; int nr_pages = 0; @@ -1077,16 +1078,20 @@ static int osc_extent_make_ready(const struct lu_env *env, if (!(last->oap_async_flags & ASYNC_COUNT_STABLE)) { last->oap_count = osc_refresh_count(env, last, OBD_BRW_WRITE); LASSERT(last->oap_count > 0); - LASSERT(last->oap_page_off + last->oap_count <= CFS_PAGE_SIZE); + LASSERT(last->oap_page_off + last->oap_count <= PAGE_CACHE_SIZE); + spin_lock(&last->oap_lock); last->oap_async_flags |= ASYNC_COUNT_STABLE; + spin_unlock(&last->oap_lock); } /* for the rest of pages, we don't need to call osf_refresh_count() * because it's known they are not the last page */ cfs_list_for_each_entry(oap, &ext->oe_pages, oap_pending_item) { if (!(oap->oap_async_flags & ASYNC_COUNT_STABLE)) { - oap->oap_count = CFS_PAGE_SIZE - oap->oap_page_off; + oap->oap_count = PAGE_CACHE_SIZE - oap->oap_page_off; + spin_lock(&oap->oap_lock); oap->oap_async_flags |= ASYNC_COUNT_STABLE; + spin_unlock(&oap->oap_lock); } } @@ -1109,7 +1114,7 @@ static int osc_extent_expand(struct osc_extent *ext, pgoff_t index, int *grants) struct osc_object *obj = ext->oe_obj; struct client_obd *cli = osc_cli(obj); struct osc_extent *next; - int ppc_bits = cli->cl_chunkbits - CFS_PAGE_SHIFT; + int ppc_bits = cli->cl_chunkbits - PAGE_CACHE_SHIFT; pgoff_t chunk = index >> ppc_bits; pgoff_t end_chunk; pgoff_t end_index; @@ -1241,9 +1246,9 @@ static int osc_refresh_count(const struct lu_env *env, return 0; else if (cl_offset(obj, page->cp_index + 1) > kms) /* catch sub-page write at end of file */ - return kms % CFS_PAGE_SIZE; + return kms % PAGE_CACHE_SIZE; else - return CFS_PAGE_SIZE; + return PAGE_CACHE_SIZE; } static int osc_completion(const struct lu_env *env, struct osc_async_page *oap, @@ -1308,28 +1313,32 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap, RETURN(0); } -#define OSC_DUMP_GRANT(cli, fmt, args...) do { \ +#define OSC_DUMP_GRANT(lvl, cli, fmt, args...) do { \ struct client_obd *__tmp = (cli); \ - CDEBUG(D_CACHE, "%s: { dirty: %ld/%ld dirty_pages: %d/%d " \ - "dropped: %ld avail: %ld, reserved: %ld, flight: %d } " fmt, \ + CDEBUG(lvl, "%s: grant { dirty: %ld/%ld dirty_pages: %d/%d " \ + "dropped: %ld avail: %ld, reserved: %ld, flight: %d } " \ + "lru {in list: %d, left: %d, waiters: %d }" fmt, \ __tmp->cl_import->imp_obd->obd_name, \ __tmp->cl_dirty, __tmp->cl_dirty_max, \ cfs_atomic_read(&obd_dirty_pages), obd_max_dirty_pages, \ __tmp->cl_lost_grant, __tmp->cl_avail_grant, \ - __tmp->cl_reserved_grant, __tmp->cl_w_in_flight, ##args); \ + __tmp->cl_reserved_grant, __tmp->cl_w_in_flight, \ + cfs_atomic_read(&__tmp->cl_lru_in_list), \ + cfs_atomic_read(&__tmp->cl_lru_busy), \ + cfs_atomic_read(&__tmp->cl_lru_shrinkers), ##args); \ } while (0) /* caller must hold loi_list_lock */ static void osc_consume_write_grant(struct client_obd *cli, struct brw_page *pga) { - LASSERT_SPIN_LOCKED(&cli->cl_loi_list_lock.lock); + LASSERT(spin_is_locked(&cli->cl_loi_list_lock.lock)); LASSERT(!(pga->flag & OBD_BRW_FROM_GRANT)); cfs_atomic_inc(&obd_dirty_pages); - cli->cl_dirty += CFS_PAGE_SIZE; + cli->cl_dirty += PAGE_CACHE_SIZE; pga->flag |= OBD_BRW_FROM_GRANT; CDEBUG(D_CACHE, "using %lu grant credits for brw %p page %p\n", - CFS_PAGE_SIZE, pga, pga->pg); + PAGE_CACHE_SIZE, pga, pga->pg); osc_update_next_shrink(cli); } @@ -1340,7 +1349,7 @@ static void osc_release_write_grant(struct client_obd *cli, { ENTRY; - LASSERT_SPIN_LOCKED(&cli->cl_loi_list_lock.lock); + LASSERT(spin_is_locked(&cli->cl_loi_list_lock.lock)); if (!(pga->flag & OBD_BRW_FROM_GRANT)) { EXIT; return; @@ -1348,11 +1357,11 @@ static void osc_release_write_grant(struct client_obd *cli, pga->flag &= ~OBD_BRW_FROM_GRANT; cfs_atomic_dec(&obd_dirty_pages); - cli->cl_dirty -= CFS_PAGE_SIZE; + cli->cl_dirty -= PAGE_CACHE_SIZE; if (pga->flag & OBD_BRW_NOCACHE) { pga->flag &= ~OBD_BRW_NOCACHE; cfs_atomic_dec(&obd_dirty_transit_pages); - cli->cl_dirty_transit -= CFS_PAGE_SIZE; + cli->cl_dirty_transit -= PAGE_CACHE_SIZE; } EXIT; } @@ -1408,7 +1417,7 @@ void osc_unreserve_grant(struct client_obd *cli, * used, we should return these grants to OST. There're two cases where grants * can be lost: * 1. truncate; - * 2. blocksize at OST is less than CFS_PAGE_SIZE and a partial page was + * 2. blocksize at OST is less than PAGE_CACHE_SIZE and a partial page was * written. In this case OST may use less chunks to serve this partial * write. OSTs don't actually know the page size on the client side. so * clients have to calculate lost grant by the blocksize on the OST. @@ -1421,7 +1430,7 @@ static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages, client_obd_list_lock(&cli->cl_loi_list_lock); cfs_atomic_sub(nr_pages, &obd_dirty_pages); - cli->cl_dirty -= nr_pages << CFS_PAGE_SHIFT; + cli->cl_dirty -= nr_pages << PAGE_CACHE_SHIFT; cli->cl_lost_grant += lost_grant; if (cli->cl_avail_grant < grant && cli->cl_lost_grant >= grant) { /* borrow some grant from truncate to avoid the case that @@ -1457,17 +1466,17 @@ static int osc_enter_cache_try(struct client_obd *cli, { int rc; - OSC_DUMP_GRANT(cli, "need:%d.\n", bytes); + OSC_DUMP_GRANT(D_CACHE, cli, "need:%d.\n", bytes); rc = osc_reserve_grant(cli, bytes); if (rc < 0) return 0; - if (cli->cl_dirty + CFS_PAGE_SIZE <= cli->cl_dirty_max && + if (cli->cl_dirty + PAGE_CACHE_SIZE <= cli->cl_dirty_max && cfs_atomic_read(&obd_dirty_pages) + 1 <= obd_max_dirty_pages) { osc_consume_write_grant(cli, &oap->oap_brw_page); if (transient) { - cli->cl_dirty_transit += CFS_PAGE_SIZE; + cli->cl_dirty_transit += PAGE_CACHE_SIZE; cfs_atomic_inc(&obd_dirty_transit_pages); oap->oap_brw_flags |= OBD_BRW_NOCACHE; } @@ -1501,18 +1510,19 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, struct osc_object *osc = oap->oap_obj; struct lov_oinfo *loi = osc->oo_oinfo; struct osc_cache_waiter ocw; - struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); + struct l_wait_info lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(600), NULL, + LWI_ON_SIGNAL_NOOP, NULL); int rc = -EDQUOT; ENTRY; - OSC_DUMP_GRANT(cli, "need:%d.\n", bytes); + OSC_DUMP_GRANT(D_CACHE, cli, "need:%d.\n", bytes); client_obd_list_lock(&cli->cl_loi_list_lock); /* force the caller to try sync io. this can jump the list * of queued writes and create a discontiguous rpc stream */ if (OBD_FAIL_CHECK(OBD_FAIL_OSC_NO_GRANT) || - cli->cl_dirty_max < CFS_PAGE_SIZE || + cli->cl_dirty_max < PAGE_CACHE_SIZE || cli->cl_ar.ar_force_sync || loi->loi_ar.ar_force_sync) GOTO(out, rc = -EDQUOT); @@ -1543,8 +1553,26 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, client_obd_list_lock(&cli->cl_loi_list_lock); - /* l_wait_event is interrupted by signal */ + /* l_wait_event is interrupted by signal, or timed out */ if (rc < 0) { + switch (rc) { + case -ETIMEDOUT: + OSC_DUMP_GRANT(D_ERROR, cli, + "try to reserve %d.\n", bytes); + osc_extent_tree_dump(D_ERROR, osc); + rc = -EDQUOT; + break; + case -EINTR: + /* Ensures restartability - LU-3581 */ + rc = -ERESTARTSYS; + break; + default: + CDEBUG(D_CACHE, "%s: event for cache space @" + " %p never arrived due to %d\n", + cli->cl_import->imp_obd->obd_name, + &ocw, rc); + break; + } cfs_list_del_init(&ocw.ocw_entry); GOTO(out, rc); } @@ -1560,7 +1588,7 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, EXIT; out: client_obd_list_unlock(&cli->cl_loi_list_lock); - OSC_DUMP_GRANT(cli, "returned %d.\n", rc); + OSC_DUMP_GRANT(D_CACHE, cli, "returned %d.\n", rc); RETURN(rc); } @@ -1577,7 +1605,7 @@ void osc_wake_cache_waiters(struct client_obd *cli) ocw->ocw_rc = -EDQUOT; /* we can't dirty more */ - if ((cli->cl_dirty + CFS_PAGE_SIZE > cli->cl_dirty_max) || + if ((cli->cl_dirty + PAGE_CACHE_SIZE > cli->cl_dirty_max) || (cfs_atomic_read(&obd_dirty_pages) + 1 > obd_max_dirty_pages)) { CDEBUG(D_CACHE, "no dirty room: dirty: %ld " @@ -2063,7 +2091,7 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli, while ((osc = osc_next_obj(cli)) != NULL) { struct cl_object *obj = osc2cl(osc); - struct lu_ref_link *link; + struct lu_ref_link link; OSC_IO_DEBUG(osc, "%lu in flight\n", rpcs_in_flight(cli)); @@ -2074,7 +2102,8 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli, cl_object_get(obj); client_obd_list_unlock(&cli->cl_loi_list_lock); - link = lu_object_ref_add(&obj->co_lu, "check", cfs_current()); + lu_object_ref_add_at(&obj->co_lu, &link, "check", + cfs_current()); /* attempt some read/write balancing by alternating between * reads and writes in an object. The makes_rpc checks here @@ -2115,7 +2144,8 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli, osc_object_unlock(osc); osc_list_maint(cli, osc); - lu_object_ref_del_at(&obj->co_lu, link, "check", cfs_current()); + lu_object_ref_del_at(&obj->co_lu, &link, "check", + cfs_current()); cl_object_put(env, obj); client_obd_list_lock(&cli->cl_loi_list_lock); @@ -2160,7 +2190,7 @@ void osc_io_unplug(const struct lu_env *env, struct client_obd *cli, } int osc_prep_async_page(struct osc_object *osc, struct osc_page *ops, - cfs_page_t *page, loff_t offset) + struct page *page, loff_t offset) { struct obd_export *exp = osc_export(osc); struct osc_async_page *oap = &ops->ops_oap; @@ -2247,6 +2277,8 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, oap->oap_cmd = cmd; oap->oap_page_off = ops->ops_from; oap->oap_count = ops->ops_to - ops->ops_from; + /* No need to hold a lock here, + * since this page is not in any list yet. */ oap->oap_async_flags = 0; oap->oap_brw_flags = brw_flags; @@ -2441,7 +2473,7 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io, oap->oap_async_flags |= ASYNC_READY|ASYNC_URGENT; spin_unlock(&oap->oap_lock); - if (cfs_memory_pressure_get()) + if (memory_pressure_get()) ext->oe_memalloc = 1; ext->oe_urgent = 1; @@ -2581,7 +2613,7 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj, } osc_object_unlock(obj); - osc_io_unplug_async(env, cli, obj); + osc_io_unplug(env, cli, obj, PDL_POLICY_ROUND); RETURN(0); } @@ -2698,7 +2730,7 @@ again: * should take care of it. */ rc = osc_extent_wait(env, waiting, OES_INV); if (rc < 0) - OSC_EXTENT_DUMP(D_CACHE, ext, "wait error: %d.\n", rc); + OSC_EXTENT_DUMP(D_CACHE, waiting, "error: %d.\n", rc); osc_extent_put(env, waiting); waiting = NULL; @@ -2908,7 +2940,7 @@ int osc_cache_writeback_range(const struct lu_env *env, struct osc_object *obj, result = rc; } - OSC_IO_DEBUG(obj, "cache page out.\n"); + OSC_IO_DEBUG(obj, "pageout [%lu, %lu], %d.\n", start, end, result); RETURN(result); }