Skip to content

Commit 972248e

Browse files
Christoph Hellwigmartinkpetersen
authored andcommitted
scsi: bsg-lib: handle bidi requests without block layer help
We can just stash away the second request in struct bsg_job instead of using the block layer req->next_rq field, allowing for the eventual removal of the latter. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent ccf3209 commit 972248e

File tree

4 files changed

+56
-61
lines changed

4 files changed

+56
-61
lines changed

block/bsg-lib.c

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,40 @@ static int bsg_transport_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
5151
fmode_t mode)
5252
{
5353
struct bsg_job *job = blk_mq_rq_to_pdu(rq);
54+
int ret;
5455

5556
job->request_len = hdr->request_len;
5657
job->request = memdup_user(uptr64(hdr->request), hdr->request_len);
58+
if (IS_ERR(job->request))
59+
return PTR_ERR(job->request);
60+
61+
if (hdr->dout_xfer_len && hdr->din_xfer_len) {
62+
job->bidi_rq = blk_get_request(rq->q, REQ_OP_SCSI_IN, 0);
63+
if (IS_ERR(job->bidi_rq)) {
64+
ret = PTR_ERR(job->bidi_rq);
65+
goto out;
66+
}
67+
68+
ret = blk_rq_map_user(rq->q, job->bidi_rq, NULL,
69+
uptr64(hdr->din_xferp), hdr->din_xfer_len,
70+
GFP_KERNEL);
71+
if (ret)
72+
goto out_free_bidi_rq;
73+
74+
job->bidi_bio = job->bidi_rq->bio;
75+
} else {
76+
job->bidi_rq = NULL;
77+
job->bidi_bio = NULL;
78+
}
5779

58-
return PTR_ERR_OR_ZERO(job->request);
80+
return 0;
81+
82+
out_free_bidi_rq:
83+
if (job->bidi_rq)
84+
blk_put_request(job->bidi_rq);
85+
out:
86+
kfree(job->request);
87+
return ret;
5988
}
6089

6190
static int bsg_transport_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
@@ -93,7 +122,7 @@ static int bsg_transport_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
93122
/* we assume all request payload was transferred, residual == 0 */
94123
hdr->dout_resid = 0;
95124

