VFS/FS: REQ_NEW_DRIVER now provides a label

This commit is contained in:
David van Moolenbroek
2011-11-30 19:05:26 +01:00
parent 41e69065b9
commit db087efac4
23 changed files with 236 additions and 186 deletions

View File

@@ -9,7 +9,7 @@
#include "proto.h"
void bdev_driver(dev_t dev, endpoint_t endpt)
void bdev_driver(dev_t dev, char *label)
{
/* Associate a driver with the given (major) device, using its endpoint.
* File system usage note: typically called from mount and newdriver.
@@ -23,7 +23,7 @@ void bdev_driver(dev_t dev, endpoint_t endpt)
first = FALSE;
}
bdev_update(dev, endpt);
bdev_update(dev, label);
}
static int bdev_opcl(int req, dev_t dev, int access)

7
lib/libbdev/const.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef _BDEV_CONST_H
#define _BDEV_CONST_H
#define DS_NR_TRIES 100 /* number of times to check endpoint in DS */
#define DS_DELAY 50000 /* delay time (us) between DS checks */
#endif /* _BDEV_CONST_H */

View File

@@ -2,11 +2,16 @@
#include <minix/drivers.h>
#include <minix/bdev.h>
#include <minix/ds.h>
#include <assert.h>
#include "const.h"
#include "proto.h"
static endpoint_t driver_endpt[NR_DEVICES];
static struct {
endpoint_t endpt;
char label[DS_MAX_KEYLEN];
} driver_tab[NR_DEVICES];
void bdev_driver_init(void)
{
@@ -14,8 +19,10 @@ void bdev_driver_init(void)
*/
int i;
for (i = 0; i < NR_DEVICES; i++)
driver_endpt[i] = NONE;
for (i = 0; i < NR_DEVICES; i++) {
driver_tab[i].endpt = NONE;
driver_tab[i].label[0] = '\0';
}
}
void bdev_driver_clear(dev_t dev)
@@ -28,20 +35,26 @@ void bdev_driver_clear(dev_t dev)
assert(major >= 0 && major < NR_DEVICES);
driver_endpt[major] = NONE;
driver_tab[major].endpt = NONE;
driver_tab[major].label[0] = '\0';
}
void bdev_driver_set(dev_t dev, endpoint_t endpt)
endpoint_t bdev_driver_set(dev_t dev, char *label)
{
/* Set the endpoint for a driver.
/* Set the label for a driver, and retrieve the associated endpoint.
*/
int major;
major = major(dev);
assert(major >= 0 && major < NR_DEVICES);
assert(strlen(label) < sizeof(driver_tab[major].label));
driver_endpt[major] = endpt;
strcpy(driver_tab[major].label, label);
driver_tab[major].endpt = NONE;
return bdev_driver_update(dev);
}
endpoint_t bdev_driver_get(dev_t dev)
@@ -54,5 +67,55 @@ endpoint_t bdev_driver_get(dev_t dev)
assert(major >= 0 && major < NR_DEVICES);
return driver_endpt[major];
return driver_tab[major].endpt;
}
endpoint_t bdev_driver_update(dev_t dev)
{
/* Update the endpoint of a driver. The caller of this function already knows
* that the current endpoint may no longer be valid, and must be updated.
* Return the new endpoint upon success, and NONE otherwise.
*/
endpoint_t endpt;
int r, major, nr_tries;
major = major(dev);
assert(major >= 0 && major < NR_DEVICES);
assert(driver_tab[major].label[0] != '\0');
/* Repeatedly retrieve the endpoint for the driver label, and see if it is a
* different, valid endpoint. If retrieval fails at first, we have to wait.
* We use polling, as opposed to a DS subscription, for a number of reasons:
* 1) DS supports only one subscription per process, and our main program may
* already have a subscription;
* 2) if we block on receiving a notification from DS, we cannot impose an
* upper bound on the retry time;
* 3) temporarily subscribing and then unsubscribing may cause leftover DS
* notifications, which the main program would then have to deal with.
* As of writing, unsubscribing from DS is not possible at all, anyway.
*
* In the normal case, the driver's label/endpoint mapping entry disappears
* completely for a short moment, before being replaced with the new mapping.
* Hence, failure to retrieve the entry at all does not constitute permanent
* failure. In fact, there is no way to determine reliably that a driver has
* failed permanently in the current approach. For this we simply rely on the
* retry limit.
*/
for (nr_tries = 0; nr_tries < DS_NR_TRIES; nr_tries++) {
r = ds_retrieve_label_endpt(driver_tab[major].label, &endpt);
if (r == OK && endpt != NONE && endpt != driver_tab[major].endpt) {
driver_tab[major].endpt = endpt;
return endpt;
}
if (nr_tries < DS_NR_TRIES - 1)
micro_delay(DS_DELAY);
}
driver_tab[major].endpt = NONE;
return NONE;
}

View File

@@ -19,15 +19,19 @@ static void bdev_cancel(dev_t dev)
bdev_driver_clear(dev);
}
void bdev_update(dev_t dev, endpoint_t endpt)
void bdev_update(dev_t dev, char *label)
{
/* Set the endpoint for a driver. Perform recovery if necessary.
*/
endpoint_t old_endpt;
endpoint_t endpt, old_endpt;
old_endpt = bdev_driver_get(dev);
bdev_driver_set(dev, endpt);
endpt = bdev_driver_set(dev, label);
/* If updating the driver causes an endpoint change, we need to perform
* recovery, but not update the endpoint yet again.
*/
}
int bdev_sendrec(dev_t dev, const message *m_orig)

View File

@@ -4,11 +4,12 @@
/* driver.c */
extern void bdev_driver_init(void);
extern void bdev_driver_clear(dev_t dev);
extern void bdev_driver_set(dev_t dev, endpoint_t endpt);
extern endpoint_t bdev_driver_set(dev_t dev, char *label);
extern endpoint_t bdev_driver_get(dev_t dev);
extern endpoint_t bdev_driver_update(dev_t dev);
/* ipc.c */
extern void bdev_update(dev_t dev, endpoint_t endpt);
extern void bdev_update(dev_t dev, char *label);
extern int bdev_sendrec(dev_t dev, const message *m_orig);
#endif /* _BDEV_PROTO_H */