Hi Steven-san,
On Tue, 24 Jun 2008 14:13:13 +0100
Steven Smith <steven.smith@xxxxxxxxxx> wrote:
> rather than anything architectural. The only bit which worries me is
> the xenbus-level protocol for adding and removing LUNs, and I suspect
> that's just because I've not understood what you're actually doing.
> If you could briefly explain how you expect this to work, at the level
> of individual xenstore operations, I expect that would make things a
> lot clearer.
I will briefly explain the xenbus-level protocol below.
I have to say first is that the protocol uses following two kinds of
states, "XenBusState" and "DeviceState".
(Please do not being confused, because the two states use similar
notation (XenBusState*ing or XenBusState*ed) as state name.)
1.) XenbusState
The XenBusState is used to control frontend's and backend's
automata.
The newly defined two states, "XenBusStateReconfiguring" and
"XenBusStateReconfigured", are used for attach/detach protocol.
2.) DeviceState
In addition to the XenBusState, we need another kind of state
for each LUN to be attached and detached. The "DeviceState" is
used for such a purpose.
It uses "XenBusStateInitializing", "XenBusStateIntialized" and
"XenBusStateConnected" in normal case, and they are stored at
"vscsi-devs/dev-*/state" in xenstore.
Following is a protocol for attaching a LUN. Please note that error
case is not described for simplicity.
xend backend frontend
-----------------------------------------------------------------------
set DeviceState to
XenBusStateInitializing.
set XenBusState to
XenBusStateReconfiguring.
detect backend has
changed.
set XenBusState to
XenBusStateReconfiguring.
detect frontend has
changed.
export a specified LUN.
(call scsi_device_lookup(),
maintain translation table
and so on.)
set DeviceState to
XenBusStateInitialized.
set XenBusState to
XenBusStateReconfigured.
detect backend has
changed.
import the exported LUN.
(call scsi_add_device().)
set DeviceState to
XenBusStateConnected.
set XenBusState to
XenBusStateConnected.
detect frontend has
changed.
set DeviceState to
XenBusStateConnected.
set XenBusState to
XenBusStateConnected.
-----------------------------------------------------------------------
> > /* quoted scsi_lib.c/scsi_req_map_sg . */
> > static int requset_map_sg(struct request *rq, pending_req_t *pending_req,
> > unsigned int count)
> > {
> I don't quite understand why it was necessary to duplicate all of this
> code. Would you mind explaining why you were unable to use the
> existing implementation, please?
In general, each segment of scatter/gather may start at offset
non-zero like following figure.
segment #0 segemnt #1 segemnt #2
|~~~~~~| |~~~~~~| |~~~~~~|
| | | | |~~~~~~|
|~~~~~~| |______| | |
| Data | | Data | | Data |
|______| |~~~~~~| | |
| | | | |______|
|______| |______| |______|
However, I suppose that the existing requset_map_sg() implementation
assumes following structure, segment #0 may start offset non-zero but
segment #1 and later should start at offset zero.
segment #0 segemnt #1 segemnt #2
|~~~~~~| |~~~~~~| |~~~~~~|
| | | | | |
|~~~~~~| | | | |
| | | Data | | Data |
| Data | | | | |
| | | | |______|
|______| |______| |______|
Of cource, we can create a later type of scatter/gather structure on
backend driver by copying data, however performance will be degraded
maybe.
On the other hand, we can also take another way that we define
scatter/gather interface between frontend and backend (defined in
vscsiif.h) should be later type. However, it will spoil flexibility
of the interface.
That is the reason why we use duplicate (and bit modify) the existing
implementation.
Could you please suggest another good way?
> Also, there's a typo in the name of the function.
>
> > struct request_queue *q = rq->q;
> > int nr_pages;
> > unsigned int nsegs = count;
> >
> > unsigned int data_len = 0, len, bytes, off;
> > struct page *page;
> > struct bio *bio = NULL;
> > int i, err, nr_vecs = 0;
> >
> > for (i = 0; i < nsegs; i++) {
> > page = pending_req->sgl[i].page;
> > off = (unsigned int)pending_req->sgl[i].offset;
> > len = (unsigned int)pending_req->sgl[i].length;
> > data_len += len;
> >
> > nr_pages = (len + off + PAGE_SIZE - 1) >> PAGE_SHIFT;
> > while (len > 0) {
> > bytes = min_t(unsigned int, len, PAGE_SIZE - off);
> >
> > if (!bio) {
> > nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages);
> > nr_pages -= nr_vecs;
> > bio = bio_alloc(GFP_KERNEL, nr_vecs);
> > if (!bio) {
> > err = -ENOMEM;
> > goto free_bios;
> > }
> > bio->bi_end_io = scsiback_bi_endio;
> > }
> >
> > if (bio_add_pc_page(q, bio, page, bytes, off) !=
> > bytes) {
> > bio_put(bio);
> > err = -EINVAL;
> > goto free_bios;
> > }
> >
> > if (bio->bi_vcnt >= nr_vecs) {
> > err = scsiback_merge_bio(rq, bio);
> > if (err) {
> > bio_endio(bio, bio->bi_size, 0);
> > goto free_bios;
> > }
> > bio = NULL;
> > }
> >
> > page++;
> > len -= bytes;
> > off = 0;
> > }
> > }
> >
> > rq->buffer = rq->data = NULL;
> > rq->data_len = data_len;
> >
> > return 0;
> >
> > free_bios:
> > while ((bio = rq->bio) != NULL) {
> > rq->bio = bio->bi_next;
> > /*
> > * call endio instead of bio_put incase it was bounced
> > */
> > bio_endio(bio, bio->bi_size, 0);
> > }
> >
> > return err;
> > }
> >
> > #endif
Best regards,
-----
Jun Kamada
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|