If you have set DO_BUFFERED_IO, you should receive an IRP with Irp->AssociatedIrp.SystemBuffer.
You say “with read cache” - but I think what you mean is “with IRP_PAGING_IO set in Irp->Flags”. In that case, I’m surprised you are getting mapped MDLs in the first place, since the Memory Manager doesn’t generally map them if it can avoid doing so (the unmap is a performance killer, as it causes TLB shootdown across all the CPUs on the system.)
Are you sure the MDL you are getting has been mapped? That is, are you sure Irp->MdlAddress->MdlFlags has MDL_MAPPED_TO_SYSTEM_VA set?
If not, then all that matters is Irp->UserBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress) so it can be used to construct partial MDLs properly.