[S390] dasd: fix idaw boundary checking for track based ccw
A ccw command that reads or writes several records at once will
usually transfer more data then fits into one page and needs to
address memory areas using a list of indirect data address words
(idaw). All but the first of these areas must start on a 4KB or 2KB
block boundary (depending on the idaw format).
A check for this restriction was missing and has been added with
this patch.
Signed-off-by: Stefan Weinhuber <wein@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 2125479..cb52da0 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -2019,15 +2019,23 @@
ccw++;
recid += count;
new_track = 0;
+ /* first idaw for a ccw may start anywhere */
+ if (!idaw_dst)
+ idaw_dst = dst;
}
- /* If we start a new idaw, everything is fine and the
- * start of the new idaw is the start of this segment.
+ /* If we start a new idaw, we must make sure that it
+ * starts on an IDA_BLOCK_SIZE boundary.
* If we continue an idaw, we must make sure that the
* current segment begins where the so far accumulated
* idaw ends
*/
- if (!idaw_dst)
- idaw_dst = dst;
+ if (!idaw_dst) {
+ if (__pa(dst) & (IDA_BLOCK_SIZE-1)) {
+ dasd_sfree_request(cqr, startdev);
+ return ERR_PTR(-ERANGE);
+ } else
+ idaw_dst = dst;
+ }
if ((idaw_dst + idaw_len) != dst) {
dasd_sfree_request(cqr, startdev);
return ERR_PTR(-ERANGE);