aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorJens Axboe <axboe@fb.com>2014-03-14 12:43:15 -0400
committerJens Axboe <axboe@fb.com>2014-03-14 12:43:15 -0400
commit95363efde193079541cb379eb47140e9c4d355d5 (patch)
treeda7417035ca5f25d6818430feaa54cb09a2ba86d /block
parent89f8b33ca1ea881d1d84542282cb85d07d02e78d (diff)
blk-mq: allow blk_mq_init_commands() to return failure
If drivers do dynamic allocation in the hardware command init path, then we need to be able to handle and return failures. And if they do allocations or mappings in the init command path, then we need a cleanup function to free up that space at exit time. So add blk_mq_free_commands() as the cleanup function. This is required for the mtip32xx driver conversion to blk-mq. Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block')
-rw-r--r--block/blk-mq.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 01d8735db8d3..92284af4e0df 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1058,8 +1058,46 @@ static void blk_mq_hctx_notify(void *data, unsigned long action,
1058 blk_mq_put_ctx(ctx); 1058 blk_mq_put_ctx(ctx);
1059} 1059}
1060 1060
1061static void blk_mq_init_hw_commands(struct blk_mq_hw_ctx *hctx, 1061static int blk_mq_init_hw_commands(struct blk_mq_hw_ctx *hctx,
1062 void (*init)(void *, struct blk_mq_hw_ctx *, 1062 int (*init)(void *, struct blk_mq_hw_ctx *,
1063 struct request *, unsigned int),
1064 void *data)
1065{
1066 unsigned int i;
1067 int ret = 0;
1068
1069 for (i = 0; i < hctx->queue_depth; i++) {
1070 struct request *rq = hctx->rqs[i];
1071
1072 ret = init(data, hctx, rq, i);
1073 if (ret)
1074 break;
1075 }
1076
1077 return ret;
1078}
1079
1080int blk_mq_init_commands(struct request_queue *q,
1081 int (*init)(void *, struct blk_mq_hw_ctx *,
1082 struct request *, unsigned int),
1083 void *data)
1084{
1085 struct blk_mq_hw_ctx *hctx;
1086 unsigned int i;
1087 int ret = 0;
1088
1089 queue_for_each_hw_ctx(q, hctx, i) {
1090 ret = blk_mq_init_hw_commands(hctx, init, data);
1091 if (ret)
1092 break;
1093 }
1094
1095 return ret;
1096}
1097EXPORT_SYMBOL(blk_mq_init_commands);
1098
1099static void blk_mq_free_hw_commands(struct blk_mq_hw_ctx *hctx,
1100 void (*free)(void *, struct blk_mq_hw_ctx *,
1063 struct request *, unsigned int), 1101 struct request *, unsigned int),
1064 void *data) 1102 void *data)
1065{ 1103{
@@ -1068,12 +1106,12 @@ static void blk_mq_init_hw_commands(struct blk_mq_hw_ctx *hctx,
1068 for (i = 0; i < hctx->queue_depth; i++) { 1106 for (i = 0; i < hctx->queue_depth; i++) {
1069 struct request *rq = hctx->rqs[i]; 1107 struct request *rq = hctx->rqs[i];
1070 1108
1071 init(data, hctx, rq, i); 1109 free(data, hctx, rq, i);
1072 } 1110 }
1073} 1111}
1074 1112
1075void blk_mq_init_commands(struct request_queue *q, 1113void blk_mq_free_commands(struct request_queue *q,
1076 void (*init)(void *, struct blk_mq_hw_ctx *, 1114 void (*free)(void *, struct blk_mq_hw_ctx *,
1077 struct request *, unsigned int), 1115 struct request *, unsigned int),
1078 void *data) 1116 void *data)
1079{ 1117{
@@ -1081,9 +1119,9 @@ void blk_mq_init_commands(struct request_queue *q,
1081 unsigned int i; 1119 unsigned int i;
1082 1120
1083 queue_for_each_hw_ctx(q, hctx, i) 1121 queue_for_each_hw_ctx(q, hctx, i)
1084 blk_mq_init_hw_commands(hctx, init, data); 1122 blk_mq_free_hw_commands(hctx, free, data);
1085} 1123}
1086EXPORT_SYMBOL(blk_mq_init_commands); 1124EXPORT_SYMBOL(blk_mq_free_commands);
1087 1125
1088static void blk_mq_free_rq_map(struct blk_mq_hw_ctx *hctx) 1126static void blk_mq_free_rq_map(struct blk_mq_hw_ctx *hctx)
1089{ 1127{