VFS: further cleanup of device code
- all TTY-related exceptions have now been merged into the regular code paths, allowing non-TTY drivers to expose TTY-like devices; - as part of this, CTTY_MAJOR is now fully managed by VFS instead of being an ugly stepchild of the TTY driver; - device styles have become completely obsolete, support for them has been removed throughout the system; same for device flags, which had already become useless a while ago; - device map open/close and I/O function pointers have lost their use, thus finally making the VFS device code actually readable; - the device-unrelated pm_setsid has been moved to misc.c; - some other small cleanup-related changes. Change-Id: If90b10d1818e98a12139da3e94a15d250c9933da
This commit is contained in:
parent
cf12dbac0d
commit
664b726cd3
25 changed files with 274 additions and 564 deletions
|
@ -5,7 +5,7 @@ service \- Manage an operating system service.
|
|||
.PP
|
||||
\fBservice [-b -c -n -p -r] (up|run|edit|update)\fR \fI<binary|self>\fR
|
||||
[\fB-args\fR \fI<args>\fR] [\fB-dev\fR \fI<special>\fR]
|
||||
[\fB-devstyle\fR \fI<style>\fR] [\fB-period\fR \fI<ticks>\fR]
|
||||
[\fB-period\fR \fI<ticks>\fR]
|
||||
[\fB-script\fR \fI<path>\fR] [\fB-label\fR \fI<name>\fR]
|
||||
[\fB-config\fR \fI<path>\fR] [\fB-state\fR \fI<state>\fR]
|
||||
[\fB-maxtime\fR \fI<time>\fR]
|
||||
|
@ -103,12 +103,6 @@ given by \fI<binary>\fR. The default is to use no arguments.
|
|||
specifies the device file to associate to the system service (used only for
|
||||
device drivers). The default is to associate no device file to the service.
|
||||
.TP
|
||||
.BI \-devstyle " <style>"
|
||||
specifies the device style to associate to the system service (used only for
|
||||
device drivers). The list of supported device styles is available in
|
||||
the header file \fB<minix/dmap.h>\fR.
|
||||
The default is to associate no device style (\fBSTYLE_NDEV\fR) to the service.
|
||||
.TP
|
||||
.BI \-period " <ticks>"
|
||||
specifies the period to use for the system service.
|
||||
When a period is specified, \fBRS\fR sends a ping request to
|
||||
|
@ -160,7 +154,7 @@ label \fI<name>\fR. This action can be used to dynamically update the
|
|||
properties of any system service, including those contained in the
|
||||
boot image (e.g. \fBVM\fR). There are a few exceptions to the properties
|
||||
that can be actually overridden dynamically. For example, the device file
|
||||
and the device style associated to the service will no be updated. This
|
||||
associated to the service will no be updated. This
|
||||
action takes the same options supported by the \fBup\fR action.
|
||||
.PP
|
||||
.SS
|
||||
|
|
|
@ -86,7 +86,6 @@ static char *known_requests[] = {
|
|||
#define ARG_ARGS "-args" /* list of arguments to be passed */
|
||||
#define ARG_DEV "-dev" /* major device number for drivers */
|
||||
#define ARG_MAJOR "-major" /* major number */
|
||||
#define ARG_DEVSTYLE "-devstyle" /* device style */
|
||||
#define ARG_PERIOD "-period" /* heartbeat period in ticks */
|
||||
#define ARG_SCRIPT "-script" /* name of the script to restart a
|
||||
* system service
|
||||
|
@ -113,7 +112,6 @@ static char *req_path_self = SELF_REQ_PATH;
|
|||
static char *req_args = "";
|
||||
static int req_major = 0;
|
||||
static int devman_id = 0;
|
||||
static int req_dev_style = STYLE_NDEV;
|
||||
static long req_period = 0;
|
||||
static char *req_script = NULL;
|
||||
static char *req_config = PATH_CONFIG;
|
||||
|
@ -131,9 +129,9 @@ static void print_usage(char *app_name, char *problem)
|
|||
fprintf(stderr, "Warning, %s\n", problem);
|
||||
fprintf(stderr, "Usage:\n");
|
||||
fprintf(stderr,
|
||||
" %s [%s %s %s %s] (up|run|edit|update) <binary|%s> [%s <args>] [%s <special>] [%s <style>] [%s <major_nr>] [%s <dev_id>] [%s <ticks>] [%s <path>] [%s <name>] [%s <path>] [%s <state>] [%s <time>]\n",
|
||||
" %s [%s %s %s %s] (up|run|edit|update) <binary|%s> [%s <args>] [%s <special>] [%s <major_nr>] [%s <dev_id>] [%s <ticks>] [%s <path>] [%s <name>] [%s <path>] [%s <state>] [%s <time>]\n",
|
||||
app_name, OPT_COPY, OPT_REUSE, OPT_NOBLOCK, OPT_REPLICA, SELF_BINARY,
|
||||
ARG_ARGS, ARG_DEV, ARG_DEVSTYLE, ARG_MAJOR, ARG_DEVMANID, ARG_PERIOD, ARG_SCRIPT,
|
||||
ARG_ARGS, ARG_DEV, ARG_MAJOR, ARG_DEVMANID, ARG_PERIOD, ARG_SCRIPT,
|
||||
ARG_LABELNAME, ARG_CONFIG, ARG_LU_STATE, ARG_LU_MAXTIME);
|
||||
fprintf(stderr, " %s down <label>\n", app_name);
|
||||
fprintf(stderr, " %s refresh <label>\n", app_name);
|
||||
|
@ -315,9 +313,6 @@ static int parse_arguments(int argc, char **argv, u32_t *rss_flags)
|
|||
exit(EINVAL);
|
||||
}
|
||||
req_major = major(stat_buf.st_rdev);
|
||||
if(req_dev_style == STYLE_NDEV) {
|
||||
req_dev_style = STYLE_DEV;
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i], ARG_MAJOR)==0) {
|
||||
if (req_major != 0) {
|
||||
|
@ -329,26 +324,7 @@ static int parse_arguments(int argc, char **argv, u32_t *rss_flags)
|
|||
} else {
|
||||
exit(EINVAL);
|
||||
}
|
||||
if(req_dev_style == STYLE_NDEV) {
|
||||
req_dev_style = STYLE_DEV;
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i], ARG_DEVSTYLE)==0) {
|
||||
char* dev_style_keys[] = { "STYLE_DEV", "STYLE_TTY",
|
||||
"STYLE_CTTY", NULL };
|
||||
int dev_style_values[] = { STYLE_DEV, STYLE_TTY,
|
||||
STYLE_CTTY };
|
||||
for(j=0;dev_style_keys[j]!=NULL;j++) {
|
||||
if(!strcmp(dev_style_keys[j], argv[i+1])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(dev_style_keys[j] == NULL) {
|
||||
print_usage(argv[ARG_NAME], "bad device style");
|
||||
exit(EINVAL);
|
||||
}
|
||||
req_dev_style = dev_style_values[j];
|
||||
}
|
||||
else if (strcmp(argv[i], ARG_SCRIPT)==0) {
|
||||
req_script = argv[i+1];
|
||||
}
|
||||
|
@ -466,7 +442,6 @@ int main(int argc, char **argv)
|
|||
config.rs_start.rss_cmd= command;
|
||||
config.rs_start.rss_cmdlen= strlen(command);
|
||||
config.rs_start.rss_major= req_major;
|
||||
config.rs_start.rss_dev_style= req_dev_style;
|
||||
config.rs_start.rss_period= req_period;
|
||||
config.rs_start.rss_script= req_script;
|
||||
config.rs_start.devman_id= devman_id;
|
||||
|
|
|
@ -40,7 +40,7 @@ int getprocnr(void);
|
|||
int getnprocnr(pid_t pid);
|
||||
int getpprocnr(void);
|
||||
int _pm_findproc(char *proc_name, int *proc_nr);
|
||||
int mapdriver(char *label, int major, int style, int flags);
|
||||
int mapdriver(char *label, int major);
|
||||
pid_t getnpid(endpoint_t proc_ep);
|
||||
uid_t getnuid(endpoint_t proc_ep);
|
||||
gid_t getngid(endpoint_t proc_ep);
|
||||
|
|
|
@ -149,9 +149,6 @@
|
|||
#define LU_SYS_PROC 0x400 /* this is a live updated sys proc instance */
|
||||
#define RST_SYS_PROC 0x800 /* this is a restarted sys proc instance */
|
||||
|
||||
/* Bits for device driver flags managed by RS and VFS. */
|
||||
#define DRV_FORCED 0x01 /* driver is mapped even if not alive yet */
|
||||
|
||||
/* Values for the "verbose" boot monitor variable */
|
||||
#define VERBOSEBOOT_QUIET 0
|
||||
#define VERBOSEBOOT_BASIC 1
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
#include <minix/sys_config.h>
|
||||
#include <minix/ipc.h>
|
||||
|
||||
enum dev_style { STYLE_NDEV, STYLE_DEV, STYLE_TTY, STYLE_CTTY };
|
||||
#define IS_DEV_STYLE(s) (s>=STYLE_NDEV && s<=STYLE_CTTY)
|
||||
|
||||
/*===========================================================================*
|
||||
* Major and minor device numbers *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -73,7 +73,6 @@ struct rs_start
|
|||
int rss_priority;
|
||||
int rss_quantum;
|
||||
int rss_major;
|
||||
int rss_dev_style;
|
||||
long rss_period;
|
||||
char *rss_script;
|
||||
size_t rss_scriptlen;
|
||||
|
@ -119,10 +118,7 @@ struct rprocpub {
|
|||
unsigned sys_flags; /* sys flags */
|
||||
endpoint_t endpoint; /* process endpoint number */
|
||||
|
||||
int dev_flags; /* device flags */
|
||||
dev_t dev_nr; /* major device number */
|
||||
int dev_style; /* device style */
|
||||
int dev_style2; /* device style for next major dev number */
|
||||
dev_t dev_nr; /* major device number or NO_DEV */
|
||||
|
||||
char label[RS_MAX_LABEL_LEN]; /* label of this service */
|
||||
char proc_name[RS_MAX_LABEL_LEN]; /* process name of this service */
|
||||
|
|
|
@ -3,18 +3,14 @@
|
|||
#include <unistd.h>
|
||||
|
||||
|
||||
int mapdriver(label, major, dev_style, flags)
|
||||
int mapdriver(label, major)
|
||||
char *label;
|
||||
int major;
|
||||
int dev_style;
|
||||
int flags;
|
||||
{
|
||||
message m;
|
||||
m.m2_p1 = label;
|
||||
m.m2_l1 = strlen(label);
|
||||
m.m2_i1 = major;
|
||||
m.m2_i2 = dev_style;
|
||||
m.m2_i3 = flags;
|
||||
if (_syscall(VFS_PROC_NR, MAPDRIVER, &m) < 0) return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
|
|
@ -58,30 +58,6 @@ void fproc_dmp()
|
|||
prev_i = i;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* dmap_flags *
|
||||
*===========================================================================*/
|
||||
static char * dmap_flags(int flags)
|
||||
{
|
||||
static char fl[10];
|
||||
strlcpy(fl, "-----", sizeof(fl));
|
||||
if(flags & DRV_FORCED) fl[0] = 'F';
|
||||
return fl;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* dmap_style *
|
||||
*===========================================================================*/
|
||||
static char * dmap_style(int dev_style)
|
||||
{
|
||||
switch(dev_style) {
|
||||
case STYLE_DEV: return "STYLE_DEV";
|
||||
case STYLE_TTY: return "STYLE_TTY";
|
||||
case STYLE_CTTY: return "STYLE_CTTY";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* dtab_dmp *
|
||||
*===========================================================================*/
|
||||
|
@ -95,13 +71,10 @@ void dtab_dmp()
|
|||
}
|
||||
|
||||
printf("File System (FS) device <-> driver mappings\n");
|
||||
printf(" Label Major Driver ept Flags Style \n");
|
||||
printf("------------- ----- ---------- ----- -------------\n");
|
||||
printf(" Label Major Driver ept\n");
|
||||
printf("------------- ----- ----------\n");
|
||||
for (i=0; i<NR_DEVICES; i++) {
|
||||
if (dmap[i].dmap_driver == NONE) continue;
|
||||
printf("%13s %5d %10d %s %-13s\n",
|
||||
dmap[i].dmap_label, i, dmap[i].dmap_driver,
|
||||
dmap_flags(dmap[i].dmap_flags), dmap_style(dmap[i].dmap_style));
|
||||
printf("%13s %5d %10d\n", dmap[i].dmap_label, i, dmap[i].dmap_driver);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,10 +42,10 @@ void rproc_dmp()
|
|||
rpub = &rprocpub[i];
|
||||
if (! (rp->r_flags & RS_IN_USE)) continue;
|
||||
if (++n > 22) break;
|
||||
printf("%13s %9d %5d %6s %3d/%1d %3ld %8lu %5dx %s",
|
||||
printf("%13s %9d %5d %6s %4d %4ld %8lu %5dx %s",
|
||||
rpub->label, rpub->endpoint, rp->r_pid,
|
||||
s_flags_str(rp->r_flags, rpub->sys_flags), rpub->dev_nr,
|
||||
rpub->dev_style, rp->r_period, rp->r_alive_tm, rp->r_restarts,
|
||||
rp->r_period, rp->r_alive_tm, rp->r_restarts,
|
||||
rp->r_args
|
||||
);
|
||||
printf("\n");
|
||||
|
|
|
@ -71,10 +71,6 @@
|
|||
#define DSRV_SF (0) /* dynamic system services */
|
||||
#define VM_SF (SRVR_SF) /* vm */
|
||||
|
||||
/* Define device flags for the various process types. */
|
||||
#define SRV_DF (DRV_FORCED) /* system services */
|
||||
#define DSRV_DF (SRV_DF) /* dynamic system services */
|
||||
|
||||
/* Shorthands. */
|
||||
#define SRV_OR_USR(rp, X, Y) (rp->r_priv.s_flags & SYS_PROC ? X : Y)
|
||||
|
||||
|
|
|
@ -299,10 +299,7 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
|||
/*
|
||||
* Set dev properties.
|
||||
*/
|
||||
rpub->dev_flags = boot_image_dev->flags; /* device flags */
|
||||
rpub->dev_nr = boot_image_dev->dev_nr; /* major device number */
|
||||
rpub->dev_style = boot_image_dev->dev_style; /* device style */
|
||||
rpub->dev_style2 = boot_image_dev->dev_style2; /* device style 2 */
|
||||
|
||||
/* Build command settings. This will also set the process name. */
|
||||
strlcpy(rp->r_cmd, ip->proc_name, sizeof(rp->r_cmd));
|
||||
|
|
|
@ -677,8 +677,7 @@ struct rproc *rp; /* pointer to service slot */
|
|||
*/
|
||||
setuid(0);
|
||||
|
||||
if (mapdriver(rpub->label, rpub->dev_nr, rpub->dev_style,
|
||||
rpub->dev_flags) != OK) {
|
||||
if (mapdriver(rpub->label, rpub->dev_nr) != OK) {
|
||||
return kill_service(rp, "couldn't map driver", errno);
|
||||
}
|
||||
}
|
||||
|
@ -1225,10 +1224,7 @@ struct rproc *rp;
|
|||
rpub = rp->r_pub;
|
||||
|
||||
/* Device and PCI settings. These properties cannot change. */
|
||||
rpub->dev_flags = def_rpub->dev_flags;
|
||||
rpub->dev_nr = def_rpub->dev_nr;
|
||||
rpub->dev_style = def_rpub->dev_style;
|
||||
rpub->dev_style2 = def_rpub->dev_style2;
|
||||
rpub->pci_acl = def_rpub->pci_acl;
|
||||
|
||||
/* Immutable system and privilege flags. */
|
||||
|
@ -1608,15 +1604,8 @@ endpoint_t source;
|
|||
rp->r_uid= rs_start->rss_uid;
|
||||
|
||||
/* Initialize device driver settings. */
|
||||
rpub->dev_flags = DSRV_DF;
|
||||
rpub->dev_nr = rs_start->rss_major;
|
||||
rpub->dev_style = rs_start->rss_dev_style;
|
||||
rpub->devman_id = rs_start->devman_id;
|
||||
if(rpub->dev_nr && !IS_DEV_STYLE(rs_start->rss_dev_style)) {
|
||||
printf("RS: init_slot: bad device style\n");
|
||||
return EINVAL;
|
||||
}
|
||||
rpub->dev_style2 = STYLE_NDEV;
|
||||
|
||||
/* Initialize pci settings. */
|
||||
if (rs_start->rss_nr_pci_id > RS_NR_PCI_DEVICE) {
|
||||
|
|
|
@ -42,11 +42,8 @@ struct boot_image_sys boot_image_sys_table[] = {
|
|||
|
||||
/* Definition of the boot image dev table. */
|
||||
struct boot_image_dev boot_image_dev_table[] = {
|
||||
/*endpoint, flags, dev_nr, dev_style, dev_style2 */
|
||||
{ TTY_PROC_NR, SRV_DF, TTY_MAJOR, STYLE_TTY, STYLE_CTTY },
|
||||
{ MEM_PROC_NR, SRV_DF, MEMORY_MAJOR, STYLE_DEV, STYLE_NDEV },
|
||||
{ DEFAULT_BOOT_NR, SRV_DF, 0, STYLE_NDEV, STYLE_NDEV } /* default
|
||||
* entry
|
||||
*/
|
||||
/*endpoint, dev_nr */
|
||||
{ TTY_PROC_NR, TTY_MAJOR },
|
||||
{ MEM_PROC_NR, MEMORY_MAJOR },
|
||||
{ DEFAULT_BOOT_NR, 0 } /* default entry */
|
||||
};
|
||||
|
||||
|
|
|
@ -22,10 +22,7 @@ struct boot_image_sys {
|
|||
struct boot_image_dev {
|
||||
endpoint_t endpoint; /* process endpoint number */
|
||||
|
||||
int flags; /* device flags */
|
||||
dev_t dev_nr; /* major device number */
|
||||
int dev_style; /* device style */
|
||||
int dev_style2; /* device style for next major device number */
|
||||
};
|
||||
|
||||
/* Definition of an entry of the system process table. */
|
||||
|
|
|
@ -135,11 +135,11 @@ struct rproc *rp; /* pointer to process slot */
|
|||
((rp)->r_old_rp || (rp)->r_prev_rp ? "+" : " "))
|
||||
|
||||
#if DEBUG
|
||||
sprintf(srv_string, "service '%s'%s%s(slot %d, ep %d, pid %d, cmd %s, script %s, proc %s, major %d, style %d, flags 0x%03x, sys_flags 0x%02x)",
|
||||
sprintf(srv_string, "service '%s'%s%s(slot %d, ep %d, pid %d, cmd %s, script %s, proc %s, major %d, flags 0x%03x, sys_flags 0x%02x)",
|
||||
rpub->label, srv_active_str(rp), srv_version_str(rp),
|
||||
slot_nr, rpub->endpoint, rp->r_pid, srv_str(rp->r_cmd),
|
||||
srv_str(rp->r_script), srv_str(rpub->proc_name), rpub->dev_nr,
|
||||
rpub->dev_style, rp->r_flags, rpub->sys_flags);
|
||||
rp->r_flags, rpub->sys_flags);
|
||||
#else
|
||||
sprintf(srv_string, "service '%s'%s%s(slot %d, ep %d, pid %d)",
|
||||
rpub->label, srv_active_str(rp), srv_version_str(rp),
|
||||
|
|
|
@ -89,6 +89,16 @@ int drv_sendrec(endpoint_t drv_e, message *reqmp)
|
|||
int r;
|
||||
struct dmap *dp;
|
||||
|
||||
/* For the CTTY_MAJOR case, we would actually have to lock the device
|
||||
* entry being redirected to. However, the CTTY major only hosts a
|
||||
* character device while this function is used only for block devices.
|
||||
* Thus, we can simply deny the request immediately.
|
||||
*/
|
||||
if (drv_e == CTTY_ENDPT) {
|
||||
printf("VFS: /dev/tty is not a block device!\n");
|
||||
return EIO;
|
||||
}
|
||||
|
||||
if ((dp = get_dmap(drv_e)) == NULL)
|
||||
panic("driver endpoint %d invalid", drv_e);
|
||||
|
||||
|
|
|
@ -42,4 +42,7 @@
|
|||
#define SEL_ERR CDEV_OP_ERR
|
||||
#define SEL_NOTIFY CDEV_NOTIFY /* not a real select operation */
|
||||
|
||||
/* special driver endpoint for CTTY_MAJOR; must be able to pass isokendpt() */
|
||||
#define CTTY_ENDPT VFS_PROC_NR
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,14 +12,6 @@
|
|||
* bdev_close: close a block device
|
||||
* bdev_reply: process the result of a block driver request
|
||||
* bdev_up: a block driver has been mapped in
|
||||
* gen_opcl: generic call to a character driver to perform an open/close
|
||||
* gen_io: generic call to a character driver to initiate I/O
|
||||
* no_dev: open/close processing for devices that don't exist
|
||||
* no_dev_io: i/o processing for devices that don't exist
|
||||
* tty_opcl: perform tty-specific processing for open/close
|
||||
* ctty_opcl: perform controlling-tty-specific processing for open/close
|
||||
* ctty_io: perform controlling-tty-specific processing for I/O
|
||||
* pm_setsid: perform VFS's side of setsid system call
|
||||
* do_ioctl: perform the IOCTL system call
|
||||
*/
|
||||
|
||||
|
@ -41,49 +33,11 @@
|
|||
#include "vmnt.h"
|
||||
#include "param.h"
|
||||
|
||||
static int cdev_opcl(int op, dev_t dev, int flags);
|
||||
static int block_io(endpoint_t driver_e, message *mess_ptr);
|
||||
static cp_grant_id_t make_grant(endpoint_t driver_e, endpoint_t user_e, int op,
|
||||
void *buf, unsigned long size);
|
||||
|
||||
/*===========================================================================*
|
||||
* cdev_open *
|
||||
*===========================================================================*/
|
||||
int cdev_open(dev_t dev, int flags)
|
||||
{
|
||||
/* Open a character device. */
|
||||
devmajor_t major_dev;
|
||||
int r;
|
||||
|
||||
/* Determine the major device number so as to call the device class specific
|
||||
* open/close routine. (This is the only routine that must check the
|
||||
* device number for being in range. All others can trust this check.)
|
||||
*/
|
||||
major_dev = major(dev);
|
||||
if (major_dev < 0 || major_dev >= NR_DEVICES) return(ENXIO);
|
||||
if (dmap[major_dev].dmap_driver == NONE) return(ENXIO);
|
||||
r = (*dmap[major_dev].dmap_opcl)(CDEV_OPEN, dev, fp->fp_endpoint, flags);
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* cdev_close *
|
||||
*===========================================================================*/
|
||||
int cdev_close(dev_t dev)
|
||||
{
|
||||
/* Close a character device. */
|
||||
devmajor_t major_dev;
|
||||
int r;
|
||||
|
||||
/* See if driver is roughly valid. */
|
||||
major_dev = major(dev);
|
||||
if (major_dev < 0 || major_dev >= NR_DEVICES) return(ENXIO);
|
||||
if (dmap[major_dev].dmap_driver == NONE) return(ENXIO);
|
||||
r = (*dmap[major_dev].dmap_opcl)(CDEV_CLOSE, dev, fp->fp_endpoint, 0);
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* bdev_open *
|
||||
*===========================================================================*/
|
||||
|
@ -158,6 +112,7 @@ static int bdev_ioctl(dev_t dev, endpoint_t proc_e, unsigned long req,
|
|||
message dev_mess;
|
||||
devmajor_t major_dev;
|
||||
devminor_t minor_dev;
|
||||
int r;
|
||||
|
||||
major_dev = major(dev);
|
||||
minor_dev = minor(dev);
|
||||
|
@ -183,17 +138,15 @@ static int bdev_ioctl(dev_t dev, endpoint_t proc_e, unsigned long req,
|
|||
dev_mess.BDEV_ID = 0;
|
||||
|
||||
/* Call the task. */
|
||||
block_io(dp->dmap_driver, &dev_mess);
|
||||
r = block_io(dp->dmap_driver, &dev_mess);
|
||||
|
||||
/* Clean up. */
|
||||
if (GRANT_VALID(gid)) cpf_revoke(gid);
|
||||
|
||||
if (dp->dmap_driver == NONE) {
|
||||
printf("VFS: block driver gone!?\n");
|
||||
return(EIO);
|
||||
}
|
||||
|
||||
/* Return the result. */
|
||||
if (r != OK)
|
||||
return(r);
|
||||
|
||||
return(dev_mess.BDEV_STATUS);
|
||||
}
|
||||
|
||||
|
@ -246,6 +199,48 @@ static cp_grant_id_t make_grant(endpoint_t driver_e, endpoint_t user_e, int op,
|
|||
return gid;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* cdev_get *
|
||||
*===========================================================================*/
|
||||
static struct dmap *cdev_get(dev_t dev, devminor_t *minor_dev)
|
||||
{
|
||||
/* Obtain the dmap structure for the given device, if a valid driver exists for
|
||||
* the major device. Perform redirection for CTTY_MAJOR.
|
||||
*/
|
||||
devmajor_t major_dev;
|
||||
struct dmap *dp;
|
||||
int slot;
|
||||
|
||||
/* First cover one special case: /dev/tty, the magic device that translates
|
||||
* to the controlling tty.
|
||||
*/
|
||||
if (major(dev) == CTTY_MAJOR) {
|
||||
/* No controlling terminal? Fail the request. */
|
||||
if (fp->fp_tty == 0) return(NULL);
|
||||
|
||||
/* Substitute the controlling terminal device. */
|
||||
dev = fp->fp_tty;
|
||||
}
|
||||
|
||||
/* Determine task dmap. */
|
||||
major_dev = major(dev);
|
||||
if (major_dev < 0 || major_dev >= NR_DEVICES) return(NULL);
|
||||
|
||||
dp = &dmap[major_dev];
|
||||
|
||||
/* See if driver is roughly valid. */
|
||||
if (dp->dmap_driver == NONE) return(NULL);
|
||||
|
||||
if (isokendpt(dp->dmap_driver, &slot) != OK) {
|
||||
printf("VFS: cdev_get: old driver for major %x (%d)\n", major_dev,
|
||||
dp->dmap_driver);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Also return the (possibly redirected) minor number. */
|
||||
*minor_dev = minor(dev);
|
||||
return dp;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* cdev_io *
|
||||
|
@ -261,28 +256,17 @@ int cdev_io(
|
|||
)
|
||||
{
|
||||
/* Initiate a read, write, or ioctl to a character device. */
|
||||
devminor_t minor_dev;
|
||||
struct dmap *dp;
|
||||
message dev_mess;
|
||||
cp_grant_id_t gid;
|
||||
devmajor_t major_dev;
|
||||
devminor_t minor_dev;
|
||||
int r, slot;
|
||||
int r;
|
||||
|
||||
assert(op == CDEV_READ || op == CDEV_WRITE || op == CDEV_IOCTL);
|
||||
|
||||
/* Determine task dmap. */
|
||||
major_dev = major(dev);
|
||||
minor_dev = minor(dev);
|
||||
dp = &dmap[major_dev];
|
||||
|
||||
/* See if driver is roughly valid. */
|
||||
if (dp->dmap_driver == NONE) return(ENXIO);
|
||||
|
||||
if(isokendpt(dp->dmap_driver, &slot) != OK) {
|
||||
printf("VFS: dev_io: old driver for major %x (%d)\n", major_dev,
|
||||
dp->dmap_driver);
|
||||
return(ENXIO);
|
||||
}
|
||||
/* Determine task map. */
|
||||
if ((dp = cdev_get(dev, &minor_dev)) == NULL)
|
||||
return(EIO);
|
||||
|
||||
/* Create a grant for the buffer provided by the user process. */
|
||||
gid = make_grant(dp->dmap_driver, proc_e, op, buf, bytes);
|
||||
|
@ -306,13 +290,8 @@ int cdev_io(
|
|||
dev_mess.CDEV_FLAGS |= CDEV_NONBLOCK;
|
||||
|
||||
/* Send the request to the driver. */
|
||||
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
|
||||
|
||||
if (r != OK) {
|
||||
cpf_revoke(gid);
|
||||
|
||||
return r;
|
||||
}
|
||||
if ((r = asynsend3(dp->dmap_driver, &dev_mess, AMF_NOREPLY)) != OK)
|
||||
panic("VFS: asynsend in cdev_io failed: %d", r);
|
||||
|
||||
/* Suspend the calling process until a reply arrives. */
|
||||
wait_for(dp->dmap_driver);
|
||||
|
@ -324,9 +303,9 @@ int cdev_io(
|
|||
|
||||
|
||||
/*===========================================================================*
|
||||
* clone_cdev *
|
||||
* cdev_clone *
|
||||
*===========================================================================*/
|
||||
static int cdev_clone(dev_t dev, endpoint_t proc_e, devminor_t new_minor)
|
||||
static int cdev_clone(dev_t dev, devminor_t new_minor)
|
||||
{
|
||||
/* A new minor device number has been returned. Request PFS to create a
|
||||
* temporary device file to hold it.
|
||||
|
@ -335,8 +314,6 @@ static int cdev_clone(dev_t dev, endpoint_t proc_e, devminor_t new_minor)
|
|||
struct node_details res;
|
||||
int r;
|
||||
|
||||
assert(proc_e == fp->fp_endpoint);
|
||||
|
||||
/* Device number of the new device. */
|
||||
dev = makedev(major(dev), new_minor);
|
||||
|
||||
|
@ -344,14 +321,14 @@ static int cdev_clone(dev_t dev, endpoint_t proc_e, devminor_t new_minor)
|
|||
r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid,
|
||||
ALL_MODES | I_CHAR_SPECIAL, dev, &res);
|
||||
if (r != OK) {
|
||||
(void) gen_opcl(CDEV_CLOSE, dev, proc_e, 0);
|
||||
(void) cdev_opcl(CDEV_CLOSE, dev, 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Drop old node and use the new values */
|
||||
if ((vp = get_free_vnode()) == NULL) {
|
||||
req_putnode(PFS_PROC_NR, res.inode_nr, 1); /* is this right? */
|
||||
(void) gen_opcl(CDEV_CLOSE, dev, proc_e, 0);
|
||||
(void) cdev_opcl(CDEV_CLOSE, dev, 0);
|
||||
return(err_code);
|
||||
}
|
||||
lock_vnode(vp, VNODE_OPCL);
|
||||
|
@ -376,49 +353,63 @@ static int cdev_clone(dev_t dev, endpoint_t proc_e, devminor_t new_minor)
|
|||
|
||||
|
||||
/*===========================================================================*
|
||||
* gen_opcl *
|
||||
* cdev_opcl *
|
||||
*===========================================================================*/
|
||||
int gen_opcl(
|
||||
static int cdev_opcl(
|
||||
int op, /* operation, CDEV_OPEN or CDEV_CLOSE */
|
||||
dev_t dev, /* device to open or close */
|
||||
endpoint_t proc_e, /* process to open/close for */
|
||||
int flags /* mode bits and flags */
|
||||
)
|
||||
{
|
||||
/* Called from the dmap struct on opens & closes of special files.*/
|
||||
devmajor_t major_dev;
|
||||
/* Open or close a character device. */
|
||||
devminor_t minor_dev, new_minor;
|
||||
struct dmap *dp;
|
||||
struct fproc *rfp;
|
||||
message dev_mess;
|
||||
int r, r2;
|
||||
|
||||
/* Determine task dmap. */
|
||||
major_dev = major(dev);
|
||||
minor_dev = minor(dev);
|
||||
assert(major_dev >= 0 && major_dev < NR_DEVICES);
|
||||
dp = &dmap[major_dev];
|
||||
assert(dp->dmap_driver != NONE);
|
||||
assert(op == CDEV_OPEN || op == CDEV_CLOSE);
|
||||
|
||||
assert(!IS_BDEV_RQ(op));
|
||||
/* Determine task dmap. */
|
||||
if ((dp = cdev_get(dev, &minor_dev)) == NULL)
|
||||
return(ENXIO);
|
||||
|
||||
/* CTTY exception: do not actually send the open/close request for /dev/tty
|
||||
* to the driver. This avoids the case that the actual device will remain
|
||||
* open forever if the process calls setsid() after opening /dev/tty.
|
||||
*/
|
||||
if (major(dev) == CTTY_MAJOR) return(OK);
|
||||
|
||||
/* Add O_NOCTTY to the access flags if this process is not a session leader,
|
||||
* or if it already has a controlling tty, or if it is someone else's
|
||||
* controlling tty. For performance reasons, only search the full process
|
||||
* table if this driver has set controlling ttys before.
|
||||
*/
|
||||
if (!(fp->fp_flags & FP_SESLDR) || fp->fp_tty != 0) {
|
||||
flags |= O_NOCTTY;
|
||||
} else if (!(flags & O_NOCTTY) && dp->dmap_seen_tty) {
|
||||
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++)
|
||||
if (rfp->fp_pid != PID_FREE && rfp->fp_tty == dev)
|
||||
flags |= O_NOCTTY;
|
||||
}
|
||||
|
||||
/* Prepare the request message. */
|
||||
memset(&dev_mess, 0, sizeof(dev_mess));
|
||||
|
||||
dev_mess.m_type = op;
|
||||
dev_mess.CDEV_MINOR = minor_dev;
|
||||
dev_mess.CDEV_ID = proc_e;
|
||||
dev_mess.CDEV_ID = who_e;
|
||||
if (op == CDEV_OPEN) {
|
||||
dev_mess.CDEV_USER = proc_e;
|
||||
dev_mess.CDEV_USER = who_e;
|
||||
dev_mess.CDEV_ACCESS = 0;
|
||||
if (flags & R_BIT) dev_mess.CDEV_ACCESS |= CDEV_R_BIT;
|
||||
if (flags & W_BIT) dev_mess.CDEV_ACCESS |= CDEV_W_BIT;
|
||||
if (flags & O_NOCTTY) dev_mess.CDEV_ACCESS |= CDEV_NOCTTY;
|
||||
}
|
||||
|
||||
/* Call the task. */
|
||||
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
|
||||
|
||||
if (r != OK) return(r);
|
||||
/* Send the request to the driver. */
|
||||
if ((r = asynsend3(dp->dmap_driver, &dev_mess, AMF_NOREPLY)) != OK)
|
||||
panic("VFS: asynsend in cdev_opcl failed: %d", r);
|
||||
|
||||
/* Block the thread waiting for a reply. */
|
||||
fp->fp_task = dp->dmap_driver;
|
||||
|
@ -430,106 +421,55 @@ int gen_opcl(
|
|||
self->w_task = NONE;
|
||||
self->w_drv_sendrec = NULL;
|
||||
|
||||
/* Process the reply. */
|
||||
r = dev_mess.CDEV_STATUS;
|
||||
|
||||
/* Some devices need special processing upon open. Such a device is "cloned",
|
||||
* i.e. on a succesful open it is replaced by a new device with a new unique
|
||||
* minor device number. This new device number identifies a new object (such
|
||||
* as a new network connection) that has been allocated within a task.
|
||||
*/
|
||||
if (op == CDEV_OPEN && r >= 0) {
|
||||
/* Some devices need special processing upon open. Such a device is
|
||||
* "cloned", i.e. on a succesful open it is replaced by a new device
|
||||
* with a new unique minor device number. This new device number
|
||||
* identifies a new object (such as a new network connection) that has
|
||||
* been allocated within a driver.
|
||||
*/
|
||||
if (r & CDEV_CLONED) {
|
||||
new_minor = r & ~(CDEV_CLONED | CDEV_CTTY);
|
||||
r &= CDEV_CTTY;
|
||||
if ((r2 = cdev_clone(dev, proc_e, new_minor)) < 0)
|
||||
r = r2;
|
||||
} else
|
||||
r &= CDEV_CTTY;
|
||||
/* Upon success, we now return either OK or CDEV_CTTY. */
|
||||
if ((r2 = cdev_clone(dev, new_minor)) < 0)
|
||||
return(r2);
|
||||
}
|
||||
|
||||
/* Did this call make the tty the controlling tty? */
|
||||
if (r & CDEV_CTTY) {
|
||||
fp->fp_tty = dev;
|
||||
dp->dmap_seen_tty = TRUE;
|
||||
}
|
||||
|
||||
r = OK;
|
||||
}
|
||||
|
||||
/* Return the result from the driver. */
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* tty_opcl *
|
||||
* cdev_open *
|
||||
*===========================================================================*/
|
||||
int tty_opcl(
|
||||
int op, /* operation, CDEV_OPEN or CDEV_CLOSE */
|
||||
dev_t dev, /* device to open or close */
|
||||
endpoint_t proc_e, /* process to open/close for */
|
||||
int flags /* mode bits and flags */
|
||||
)
|
||||
int cdev_open(dev_t dev, int flags)
|
||||
{
|
||||
/* This procedure is called from the dmap struct on tty open/close. */
|
||||
int r;
|
||||
register struct fproc *rfp;
|
||||
/* Open a character device. */
|
||||
|
||||
assert(!IS_BDEV_RQ(op));
|
||||
|
||||
/* Add O_NOCTTY to the flags if this process is not a session leader, or
|
||||
* if it already has a controlling tty, or if it is someone elses
|
||||
* controlling tty.
|
||||
*/
|
||||
if (!(fp->fp_flags & FP_SESLDR) || fp->fp_tty != 0) {
|
||||
flags |= O_NOCTTY;
|
||||
} else {
|
||||
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
|
||||
if(rfp->fp_pid == PID_FREE) continue;
|
||||
if (rfp->fp_tty == dev) flags |= O_NOCTTY;
|
||||
}
|
||||
}
|
||||
|
||||
r = gen_opcl(op, dev, proc_e, flags);
|
||||
|
||||
/* Did this call make the tty the controlling tty? */
|
||||
if (r >= 0 && (r & CDEV_CTTY)) {
|
||||
fp->fp_tty = dev;
|
||||
r = OK;
|
||||
}
|
||||
|
||||
return(r);
|
||||
return cdev_opcl(CDEV_OPEN, dev, flags);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* ctty_opcl *
|
||||
* cdev_close *
|
||||
*===========================================================================*/
|
||||
int ctty_opcl(
|
||||
int op, /* operation, CDEV_OPEN or CDEV_CLOSE */
|
||||
dev_t UNUSED(dev), /* device to open or close */
|
||||
endpoint_t UNUSED(proc_e), /* process to open/close for */
|
||||
int UNUSED(flags) /* mode bits and flags */
|
||||
)
|
||||
int cdev_close(dev_t dev)
|
||||
{
|
||||
/* This procedure is called from the dmap struct on opening or closing
|
||||
* /dev/tty, the magic device that translates to the controlling tty.
|
||||
*/
|
||||
/* Close a character device. */
|
||||
|
||||
if (IS_BDEV_RQ(op))
|
||||
panic("ctty_opcl() called for block device request?");
|
||||
|
||||
return(fp->fp_tty == 0 ? ENXIO : OK);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* pm_setsid *
|
||||
*===========================================================================*/
|
||||
void pm_setsid(endpoint_t proc_e)
|
||||
{
|
||||
/* Perform the VFS side of the SETSID call, i.e. get rid of the controlling
|
||||
* terminal of a process, and make the process a session leader.
|
||||
*/
|
||||
register struct fproc *rfp;
|
||||
int slot;
|
||||
|
||||
/* Make the process a session leader with no controlling tty. */
|
||||
okendpt(proc_e, &slot);
|
||||
rfp = &fproc[slot];
|
||||
rfp->fp_flags |= FP_SESLDR;
|
||||
rfp->fp_tty = 0;
|
||||
return cdev_opcl(CDEV_CLOSE, dev, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -583,25 +523,27 @@ int do_ioctl(message *UNUSED(m_out))
|
|||
int cdev_select(dev_t dev, int ops)
|
||||
{
|
||||
/* Initiate a select call on a device. Return OK iff the request was sent. */
|
||||
devmajor_t major_dev;
|
||||
devminor_t minor_dev;
|
||||
message dev_mess;
|
||||
struct dmap *dp;
|
||||
int r;
|
||||
|
||||
major_dev = major(dev);
|
||||
minor_dev = minor(dev);
|
||||
dp = &dmap[major_dev];
|
||||
|
||||
if (dp->dmap_driver == NONE) return ENXIO;
|
||||
/* Determine task dmap. */
|
||||
if ((dp = cdev_get(dev, &minor_dev)) == NULL)
|
||||
return(EIO);
|
||||
|
||||
/* Prepare the request message. */
|
||||
memset(&dev_mess, 0, sizeof(dev_mess));
|
||||
|
||||
dev_mess.m_type = CDEV_SELECT;
|
||||
dev_mess.CDEV_MINOR = minor_dev;
|
||||
dev_mess.CDEV_OPS = ops;
|
||||
|
||||
/* Call the task. */
|
||||
return (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
|
||||
/* Send the request to the driver. */
|
||||
if ((r = asynsend3(dp->dmap_driver, &dev_mess, AMF_NOREPLY)) != OK)
|
||||
panic("VFS: asynsend in cdev_select failed: %d", r);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
|
@ -611,24 +553,25 @@ int cdev_select(dev_t dev, int ops)
|
|||
int cdev_cancel(dev_t dev)
|
||||
{
|
||||
/* Cancel an I/O request, blocking until it has been cancelled. */
|
||||
devmajor_t major_dev;
|
||||
devminor_t minor_dev;
|
||||
message dev_mess;
|
||||
struct dmap *dp;
|
||||
int r;
|
||||
|
||||
major_dev = major(dev);
|
||||
minor_dev = minor(dev);
|
||||
dp = &dmap[major_dev];
|
||||
/* Determine task dmap. */
|
||||
if ((dp = cdev_get(dev, &minor_dev)) == NULL)
|
||||
return(EIO);
|
||||
|
||||
/* Prepare the request message. */
|
||||
memset(&dev_mess, 0, sizeof(dev_mess));
|
||||
|
||||
dev_mess.m_type = CDEV_CANCEL;
|
||||
dev_mess.CDEV_MINOR = minor_dev;
|
||||
dev_mess.CDEV_ID = fp->fp_endpoint;
|
||||
|
||||
r = (*dp->dmap_io)(fp->fp_task, &dev_mess);
|
||||
if (r != OK) return r; /* ctty_io returned an error? should be impossible */
|
||||
/* Send the request to the driver. */
|
||||
if ((r = asynsend3(dp->dmap_driver, &dev_mess, AMF_NOREPLY)) != OK)
|
||||
panic("VFS: asynsend in cdev_cancel failed: %d", r);
|
||||
|
||||
/* Suspend this thread until we have received the response. */
|
||||
fp->fp_task = dp->dmap_driver;
|
||||
|
@ -668,30 +611,29 @@ static int block_io(endpoint_t driver_e, message *mess_ptr)
|
|||
|
||||
do {
|
||||
r = drv_sendrec(driver_e, mess_ptr);
|
||||
if (r == OK) {
|
||||
status = mess_ptr->BDEV_STATUS;
|
||||
if (status == ERESTART) {
|
||||
r = EDEADEPT;
|
||||
*mess_ptr = mess_retry;
|
||||
retry_count++;
|
||||
}
|
||||
if (r != OK)
|
||||
return r;
|
||||
|
||||
status = mess_ptr->BDEV_STATUS;
|
||||
if (status == ERESTART) {
|
||||
r = EDEADEPT;
|
||||
*mess_ptr = mess_retry;
|
||||
retry_count++;
|
||||
}
|
||||
} while (status == ERESTART && retry_count < 5);
|
||||
|
||||
/* If we failed to restart the request, return EIO */
|
||||
if (status == ERESTART && retry_count >= 5) {
|
||||
r = OK;
|
||||
mess_ptr->m_type = EIO;
|
||||
}
|
||||
if (status == ERESTART && retry_count >= 5)
|
||||
return EIO;
|
||||
|
||||
if (r != OK) {
|
||||
if (r == EDEADSRCDST || r == EDEADEPT) {
|
||||
printf("VFS: dead driver %d\n", driver_e);
|
||||
dmap_unmap_by_endpt(driver_e);
|
||||
return(r);
|
||||
return(EIO);
|
||||
} else if (r == ELOCKED) {
|
||||
printf("VFS: ELOCKED talking to %d\n", driver_e);
|
||||
return(r);
|
||||
return(EIO);
|
||||
}
|
||||
panic("block_io: can't send/receive: %d", r);
|
||||
}
|
||||
|
@ -700,87 +642,6 @@ static int block_io(endpoint_t driver_e, message *mess_ptr)
|
|||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* gen_io *
|
||||
*===========================================================================*/
|
||||
int gen_io(endpoint_t drv_e, message *mess_ptr)
|
||||
{
|
||||
/* Initiate I/O to a character driver. Do not wait for the reply. */
|
||||
int r;
|
||||
|
||||
assert(!IS_BDEV_RQ(mess_ptr->m_type));
|
||||
|
||||
r = asynsend3(drv_e, mess_ptr, AMF_NOREPLY);
|
||||
|
||||
if (r != OK) panic("VFS: asynsend in gen_io failed: %d", r);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* ctty_io *
|
||||
*===========================================================================*/
|
||||
int ctty_io(
|
||||
endpoint_t UNUSED(task_nr), /* not used - for compatibility with dmap_t */
|
||||
message *mess_ptr /* pointer to message for task */
|
||||
)
|
||||
{
|
||||
/* This routine is only called for one device, namely /dev/tty. Its job
|
||||
* is to change the message to use the controlling terminal, instead of the
|
||||
* major/minor pair for /dev/tty itself.
|
||||
*/
|
||||
struct dmap *dp;
|
||||
int slot;
|
||||
|
||||
if (fp->fp_tty == 0) {
|
||||
/* No controlling tty present anymore, return an I/O error. */
|
||||
return(EIO);
|
||||
} else {
|
||||
/* Substitute the controlling terminal device. */
|
||||
dp = &dmap[major(fp->fp_tty)];
|
||||
mess_ptr->CDEV_MINOR = minor(fp->fp_tty);
|
||||
|
||||
if (dp->dmap_driver == NONE) {
|
||||
printf("FS: ctty_io: no driver for dev\n");
|
||||
return(EIO);
|
||||
}
|
||||
|
||||
if (isokendpt(dp->dmap_driver, &slot) != OK) {
|
||||
printf("VFS: ctty_io: old driver %d\n", dp->dmap_driver);
|
||||
return(EIO);
|
||||
}
|
||||
|
||||
return (*dp->dmap_io)(dp->dmap_driver, mess_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* no_dev *
|
||||
*===========================================================================*/
|
||||
int no_dev(
|
||||
int UNUSED(op), /* operation, CDEV_OPEN or CDEV_CLOSE */
|
||||
dev_t UNUSED(dev), /* device to open or close */
|
||||
endpoint_t UNUSED(proc), /* process to open/close for */
|
||||
int UNUSED(flags) /* mode bits and flags */
|
||||
)
|
||||
{
|
||||
/* Called when opening a nonexistent device. */
|
||||
return(ENODEV);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* no_dev_io *
|
||||
*===========================================================================*/
|
||||
int no_dev_io(endpoint_t UNUSED(proc), message *UNUSED(m))
|
||||
{
|
||||
/* Called when doing i/o on a nonexistent device. */
|
||||
printf("VFS: I/O on unmapped device number\n");
|
||||
return(EIO);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* bdev_up *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -36,7 +36,7 @@ void lock_dmap(struct dmap *dp)
|
|||
|
||||
org_self = worker_suspend();
|
||||
|
||||
if ((r = mutex_lock(dp->dmap_lock_ref)) != 0)
|
||||
if ((r = mutex_lock(&dp->dmap_lock)) != 0)
|
||||
panic("unable to get a lock on dmap: %d\n", r);
|
||||
|
||||
worker_resume(org_self);
|
||||
|
@ -52,10 +52,57 @@ void unlock_dmap(struct dmap *dp)
|
|||
|
||||
assert(dp != NULL);
|
||||
|
||||
if ((r = mutex_unlock(dp->dmap_lock_ref)) != 0)
|
||||
if ((r = mutex_unlock(&dp->dmap_lock)) != 0)
|
||||
panic("unable to unlock dmap lock: %d\n", r);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* map_driver *
|
||||
*===========================================================================*/
|
||||
static int map_driver(label, major, proc_nr_e)
|
||||
const char label[LABEL_MAX]; /* name of the driver */
|
||||
int major; /* major number of the device */
|
||||
endpoint_t proc_nr_e; /* process number of the driver */
|
||||
{
|
||||
/* Add a new device driver mapping in the dmap table. If the proc_nr is set to
|
||||
* NONE, we're supposed to unmap it.
|
||||
*/
|
||||
size_t len;
|
||||
struct dmap *dp;
|
||||
|
||||
/* Get pointer to device entry in the dmap table. */
|
||||
if (major < 0 || major >= NR_DEVICES) return(ENODEV);
|
||||
dp = &dmap[major];
|
||||
|
||||
/* Check if we're supposed to unmap it. */
|
||||
if (proc_nr_e == NONE) {
|
||||
/* Even when a driver is now unmapped and is shortly to be mapped in
|
||||
* due to recovery, invalidate associated filps if they're character
|
||||
* special files. More sophisticated recovery mechanisms which would
|
||||
* reduce the need to invalidate files are possible, but would require
|
||||
* cooperation of the driver and more recovery framework between RS,
|
||||
* VFS, and DS.
|
||||
*/
|
||||
invalidate_filp_by_char_major(major);
|
||||
dp->dmap_driver = NONE;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
if (label != NULL) {
|
||||
len = strlen(label);
|
||||
if (len+1 > sizeof(dp->dmap_label)) {
|
||||
printf("VFS: map_driver: label too long: %d\n", len);
|
||||
return(EINVAL);
|
||||
}
|
||||
strlcpy(dp->dmap_label, label, sizeof(dp->dmap_label));
|
||||
}
|
||||
|
||||
/* Store driver I/O routines based on type of device */
|
||||
dp->dmap_driver = proc_nr_e;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_mapdriver *
|
||||
*===========================================================================*/
|
||||
|
@ -66,7 +113,7 @@ int do_mapdriver(message *UNUSED(m_out))
|
|||
* etc), and its label. This label is registered with DS, and allows us to
|
||||
* retrieve the driver's endpoint.
|
||||
*/
|
||||
int r, flags, major, style, slot;
|
||||
int r, major, slot;
|
||||
endpoint_t endpoint;
|
||||
vir_bytes label_vir;
|
||||
size_t label_len;
|
||||
|
@ -79,8 +126,6 @@ int do_mapdriver(message *UNUSED(m_out))
|
|||
label_vir = (vir_bytes) job_m_in.md_label;
|
||||
label_len = (size_t) job_m_in.md_label_len;
|
||||
major = job_m_in.md_major;
|
||||
flags = job_m_in.md_flags;
|
||||
style = job_m_in.md_style;
|
||||
|
||||
/* Get the label */
|
||||
if (label_len+1 > sizeof(label)) { /* Can we store this label? */
|
||||
|
@ -110,88 +155,7 @@ int do_mapdriver(message *UNUSED(m_out))
|
|||
rfp->fp_flags |= FP_SRV_PROC;
|
||||
|
||||
/* Try to update device mapping. */
|
||||
return map_driver(label, major, endpoint, style, flags);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* map_driver *
|
||||
*===========================================================================*/
|
||||
int map_driver(label, major, proc_nr_e, style, flags)
|
||||
const char label[LABEL_MAX]; /* name of the driver */
|
||||
int major; /* major number of the device */
|
||||
endpoint_t proc_nr_e; /* process number of the driver */
|
||||
int style; /* style of the device */
|
||||
int flags; /* device flags */
|
||||
{
|
||||
/* Add a new device driver mapping in the dmap table. If the proc_nr is set to
|
||||
* NONE, we're supposed to unmap it.
|
||||
*/
|
||||
|
||||
int slot, s;
|
||||
size_t len;
|
||||
struct dmap *dp;
|
||||
|
||||
/* Get pointer to device entry in the dmap table. */
|
||||
if (major < 0 || major >= NR_DEVICES) return(ENODEV);
|
||||
dp = &dmap[major];
|
||||
|
||||
/* Check if we're supposed to unmap it. */
|
||||
if (proc_nr_e == NONE) {
|
||||
/* Even when a driver is now unmapped and is shortly to be mapped in
|
||||
* due to recovery, invalidate associated filps if they're character
|
||||
* special files. More sophisticated recovery mechanisms which would
|
||||
* reduce the need to invalidate files are possible, but would require
|
||||
* cooperation of the driver and more recovery framework between RS,
|
||||
* VFS, and DS.
|
||||
*/
|
||||
invalidate_filp_by_char_major(major);
|
||||
dp->dmap_opcl = no_dev;
|
||||
dp->dmap_io = no_dev_io;
|
||||
dp->dmap_driver = NONE;
|
||||
dp->dmap_flags = flags;
|
||||
dp->dmap_lock_ref = &dp->dmap_lock;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/* Check process number of new driver if it was alive before mapping */
|
||||
s = isokendpt(proc_nr_e, &slot);
|
||||
if (s != OK) {
|
||||
/* This is not a problem only when we force this driver mapping */
|
||||
if (! (flags & DRV_FORCED))
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
if (label != NULL) {
|
||||
len = strlen(label);
|
||||
if (len+1 > sizeof(dp->dmap_label))
|
||||
panic("VFS: map_driver: label too long: %d", len);
|
||||
strlcpy(dp->dmap_label, label, LABEL_MAX);
|
||||
}
|
||||
|
||||
/* Store driver I/O routines based on type of device */
|
||||
switch (style) {
|
||||
case STYLE_DEV:
|
||||
dp->dmap_opcl = gen_opcl;
|
||||
dp->dmap_io = gen_io;
|
||||
break;
|
||||
case STYLE_TTY:
|
||||
dp->dmap_opcl = tty_opcl;
|
||||
dp->dmap_io = gen_io;
|
||||
break;
|
||||
case STYLE_CTTY:
|
||||
dp->dmap_opcl = ctty_opcl;
|
||||
dp->dmap_io = ctty_io;
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
dp->dmap_driver = proc_nr_e;
|
||||
dp->dmap_flags = flags;
|
||||
dp->dmap_style = style;
|
||||
|
||||
return(OK);
|
||||
return map_driver(label, major, endpoint);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
@ -205,7 +169,7 @@ void dmap_unmap_by_endpt(endpoint_t proc_e)
|
|||
for (major = 0; major < NR_DEVICES; major++) {
|
||||
if (dmap_driver_match(proc_e, major)) {
|
||||
/* Found driver; overwrite it with a NULL entry */
|
||||
if ((r = map_driver(NULL, major, NONE, 0, 0)) != OK) {
|
||||
if ((r = map_driver(NULL, major, NONE)) != OK) {
|
||||
printf("VFS: unmapping driver %d for major %d failed:"
|
||||
" %d\n", proc_e, major, r);
|
||||
}
|
||||
|
@ -220,7 +184,6 @@ int map_service(struct rprocpub *rpub)
|
|||
{
|
||||
/* Map a new service by storing its device driver properties. */
|
||||
int r, slot;
|
||||
struct dmap *fdp, *sdp;
|
||||
struct fproc *rfp;
|
||||
|
||||
if (IS_RPUB_BOOT_USR(rpub)) return(OK);
|
||||
|
@ -238,62 +201,32 @@ int map_service(struct rprocpub *rpub)
|
|||
if (rpub->dev_nr == NO_DEV) return(OK);
|
||||
|
||||
/* Map driver. */
|
||||
r = map_driver(rpub->label, rpub->dev_nr, rpub->endpoint, rpub->dev_style,
|
||||
rpub->dev_flags);
|
||||
r = map_driver(rpub->label, rpub->dev_nr, rpub->endpoint);
|
||||
if(r != OK) return(r);
|
||||
|
||||
/* If driver has two major numbers associated, also map the other one. */
|
||||
if(rpub->dev_style2 != STYLE_NDEV) {
|
||||
r = map_driver(rpub->label, rpub->dev_nr+1, rpub->endpoint,
|
||||
rpub->dev_style2, rpub->dev_flags);
|
||||
if(r != OK) return(r);
|
||||
|
||||
/* To ensure that future dmap lock attempts always lock the same driver
|
||||
* regardless of major number, refer the second dmap lock reference
|
||||
* to the first dmap entry.
|
||||
*/
|
||||
fdp = get_dmap_by_major(rpub->dev_nr);
|
||||
sdp = get_dmap_by_major(rpub->dev_nr+1);
|
||||
assert(fdp != NULL);
|
||||
assert(sdp != NULL);
|
||||
assert(fdp != sdp);
|
||||
sdp->dmap_lock_ref = &fdp->dmap_lock;
|
||||
}
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* init_dmap *
|
||||
*===========================================================================*/
|
||||
void init_dmap()
|
||||
void init_dmap(void)
|
||||
{
|
||||
/* Initialize the table with empty device <-> driver mappings. */
|
||||
/* Initialize the device mapping table. */
|
||||
int i;
|
||||
|
||||
memset(dmap, 0, sizeof(dmap));
|
||||
|
||||
for (i = 0; i < NR_DEVICES; i++) {
|
||||
dmap[i].dmap_opcl = no_dev;
|
||||
dmap[i].dmap_io = no_dev_io;
|
||||
dmap[i].dmap_driver = NONE;
|
||||
dmap[i].dmap_style = STYLE_NDEV;
|
||||
dmap[i].dmap_servicing = INVALID_THREAD;
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* init_dmap_locks *
|
||||
*===========================================================================*/
|
||||
void init_dmap_locks()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NR_DEVICES; i++) {
|
||||
if (mutex_init(&dmap[i].dmap_lock, NULL) != 0)
|
||||
panic("unable to initialize dmap lock");
|
||||
dmap[i].dmap_lock_ref = &dmap[i].dmap_lock;
|
||||
}
|
||||
|
||||
/* CTTY_MAJOR is a special case, which is handled by VFS itself. */
|
||||
if (map_driver("vfs", CTTY_MAJOR, CTTY_ENDPT) != OK)
|
||||
panic("map_driver(CTTY_MAJOR) failed");
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
@ -14,18 +14,14 @@
|
|||
*/
|
||||
|
||||
extern struct dmap {
|
||||
int(*dmap_opcl) (int, dev_t, endpoint_t, int);
|
||||
int(*dmap_io) (endpoint_t, message *);
|
||||
endpoint_t dmap_driver;
|
||||
char dmap_label[LABEL_MAX];
|
||||
int dmap_flags;
|
||||
int dmap_style;
|
||||
int dmap_sel_busy;
|
||||
struct filp *dmap_sel_filp;
|
||||
thread_t dmap_servicing;
|
||||
mutex_t dmap_lock;
|
||||
mutex_t *dmap_lock_ref;
|
||||
int dmap_recovering;
|
||||
int dmap_seen_tty;
|
||||
} dmap[];
|
||||
|
||||
#endif
|
||||
|
|
|
@ -325,10 +325,21 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
|
|||
mess.m_type = OK; /* tell PM that we succeeded */
|
||||
s = send(PM_PROC_NR, &mess); /* send synchronization message */
|
||||
|
||||
/* All process table entries have been set. Continue with initialization. */
|
||||
init_dmap(); /* Initialize device table. */
|
||||
system_hz = sys_hz();
|
||||
|
||||
/* Subscribe to block and character driver events. */
|
||||
s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE);
|
||||
if (s != OK) panic("VFS: can't subscribe to driver events (%d)", s);
|
||||
|
||||
/* Initialize worker threads */
|
||||
worker_init();
|
||||
|
||||
/* Initialize global locks */
|
||||
if (mthread_mutex_init(&bsf_lock, NULL) != 0)
|
||||
panic("VFS: couldn't initialize block special file lock");
|
||||
|
||||
init_dmap(); /* Initialize device table. */
|
||||
|
||||
/* Map all the services in the boot image. */
|
||||
if ((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
|
||||
(vir_bytes) rprocpub, sizeof(rprocpub))) != OK){
|
||||
|
@ -342,17 +353,6 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
|
|||
}
|
||||
}
|
||||
|
||||
/* Subscribe to block and character driver events. */
|
||||
s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE);
|
||||
if (s != OK) panic("VFS: can't subscribe to driver events (%d)", s);
|
||||
|
||||
/* Initialize worker threads */
|
||||
worker_init();
|
||||
|
||||
/* Initialize global locks */
|
||||
if (mthread_mutex_init(&bsf_lock, NULL) != 0)
|
||||
panic("VFS: couldn't initialize block special file lock");
|
||||
|
||||
/* Initialize locks and initial values for all processes. */
|
||||
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
|
||||
if (mutex_init(&rfp->fp_lock, NULL) != 0)
|
||||
|
@ -372,7 +372,6 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
|
|||
rfp->fp_wd = NULL;
|
||||
}
|
||||
|
||||
init_dmap_locks(); /* init dmap locks */
|
||||
init_vnodes(); /* init vnodes */
|
||||
init_vmnts(); /* init vmnt structures */
|
||||
init_select(); /* init select() structures */
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* do_fcntl: perform the FCNTL system call
|
||||
* do_sync: perform the SYNC system call
|
||||
* do_fsync: perform the FSYNC system call
|
||||
* pm_setsid: perform VFS's side of setsid system call
|
||||
* pm_reboot: sync disks and prepare for shutdown
|
||||
* pm_fork: adjust the tables after PM has performed a FORK system call
|
||||
* do_exec: handle files with FD_CLOEXEC on after PM has done an EXEC
|
||||
|
@ -745,6 +746,24 @@ int ruid;
|
|||
tfp->fp_realuid = ruid;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pm_setsid *
|
||||
*===========================================================================*/
|
||||
void pm_setsid(endpoint_t proc_e)
|
||||
{
|
||||
/* Perform the VFS side of the SETSID call, i.e. get rid of the controlling
|
||||
* terminal of a process, and make the process a session leader.
|
||||
*/
|
||||
struct fproc *rfp;
|
||||
int slot;
|
||||
|
||||
/* Make the process a session leader with no controlling tty. */
|
||||
okendpt(proc_e, &slot);
|
||||
rfp = &fproc[slot];
|
||||
rfp->fp_flags |= FP_SESLDR;
|
||||
rfp->fp_tty = 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_svrctl *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -49,8 +49,6 @@
|
|||
#define md_label m2_p1
|
||||
#define md_label_len m2_l1
|
||||
#define md_major m2_i1
|
||||
#define md_style m2_i2
|
||||
#define md_flags m2_i3
|
||||
|
||||
/* The following names are synonyms for the variables in the output message. */
|
||||
#define reply_type m_type
|
||||
|
|
|
@ -39,32 +39,18 @@ int bdev_open(dev_t dev, int access);
|
|||
int bdev_close(dev_t dev);
|
||||
void bdev_reply(void);
|
||||
void bdev_up(int major);
|
||||
int gen_opcl(int op, dev_t dev, endpoint_t task_nr, int flags);
|
||||
int gen_io(endpoint_t drv_e, message *mess_ptr);
|
||||
int no_dev(int op, dev_t dev, endpoint_t proc, int flags);
|
||||
int no_dev_io(endpoint_t, message *);
|
||||
int tty_opcl(int op, dev_t dev, endpoint_t proc, int flags);
|
||||
int ctty_opcl(int op, dev_t dev, endpoint_t proc, int flags);
|
||||
int clone_opcl(int op, dev_t dev, endpoint_t proc, int flags);
|
||||
int ctty_io(endpoint_t task_nr, message *mess_ptr);
|
||||
int do_ioctl(message *m_out);
|
||||
void pm_setsid(endpoint_t proc_e);
|
||||
|
||||
/* dmap.c */
|
||||
void lock_dmap(struct dmap *dp);
|
||||
void unlock_dmap(struct dmap *dp);
|
||||
int do_mapdriver(message *m_out);
|
||||
void init_dmap(void);
|
||||
void init_dmap_locks(void);
|
||||
int dmap_driver_match(endpoint_t proc, int major);
|
||||
void dmap_endpt_up(endpoint_t proc_nr, int is_blk);
|
||||
void dmap_unmap_by_endpt(endpoint_t proc_nr);
|
||||
struct dmap *get_dmap(endpoint_t proc_e);
|
||||
struct dmap *get_dmap_by_major(int major);
|
||||
int map_service(struct rprocpub *rpub);
|
||||
void dmap_unmap_by_endpt(endpoint_t proc_nr);
|
||||
int map_driver(const char *label, int major, endpoint_t proc_nr, int
|
||||
dev_style, int flags);
|
||||
int map_service(struct rprocpub *rpub);
|
||||
|
||||
/* elf_core_dump.c */
|
||||
|
@ -124,6 +110,7 @@ void pm_fork(endpoint_t pproc, endpoint_t cproc, pid_t cpid);
|
|||
void pm_setgid(endpoint_t proc_e, int egid, int rgid);
|
||||
void pm_setuid(endpoint_t proc_e, int euid, int ruid);
|
||||
void pm_setgroups(endpoint_t proc_e, int ngroups, gid_t *addr);
|
||||
void pm_setsid(endpoint_t proc_e);
|
||||
int do_sync(message *m_out);
|
||||
int do_fsync(message *m_out);
|
||||
void pm_reboot(void);
|
||||
|
@ -296,7 +283,7 @@ long conv4(int norm, long x);
|
|||
int copy_name(size_t len, char *dest);
|
||||
int fetch_name(vir_bytes path, size_t len, char *dest);
|
||||
int no_sys(message *);
|
||||
int isokendpt_f(char *f, int l, endpoint_t e, int *p, int ft);
|
||||
int isokendpt_f(const char *f, int l, endpoint_t e, int *p, int ft);
|
||||
int in_group(struct fproc *rfp, gid_t grp);
|
||||
|
||||
#define okendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 1)
|
||||
|
|
|
@ -106,7 +106,7 @@ int no_sys(message *UNUSED(m_out))
|
|||
/*===========================================================================*
|
||||
* isokendpt_f *
|
||||
*===========================================================================*/
|
||||
int isokendpt_f(char *file, int line, endpoint_t endpoint, int *proc,
|
||||
int isokendpt_f(const char *file, int line, endpoint_t endpoint, int *proc,
|
||||
int fatal)
|
||||
{
|
||||
int failed = 0;
|
||||
|
|
Loading…
Reference in a new issue