Replace problematic bi_idx usage in crypt_free_buffer_pages with a bi_vcnt and bi_size based solution until issues in the kernel code are sorted out. [Christophe Saout] --- diff/drivers/md/dm-crypt.c 2004-01-03 12:14:42.000000000 +0000 +++ source/drivers/md/dm-crypt.c 2004-01-03 12:14:48.000000000 +0000 @@ -272,17 +272,35 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *bio, unsigned int bytes) { - int i = bio->bi_idx; + unsigned int start, end; + struct bio_vec *bv; + int i; - while(bytes) { - struct bio_vec *bv = bio_iovec_idx(bio, i++); - if (bytes < bv->bv_len) - break; + /* + * This is ugly, but Jens Axboe thinks that using bi_idx in the + * endio function is too dangerous at the moment, so I calculate the + * correct position using bi_vcnt and bi_size. + * The bv_offset and bv_len fields might already be modified but we + * know that we always allocated whole pages. + * A fix to the bi_idx issue in the kernel is in the works, so + * we will hopefully be able to revert to the cleaner solution soon. + */ + i = bio->bi_vcnt - 1; + bv = bio_iovec_idx(bio, i); + end = (i << PAGE_SHIFT) + (bv->bv_offset + bv->bv_len) - bio->bi_size; + start = end - bytes; + + start >>= PAGE_SHIFT; + if (!bio->bi_size) + end = bio->bi_vcnt; + else + end >>= PAGE_SHIFT; + for(i = start; i < end; i++) { + bv = bio_iovec_idx(bio, i); BUG_ON(!bv->bv_page); mempool_free(bv->bv_page, cc->page_pool); bv->bv_page = NULL; - bytes -= bv->bv_len; } }