block: introduce new block status code type

Currently we use nornal Linux errno values in the block layer, and while
we accept any error a few have overloaded magic meanings.  This patch
instead introduces a new  blk_status_t value that holds block layer specific
status codes and explicitly explains their meaning.  Helpers to convert from
and to the previous special meanings are provided for now, but I suspect
we want to get rid of them in the long run - those drivers that have a
errno input (e.g. networking) usually get errnos that don't know about
the special block layer overloads, and similarly returning them to userspace
will usually return somethings that strictly speaking isn't correct
for file system operations, but that's left as an exercise for later.

For now the set of errors is a very limited set that closely corresponds
to the previous overloaded errno values, but there is some low hanging
fruite to improve it.

blk_status_t (ab)uses the sparse __bitwise annotations to allow for sparse
typechecking, so that we can easily catch places passing the wrong values.

Signed-off-by: Christoph Hellwig <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
This commit is contained in:
Christoph Hellwig 2017-06-03 09:38:04 +02:00 • committed by Jens Axboe
commit 2a842acab1
76 changed files with 474 additions and 428 deletions

View file

@ -73,7 +73,7 @@ static void blktrans_dev_put(struct mtd_blktrans_dev *dev)
}
static int do_blktrans_request(struct mtd_blktrans_ops *tr,
static blk_status_t do_blktrans_request(struct mtd_blktrans_ops *tr,
struct mtd_blktrans_dev *dev,
struct request *req)
{
@ -84,33 +84,37 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
nsect = blk_rq_cur_bytes(req) >> tr->blkshift;
buf = bio_data(req->bio);
if (req_op(req) == REQ_OP_FLUSH)
return tr->flush(dev);
if (req_op(req) == REQ_OP_FLUSH) {
if (tr->flush(dev))
return BLK_STS_IOERR;
return BLK_STS_OK;
}
if (blk_rq_pos(req) + blk_rq_cur_sectors(req) >
get_capacity(req->rq_disk))
return -EIO;
return BLK_STS_IOERR;
switch (req_op(req)) {
case REQ_OP_DISCARD:
return tr->discard(dev, block, nsect);
if (tr->discard(dev, block, nsect))
return BLK_STS_IOERR;
return BLK_STS_OK;
case REQ_OP_READ:
for (; nsect > 0; nsect--, block++, buf += tr->blksize)
if (tr->readsect(dev, block, buf))
return -EIO;
return BLK_STS_IOERR;
rq_flush_dcache_pages(req);
return 0;
return BLK_STS_OK;
case REQ_OP_WRITE:
if (!tr->writesect)
return -EIO;
return BLK_STS_IOERR;
rq_flush_dcache_pages(req);
for (; nsect > 0; nsect--, block++, buf += tr->blksize)
if (tr->writesect(dev, block, buf))
return -EIO;
return 0;
return BLK_STS_IOERR;
default:
return -EIO;
return BLK_STS_IOERR;
}
}
@ -132,7 +136,7 @@ static void mtd_blktrans_work(struct work_struct *work)
spin_lock_irq(rq->queue_lock);
while (1) {
int res;
blk_status_t res;
dev->bg_stop = false;
if (!req && !(req = blk_fetch_request(rq))) {
@ -178,7 +182,7 @@ static void mtd_blktrans_request(struct request_queue *rq)
if (!dev)
while ((req = blk_fetch_request(rq)) != NULL)
__blk_end_request_all(req, -ENODEV);
__blk_end_request_all(req, BLK_STS_IOERR);
else
queue_work(dev->wq, &dev->work);
}

View file

@ -313,7 +313,7 @@ static void ubiblock_do_work(struct work_struct *work)
ret = ubiblock_read(pdu);
rq_flush_dcache_pages(req);
blk_mq_end_request(req, ret);
blk_mq_end_request(req, errno_to_blk_status(ret));
}
static int ubiblock_queue_rq(struct blk_mq_hw_ctx *hctx,