Hi all,
Now i am porting an OS to xen3.1.4(no-PAE). I want to implement blkfront driver
according to Linux. But when i using my driver to read mbr, i got the data which
is different from the phisical disk. I want to read the segment 0 on disk to
req->bufs[0].buffer,
The following is what i did:
ring_req->id = id;
ring_req->sector_number = 0;
ring_req->handle = info->handle;
ring_req->operation = BLKIF_OP_READ;
ring_req->nr_segments = 1 ;/*just one segment*/
buffer_mfn = virt_to_mfn(((unsigned int)req->bufs[0].buffer));/*macro in
MiniOS, get the machine page of buffer*/
fsect = (((unsigned int)req->bufs[0].buffer) >> 9) %8;
lsect = fsect + (req->bufs[0].length >> 9) - 1;/*length of
req->bufs[0].buffer*/
ref = gnttab_grant_access(info->xbdev->otherend_id, buffer_mfn, 0 );
info->shadow[id].frame[0] = mfn_to_pfn(buffer_mfn);
ring_req->seg[0] = (struct blkif_request_segment) {
.gref = ref,
.first_sect = fsect,
.last_sect = lsect
};
Then i try to modify linux domU source code(
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c). I still got the same
result.
The following is what i did:
volatile unsigned char * test_data = 0;
static int blkif_queue_request(struct request *req)
{
struct blkfront_info *info = req->rq_disk->private_data;
unsigned long buffer_mfn;
blkif_request_t *ring_req;
struct bio *bio;
struct bio_vec *bvec;
int idx;
unsigned long id;
unsigned int fsect, lsect;
int ref;
grant_ref_t gref_head;
int i=0;
if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
return 1;
if (gnttab_alloc_grant_references(
BLKIF_MAX_SEGMENTS_PER_REQUEST, &gref_head) < 0) {
gnttab_request_free_callback(
&info->callback,
blkif_restart_queue_callback,
info,
BLKIF_MAX_SEGMENTS_PER_REQUEST);
return 1;
}
ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
id = GET_ID_FROM_FREELIST(info);
info->shadow[id].request = (unsigned long)req;
ring_req->id = id;
ring_req->sector_number = (blkif_sector_t)0;
ring_req->handle = info->handle;
ring_req->operation = rq_data_dir(req) ?
BLKIF_OP_WRITE : BLKIF_OP_READ;
if (blk_barrier_rq(req))
ring_req->operation = BLKIF_OP_WRITE_BARRIER;
ring_req->nr_segments = 0;
rq_for_each_bio (bio, req) {
bio_for_each_segment (bvec, bio, idx) {
BUG_ON(ring_req->nr_segments
== BLKIF_MAX_SEGMENTS_PER_REQUEST);
buffer_mfn = page_to_phys(bvec->bv_page) >> PAGE_SHIFT;
fsect = bvec->bv_offset >> 9;
lsect = fsect + (bvec->bv_len >> 9) - 1;
/* install a grant reference. */
ref = gnttab_claim_grant_reference(&gref_head);
BUG_ON(ref == -ENOSPC);
gnttab_grant_foreign_access_ref(
ref,
info->xbdev->otherend_id,
buffer_mfn,
rq_data_dir(req) );
info->shadow[id].frame[ring_req->nr_segments] mfn_to_pfn(buffer_mfn);
ring_req->seg[ring_req->nr_segments] (struct blkif_request_segment) {
.gref = ref,
.first_sect = fsect,
.last_sect = lsect };
ring_req->nr_segments++;
if(ring_req->nr_segments == 1)
goto end;
}
}
end:
if(!test_data){
test_data = ((char*)(bvec->bv_page)) + bvec->bv_offset;
printk("buffer_mfn = %d, buffer_mfn address = 0x%x\n", buffer_mfn,
test_data);
for(i=0;i<256;i++){
printk("%02x ", *(test_data + i));
if(i%16 == 15)
printk("\n");
}
}
info->ring.req_prod_pvt++;
/* Keep a private copy so we can reissue requests when recovering. */
info->shadow[id].req = *ring_req;
gnttab_free_grant_references(gref_head);
return 0;
}
static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
{
struct request *req;
blkif_response_t *bret;
RING_IDX i, rp;
unsigned long flags;
struct blkfront_info *info = (struct blkfront_info *)dev_id;
int uptodate;
spin_lock_irqsave(&blkif_io_lock, flags);
if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) {
spin_unlock_irqrestore(&blkif_io_lock, flags);
return IRQ_HANDLED;
}
again:
rp = info->ring.sring->rsp_prod;
rmb(); /* Ensure we see queued responses up to ''rp''. */
for (i = info->ring.rsp_cons; i != rp; i++) {
unsigned long id;
int ret;
bret = RING_GET_RESPONSE(&info->ring, i);
id = bret->id;
req = (struct request *)info->shadow[id].request;
blkif_completion(&info->shadow[id]);
ADD_ID_TO_FREELIST(info, id);
uptodate = (bret->status == BLKIF_RSP_OKAY);
switch (bret->operation) {
case BLKIF_OP_WRITE_BARRIER:
if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
printk("blkfront: %s: write barrier op failed\n",
info->gd->disk_name);
uptodate = -EOPNOTSUPP;
info->feature_barrier = 0;
xlvbd_barrier(info);
}
/* fall through */
case BLKIF_OP_READ:
case BLKIF_OP_WRITE:
if (unlikely(bret->status != BLKIF_RSP_OKAY))
DPRINTK("Bad return from blkdev data "
"request: %x\n", bret->status);
ret = end_that_request_first(req, uptodate,
req->hard_nr_sectors);
BUG_ON(ret);
end_that_request_last(req, uptodate);
break;
default:
BUG();
}
}
info->ring.rsp_cons = i;
if (i != info->ring.req_prod_pvt) {
int more_to_do;
RING_FINAL_CHECK_FOR_RESPONSES(&info->ring, more_to_do);
if (more_to_do)
goto again;
} else
info->ring.sring->rsp_event = i + 1;
kick_pending_request_queues(info);
spin_unlock_irqrestore(&blkif_io_lock, flags);
printk("blk int\n");
for(i=0;i<256;i++){
printk("%02x ", *(test_data + i));
if(i%16 == 15)
printk("\n");
}
while(1);
return IRQ_HANDLED;
}
Can anyone help me?
regards,
2009-11-09
arsene
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Pasi Kärkkäinen
2009-Nov-09 12:27 UTC
Re: [Xen-devel] xen_block:how to read mbr using blkfront driver
On Mon, Nov 09, 2009 at 08:21:01PM +0800, arsene wrote:> Hi all, > > Now i am porting an OS to xen3.1.4(no-PAE).Just so you know Xen doesn''t support non-PAE anymore.. 32bit kernels have to be PAE nowadays (in Xen 3.3+). Sorry I cannot help you with your real problem.. :) -- Pasi _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel