2009-12-02 11:08:58 +01:00
|
|
|
/* Filter driver - lowest layer - disk driver management */
|
|
|
|
|
|
|
|
#include "inc.h"
|
|
|
|
|
|
|
|
/* Drivers. */
|
2010-04-08 15:41:35 +02:00
|
|
|
static struct driverinfo driver[2];
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
/* State variables. */
|
|
|
|
static asynmsg_t amsgtable[2];
|
|
|
|
|
|
|
|
static int size_known = 0;
|
|
|
|
static u64_t disk_size;
|
|
|
|
|
|
|
|
static int problem_stats[BD_LAST] = { 0 };
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* driver_open *
|
|
|
|
*===========================================================================*/
|
|
|
|
static int driver_open(int which)
|
|
|
|
{
|
|
|
|
/* Perform an open or close operation on the driver. This is
|
2013-11-01 13:34:14 +01:00
|
|
|
* unfinished code: we should never be doing a blocking ipc_sendrec()
|
|
|
|
* to the driver.
|
2009-12-02 11:08:58 +01:00
|
|
|
*/
|
|
|
|
message msg;
|
|
|
|
cp_grant_id_t gid;
|
2013-03-08 14:52:24 +01:00
|
|
|
struct part_geom part;
|
2009-12-02 11:08:58 +01:00
|
|
|
sector_t sectors;
|
|
|
|
int r;
|
|
|
|
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
|
msg.m_type = BDEV_OPEN;
|
|
|
|
msg.BDEV_MINOR = driver[which].minor;
|
2013-07-27 00:49:49 +02:00
|
|
|
msg.BDEV_ACCESS = BDEV_R_BIT | BDEV_W_BIT;
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
msg.BDEV_ID = 0;
|
2013-11-01 13:34:14 +01:00
|
|
|
r = ipc_sendrec(driver[which].endpt, &msg);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
if (r != OK) {
|
|
|
|
/* Should we restart the driver now? */
|
2013-11-01 13:34:14 +01:00
|
|
|
printf("Filter: driver_open: ipc_sendrec returned %d\n", r);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
return RET_REDO;
|
|
|
|
}
|
|
|
|
|
2014-07-25 20:39:06 +02:00
|
|
|
if(msg.m_type != BDEV_REPLY ||
|
|
|
|
msg.m_lblockdriver_lbdev_reply.status != OK) {
|
2013-11-01 13:34:14 +01:00
|
|
|
printf("Filter: driver_open: ipc_sendrec returned %d, %d\n",
|
2014-07-25 20:39:06 +02:00
|
|
|
msg.m_type, msg.m_lblockdriver_lbdev_reply.status);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
return RET_REDO;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Take the opportunity to retrieve the hard disk size. */
|
|
|
|
gid = cpf_grant_direct(driver[which].endpt,
|
|
|
|
(vir_bytes) &part, sizeof(part), CPF_WRITE);
|
|
|
|
if(!GRANT_VALID(gid))
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("invalid grant: %d", gid);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
|
msg.m_type = BDEV_IOCTL;
|
|
|
|
msg.BDEV_MINOR = driver[which].minor;
|
|
|
|
msg.BDEV_REQUEST = DIOCGETP;
|
|
|
|
msg.BDEV_GRANT = gid;
|
2013-07-27 00:49:49 +02:00
|
|
|
msg.BDEV_USER = NONE;
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
msg.BDEV_ID = 0;
|
2009-12-02 11:08:58 +01:00
|
|
|
|
2013-11-01 13:34:14 +01:00
|
|
|
r = ipc_sendrec(driver[which].endpt, &msg);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
cpf_revoke(gid);
|
|
|
|
|
2014-07-25 20:39:06 +02:00
|
|
|
if (r != OK || msg.m_type != BDEV_REPLY ||
|
|
|
|
msg.m_lblockdriver_lbdev_reply.status != OK) {
|
2009-12-02 11:08:58 +01:00
|
|
|
/* Not sure what to do here, either. */
|
|
|
|
printf("Filter: ioctl(DIOCGETP) returned (%d, %d)\n",
|
|
|
|
r, msg.m_type);
|
|
|
|
|
|
|
|
return RET_REDO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!size_known) {
|
|
|
|
disk_size = part.size;
|
|
|
|
size_known = 1;
|
2013-08-07 12:17:09 +02:00
|
|
|
sectors = (unsigned long)(disk_size / SECTOR_SIZE);
|
|
|
|
if ((u64_t)sectors * SECTOR_SIZE != disk_size) {
|
2009-12-02 11:08:58 +01:00
|
|
|
printf("Filter: partition too large\n");
|
|
|
|
|
|
|
|
return RET_REDO;
|
|
|
|
}
|
|
|
|
#if DEBUG
|
2012-07-24 18:14:48 +02:00
|
|
|
printf("Filter: partition size: 0x%"PRIx64" / %lu sectors\n",
|
|
|
|
disk_size, sectors);
|
2009-12-02 11:08:58 +01:00
|
|
|
#endif
|
|
|
|
} else {
|
2013-08-07 12:17:09 +02:00
|
|
|
if (disk_size != part.size) {
|
2012-07-24 18:14:48 +02:00
|
|
|
printf("Filter: partition size mismatch "
|
|
|
|
"(0x%"PRIx64" != 0x%"PRIx64")\n",
|
|
|
|
part.size, disk_size);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
return RET_REDO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* driver_close *
|
|
|
|
*===========================================================================*/
|
|
|
|
static int driver_close(int which)
|
|
|
|
{
|
|
|
|
message msg;
|
|
|
|
int r;
|
|
|
|
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
|
msg.m_type = BDEV_CLOSE;
|
|
|
|
msg.BDEV_MINOR = driver[which].minor;
|
|
|
|
msg.BDEV_ID = 0;
|
2013-11-01 13:34:14 +01:00
|
|
|
r = ipc_sendrec(driver[which].endpt, &msg);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
if (r != OK) {
|
|
|
|
/* Should we restart the driver now? */
|
2013-11-01 13:34:14 +01:00
|
|
|
printf("Filter: driver_close: ipc_sendrec returned %d\n", r);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
return RET_REDO;
|
|
|
|
}
|
|
|
|
|
2014-07-25 20:39:06 +02:00
|
|
|
if(msg.m_type != BDEV_REPLY ||
|
|
|
|
msg.m_lblockdriver_lbdev_reply.status != OK) {
|
2013-11-01 13:34:14 +01:00
|
|
|
printf("Filter: driver_close: ipc_sendrec returned %d, %d\n",
|
2014-07-25 20:39:06 +02:00
|
|
|
msg.m_type, msg.m_lblockdriver_lbdev_reply.status);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
return RET_REDO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* driver_init *
|
|
|
|
*===========================================================================*/
|
|
|
|
void driver_init(void)
|
|
|
|
{
|
|
|
|
/* Initialize the driver layer. */
|
|
|
|
int r;
|
|
|
|
|
|
|
|
memset(driver, 0, sizeof(driver));
|
|
|
|
|
|
|
|
/* Endpoints unknown. */
|
|
|
|
driver[DRIVER_MAIN].endpt = NONE;
|
|
|
|
driver[DRIVER_BACKUP].endpt = NONE;
|
|
|
|
|
|
|
|
/* Get disk driver's and this proc's endpoint. */
|
|
|
|
driver[DRIVER_MAIN].label = MAIN_LABEL;
|
|
|
|
driver[DRIVER_MAIN].minor = MAIN_MINOR;
|
|
|
|
|
2010-04-08 15:41:35 +02:00
|
|
|
/* No up received yet but expected when the driver starts. */
|
|
|
|
driver[DRIVER_MAIN].up_event = UP_EXPECTED;
|
|
|
|
driver[DRIVER_BACKUP].up_event = UP_EXPECTED;
|
|
|
|
|
|
|
|
r = ds_retrieve_label_endpt(driver[DRIVER_MAIN].label,
|
|
|
|
&driver[DRIVER_MAIN].endpt);
|
2009-12-02 11:08:58 +01:00
|
|
|
if (r != OK) {
|
|
|
|
printf("Filter: failed to get main disk driver's endpoint: "
|
|
|
|
"%d\n", r);
|
|
|
|
bad_driver(DRIVER_MAIN, BD_DEAD, EFAULT);
|
|
|
|
check_driver(DRIVER_MAIN);
|
|
|
|
}
|
|
|
|
else if (driver_open(DRIVER_MAIN) != OK) {
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("unhandled driver_open failure");
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if(USE_MIRROR) {
|
|
|
|
driver[DRIVER_BACKUP].label = BACKUP_LABEL;
|
|
|
|
driver[DRIVER_BACKUP].minor = BACKUP_MINOR;
|
|
|
|
|
|
|
|
if(!strcmp(driver[DRIVER_MAIN].label,
|
|
|
|
driver[DRIVER_BACKUP].label)) {
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("same driver: not tested");
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
|
2010-04-08 15:41:35 +02:00
|
|
|
r = ds_retrieve_label_endpt(driver[DRIVER_BACKUP].label,
|
|
|
|
&driver[DRIVER_BACKUP].endpt);
|
2009-12-02 11:08:58 +01:00
|
|
|
if (r != OK) {
|
|
|
|
printf("Filter: failed to get backup disk driver's "
|
|
|
|
"endpoint: %d\n", r);
|
|
|
|
bad_driver(DRIVER_BACKUP, BD_DEAD, EFAULT);
|
|
|
|
check_driver(DRIVER_BACKUP);
|
|
|
|
}
|
|
|
|
else if (driver_open(DRIVER_BACKUP) != OK) {
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("unhandled driver_open failure");
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* driver_shutdown *
|
|
|
|
*===========================================================================*/
|
|
|
|
void driver_shutdown(void)
|
|
|
|
{
|
|
|
|
/* Clean up. */
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: %u driver deaths, %u protocol errors, "
|
|
|
|
"%u data errors\n", problem_stats[BD_DEAD],
|
|
|
|
problem_stats[BD_PROTO], problem_stats[BD_DATA]);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if(driver_close(DRIVER_MAIN) != OK)
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
printf("Filter: BDEV_CLOSE failed on shutdown (1)\n");
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
if(USE_MIRROR)
|
|
|
|
if(driver_close(DRIVER_BACKUP) != OK)
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
printf("Filter: BDEV_CLOSE failed on shutdown (2)\n");
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* get_raw_size *
|
|
|
|
*===========================================================================*/
|
|
|
|
u64_t get_raw_size(void)
|
|
|
|
{
|
|
|
|
/* Return the size of the raw disks as used by the filter driver.
|
|
|
|
*/
|
|
|
|
|
|
|
|
return disk_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* reset_kills *
|
|
|
|
*===========================================================================*/
|
|
|
|
void reset_kills(void)
|
|
|
|
{
|
|
|
|
/* Reset kill and retry statistics. */
|
|
|
|
driver[DRIVER_MAIN].kills = 0;
|
|
|
|
driver[DRIVER_MAIN].retries = 0;
|
|
|
|
driver[DRIVER_BACKUP].kills = 0;
|
|
|
|
driver[DRIVER_BACKUP].retries = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* bad_driver *
|
|
|
|
*===========================================================================*/
|
|
|
|
int bad_driver(int which, int type, int error)
|
|
|
|
{
|
|
|
|
/* A disk driver has died or produced an error. Mark it so that we can
|
|
|
|
* deal with it later, and return RET_REDO to indicate that the
|
|
|
|
* current operation is to be retried. Also store an error code to
|
|
|
|
* return to the user if the situation is unrecoverable.
|
|
|
|
*/
|
|
|
|
driver[which].problem = type;
|
|
|
|
driver[which].error = error;
|
|
|
|
|
|
|
|
return RET_REDO;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* new_driver_ep *
|
|
|
|
*===========================================================================*/
|
|
|
|
static int new_driver_ep(int which)
|
|
|
|
{
|
|
|
|
/* See if a new driver instance has already been started for the given
|
|
|
|
* driver, by retrieving its entry from DS.
|
|
|
|
*/
|
|
|
|
int r;
|
|
|
|
endpoint_t endpt;
|
|
|
|
|
2010-04-08 15:41:35 +02:00
|
|
|
r = ds_retrieve_label_endpt(driver[which].label, &endpt);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
if (r != OK) {
|
|
|
|
printf("Filter: DS query for %s failed\n",
|
|
|
|
driver[which].label);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (endpt == driver[which].endpt) {
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: same endpoint for %s\n", driver[which].label);
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: new enpdoint for %s: %d -> %d\n", driver[which].label,
|
|
|
|
driver[which].endpt, endpt);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
driver[which].endpt = endpt;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* check_problem *
|
|
|
|
*===========================================================================*/
|
|
|
|
static int check_problem(int which, int problem, int retries, int *tell_rs)
|
|
|
|
{
|
|
|
|
/* A problem has occurred with a driver. Update statistics, and decide
|
|
|
|
* what to do. If EAGAIN is returned, the driver should be restarted;
|
|
|
|
* any other result will be passed up.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if DEBUG
|
2010-03-16 17:21:28 +01:00
|
|
|
printf("Filter: check_problem processing driver %d, problem %d\n",
|
2009-12-02 11:08:58 +01:00
|
|
|
which, problem);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
problem_stats[problem]++;
|
|
|
|
|
|
|
|
if(new_driver_ep(which)) {
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: check_problem: noticed a new driver\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if(driver_open(which) == OK) {
|
|
|
|
#if DEBUG2
|
|
|
|
printf("Filter: open OK -> no recovery\n");
|
|
|
|
#endif
|
|
|
|
return OK;
|
|
|
|
} else {
|
|
|
|
#if DEBUG2
|
|
|
|
printf("Filter: open not OK -> recovery\n");
|
|
|
|
#endif
|
|
|
|
problem = BD_PROTO;
|
|
|
|
problem_stats[problem]++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the driver has died, we always need to restart it. If it has
|
|
|
|
* been giving problems, we first retry the request, up to N times,
|
|
|
|
* after which we kill and restart the driver. We restart the driver
|
|
|
|
* up to M times, after which we remove the driver from the mirror
|
|
|
|
* configuration. If we are not set up to do mirroring, we can only
|
|
|
|
* do one thing, and that is continue to limp along with the bad
|
|
|
|
* driver..
|
|
|
|
*/
|
|
|
|
switch(problem) {
|
|
|
|
case BD_PROTO:
|
|
|
|
case BD_DATA:
|
|
|
|
driver[which].retries++;
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: disk driver %d has had "
|
|
|
|
"%d/%d retry attempts, %d/%d kills\n", which,
|
|
|
|
driver[which].retries, NR_RETRIES,
|
|
|
|
driver[which].kills, NR_RESTARTS);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (driver[which].retries < NR_RETRIES) {
|
|
|
|
if(retries == 1) {
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: not restarting; retrying "
|
|
|
|
"(retries %d/%d, kills %d/%d)\n",
|
|
|
|
driver[which].retries, NR_RETRIES,
|
|
|
|
driver[which].kills, NR_RESTARTS);
|
|
|
|
#endif
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: restarting (retries %d/%d, "
|
|
|
|
"kills %d/%d, internal retry %d)\n",
|
|
|
|
driver[which].retries, NR_RETRIES,
|
|
|
|
driver[which].kills, NR_RESTARTS, retries);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: disk driver %d has reached error "
|
|
|
|
"threshold, restarting driver\n", which);
|
|
|
|
#endif
|
|
|
|
|
2010-04-08 15:41:35 +02:00
|
|
|
*tell_rs = (driver[which].up_event != UP_PENDING);
|
2009-12-02 11:08:58 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case BD_DEAD:
|
|
|
|
/* Can't kill that which is already dead.. */
|
|
|
|
*tell_rs = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("invalid problem: %d", problem);
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* At this point, the driver will be restarted. */
|
|
|
|
driver[which].retries = 0;
|
|
|
|
driver[which].kills++;
|
|
|
|
|
|
|
|
if (driver[which].kills < NR_RESTARTS)
|
|
|
|
return EAGAIN;
|
|
|
|
|
|
|
|
/* We've reached the maximum number of restarts for this driver. */
|
|
|
|
if (USE_MIRROR) {
|
|
|
|
printf("Filter: kill threshold reached, disabling mirroring\n");
|
|
|
|
|
|
|
|
USE_MIRROR = 0;
|
|
|
|
|
|
|
|
if (which == DRIVER_MAIN) {
|
|
|
|
driver[DRIVER_MAIN] = driver[DRIVER_BACKUP];
|
|
|
|
|
|
|
|
/* This is not necessary. */
|
2012-07-27 16:52:23 +02:00
|
|
|
strlcpy(MAIN_LABEL, BACKUP_LABEL, sizeof(MAIN_LABEL));
|
2009-12-02 11:08:58 +01:00
|
|
|
MAIN_MINOR = BACKUP_MINOR;
|
|
|
|
}
|
|
|
|
|
|
|
|
driver[DRIVER_BACKUP].endpt = NONE;
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* We tried, we really did. But now we give up. Tell the user.
|
|
|
|
*/
|
|
|
|
printf("Filter: kill threshold reached, returning error\n");
|
|
|
|
|
|
|
|
if (driver[which].error == EAGAIN) return EIO;
|
|
|
|
|
|
|
|
return driver[which].error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* restart_driver *
|
|
|
|
*===========================================================================*/
|
|
|
|
static void restart_driver(int which, int tell_rs)
|
|
|
|
{
|
|
|
|
/* Restart the given driver. Block until the new instance is up.
|
|
|
|
*/
|
|
|
|
message msg;
|
2010-04-08 15:41:35 +02:00
|
|
|
int ipc_status;
|
2010-04-15 20:49:36 +02:00
|
|
|
int r;
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
if (tell_rs) {
|
|
|
|
/* Tell RS to refresh or restart the driver */
|
|
|
|
msg.m_type = RS_REFRESH;
|
2014-07-26 13:54:01 +02:00
|
|
|
msg.m_rs_req.addr = driver[which].label;
|
|
|
|
msg.m_rs_req.len = strlen(driver[which].label);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: asking RS to refresh %s..\n",
|
|
|
|
driver[which].label);
|
|
|
|
#endif
|
|
|
|
|
2013-11-01 13:34:14 +01:00
|
|
|
r = ipc_sendrec(RS_PROC_NR, &msg);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
if (r != OK || msg.m_type != OK)
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("RS request failed: %d", r);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: RS call succeeded\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Wait until the new driver instance is up, and get its endpoint. */
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: endpoint update driver %d; old endpoint %d\n",
|
|
|
|
which, driver[which].endpt);
|
|
|
|
#endif
|
|
|
|
|
2010-04-08 15:41:35 +02:00
|
|
|
if(driver[which].up_event == UP_EXPECTED) {
|
|
|
|
driver[which].up_event = UP_NONE;
|
|
|
|
}
|
|
|
|
while(driver[which].up_event != UP_PENDING) {
|
|
|
|
r = driver_receive(DS_PROC_NR, &msg, &ipc_status);
|
|
|
|
if(r != OK)
|
|
|
|
panic("driver_receive returned error: %d", r);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
2010-04-08 15:41:35 +02:00
|
|
|
ds_event();
|
|
|
|
}
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* check_driver *
|
|
|
|
*===========================================================================*/
|
|
|
|
int check_driver(int which)
|
|
|
|
{
|
|
|
|
/* See if the given driver has been troublesome, and if so, deal with
|
|
|
|
* it.
|
|
|
|
*/
|
|
|
|
int problem, tell_rs;
|
|
|
|
int r, retries = 0;
|
|
|
|
|
|
|
|
problem = driver[which].problem;
|
|
|
|
|
|
|
|
if (problem == BD_NONE)
|
|
|
|
return OK;
|
|
|
|
|
|
|
|
do {
|
|
|
|
if(retries) {
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: check_driver: retry number %d\n",
|
|
|
|
retries);
|
|
|
|
#endif
|
|
|
|
problem = BD_PROTO;
|
|
|
|
}
|
|
|
|
retries++;
|
|
|
|
driver[which].problem = BD_NONE;
|
|
|
|
|
|
|
|
/* Decide what to do: continue operation, restart the driver,
|
|
|
|
* or return an error.
|
|
|
|
*/
|
|
|
|
r = check_problem(which, problem, retries, &tell_rs);
|
|
|
|
if (r != EAGAIN)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
/* Restarting the driver it is. First tell RS (if necessary),
|
|
|
|
* then wait for the new driver instance to come up.
|
|
|
|
*/
|
|
|
|
restart_driver(which, tell_rs);
|
|
|
|
|
|
|
|
/* Finally, open the device on the new driver */
|
|
|
|
} while (driver_open(which) != OK);
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: check_driver restarted driver %d, endpoint %d\n",
|
|
|
|
which, driver[which].endpt);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* flt_senda *
|
|
|
|
*===========================================================================*/
|
|
|
|
static int flt_senda(message *mess, int which)
|
|
|
|
{
|
|
|
|
/* Send a message to one driver. Can only return OK at the moment. */
|
|
|
|
int r;
|
|
|
|
asynmsg_t *amp;
|
|
|
|
|
|
|
|
/* Fill in the last bits of the message. */
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
mess->BDEV_MINOR = driver[which].minor;
|
|
|
|
mess->BDEV_ID = 0;
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
/* Send the message asynchronously. */
|
|
|
|
amp = &amsgtable[which];
|
|
|
|
amp->dst = driver[which].endpt;
|
|
|
|
amp->msg = *mess;
|
|
|
|
amp->flags = AMF_VALID;
|
2013-11-01 13:34:14 +01:00
|
|
|
r = ipc_senda(amsgtable, 2);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
if(r != OK)
|
2013-11-01 13:34:14 +01:00
|
|
|
panic("ipc_senda returned error: %d", r);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* check_senda *
|
|
|
|
*===========================================================================*/
|
|
|
|
static int check_senda(int which)
|
|
|
|
{
|
|
|
|
/* Check whether an earlier senda resulted in an error indicating the
|
|
|
|
* message never got delivered. Only in that case can we reliably say
|
|
|
|
* that the driver died. Return BD_DEAD in this case, and BD_PROTO
|
|
|
|
* otherwise.
|
|
|
|
*/
|
|
|
|
asynmsg_t *amp;
|
|
|
|
|
|
|
|
amp = &amsgtable[which];
|
|
|
|
|
2010-03-03 16:47:16 +01:00
|
|
|
if ((amp->flags & AMF_DONE) && (amp->result == EDEADSRCDST)) {
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
return BD_DEAD;
|
|
|
|
}
|
|
|
|
|
|
|
|
return BD_PROTO;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* flt_receive *
|
|
|
|
*===========================================================================*/
|
|
|
|
static int flt_receive(message *mess, int which)
|
|
|
|
{
|
|
|
|
/* Receive a message from one or either driver, unless a timeout
|
|
|
|
* occurs. Can only return OK or RET_REDO.
|
|
|
|
*/
|
|
|
|
int r;
|
2010-04-08 15:41:35 +02:00
|
|
|
int ipc_status;
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
for (;;) {
|
2010-04-08 15:41:35 +02:00
|
|
|
r = driver_receive(ANY, mess, &ipc_status);
|
2009-12-02 11:08:58 +01:00
|
|
|
if(r != OK)
|
2010-04-08 15:41:35 +02:00
|
|
|
panic("driver_receive returned error: %d", r);
|
|
|
|
|
|
|
|
if(mess->m_source == DS_PROC_NR && is_ipc_notify(ipc_status)) {
|
|
|
|
ds_event();
|
|
|
|
continue;
|
|
|
|
}
|
2009-12-02 11:08:58 +01:00
|
|
|
|
2010-04-08 15:41:35 +02:00
|
|
|
if(mess->m_source == CLOCK && is_ipc_notify(ipc_status)) {
|
2013-11-28 18:17:38 +01:00
|
|
|
if (mess->m_notify.timestamp < flt_alarm((clock_t) -1)) {
|
2009-12-02 11:08:58 +01:00
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: SKIPPING old alarm "
|
|
|
|
"notification\n");
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: timeout waiting for disk driver %d "
|
|
|
|
"reply!\n", which);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* If we're waiting for either driver,
|
|
|
|
* both are at fault.
|
|
|
|
*/
|
|
|
|
if (which < 0) {
|
|
|
|
bad_driver(DRIVER_MAIN,
|
|
|
|
check_senda(DRIVER_MAIN), EFAULT);
|
|
|
|
|
|
|
|
return bad_driver(DRIVER_BACKUP,
|
|
|
|
check_senda(DRIVER_BACKUP), EFAULT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Otherwise, just report the one not replying as dead.
|
|
|
|
*/
|
|
|
|
return bad_driver(which, check_senda(which), EFAULT);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mess->m_source != driver[DRIVER_MAIN].endpt &&
|
|
|
|
mess->m_source != driver[DRIVER_BACKUP].endpt) {
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: got STRAY message %d from %d\n",
|
|
|
|
mess->m_type, mess->m_source);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We are waiting for a reply from one specific driver. */
|
|
|
|
if (which >= 0) {
|
|
|
|
/* If the message source is that driver, good. */
|
|
|
|
if (mess->m_source == driver[which].endpt)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* This should probably be treated as a real protocol
|
|
|
|
* error. We do not abort any receives (not even paired
|
|
|
|
* receives) except because of timeouts. Getting here
|
|
|
|
* means a driver replied at least the timeout period
|
|
|
|
* later than expected, which should be enough reason
|
|
|
|
* to kill it really. The other explanation is that it
|
|
|
|
* is actually violating the protocol and sending bogus
|
|
|
|
* messages...
|
|
|
|
*/
|
|
|
|
#if DEBUG
|
|
|
|
printf("Filter: got UNEXPECTED reply from %d\n",
|
|
|
|
mess->m_source);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We got a message from one of the drivers, and we didn't
|
|
|
|
* care which one we wanted to receive from. A-OK.
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* flt_sendrec *
|
|
|
|
*===========================================================================*/
|
|
|
|
static int flt_sendrec(message *mess, int which)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
|
|
|
r = flt_senda(mess, which);
|
|
|
|
if(r != OK)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if(check_senda(which) == BD_DEAD) {
|
|
|
|
return bad_driver(which, BD_DEAD, EFAULT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set alarm. */
|
|
|
|
flt_alarm(DRIVER_TIMEOUT);
|
|
|
|
|
|
|
|
r = flt_receive(mess, which);
|
|
|
|
|
|
|
|
/* Clear the alarm. */
|
|
|
|
flt_alarm(0);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* do_sendrec_both *
|
|
|
|
*===========================================================================*/
|
|
|
|
static int do_sendrec_both(message *m1, message *m2)
|
|
|
|
{
|
|
|
|
/* If USEE_MIRROR is set, call flt_sendrec() to both drivers.
|
|
|
|
* Otherwise, only call flt_sendrec() to the main driver.
|
|
|
|
* This function will only return either OK or RET_REDO.
|
|
|
|
*/
|
|
|
|
int r, which = -1;
|
|
|
|
message ma, mb;
|
|
|
|
|
|
|
|
/* If the two disks use the same driver, call flt_sendrec() twice
|
|
|
|
* sequentially. Such a setup is not very useful though.
|
|
|
|
*/
|
|
|
|
if (!strcmp(driver[DRIVER_MAIN].label, driver[DRIVER_BACKUP].label)) {
|
|
|
|
if ((r = flt_sendrec(m1, DRIVER_MAIN)) != OK) return r;
|
|
|
|
return flt_sendrec(m2, DRIVER_BACKUP);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the two disks use different drivers, call flt_senda()
|
|
|
|
* twice, and then flt_receive(), and distinguish the return
|
|
|
|
* messages by means of m_source.
|
|
|
|
*/
|
|
|
|
if ((r = flt_senda(m1, DRIVER_MAIN)) != OK) return r;
|
|
|
|
if ((r = flt_senda(m2, DRIVER_BACKUP)) != OK) return r;
|
|
|
|
|
|
|
|
/* Set alarm. */
|
|
|
|
flt_alarm(DRIVER_TIMEOUT);
|
|
|
|
|
|
|
|
/* The message received by the 1st flt_receive() may not be
|
|
|
|
* from DRIVER_MAIN.
|
|
|
|
*/
|
|
|
|
if ((r = flt_receive(&ma, -1)) != OK) {
|
|
|
|
flt_alarm(0);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ma.m_source == driver[DRIVER_MAIN].endpt) {
|
|
|
|
which = DRIVER_BACKUP;
|
|
|
|
} else if (ma.m_source == driver[DRIVER_BACKUP].endpt) {
|
|
|
|
which = DRIVER_MAIN;
|
|
|
|
} else {
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("message from unexpected source: %d",
|
2009-12-02 11:08:58 +01:00
|
|
|
ma.m_source);
|
|
|
|
}
|
|
|
|
|
|
|
|
r = flt_receive(&mb, which);
|
|
|
|
|
|
|
|
/* Clear the alarm. */
|
|
|
|
flt_alarm(0);
|
|
|
|
|
|
|
|
if(r != OK)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (ma.m_source == driver[DRIVER_MAIN].endpt) {
|
|
|
|
*m1 = ma;
|
|
|
|
*m2 = mb;
|
|
|
|
} else {
|
|
|
|
*m1 = mb;
|
|
|
|
*m2 = ma;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* do_sendrec_one *
|
|
|
|
*===========================================================================*/
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
static int do_sendrec_one(message *m1)
|
2009-12-02 11:08:58 +01:00
|
|
|
{
|
|
|
|
/* Only talk to the main driver. If something goes wrong, it will
|
|
|
|
* be fixed elsewhere.
|
|
|
|
* This function will only return either OK or RET_REDO.
|
|
|
|
*/
|
|
|
|
|
|
|
|
return flt_sendrec(m1, DRIVER_MAIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* paired_sendrec *
|
|
|
|
*===========================================================================*/
|
|
|
|
static int paired_sendrec(message *m1, message *m2, int both)
|
|
|
|
{
|
|
|
|
/* Sendrec with the disk driver. If the disk driver is down, and was
|
|
|
|
* restarted, redo the request, until the driver works fine, or can't
|
|
|
|
* be restarted again.
|
|
|
|
*/
|
|
|
|
int r;
|
|
|
|
|
|
|
|
#if DEBUG2
|
2014-02-24 14:22:04 +01:00
|
|
|
printf("paired_sendrec(%d) - <%d,%llx,%d> - %x,%x\n",
|
|
|
|
both, m1->m_type, m1->BDEV_POS,
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
m1->BDEV_COUNT, m1->BDEV_GRANT, m2->BDEV_GRANT);
|
2009-12-02 11:08:58 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (both)
|
|
|
|
r = do_sendrec_both(m1, m2);
|
|
|
|
else
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
r = do_sendrec_one(m1);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
#if DEBUG2
|
|
|
|
if (r != OK)
|
|
|
|
printf("paired_sendrec about to return %d\n", r);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2009-12-22 00:30:01 +01:00
|
|
|
/*===========================================================================*
|
|
|
|
* single_grant *
|
|
|
|
*===========================================================================*/
|
|
|
|
static int single_grant(endpoint_t endpt, vir_bytes buf, int access,
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
cp_grant_id_t *gid, iovec_s_t vector[NR_IOREQS], size_t size)
|
2009-12-22 00:30:01 +01:00
|
|
|
{
|
|
|
|
/* Create grants for a vectored request to a single driver.
|
|
|
|
*/
|
|
|
|
cp_grant_id_t grant;
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
size_t chunk;
|
2009-12-22 00:30:01 +01:00
|
|
|
int count;
|
|
|
|
|
|
|
|
/* Split up the request into chunks, if requested. This makes no
|
|
|
|
* difference at all, except that this works around a weird performance
|
|
|
|
* bug with large DMA PRDs on some machines.
|
|
|
|
*/
|
|
|
|
if (CHUNK_SIZE > 0) chunk = CHUNK_SIZE;
|
|
|
|
else chunk = size;
|
|
|
|
|
|
|
|
/* Fill in the vector, creating a grant for each item. */
|
|
|
|
for (count = 0; size > 0 && count < NR_IOREQS; count++) {
|
|
|
|
/* The last chunk will contain all the remaining data. */
|
|
|
|
if (chunk > size || count == NR_IOREQS - 1)
|
|
|
|
chunk = size;
|
|
|
|
|
|
|
|
grant = cpf_grant_direct(endpt, buf, chunk, access);
|
|
|
|
if (!GRANT_VALID(grant))
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("invalid grant: %d", grant);
|
2009-12-22 00:30:01 +01:00
|
|
|
|
|
|
|
vector[count].iov_grant = grant;
|
|
|
|
vector[count].iov_size = chunk;
|
|
|
|
|
|
|
|
buf += chunk;
|
|
|
|
size -= chunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Then create a grant for the vector itself. */
|
|
|
|
*gid = cpf_grant_direct(endpt, (vir_bytes) vector,
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
sizeof(vector[0]) * count, CPF_READ);
|
2009-12-22 00:30:01 +01:00
|
|
|
|
|
|
|
if (!GRANT_VALID(*gid))
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("invalid grant: %d", *gid);
|
2009-12-22 00:30:01 +01:00
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2009-12-02 11:08:58 +01:00
|
|
|
/*===========================================================================*
|
|
|
|
* paired_grant *
|
|
|
|
*===========================================================================*/
|
2009-12-22 00:30:01 +01:00
|
|
|
static int paired_grant(char *buf1, char *buf2, int request,
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
cp_grant_id_t *gids, iovec_s_t vectors[2][NR_IOREQS], size_t size,
|
2009-12-22 00:30:01 +01:00
|
|
|
int both)
|
2009-12-02 11:08:58 +01:00
|
|
|
{
|
2009-12-22 00:30:01 +01:00
|
|
|
/* Create memory grants, either to one or to both drivers.
|
2009-12-02 11:08:58 +01:00
|
|
|
*/
|
2009-12-22 00:30:01 +01:00
|
|
|
int count, access;
|
2009-12-02 11:08:58 +01:00
|
|
|
|
2009-12-22 00:30:01 +01:00
|
|
|
count = 0;
|
2009-12-02 11:08:58 +01:00
|
|
|
access = (request == FLT_WRITE) ? CPF_READ : CPF_WRITE;
|
|
|
|
|
|
|
|
if(driver[DRIVER_MAIN].endpt > 0) {
|
2009-12-22 00:30:01 +01:00
|
|
|
count = single_grant(driver[DRIVER_MAIN].endpt,
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
(vir_bytes) buf1, access, &gids[0], vectors[0], size);
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (both) {
|
|
|
|
if(driver[DRIVER_BACKUP].endpt > 0) {
|
2009-12-22 00:30:01 +01:00
|
|
|
count = single_grant(driver[DRIVER_BACKUP].endpt,
|
|
|
|
(vir_bytes) buf2, access, &gids[1],
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
vectors[1], size);
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
}
|
2010-01-15 22:45:30 +01:00
|
|
|
return count;
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
|
2009-12-22 00:30:01 +01:00
|
|
|
/*===========================================================================*
|
|
|
|
* single_revoke *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
static void single_revoke(cp_grant_id_t gid,
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
const iovec_s_t vector[NR_IOREQS], int count)
|
2009-12-22 00:30:01 +01:00
|
|
|
{
|
|
|
|
/* Revoke all grants associated with a request to a single driver.
|
|
|
|
* Modify the given size to reflect the actual I/O performed.
|
|
|
|
*/
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Revoke the grants for all the elements of the vector. */
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
for (i = 0; i < count; i++)
|
2009-12-22 00:30:01 +01:00
|
|
|
cpf_revoke(vector[i].iov_grant);
|
|
|
|
|
|
|
|
/* Then revoke the grant for the vector itself. */
|
|
|
|
cpf_revoke(gid);
|
|
|
|
}
|
|
|
|
|
2009-12-02 11:08:58 +01:00
|
|
|
/*===========================================================================*
|
|
|
|
* paired_revoke *
|
|
|
|
*===========================================================================*/
|
2010-04-07 13:25:51 +02:00
|
|
|
static void paired_revoke(const cp_grant_id_t *gids,
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
iovec_s_t vectors[2][NR_IOREQS], int count, int both)
|
2009-12-02 11:08:58 +01:00
|
|
|
{
|
2009-12-22 00:30:01 +01:00
|
|
|
/* Revoke grants to drivers for a single request.
|
|
|
|
*/
|
|
|
|
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
single_revoke(gids[0], vectors[0], count);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
if (both)
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
single_revoke(gids[1], vectors[1], count);
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* read_write *
|
|
|
|
*===========================================================================*/
|
|
|
|
int read_write(u64_t pos, char *bufa, char *bufb, size_t *sizep, int request)
|
|
|
|
{
|
2009-12-22 00:30:01 +01:00
|
|
|
iovec_s_t vectors[2][NR_IOREQS];
|
2009-12-02 11:08:58 +01:00
|
|
|
message m1, m2;
|
|
|
|
cp_grant_id_t gids[2];
|
2009-12-22 00:30:01 +01:00
|
|
|
int r, both, count;
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
gids[0] = gids[1] = GRANT_INVALID;
|
|
|
|
|
|
|
|
/* Send two requests only if mirroring is enabled and the given request
|
|
|
|
* is either FLT_READ2 or FLT_WRITE.
|
|
|
|
*/
|
|
|
|
both = (USE_MIRROR && request != FLT_READ);
|
|
|
|
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
count = paired_grant(bufa, bufb, request, gids, vectors, *sizep, both);
|
2009-12-22 00:30:01 +01:00
|
|
|
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
memset(&m1, 0, sizeof(m1));
|
|
|
|
m1.m_type = (request == FLT_WRITE) ? BDEV_SCATTER : BDEV_GATHER;
|
|
|
|
m1.BDEV_COUNT = count;
|
2014-02-24 14:22:04 +01:00
|
|
|
m1.BDEV_POS = pos;
|
2009-12-22 00:30:01 +01:00
|
|
|
|
2009-12-02 11:08:58 +01:00
|
|
|
m2 = m1;
|
|
|
|
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
m1.BDEV_GRANT = gids[0];
|
|
|
|
m2.BDEV_GRANT = gids[1];
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
r = paired_sendrec(&m1, &m2, both);
|
|
|
|
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
paired_revoke(gids, vectors, count, both);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
if(r != OK) {
|
|
|
|
#if DEBUG
|
|
|
|
if (r != RET_REDO)
|
|
|
|
printf("Filter: paired_sendrec returned %d\n", r);
|
|
|
|
#endif
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2014-07-25 20:39:06 +02:00
|
|
|
if (m1.m_type != BDEV_REPLY ||
|
|
|
|
m1.m_lblockdriver_lbdev_reply.status < 0) {
|
2009-12-02 11:08:58 +01:00
|
|
|
printf("Filter: unexpected/invalid reply from main driver: "
|
2014-07-25 20:39:06 +02:00
|
|
|
"(%x, %d)\n", m1.m_type,
|
|
|
|
m1.m_lblockdriver_lbdev_reply.status);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
return bad_driver(DRIVER_MAIN, BD_PROTO,
|
2014-07-25 20:39:06 +02:00
|
|
|
(m1.m_type == BDEV_REPLY) ?
|
|
|
|
m1.m_lblockdriver_lbdev_reply.status : EFAULT);
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
|
2014-07-25 20:39:06 +02:00
|
|
|
if (m1.m_lblockdriver_lbdev_reply.status != (ssize_t) *sizep) {
|
2009-12-22 00:30:01 +01:00
|
|
|
printf("Filter: truncated reply from main driver\n");
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
/* If the driver returned a value *larger* than we requested,
|
|
|
|
* OR if we did NOT exceed the disk size, then we should
|
|
|
|
* report the driver for acting strangely!
|
|
|
|
*/
|
2014-07-25 20:39:06 +02:00
|
|
|
if (m1.m_lblockdriver_lbdev_reply.status > (ssize_t) *sizep ||
|
|
|
|
(pos + (unsigned int)
|
|
|
|
m1.m_lblockdriver_lbdev_reply.status < disk_size))
|
2009-12-02 11:08:58 +01:00
|
|
|
return bad_driver(DRIVER_MAIN, BD_PROTO, EFAULT);
|
|
|
|
|
|
|
|
/* Return the actual size. */
|
2014-07-25 20:39:06 +02:00
|
|
|
*sizep = m1.m_lblockdriver_lbdev_reply.status;
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (both) {
|
2014-07-25 20:39:06 +02:00
|
|
|
if (m2.m_type != BDEV_REPLY ||
|
|
|
|
m2.m_lblockdriver_lbdev_reply.status < 0) {
|
2009-12-02 11:08:58 +01:00
|
|
|
printf("Filter: unexpected/invalid reply from "
|
|
|
|
"backup driver (%x, %d)\n",
|
2014-07-25 20:39:06 +02:00
|
|
|
m2.m_type,
|
|
|
|
m2.m_lblockdriver_lbdev_reply.status);
|
2009-12-02 11:08:58 +01:00
|
|
|
|
|
|
|
return bad_driver(DRIVER_BACKUP, BD_PROTO,
|
2014-07-25 20:39:06 +02:00
|
|
|
m2.m_type == BDEV_REPLY ?
|
|
|
|
m2.m_lblockdriver_lbdev_reply.status :
|
2009-12-02 11:08:58 +01:00
|
|
|
EFAULT);
|
|
|
|
}
|
2014-07-25 20:39:06 +02:00
|
|
|
if (m2.m_lblockdriver_lbdev_reply.status != (ssize_t) *sizep) {
|
2009-12-02 11:08:58 +01:00
|
|
|
printf("Filter: truncated reply from backup driver\n");
|
|
|
|
|
|
|
|
/* As above */
|
2014-07-25 20:39:06 +02:00
|
|
|
if (m2.m_lblockdriver_lbdev_reply.status > (ssize_t) *sizep ||
|
|
|
|
(pos + (unsigned int)
|
|
|
|
m2.m_lblockdriver_lbdev_reply.status
|
|
|
|
< disk_size))
|
2009-12-02 11:08:58 +01:00
|
|
|
return bad_driver(DRIVER_BACKUP, BD_PROTO,
|
|
|
|
EFAULT);
|
|
|
|
|
|
|
|
/* Return the actual size. */
|
2014-07-25 20:39:06 +02:00
|
|
|
if ((ssize_t)*sizep >= m2.m_lblockdriver_lbdev_reply.status)
|
|
|
|
*sizep = m2.m_lblockdriver_lbdev_reply.status;
|
2009-12-02 11:08:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
2010-04-08 15:41:35 +02:00
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* ds_event *
|
|
|
|
*===========================================================================*/
|
|
|
|
void ds_event()
|
|
|
|
{
|
|
|
|
char key[DS_MAX_KEYLEN];
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
char *blkdriver_prefix = "drv.blk.";
|
2010-04-08 15:41:35 +02:00
|
|
|
u32_t value;
|
|
|
|
int type;
|
|
|
|
endpoint_t owner_endpoint;
|
|
|
|
int r;
|
|
|
|
int which;
|
|
|
|
|
|
|
|
/* Get the event and the owner from DS. */
|
|
|
|
r = ds_check(key, &type, &owner_endpoint);
|
|
|
|
if(r != OK) {
|
|
|
|
if(r != ENOENT)
|
|
|
|
printf("Filter: ds_event: ds_check failed: %d\n", r);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
r = ds_retrieve_u32(key, &value);
|
|
|
|
if(r != OK) {
|
|
|
|
printf("Filter: ds_event: ds_retrieve_u32 failed\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Only check for VFS driver up events. */
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
if(strncmp(key, blkdriver_prefix, strlen(blkdriver_prefix))
|
2010-04-08 15:41:35 +02:00
|
|
|
|| value != DS_DRIVER_UP) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* See if this is a driver we are responsible for. */
|
|
|
|
if(driver[DRIVER_MAIN].endpt == owner_endpoint) {
|
|
|
|
which = DRIVER_MAIN;
|
|
|
|
}
|
|
|
|
else if(driver[DRIVER_BACKUP].endpt == owner_endpoint) {
|
|
|
|
which = DRIVER_BACKUP;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Mark the driver as (re)started. */
|
|
|
|
driver[which].up_event = driver[which].up_event == UP_EXPECTED ?
|
|
|
|
UP_NONE : UP_PENDING;
|
|
|
|
}
|
|
|
|
|