X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fosc%2Fosc_cache.c;h=519ed39a353a1750eee9485d1afefcbbdac759b2;hb=f78805dbf041bb42b250fe754dff7b864856203f;hp=b67911b9b70a3291d661ce31b205b261b05e832b;hpb=9fe4b52ad2ffadf125d9b5c78bb2ff9a01725707;p=fs%2Flustre-release.git diff --git a/lustre/osc/osc_cache.c b/lustre/osc/osc_cache.c index b67911b..519ed39 100644 --- a/lustre/osc/osc_cache.c +++ b/lustre/osc/osc_cache.c @@ -845,6 +845,17 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext, RETURN(0); } +static int extent_wait_cb(struct osc_extent *ext, int state) +{ + int ret; + + osc_object_lock(ext->oe_obj); + ret = ext->oe_state == state; + osc_object_unlock(ext->oe_obj); + + return ret; +} + /** * Wait for the extent's state to become @state. */ @@ -852,7 +863,8 @@ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext, int state) { struct osc_object *obj = ext->oe_obj; - 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 = 0; ENTRY; @@ -874,7 +886,16 @@ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext, osc_extent_release(env, ext); /* wait for the extent until its state becomes @state */ - rc = l_wait_event(ext->oe_waitq, ext->oe_state == state, &lwi); + rc = l_wait_event(ext->oe_waitq, extent_wait_cb(ext, state), &lwi); + if (rc == -ETIMEDOUT) { + OSC_EXTENT_DUMP(D_ERROR, ext, + "%s: wait ext to %d timedout, recovery in progress?\n", + osc_export(obj)->exp_obd->obd_name, state); + + lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); + rc = l_wait_event(ext->oe_waitq, extent_wait_cb(ext, state), + &lwi); + } if (rc == 0 && ext->oe_rc < 0) rc = ext->oe_rc; RETURN(rc); @@ -884,7 +905,8 @@ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext, * Discard pages with index greater than @size. If @ext is overlapped with * @size, then partial truncate happens. */ -static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index) +static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index, + bool partial) { struct cl_env_nest nest; struct lu_env *env; @@ -925,7 +947,8 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index) /* only discard the pages with their index greater than * trunc_index, and ... */ - if (sub->cp_index < trunc_index) { + if (sub->cp_index < trunc_index || + (sub->cp_index == trunc_index && partial)) { /* accounting how many pages remaining in the chunk * so that we can calculate grants correctly. */ if (sub->cp_index >> ppc_bits == trunc_chunk) @@ -953,8 +976,9 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index) --ext->oe_nr_pages; ++nr_pages; } - EASSERTF(ergo(ext->oe_start >= trunc_index, ext->oe_nr_pages == 0), - ext, "trunc_index %lu\n", trunc_index); + EASSERTF(ergo(ext->oe_start >= trunc_index + !!partial, + ext->oe_nr_pages == 0), + ext, "trunc_index %lu, partial %d\n", trunc_index, partial); osc_object_lock(obj); if (ext->oe_nr_pages == 0) { @@ -2560,10 +2584,12 @@ int osc_cache_truncate_start(const struct lu_env *env, struct osc_io *oio, pgoff_t index; CFS_LIST_HEAD(list); int result = 0; + bool partial; ENTRY; /* pages with index greater or equal to index will be truncated. */ - index = cl_index(osc2cl(obj), size + CFS_PAGE_SIZE - 1); + index = cl_index(osc2cl(obj), size); + partial = size > cl_offset(osc2cl(obj), index); again: osc_object_lock(obj); @@ -2621,7 +2647,7 @@ again: if (ext->oe_state != OES_TRUNC) osc_extent_wait(env, ext, OES_TRUNC); - rc = osc_extent_truncate(ext, index); + rc = osc_extent_truncate(ext, index, partial); if (rc < 0) { if (result == 0) result = rc; @@ -2634,10 +2660,11 @@ again: /* this must be an overlapped extent which means only * part of pages in this extent have been truncated. */ - EASSERTF(ext->oe_start < index, ext, - "trunc index = %lu.\n", index); + EASSERTF(ext->oe_start <= index, ext, + "trunc index = %lu/%d.\n", index, partial); /* fix index to skip this partially truncated extent */ index = ext->oe_end + 1; + partial = false; /* we need to hold this extent in OES_TRUNC state so * that no writeback will happen. This is to avoid @@ -2678,6 +2705,10 @@ void osc_cache_truncate_end(const struct lu_env *env, struct osc_io *oio, OSC_EXTENT_DUMP(D_CACHE, ext, "trunc -> cache.\n"); osc_object_lock(obj); osc_extent_state_set(ext, OES_CACHE); + if (ext->oe_fsync_wait && !ext->oe_urgent) { + ext->oe_urgent = 1; + cfs_list_move_tail(&ext->oe_link, &obj->oo_urgent_exts); + } osc_update_pending(obj, OBD_BRW_WRITE, ext->oe_nr_pages); osc_object_unlock(obj); osc_extent_put(env, ext); @@ -2691,9 +2722,9 @@ void osc_cache_truncate_end(const struct lu_env *env, struct osc_io *oio, * The caller must have called osc_cache_writeback_range() to issue IO * otherwise it will take a long time for this function to finish. * - * Caller must hold inode_mutex and i_alloc_sem, or cancel exclusive - * dlm lock so that nobody else can dirty this range of file while we're - * waiting for extents to be written. + * Caller must hold inode_mutex , or cancel exclusive dlm lock so that + * nobody else can dirty this range of file while we're waiting for + * extents to be written. */ int osc_cache_wait_range(const struct lu_env *env, struct osc_object *obj, pgoff_t start, pgoff_t end) @@ -2808,6 +2839,11 @@ int osc_cache_writeback_range(const struct lu_env *env, struct osc_object *obj, * grants. We do this for the correctness of fsync. */ LASSERT(hp == 0 && discard == 0); ext->oe_urgent = 1; + break; + case OES_TRUNC: + /* this extent is being truncated, can't do anything + * for it now. it will be set to urgent after truncate + * is finished in osc_cache_truncate_end(). */ default: break; }