+ /* Direct i/o (CPT_TRANSIENT) is split strictly to stripes, so we can
+ * cache the stripe information. Buffered i/o is differently
+ * organized, and stripe calculation isn't a significant cost for
+ * buffered i/o, so we only cache this for direct i/o.
+ */
+ stripe_cached = lio->lis_cached_entry != LIS_CACHE_ENTRY_NONE &&
+ page->cp_type == CPT_TRANSIENT;
+
+ offset = index << PAGE_SHIFT;
+
+ if (stripe_cached) {
+ entry = lio->lis_cached_entry;
+ /* if there's no layout at this offset, we'll end up here with
+ * a cached layout entry, so we must verify the layout includes
+ * this offset
+ */
+ if (!lov_io_layout_at_confirm(lio, entry, offset))
+ return -ENODATA;
+ stripe = lio->lis_cached_stripe;
+ /* Offset can never go backwards in an i/o, so this is valid */
+ suboff = lio->lis_cached_suboff + offset - lio->lis_cached_off;
+ } else {
+ entry = lov_io_layout_at(lio, offset);
+ if (entry < 0)
+ return -ENODATA;
+
+ stripe = lov_stripe_number(loo->lo_lsm, entry, offset);
+ rc = lov_stripe_offset(loo->lo_lsm, entry, offset, stripe,
+ &suboff);
+ LASSERT(rc == 0);
+ lio->lis_cached_entry = entry;
+ lio->lis_cached_stripe = stripe;
+ lio->lis_cached_off = offset;
+ lio->lis_cached_suboff = suboff;
+ }
+