VFS/FS: REQ_NEW_DRIVER now provides a label
This commit is contained in:
@@ -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
7
lib/libbdev/const.h
Normal 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 */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user