Drives with q->limits.chunk_sectors > 0 are not properly handled by
vds_blk_rw(). Drives such as NVME set chunk_sectors to indicate a performance
boundary (see call to blk_queue_chunk_sectors() in nvme_alloc_ns()). Currently,
when vds_blk_rw() calls bio_add_page() and the chunk_sectors boundary would be
crossed, bio_add_page() returns zero and vds_blk_rw() fails with -EIO.
The proposed fix now adds an additional check to vds_blk_rw() when
bio_add_page() returns zero that checks for bio->bi_iter.bi_size != 0. If
bi_size != 0, it indicates that a page or pages have been successfully added by
bio_add_page(). When this added condition has been hit, exit the for loop in
vds_blk_rw() and submit the outstanding IOs and continue.
Signed-off-by: George Kennedy <george.kennedy@oracle.com>
Reviewed-By: Bijan Mottahedeh <bijan.mottahedeh@oracle.com>
Reviewed-By: Liam Merwick <Liam.Merwick@oracle.com>
Orabug:
25373818
Signed-off-by: Allen Pais <allen.pais@oracle.com>
/*
* vds_blk.c: LDOM Virtual Disk Server.
*
- * Copyright (C) 2014, 2016 Oracle. All rights reserved.
+ * Copyright (C) 2014, 2017 Oracle. All rights reserved.
*/
#include "vds.h"
bio->bi_iter.bi_sector, bio->bi_iter.bi_size);
if (!rv) {
+ /*
+ * A drive with chunk_sectors > 0 (i.e. NVME)
+ * will result in rv = 0 when the chunk_sectors
+ * boundary has been hit. Break here if page(s)
+ * have already been added (bi_size != 0).
+ * Submit the already added pages and continue.
+ */
+ if (bio->bi_iter.bi_size != 0)
+ break;
vdsmsg(err,
- "bio_add_page: resid=%ld biolen=%ld\n",
- resid, biolen);
+ "bio_add_page: resid=%ld biolen=%ld "
+ "bi_sector=%ld\n",
+ resid, biolen, bio->bi_iter.bi_sector);
err = -EIO;
break;
}