[PATCH 2/3] osd_initiator: support bio chains

From: Jeff Garzik
Date: Fri Apr 10 2009 - 07:49:28 EST



Signed-off-by: Jeff Garzik <jgarzik@xxxxxxxxxx>
---
drivers/scsi/osd/osd_initiator.c | 83 +++++++++++++++++++++++++++++++--------
1 file changed, 67 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 2a5f077..2d35d65 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -709,14 +709,36 @@ EXPORT_SYMBOL(osd_req_remove_object);
struct osd_obj_id *first, struct osd_obj_id_list *list, unsigned nelem);
*/

+static unsigned int bio_chain_size(struct bio *bio)
+{
+ unsigned int chain_size = 0;
+
+ while (bio) {
+ chain_size += bio->bi_size;
+ bio = bio->bi_next;
+ }
+
+ return chain_size;
+}
+
void osd_req_write(struct osd_request *or,
const struct osd_obj_id *obj, struct bio *bio, u64 offset)
{
- _osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, bio->bi_size);
+ unsigned int chain_size = 0;
+ struct bio *tmp_bio = bio;
+
+ while (tmp_bio) {
+ chain_size += tmp_bio->bi_size;
+ tmp_bio->bi_rw |= (1 << BIO_RW);
+
+ tmp_bio = tmp_bio->bi_next;
+ }
+
+ _osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, chain_size);
WARN_ON(or->out.bio || or->out.total_bytes);
- bio->bi_rw |= (1 << BIO_RW);
+
or->out.bio = bio;
- or->out.total_bytes = bio->bi_size;
+ or->out.total_bytes = chain_size;
}
EXPORT_SYMBOL(osd_req_write);

@@ -747,11 +769,21 @@ EXPORT_SYMBOL(osd_req_flush_object);
void osd_req_read(struct osd_request *or,
const struct osd_obj_id *obj, struct bio *bio, u64 offset)
{
- _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, bio->bi_size);
+ unsigned int chain_size = 0;
+ struct bio *tmp_bio = bio;
+
+ while (tmp_bio) {
+ chain_size += tmp_bio->bi_size;
+ tmp_bio->bi_rw &= ~(1 << BIO_RW);
+
+ tmp_bio = tmp_bio->bi_next;
+ }
+
+ _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, chain_size);
WARN_ON(or->in.bio || or->in.total_bytes);
- bio->bi_rw &= ~(1 << BIO_RW);
+
or->in.bio = bio;
- or->in.total_bytes = bio->bi_size;
+ or->in.total_bytes = chain_size;
}
EXPORT_SYMBOL(osd_req_read);

@@ -1176,7 +1208,7 @@ static int _osd_req_finalize_data_integrity(struct osd_request *or,
unsigned pad;

or->out_data_integ.data_bytes = cpu_to_be64(
- or->out.bio ? or->out.bio->bi_size : 0);
+ or->out.bio ? bio_chain_size(or->out.bio) : 0);
or->out_data_integ.set_attributes_bytes = cpu_to_be64(
or->set_attr.total_bytes);
or->out_data_integ.get_attributes_bytes = cpu_to_be64(
@@ -1269,6 +1301,7 @@ int osd_finalize_request(struct osd_request *or,
struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
bool has_in, has_out;
int ret;
+ struct bio *bio, *tmp;

if (options & OSD_REQ_FUA)
cdbh->options |= OSD_CDB_FUA;
@@ -1292,23 +1325,40 @@ int osd_finalize_request(struct osd_request *or,
}

if (or->out.bio) {
- ret = blk_rq_append_bio(or->request->q, or->out.req,
- or->out.bio);
- if (ret) {
- OSD_DEBUG("blk_rq_append_bio out failed\n");
- return ret;
+ bio = or->out.bio;
+ while (bio) {
+ tmp = bio;
+ bio = bio->bi_next;
+
+ ret = blk_rq_append_bio(or->request->q, or->out.req,
+ tmp);
+ if (ret) {
+ OSD_DEBUG("blk_rq_append_bio out failed\n");
+ return ret;
+ }
}
OSD_DEBUG("out bytes=%llu (bytes_req=%u)\n",
_LLU(or->out.total_bytes), or->out.req->data_len);
+
+ or->out.bio = NULL;
}
if (or->in.bio) {
- ret = blk_rq_append_bio(or->request->q, or->in.req, or->in.bio);
- if (ret) {
- OSD_DEBUG("blk_rq_append_bio in failed\n");
- return ret;
+ bio = or->in.bio;
+ while (bio) {
+ tmp = bio;
+ bio = bio->bi_next;
+
+ ret = blk_rq_append_bio(or->request->q, or->in.req,
+ tmp);
+ if (ret) {
+ OSD_DEBUG("blk_rq_append_bio in failed\n");
+ return ret;
+ }
}
OSD_DEBUG("in bytes=%llu (bytes_req=%u)\n",
_LLU(or->in.total_bytes), or->in.req->data_len);
+
+ or->in.bio = NULL;
}

or->out.pad_buff = sg_out_pad_buffer;
@@ -1618,6 +1668,7 @@ void osd_sec_sign_cdb(struct osd_cdb *ocdb __unused, const u8 *cap_key __unused)
void osd_sec_sign_data(void *data_integ __unused,
struct bio *bio __unused, const u8 *cap_key __unused)
{
+ /* NOTE: bio is a linked list */
}

/*
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/