96-
if (rq->next_rq) {
125+
if (job->bidi_rq) {
97126
unsigned int rsp_len = job->reply_payload.payload_len;
98127

99128
if (WARN_ON(job->reply_payload_rcv_len > rsp_len))
@@ -111,6 +140,11 @@ static void bsg_transport_free_rq(struct request *rq)
111140
{
112141
struct bsg_job *job = blk_mq_rq_to_pdu(rq);
113142

143+
if (job->bidi_rq) {
144+
blk_rq_unmap_user(job->bidi_bio);
145+
blk_put_request(job->bidi_rq);
146+
}
147+
114148
kfree(job->request);
115149
}
116150

@@ -200,7 +234,6 @@ static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
200234
*/
201235
static bool bsg_prepare_job(struct device *dev, struct request *req)
202236
{
203-
struct request *rsp = req->next_rq;
204237
struct bsg_job *job = blk_mq_rq_to_pdu(req);
205238
int ret;
206239

@@ -211,8 +244,8 @@ static bool bsg_prepare_job(struct device *dev, struct request *req)
211244
if (ret)
212245
goto failjob_rls_job;
213246
}
214-
if (rsp && rsp->bio) {
215-
ret = bsg_map_buffer(&job->reply_payload, rsp);
247+
if (job->bidi_rq) {
248+
ret = bsg_map_buffer(&job->reply_payload, job->bidi_rq);
216249
if (ret)
217250
goto failjob_rls_rqst_payload;
218251
}
@@ -369,7 +402,6 @@ struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
369402
}
370403

371404
q->queuedata = dev;
372-
blk_queue_flag_set(QUEUE_FLAG_BIDI, q);
373405
blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
374406

375407
ret = bsg_register_queue(q, dev, name, &bsg_transport_ops);

block/bsg.c

Lines changed: 14 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ static int bsg_scsi_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
7474
{
7575
struct scsi_request *sreq = scsi_req(rq);
7676

77+
if (hdr->dout_xfer_len && hdr->din_xfer_len) {
78+
pr_warn_once("BIDI support in bsg has been removed.\n");
79+
return -EOPNOTSUPP;
80+
}
81+
7782
sreq->cmd_len = hdr->request_len;
7883
if (sreq->cmd_len > BLK_MAX_CDB) {
7984
sreq->cmd = kzalloc(sreq->cmd_len, GFP_KERNEL);
@@ -114,14 +119,10 @@ static int bsg_scsi_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
114119
hdr->response_len = len;
115120
}
116121

117-
if (rq->next_rq) {
118-
hdr->dout_resid = sreq->resid_len;
119-
hdr->din_resid = scsi_req(rq->next_rq)->resid_len;
120-
} else if (rq_data_dir(rq) == READ) {
122+
if (rq_data_dir(rq) == READ)
121123
hdr->din_resid = sreq->resid_len;
122-
} else {
124+
else
123125
hdr->dout_resid = sreq->resid_len;
124-
}
125126

126127
return ret;
127128
}
@@ -140,8 +141,8 @@ static const struct bsg_ops bsg_scsi_ops = {
140141

141142
static int bsg_sg_io(struct request_queue *q, fmode_t mode, void __user *uarg)
142143
{
143-
struct request *rq, *next_rq = NULL;
144-
struct bio *bio, *bidi_bio = NULL;
144+
struct request *rq;
145+
struct bio *bio;
145146
struct sg_io_v4 hdr;
146147
int ret;
147148

@@ -164,7 +165,7 @@ static int bsg_sg_io(struct request_queue *q, fmode_t mode, void __user *uarg)
164165

165166
ret = q->bsg_dev.ops->fill_hdr(rq, &hdr, mode);
166167
if (ret)
167-
goto out;
168+
return ret;
168169

169170
rq->timeout = msecs_to_jiffies(hdr.timeout);
170171
if (!rq->timeout)
@@ -174,29 +175,6 @@ static int bsg_sg_io(struct request_queue *q, fmode_t mode, void __user *uarg)
174175
if (rq->timeout < BLK_MIN_SG_TIMEOUT)
175176
rq->timeout = BLK_MIN_SG_TIMEOUT;
176177

177-
if (hdr.dout_xfer_len && hdr.din_xfer_len) {
178-
if (!test_bit(QUEUE_FLAG_BIDI, &q->queue_flags)) {
179-
ret = -EOPNOTSUPP;
180-
goto out;
181-
}
182-
183-
pr_warn_once(
184-
"BIDI support in bsg has been deprecated and might be removed. "
185-
"Please report your use case to linux-scsi@vger.kernel.org\n");
186-
187-
next_rq = blk_get_request(q, REQ_OP_SCSI_IN, 0);
188-
if (IS_ERR(next_rq)) {
189-
ret = PTR_ERR(next_rq);
190-
goto out;
191-
}
192-
193-
rq->next_rq = next_rq;
194-
ret = blk_rq_map_user(q, next_rq, NULL, uptr64(hdr.din_xferp),
195-
hdr.din_xfer_len, GFP_KERNEL);
196-
if (ret)
197-
goto out_free_nextrq;
198-
}
199-
200178
if (hdr.dout_xfer_len) {
201179
ret = blk_rq_map_user(q, rq, NULL, uptr64(hdr.dout_xferp),
202180
hdr.dout_xfer_len, GFP_KERNEL);
@@ -206,38 +184,20 @@ static int bsg_sg_io(struct request_queue *q, fmode_t mode, void __user *uarg)
206184
}
207185

208186
if (ret)
209-
goto out_unmap_nextrq;
187+
goto out_free_rq;
210188

211189
bio = rq->bio;
212-
if (rq->next_rq)
213-
bidi_bio = rq->next_rq->bio;
214190

215191
blk_execute_rq(q, NULL, rq, !(hdr.flags & BSG_FLAG_Q_AT_TAIL));
216192
ret = rq->q->bsg_dev.ops->complete_rq(rq, &hdr);
217-
218-
if (rq->next_rq) {
219-
blk_rq_unmap_user(bidi_bio);
220-
blk_put_request(rq->next_rq);
221-
}
222-
223193
blk_rq_unmap_user(bio);
194+
195+
out_free_rq:
224196
rq->q->bsg_dev.ops->free_rq(rq);
225197
blk_put_request(rq);
226-
227-
if (copy_to_user(uarg, &hdr, sizeof(hdr)))
198+
if (!ret && copy_to_user(uarg, &hdr, sizeof(hdr)))
228199
return -EFAULT;
229200
return ret;
230-
231-
out_unmap_nextrq:
232-
if (rq->next_rq)
233-
blk_rq_unmap_user(rq->next_rq->bio);
234-
out_free_nextrq:
235-
if (rq->next_rq)
236-
blk_put_request(rq->next_rq);
237-
out:
238-
q->bsg_dev.ops->free_rq(rq);
239-
blk_put_request(rq);
240-
return ret;
241201
}
242202

243203
static struct bsg_device *bsg_alloc_device(void)

drivers/scsi/scsi_transport_sas.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,6 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
213213
to_sas_host_attrs(shost)->q = q;
214214
}
215215

216-
blk_queue_flag_set(QUEUE_FLAG_BIDI, q);
217216
return 0;
218217
}
219218

include/linux/bsg-lib.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ struct bsg_job {
6969
int result;
7070
unsigned int reply_payload_rcv_len;
7171

72+
/* BIDI support */
73+
struct request *bidi_rq;
74+
struct bio *bidi_bio;
75+
7276
void *dd_data; /* Used for driver-specific storage */
7377
};
7478

0 commit comments

Comments
 (0)