blk_common.c revision 7eea693d6b672899726e75993fddc4e95b52647f
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/ddi_impldefs.h>
#include <sys/sysmacros.h>
#include <sys/ddidevmap.h>
#include "blk_common.h"
/* blk interface status */
enum blk_if_state {
/*
* initial state
*/
BLK_IF_UNKNOWN = 0,
/*
* frontend xenbus state changed to XenbusStateConnected,
* we finally connect
*/
/*
* frontend xenbus state changed to XenbusStateClosed,
* interface disconnected
*/
};
/* backend device status */
enum blk_be_state {
/* initial state */
BLK_BE_UNKNOWN = 0,
/* backend device is ready (hotplug script finishes successfully) */
};
/* frontend status */
enum blk_fe_state {
/* initial state */
BLK_FE_UNKNOWN = 0,
/*
* frontend's xenbus state has changed to
* XenbusStateInitialised, is ready for connecting
*/
};
typedef struct blk_ring_state_s {
/* Disk Statistics */
static char *blk_stats[] = {
"rd_reqs",
"wr_reqs",
"br_reqs",
"fl_reqs",
"oo_reqs"
};
typedef struct blk_stats_s {
} blk_stats_t;
struct blk_ring_s {
/* blk interface, backend, and frontend status */
enum blk_if_state ri_if_status;
enum blk_be_state ri_be_status;
enum blk_fe_state ri_fe_status;
enum blkif_protocol ri_protocol;
};
/*
* blk_ring_init()
*/
int
{
int e;
e = blk_kstat_init(ring);
if (e != DDI_SUCCESS) {
goto ringinitfail_kstat;
}
/* Watch frontend and hotplug state change */
goto ringinitfail_oestate;
}
goto ringinitfail_hpstate;
}
/*
* Kick-off hotplug script
*/
goto ringinitfail_postevent;
}
/*
* start waiting for hotplug event and otherend state event
* mainly for debugging, frontend will not take any op seeing this
*/
return (DDI_SUCCESS);
return (DDI_FAILURE);
}
/*
* blk_ring_fini()
*/
void
{
}
}
/*
* blk_kstat_init()
*/
static int
{
KSTAT_TYPE_NAMED, nstat, 0);
return (DDI_FAILURE);
}
while (nstat > 0) {
knp++;
cp++;
nstat--;
}
return (DDI_SUCCESS);
}
/*
* blk_kstat_fini()
*/
static void
{
}
/*
* blk_kstat_update()
*/
static int
{
if (flag != KSTAT_READ) {
return (EACCES);
}
/*
* Assignment order should match that of the names in
* blk_stats.
*/
return (0);
}
/*
* blk_oe_state_change()
*/
/*ARGSUSED*/
static void
void *impl_data)
{
return;
}
switch (new_state) {
case XenbusStateInitialised:
/* frontend is ready for connecting */
(void) blk_start_disconnect(ring);
}
break;
case XenbusStateClosing:
break;
case XenbusStateClosed:
/* clean up */
}
/* reset state in case of reconnect */
break;
default:
ASSERT(0);
}
}
/*
* blk_hp_state_change()
*/
/*ARGSUSED*/
static void
void *impl_data)
{
/* Hotplug script has completed successfully */
/* try to connect to frontend */
(void) blk_start_disconnect(ring);
}
}
}
}
/*
* blk_check_state_transition()
* check the XenbusState change to see if the change is a valid transition
* or not. The new state is written by frontend domain, or by running
* xenstore-write to change it manually in dom0.
*/
static int
{
switch (ring->ri_if_status) {
case BLK_IF_UNKNOWN:
if ((oestate == XenbusStateUnknown) ||
(oestate == XenbusStateConnected))
goto statechkfail_bug;
else if ((oestate == XenbusStateInitialising) ||
(oestate == XenbusStateInitWait))
goto statechkfail_nop;
} else {
if ((oestate == XenbusStateUnknown) ||
(oestate == XenbusStateInitialising) ||
(oestate == XenbusStateInitWait) ||
(oestate == XenbusStateConnected))
goto statechkfail_bug;
else if (oestate == XenbusStateInitialised)
goto statechkfail_nop;
}
break;
case BLK_IF_CONNECTED:
if ((oestate == XenbusStateUnknown) ||
(oestate == XenbusStateInitialising) ||
(oestate == XenbusStateInitWait) ||
goto statechkfail_bug;
else if (oestate == XenbusStateConnected)
goto statechkfail_nop;
break;
case BLK_IF_DISCONNECTED:
default:
goto statechkfail_bug;
}
return (DDI_SUCCESS);
"state change to %d!, when status is %d",
ring->ri_if_status);
return (DDI_FAILURE);
}
/*
* blk_start_connect()
* Kick-off connect process
* If ri_fe_status == BLK_FE_READY and ri_be_status == BLK_BE_READY
* the ri_if_status will be changed to BLK_IF_CONNECTED on success,
* otherwise, ri_if_status will not be changed
*/
static int
{
char *barrier;
char *xsnode;
int e;
/*
* Start connect to frontend only when backend device are ready
* and frontend has moved to XenbusStateInitialised, which means
* ready to connect
*/
}
}
if (e > 0) {
}
e = blk_bindto_frontend(ring);
if (e != DDI_SUCCESS) {
}
if (e != DDI_SUCCESS) {
}
e = xenbus_transaction_start(&xbt);
if (e != 0) {
}
/* If feature-barrier isn't present in xenstore, add it */
&len);
if (e != 0) {
if (e != 0) {
}
} else {
}
if (e > 0) {
}
e = xenbus_transaction_end(xbt, 0);
if (e != 0) {
if (e == EAGAIN) {
/* transaction is ended, don't need to abort it */
goto trans_retry;
}
}
}
}
return (DDI_SUCCESS);
return (DDI_FAILURE);
}
/*
* blk_start_disconnect()
* Kick-off disconnect process. ri_if_status will not be changed
*/
static void
{
/* Kick-off disconnect process */
}
/*
* blk_ring_close()
* Disconnect from frontend and close backend device
* ifstatus will be changed to BLK_DISCONNECTED
* Xenbus state will be changed to XenbusStateClosed
*/
static void
{
/* mutex protect ri_if_status only here */
return;
}
/* stop accepting I/O request from frontend */
}
/*
* blk_bindto_frontend()
*/
static int
{
char protocol[64];
char *oename;
int e;
protocol[0] = 0x0;
/*
* Gather info from frontend
*/
return (DDI_FAILURE);
}
if (e != 0) {
xvdi_fatal_error(dip, e,
"Getting ring-ref and evtchn from frontend");
return (DDI_FAILURE);
}
if (e != 0) {
} else {
return (DDI_FAILURE);
}
/*
* map and init ring
*/
if (e != DDI_SUCCESS) {
return (DDI_FAILURE);
}
/*
* bind event channel
*/
if (e != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* blk_unbindfrom_frontend()
*/
static void
{
}
/*
* blk_intr()
*/
static uint_t
{
return (DDI_INTR_CLAIMED);
}
return (DDI_INTR_CLAIMED);
}
/*
* blk_ring_request_get()
*/
{
return (B_FALSE);
}
switch (ring->ri_protocol) {
case BLKIF_PROTOCOL_NATIVE:
break;
case BLKIF_PROTOCOL_X86_32:
break;
case BLKIF_PROTOCOL_X86_64:
break;
default:
ring->ri_protocol);
}
case BLKIF_OP_READ:
stats->bs_req_reads++;
break;
case BLKIF_OP_WRITE:
stats->bs_req_writes++;
break;
case BLKIF_OP_WRITE_BARRIER:
stats->bs_req_barriers++;
break;
case BLKIF_OP_FLUSH_DISKCACHE:
stats->bs_req_flushes++;
break;
}
return (B_TRUE);
}
/*
* blk_ring_request_requeue()
* if a request is requeued, caller will have to poll for request
* later.
*/
void
{
}
/*
* blk_ring_response_put()
*/
void
{
int e;
switch (ring->ri_protocol) {
case BLKIF_PROTOCOL_NATIVE:
break;
case BLKIF_PROTOCOL_X86_32:
break;
case BLKIF_PROTOCOL_X86_64:
break;
default:
ring->ri_protocol);
}
if (e != 0) {
}
}
/*
* blk_ring_request_32()
*/
static void
{
int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
if (n > src->nr_segments)
n = src->nr_segments;
for (i = 0; i < n; i++)
}
/*
* blk_ring_request_64()
*/
static void
{
int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
if (n > src->nr_segments)
n = src->nr_segments;
for (i = 0; i < n; i++)
}
/*
* blk_ring_response_32()
*/
static void
{
}
/*
* blk_ring_response_64()
*/
static void
{
}
/*
* blk_ring_request_dump()
*/
void
{
int i;
/*
* Exploit the public interface definitions for BLKIF_OP_READ
* etc..
*/
(unsigned long long)req->sector_number);
for (i = 0; i < req->nr_segments; i++) {
}
}
/*
* blk_ring_response_dump()
*/
void
{
/*
* Exploit the public interface definitions for BLKIF_OP_READ
* etc..
*/
}