minix/servers/vfs/device.c

1203 lines
34 KiB
C
Raw Normal View History

2005-04-21 16:53:53 +02:00
/* When a needed block is not in the cache, it must be fetched from the disk.
* Special character files also require I/O. The routines for these are here.
*
* The entry points in this file are:
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
* dev_open: open a character device
* dev_reopen: reopen a character device after a driver crash
* dev_close: close a character device
* bdev_open: open a block device
* bdev_close: close a block device
2005-04-21 16:53:53 +02:00
* dev_io: FS does a read or write on a device
* dev_status: FS processes callback request alert
2005-04-21 16:53:53 +02:00
* gen_opcl: generic call to a task to perform an open/close
* gen_io: generic call to a task to perform an I/O operation
* no_dev: open/close processing for devices that don't exist
* no_dev_io: i/o processing for devices that don't exist
2005-04-21 16:53:53 +02:00
* 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
2012-02-13 16:28:04 +01:00
* pm_setsid: perform VFS's side of setsid system call
2005-04-21 16:53:53 +02:00
* do_ioctl: perform the IOCTL system call
*/
#include "fs.h"
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
#include <string.h>
2005-04-21 16:53:53 +02:00
#include <fcntl.h>
#include <assert.h>
#include <sys/stat.h>
2005-04-21 16:53:53 +02:00
#include <minix/callnr.h>
#include <minix/com.h>
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
#include <minix/endpoint.h>
#include <minix/ioctl.h>
#include <minix/u64.h>
2005-04-21 16:53:53 +02:00
#include "file.h"
#include "fproc.h"
2012-02-13 16:28:04 +01:00
#include "scratchpad.h"
#include "dmap.h"
#include <minix/vfsif.h>
#include "vnode.h"
#include "vmnt.h"
2005-04-21 16:53:53 +02:00
#include "param.h"
FORWARD void restart_reopen(int major);
FORWARD int safe_io_conversion(endpoint_t, cp_grant_id_t *, int *,
endpoint_t *, void **, size_t, u32_t *);
2012-02-13 16:28:04 +01:00
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
PRIVATE int dummyproc;
2005-04-21 16:53:53 +02:00
2005-04-21 16:53:53 +02:00
/*===========================================================================*
* dev_open *
*===========================================================================*/
PUBLIC int dev_open(
dev_t dev, /* device to open */
2012-02-13 16:28:04 +01:00
endpoint_t proc_e, /* process to open for */
int flags /* mode bits and flags */
)
2005-04-21 16:53:53 +02: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
/* Open a character device. */
2005-04-21 16:53:53 +02:00
int major, 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
/* Determine the major device number so as to call the device class specific
2005-04-21 16:53:53 +02:00
* open/close routine. (This is the only routine that must check the
* device number for being in range. All others can trust this check.)
*/
2012-02-13 16:28:04 +01:00
major = major(dev);
if (major < 0 || major >= NR_DEVICES) major = 0;
if (dmap[major].dmap_driver == NONE) return(ENXIO);
r = (*dmap[major].dmap_opcl)(DEV_OPEN, dev, proc_e, flags);
return(r);
}
/*===========================================================================*
* dev_reopen *
*===========================================================================*/
PUBLIC int dev_reopen(
dev_t dev, /* device to open */
int filp_no, /* filp to reopen for */
int flags /* mode bits and flags */
)
{
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
/* Reopen a character device after a failing device driver. */
2012-02-13 16:28:04 +01:00
int major, r;
struct dmap *dp;
2012-02-13 16:28:04 +01:00
/* Determine the major device number and 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.)
*/
2012-02-13 16:28:04 +01:00
major = major(dev);
if (major < 0 || major >= NR_DEVICES) major = 0;
dp = &dmap[major];
if (dp->dmap_driver == NONE) return(ENXIO);
r = (*dp->dmap_opcl)(DEV_REOPEN, dev, filp_no, flags);
if (r == SUSPEND) r = OK;
2005-04-21 16:53:53 +02:00
return(r);
}
2005-04-21 16:53:53 +02:00
/*===========================================================================*
* dev_close *
*===========================================================================*/
PUBLIC int dev_close(
dev_t dev, /* device to close */
int filp_no
)
2005-04-21 16:53:53 +02: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
/* Close a character device. */
2012-02-13 16:28:04 +01:00
int r, major;
2005-10-21 21:31:38 +02:00
/* See if driver is roughly valid. */
2012-02-13 16:28:04 +01:00
major = major(dev);
if (major < 0 || major >= NR_DEVICES) return(ENXIO);
if (dmap[major].dmap_driver == NONE) return(ENXIO);
r = (*dmap[major].dmap_opcl)(DEV_CLOSE, dev, filp_no, 0);
return(r);
2005-04-21 16:53:53 +02: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
/*===========================================================================*
2012-02-13 16:28:04 +01:00
* dev_open *
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
*===========================================================================*/
PUBLIC int bdev_open(dev_t dev, int access)
{
/* Open a block device. */
int major;
major = major(dev);
if (major < 0 || major >= NR_DEVICES) return(ENXIO);
if (dmap[major].dmap_driver == NONE) return(ENXIO);
return (*dmap[major].dmap_opcl)(BDEV_OPEN, dev, 0, access);
}
/*===========================================================================*
* bdev_close *
*===========================================================================*/
PUBLIC int bdev_close(dev_t dev)
{
/* Close a block device. */
int major;
major = major(dev);
if (major < 0 || major >= NR_DEVICES) return(ENXIO);
if (dmap[major].dmap_driver == NONE) return(ENXIO);
return (*dmap[major].dmap_opcl)(BDEV_CLOSE, dev, 0, 0);
}
/*===========================================================================*
* bdev_ioctl *
*===========================================================================*/
PRIVATE int bdev_ioctl(dev_t dev, endpoint_t proc_e, int req, void *buf)
{
/* Perform an I/O control operation on a block device. */
struct dmap *dp;
u32_t dummy;
cp_grant_id_t gid;
message dev_mess;
2012-02-13 16:28:04 +01:00
int op, major_dev, minor_dev;
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
major_dev = major(dev);
minor_dev = minor(dev);
/* Determine task dmap. */
dp = &dmap[major_dev];
if (dp->dmap_driver == NONE) {
printf("VFS: dev_io: no driver for major %d\n", major_dev);
return(ENXIO);
}
/* Set up a grant if necessary. */
op = VFS_DEV_IOCTL;
2012-02-13 16:28:04 +01:00
(void) safe_io_conversion(dp->dmap_driver, &gid, &op, &proc_e, &buf, 0,
&dummy);
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
/* Set up the message passed to the task. */
memset(&dev_mess, 0, sizeof(dev_mess));
dev_mess.m_type = BDEV_IOCTL;
dev_mess.BDEV_MINOR = minor_dev;
dev_mess.BDEV_REQUEST = req;
dev_mess.BDEV_GRANT = gid;
dev_mess.BDEV_ID = 0;
/* Call the task. */
(*dp->dmap_io)(dp->dmap_driver, &dev_mess);
/* Clean up. */
2012-02-13 16:28:04 +01:00
if (GRANT_VALID(gid)) cpf_revoke(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
if (dp->dmap_driver == NONE) {
printf("VFS: block driver gone!?\n");
return(EIO);
}
/* Return the result. */
2012-02-13 16:28:04 +01:00
return(dev_mess.BDEV_STATUS);
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
}
/*===========================================================================*
2012-02-13 16:28:04 +01:00
* find_suspended_ep *
*===========================================================================*/
2012-02-13 16:28:04 +01:00
endpoint_t find_suspended_ep(endpoint_t driver, cp_grant_id_t g)
{
2012-02-13 16:28:04 +01:00
/* A process is suspended on a driver for which VFS issued a grant. Find out
* which process it was.
*/
struct fproc *rfp;
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
2012-02-13 16:28:04 +01:00
if(rfp->fp_pid == PID_FREE)
continue;
if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER &&
rfp->fp_task == driver && rfp->fp_grant == g)
2012-02-13 16:28:04 +01:00
return(rfp->fp_endpoint);
}
2012-02-13 16:28:04 +01:00
return(NONE);
}
/*===========================================================================*
* dev_status *
*===========================================================================*/
PUBLIC void dev_status(message *m)
{
2012-02-13 16:28:04 +01:00
/* A device sent us a notification it has something for us. Retrieve it. */
message st;
2012-02-13 16:28:04 +01:00
int major, get_more = 1;
endpoint_t endpt;
2012-02-13 16:28:04 +01:00
for (major = 0; major < NR_DEVICES; major++)
if (dmap_driver_match(m->m_source, major))
break; /* 'major' is the device that sent the message */
2012-02-13 16:28:04 +01:00
if (major >= NR_DEVICES) /* Device endpoint not found; nothing to do */
return;
if (dev_style_asyn(dmap[major].dmap_style)) {
2012-02-13 16:28:04 +01:00
printf("VFS: not doing dev_status for async driver %d\n", m->m_source);
return;
}
2012-02-13 16:28:04 +01:00
/* Continuously send DEV_STATUS messages until the device has nothing to
* say to us anymore. */
do {
int r;
st.m_type = DEV_STATUS;
r = sendrec(m->m_source, &st);
if (r == OK && st.REP_STATUS == ERESTART) r = EDEADEPT;
if (r != OK) {
printf("VFS: DEV_STATUS failed to %d: %d\n", m->m_source, r);
if (r == EDEADSRCDST || r == EDEADEPT) return;
panic("VFS: couldn't sendrec for DEV_STATUS: %d", r);
}
2012-02-13 16:28:04 +01:00
switch(st.m_type) {
case DEV_REVIVE:
/* We've got results for a read/write/ioctl call to a
* synchronous character driver */
endpt = st.REP_ENDPT;
if (endpt == VFS_PROC_NR) {
endpt = find_suspended_ep(m->m_source,st.REP_IO_GRANT);
if(endpt == NONE) {
printf("VFS: proc with grant %d from %d not found\n",
st.REP_IO_GRANT, st.m_source);
continue;
}
}
revive(endpt, st.REP_STATUS);
break;
case DEV_IO_READY:
/* Reply to a select request: driver is ready for I/O */
select_reply2(st.m_source, st.DEV_MINOR, st.DEV_SEL_OPS);
break;
default:
printf("VFS: unrecognized reply %d to DEV_STATUS\n",st.m_type);
/* Fall through. */
case DEV_NO_STATUS:
get_more = 0;
break;
}
} while(get_more);
}
/*===========================================================================*
* safe_io_conversion *
*===========================================================================*/
2012-02-13 16:28:04 +01:00
PRIVATE int safe_io_conversion(driver, gid, op, io_ept, buf, bytes, pos_lo)
endpoint_t driver;
cp_grant_id_t *gid;
int *op;
endpoint_t *io_ept;
void **buf;
2012-02-13 16:28:04 +01:00
size_t bytes;
u32_t *pos_lo;
{
2012-02-13 16:28:04 +01:00
/* Convert operation to the 'safe' variant (i.e., grant based) if applicable.
* If no copying of data is involved, there is also no need to convert. */
2012-02-13 16:28:04 +01:00
int access = 0;
size_t size;
2012-02-13 16:28:04 +01:00
*gid = GRANT_INVALID; /* Grant to buffer */
switch(*op) {
2012-02-13 16:28:04 +01:00
case VFS_DEV_READ:
case VFS_DEV_WRITE:
/* Change to safe op. */
*op = (*op == VFS_DEV_READ) ? DEV_READ_S : DEV_WRITE_S;
*gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, bytes,
*op == DEV_READ_S ? CPF_WRITE : CPF_READ);
if (*gid < 0)
panic("VFS: cpf_grant_magic of READ/WRITE buffer failed");
break;
case VFS_DEV_IOCTL:
*pos_lo = *io_ept; /* Old endpoint in POSITION field. */
*op = DEV_IOCTL_S;
if(_MINIX_IOCTL_IOR(m_in.REQUEST)) access |= CPF_WRITE;
if(_MINIX_IOCTL_IOW(m_in.REQUEST)) access |= CPF_READ;
if(_MINIX_IOCTL_BIG(m_in.REQUEST))
size = _MINIX_IOCTL_SIZE_BIG(m_in.REQUEST);
2012-02-13 16:28:04 +01:00
else
size = _MINIX_IOCTL_SIZE(m_in.REQUEST);
2012-02-13 16:28:04 +01:00
/* Grant access to the buffer even if no I/O happens with the ioctl, in
* order to disambiguate requests with DEV_IOCTL_S.
*/
*gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, size, access);
if (*gid < 0)
panic("VFS: cpf_grant_magic IOCTL buffer failed");
break;
case VFS_DEV_SELECT:
*op = DEV_SELECT;
break;
default:
panic("VFS: unknown operation %d for safe I/O conversion", *op);
}
2012-02-13 16:28:04 +01:00
/* If we have converted to a safe operation, I/O endpoint becomes VFS if it
* wasn't already.
*/
if(GRANT_VALID(*gid)) {
*io_ept = VFS_PROC_NR;
2012-02-13 16:28:04 +01:00
return(1);
}
2012-02-13 16:28:04 +01:00
/* Not converted to a safe operation (because there is no copying involved in
* this operation).
*/
return(0);
}
PRIVATE int cancel_nblock(struct dmap * dp,
int minor,
int call,
endpoint_t ioproc,
cp_grant_id_t gid)
{
message dev_mess;
dev_mess.m_type = CANCEL;
dev_mess.USER_ENDPT = ioproc;
dev_mess.IO_GRANT = (char *) gid;
/* This R_BIT/W_BIT check taken from suspend()/unpause()
* logic. Mode is expected in the COUNT field.
*/
dev_mess.COUNT = 0;
if (call == READ)
dev_mess.COUNT = R_BIT;
else if (call == WRITE)
dev_mess.COUNT = W_BIT;
dev_mess.DEVICE = minor;
(*dp->dmap_io)(dp->dmap_driver, &dev_mess);
return dev_mess.REP_STATUS;
}
2005-04-21 16:53:53 +02:00
/*===========================================================================*
* dev_io *
*===========================================================================*/
PUBLIC int dev_io(
int op, /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
dev_t dev, /* major-minor device number */
int proc_e, /* in whose address space is buf? */
void *buf, /* virtual address of the buffer */
u64_t pos, /* byte position */
2012-02-13 16:28:04 +01:00
size_t bytes, /* how many bytes to transfer */
int flags, /* special flags, like O_NONBLOCK */
int suspend_reopen /* Just suspend the process */
)
2005-04-21 16:53:53 +02:00
{
2012-02-13 16:28:04 +01:00
/* Read from or write to a device. The parameter 'dev' tells which one. */
2005-04-21 16:53:53 +02:00
struct dmap *dp;
u32_t pos_lo, pos_high;
2005-04-21 16:53:53 +02:00
message dev_mess;
cp_grant_id_t gid = GRANT_INVALID;
2012-02-13 16:28:04 +01:00
int safe, minor_dev, major_dev;
void *buf_used;
endpoint_t ioproc;
int ret, is_asyn;
2005-04-21 16:53:53 +02:00
2012-02-13 16:28:04 +01:00
pos_lo = ex64lo(pos);
pos_high = ex64hi(pos);
major_dev = major(dev);
minor_dev = minor(dev);
2005-04-21 16:53:53 +02:00
/* Determine task dmap. */
2012-02-13 16:28:04 +01:00
dp = &dmap[major_dev];
2005-04-21 16:53:53 +02:00
/* See if driver is roughly valid. */
if (dp->dmap_driver == NONE) return(ENXIO);
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
if (suspend_reopen) {
/* Suspend user. */
fp->fp_grant = GRANT_INVALID;
fp->fp_ioproc = NONE;
wait_for(dp->dmap_driver);
2012-02-13 16:28:04 +01:00
fp->fp_flags |= FP_SUSP_REOPEN;
return(SUSPEND);
}
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
2012-02-13 16:28:04 +01:00
printf("VFS: dev_io: old driver for major %x (%d)\n", major_dev,
dp->dmap_driver);
return(ENXIO);
2005-10-21 21:31:38 +02:00
}
/* By default, these are right. */
dev_mess.USER_ENDPT = proc_e;
dev_mess.ADDRESS = buf;
/* Convert DEV_* to DEV_*_S variants. */
buf_used = buf;
2012-02-13 16:28:04 +01:00
safe = safe_io_conversion(dp->dmap_driver, &gid, &op,
(endpoint_t *) &dev_mess.USER_ENDPT, &buf_used,
bytes, &pos_lo);
is_asyn = dev_style_asyn(dp->dmap_style);
2012-02-13 16:28:04 +01:00
/* If the safe conversion was done, set the IO_GRANT to
* the grant id.
*/
if(safe) dev_mess.IO_GRANT = (char *) gid;
/* Set up the rest of the message passed to task. */
2005-04-21 16:53:53 +02:00
dev_mess.m_type = op;
2012-02-13 16:28:04 +01:00
dev_mess.DEVICE = minor_dev;
dev_mess.POSITION = pos_lo;
2005-04-21 16:53:53 +02:00
dev_mess.COUNT = bytes;
dev_mess.HIGHPOS = pos_high;
dev_mess.FLAGS = 0;
if (flags & O_NONBLOCK)
dev_mess.FLAGS |= FLG_OP_NONBLOCK;
/* This will be used if the i/o is suspended. */
ioproc = dev_mess.USER_ENDPT;
2005-04-21 16:53:53 +02:00
/* Call the task. */
(*dp->dmap_io)(dp->dmap_driver, &dev_mess);
if(dp->dmap_driver == NONE) {
2012-02-13 16:28:04 +01:00
/* Driver has vanished. */
printf("VFS: driver gone?!\n");
if(safe) cpf_revoke(gid);
return(EIO);
}
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
ret = dev_mess.REP_STATUS;
2005-04-21 16:53:53 +02:00
/* Task has completed. See if call completed. */
if (ret == SUSPEND) {
if ((flags & O_NONBLOCK) && !is_asyn) {
2005-04-21 16:53:53 +02:00
/* Not supposed to block. */
ret = cancel_nblock(dp, minor_dev, call_nr, ioproc, gid);
if (ret == EINTR)
ret = EAGAIN;
2005-04-21 16:53:53 +02:00
} else {
/* select() will do suspending itself. */
if(op != DEV_SELECT) {
/* Suspend user. */
wait_for(dp->dmap_driver);
}
assert(!GRANT_VALID(fp->fp_grant));
fp->fp_grant = gid; /* revoke this when unsuspended. */
fp->fp_ioproc = ioproc;
if ((flags & O_NONBLOCK) && !is_asyn) {
/* Not supposed to block, send cancel message */
cancel_nblock(dp, minor_dev, call_nr, ioproc, gid);
/*
* FIXME Should do something about EINTR -> EAGAIN
* mapping
*/
}
2005-04-21 16:53:53 +02:00
return(SUSPEND);
}
}
/* No suspend, or cancelled suspend, so I/O is over and can be cleaned up. */
2012-02-13 16:28:04 +01:00
if(safe) cpf_revoke(gid);
return ret;
2005-04-21 16:53:53 +02:00
}
/*===========================================================================*
* gen_opcl *
*===========================================================================*/
PUBLIC int gen_opcl(
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
int op, /* operation, (B)DEV_OPEN or (B)DEV_CLOSE */
dev_t dev, /* device to open or close */
2012-02-13 16:28:04 +01:00
endpoint_t proc_e, /* process to open/close for */
int flags /* mode bits and flags */
)
2005-04-21 16:53:53 +02:00
{
2012-02-13 16:28:04 +01:00
/* Called from the dmap struct on opens & closes of special files.*/
int r, minor_dev, major_dev, is_bdev;
2005-04-21 16:53:53 +02:00
struct dmap *dp;
message dev_mess;
/* Determine task dmap. */
2012-02-13 16:28:04 +01:00
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);
2005-04-21 16:53:53 +02: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
is_bdev = IS_BDEV_RQ(op);
if (is_bdev) {
memset(&dev_mess, 0, sizeof(dev_mess));
dev_mess.m_type = op;
2012-02-13 16:28:04 +01:00
dev_mess.BDEV_MINOR = minor_dev;
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
dev_mess.BDEV_ACCESS = flags;
dev_mess.BDEV_ID = 0;
} else {
dev_mess.m_type = op;
2012-02-13 16:28:04 +01:00
dev_mess.DEVICE = minor_dev;
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
dev_mess.USER_ENDPT = proc_e;
dev_mess.COUNT = flags;
}
2005-04-21 16:53:53 +02:00
/* Call the task. */
2012-02-13 16:28:04 +01:00
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
if (r != OK) return(r);
2005-04-21 16:53:53 +02:00
2012-02-13 16:28:04 +01:00
if (op == DEV_OPEN && dp->dmap_style == STYLE_DEVA) {
fp->fp_task = dp->dmap_driver;
worker_wait();
}
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 (is_bdev)
return(dev_mess.BDEV_STATUS);
else
return(dev_mess.REP_STATUS);
2005-04-21 16:53:53 +02:00
}
/*===========================================================================*
* tty_opcl *
*===========================================================================*/
PUBLIC int tty_opcl(
int op, /* operation, DEV_OPEN or DEV_CLOSE */
dev_t dev, /* device to open or close */
2012-02-13 16:28:04 +01:00
endpoint_t proc_e, /* process to open/close for */
int flags /* mode bits and flags */
)
2005-04-21 16:53:53 +02:00
{
/* This procedure is called from the dmap struct on tty open/close. */
2012-02-13 16:28:04 +01:00
2005-04-21 16:53:53 +02:00
int r;
register struct fproc *rfp;
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
assert(!IS_BDEV_RQ(op));
2005-04-21 16:53:53 +02:00
/* 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.
*/
2012-02-13 16:28:04 +01:00
if (!(fp->fp_flags & FP_SESLDR) || fp->fp_tty != 0) {
2005-04-21 16:53:53 +02:00
flags |= O_NOCTTY;
} else {
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
if(rfp->fp_pid == PID_FREE) continue;
2005-04-21 16:53:53 +02:00
if (rfp->fp_tty == dev) flags |= O_NOCTTY;
}
}
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
r = gen_opcl(op, dev, proc_e, flags);
2005-04-21 16:53:53 +02:00
/* Did this call make the tty the controlling tty? */
if (r == 1) {
fp->fp_tty = dev;
r = OK;
}
2012-02-13 16:28:04 +01:00
2005-04-21 16:53:53 +02:00
return(r);
}
2005-04-21 16:53:53 +02:00
/*===========================================================================*
* ctty_opcl *
*===========================================================================*/
PUBLIC int ctty_opcl(
int op, /* operation, DEV_OPEN or DEV_CLOSE */
2012-02-13 16:28:04 +01:00
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 */
)
2005-04-21 16:53:53 +02:00
{
2012-02-13 16:28:04 +01:00
/* This procedure is called from the dmap struct on opening or closing
2005-04-21 16:53:53 +02:00
* /dev/tty, the magic device that translates to the controlling tty.
*/
2012-02-13 16:28:04 +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
assert(!IS_BDEV_RQ(op));
2005-04-21 16:53:53 +02:00
return(fp->fp_tty == 0 ? ENXIO : OK);
}
2005-04-21 16:53:53 +02:00
/*===========================================================================*
2006-05-11 16:57:23 +02:00
* pm_setsid *
2005-04-21 16:53:53 +02:00
*===========================================================================*/
2006-05-11 16:57:23 +02:00
PUBLIC void pm_setsid(proc_e)
int proc_e;
2005-04-21 16:53:53 +02:00
{
2012-02-13 16:28:04 +01:00
/* Perform the VFS side of the SETSID call, i.e. get rid of the controlling
2005-04-21 16:53:53 +02:00
* terminal of a process, and make the process a session leader.
*/
register struct fproc *rfp;
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
int slot;
2005-04-21 16:53:53 +02:00
/* Make the process a session leader with no controlling tty. */
2006-05-11 16:57:23 +02:00
okendpt(proc_e, &slot);
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
rfp = &fproc[slot];
2012-02-13 16:28:04 +01:00
rfp->fp_flags |= FP_SESLDR;
2005-04-21 16:53:53 +02:00
rfp->fp_tty = 0;
}
2005-04-21 16:53:53 +02:00
/*===========================================================================*
* do_ioctl *
*===========================================================================*/
PUBLIC int do_ioctl()
{
/* Perform the ioctl(ls_fd, request, argx) system call (uses m2 fmt). */
2012-02-13 16:28:04 +01:00
int r = OK, suspend_reopen;
2005-04-21 16:53:53 +02:00
struct filp *f;
register struct vnode *vp;
2005-04-21 16:53:53 +02:00
dev_t dev;
2012-02-13 16:28:04 +01:00
scratch(fp).file.fd_nr = m_in.ls_fd;
if ((f = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL)
return(err_code);
vp = f->filp_vno; /* get vnode pointer */
if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL &&
2012-02-13 16:28:04 +01:00
(vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) {
r = ENOTTY;
}
2005-04-21 16:53:53 +02:00
2012-02-13 16:28:04 +01:00
if (r == OK) {
suspend_reopen = (f->filp_state != FS_NORMAL);
dev = (dev_t) vp->v_sdev;
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
2012-02-13 16:28:04 +01:00
if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL)
r = bdev_ioctl(dev, who_e, m_in.REQUEST, m_in.ADDRESS);
else
r = dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0),
m_in.REQUEST, f->filp_flags, suspend_reopen);
}
unlock_filp(f);
return(r);
2005-04-21 16:53:53 +02:00
}
2005-04-21 16:53:53 +02:00
/*===========================================================================*
* gen_io *
*===========================================================================*/
2012-02-13 16:28:04 +01:00
PUBLIC int gen_io(driver_e, mess_ptr)
endpoint_t driver_e; /* which endpoint to call */
2005-04-21 16:53:53 +02:00
message *mess_ptr; /* pointer to message for task */
{
/* All file system I/O ultimately comes down to I/O on major/minor device
* pairs. These lead to calls on the following routines via the dmap table.
*/
2012-02-13 16:28:04 +01:00
int r, status, proc_e = NONE, is_bdev;
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
is_bdev = IS_BDEV_RQ(mess_ptr->m_type);
if (!is_bdev) proc_e = mess_ptr->USER_ENDPT;
2012-02-13 16:28:04 +01:00
r = sendrec(driver_e, mess_ptr);
if (r == OK) {
if (is_bdev)
status = mess_ptr->BDEV_STATUS;
else
status = mess_ptr->REP_STATUS;
if (status == ERESTART)
r = EDEADEPT;
}
if (r != OK) {
if (r == EDEADSRCDST || r == EDEADEPT) {
printf("VFS: dead driver %d\n", driver_e);
dmap_unmap_by_endpt(driver_e);
return(r);
} else if (r == ELOCKED) {
printf("VFS: ELOCKED talking to %d\n", driver_e);
return(r);
2005-04-21 16:53:53 +02:00
}
2012-02-13 16:28:04 +01:00
panic("call_task: can't send/receive: %d", r);
}
2012-02-13 16:28:04 +01:00
/* Did the process we did the sendrec() for get a result? */
if (!is_bdev && mess_ptr->REP_ENDPT != proc_e) {
printf("VFS: strange device reply from %d, type = %d, "
"proc = %d (not %d) (2) ignored\n", mess_ptr->m_source,
mess_ptr->m_type, proc_e, mess_ptr->REP_ENDPT);
2012-02-13 16:28:04 +01:00
return(EIO);
}
return(OK);
2005-04-21 16:53:53 +02:00
}
/*===========================================================================*
* asyn_io *
*===========================================================================*/
PUBLIC int asyn_io(task_nr, mess_ptr)
int task_nr; /* which task to call */
message *mess_ptr; /* pointer to message for task */
{
/* All file system I/O ultimately comes down to I/O on major/minor device
2012-02-13 16:28:04 +01:00
* pairs. These lead to calls on the following routines via the dmap table.
*/
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
assert(!IS_BDEV_RQ(mess_ptr->m_type));
2012-02-13 16:28:04 +01:00
fp->fp_sendrec = mess_ptr; /* Remember where result should be stored */
r = asynsend3(task_nr, mess_ptr, AMF_NOREPLY);
if (r != OK) panic("VFS: asynsend in asyn_io failed: %d", r);
/* Fake a SUSPEND */
mess_ptr->REP_STATUS = SUSPEND;
return(OK);
}
2005-04-21 16:53:53 +02:00
/*===========================================================================*
* ctty_io *
*===========================================================================*/
2012-02-13 16:28:04 +01:00
PUBLIC int ctty_io(
endpoint_t UNUSED(task_nr), /* not used - for compatibility with dmap_t */
message *mess_ptr /* pointer to message for task */
)
2005-04-21 16:53:53 +02:00
{
/* 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;
if (fp->fp_tty == 0) {
/* No controlling tty present anymore, return an I/O error. */
mess_ptr->REP_STATUS = EIO;
} else {
/* Substitute the controlling terminal device. */
2012-02-13 16:28:04 +01:00
dp = &dmap[major(fp->fp_tty)];
mess_ptr->DEVICE = minor(fp->fp_tty);
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
if (dp->dmap_driver == NONE) {
printf("FS: ctty_io: no driver for dev\n");
return(EIO);
}
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
2012-02-13 16:28:04 +01:00
if (isokendpt(dp->dmap_driver, &dummyproc) != OK) {
printf("VFS: ctty_io: old driver %d\n", dp->dmap_driver);
return(EIO);
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
}
2005-04-21 16:53:53 +02:00
(*dp->dmap_io)(dp->dmap_driver, mess_ptr);
}
2012-02-13 16:28:04 +01:00
return(OK);
2005-04-21 16:53:53 +02:00
}
2005-04-21 16:53:53 +02:00
/*===========================================================================*
* no_dev *
*===========================================================================*/
PUBLIC int no_dev(
int UNUSED(op), /* operation, DEV_OPEN or DEV_CLOSE */
dev_t UNUSED(dev), /* device to open or close */
int UNUSED(proc), /* process to open/close for */
int UNUSED(flags) /* mode bits and flags */
)
2005-04-21 16:53:53 +02:00
{
/* Called when opening a nonexistent device. */
return(ENODEV);
}
/*===========================================================================*
* no_dev_io *
*===========================================================================*/
2012-02-13 16:28:04 +01:00
PUBLIC 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);
}
2005-04-21 16:53:53 +02:00
/*===========================================================================*
* clone_opcl *
*===========================================================================*/
PUBLIC int clone_opcl(
int op, /* operation, DEV_OPEN or DEV_CLOSE */
dev_t dev, /* device to open or close */
int proc_e, /* process to open/close for */
int flags /* mode bits and flags */
)
2005-04-21 16:53:53 +02:00
{
/* 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.
*/
struct dmap *dp;
2012-02-13 16:28:04 +01:00
int r, minor_dev, major_dev;
2005-04-21 16:53:53 +02:00
message dev_mess;
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
assert(!IS_BDEV_RQ(op));
2005-04-21 16:53:53 +02:00
/* Determine task dmap. */
2012-02-13 16:28:04 +01:00
minor_dev = minor(dev);
major_dev = major(dev);
assert(major_dev >= 0 && major_dev < NR_DEVICES);
dp = &dmap[major_dev];
assert(dp->dmap_driver != NONE);
2005-04-21 16:53:53 +02:00
dev_mess.m_type = op;
2012-02-13 16:28:04 +01:00
dev_mess.DEVICE = minor_dev;
dev_mess.USER_ENDPT = proc_e;
2005-04-21 16:53:53 +02:00
dev_mess.COUNT = flags;
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
2012-02-13 16:28:04 +01:00
printf("VFS clone_opcl: bad driver endpoint for major %d (%d)\n",
major_dev, dp->dmap_driver);
return(ENXIO);
endpoint-aware conversion of servers. 'who', indicating caller number in pm and fs and some other servers, has been removed in favour of 'who_e' (endpoint) and 'who_p' (proc nr.). In both PM and FS, isokendpt() convert endpoints to process slot numbers, returning OK if it was a valid and consistent endpoint number. okendpt() does the same but panic()s if it doesn't succeed. (In PM, this is pm_isok..) pm and fs keep their own records of process endpoints in their proc tables, which are needed to make kernel calls about those processes. message field names have changed. fs drivers are endpoints. fs now doesn't try to get out of driver deadlock, as the protocol isn't supposed to let that happen any more. (A warning is printed if ELOCKED is detected though.) fproc[].fp_task (indicating which driver the process is suspended on) became an int. PM and FS now get endpoint numbers of initial boot processes from the kernel. These happen to be the same as the old proc numbers, to let user processes reach them with the old numbers, but FS and PM don't know that. All new processes after INIT, even after the generation number wraps around, get endpoint numbers with generation 1 and higher, so the first instances of the boot processes are the only processes ever to have endpoint numbers in the old proc number range. More return code checks of sys_* functions have been added. IS has become endpoint-aware. Ditched the 'text' and 'data' fields in the kernel dump (which show locations, not sizes, so aren't terribly useful) in favour of the endpoint number. Proc number is still visible. Some other dumps (e.g. dmap, rs) show endpoint numbers now too which got the formatting changed. PM reading segments using rw_seg() has changed - it uses other fields in the message now instead of encoding the segment and process number and fd in the fd field. For that it uses _read_pm() and _write_pm() which to _taskcall()s directly in pm/misc.c. PM now sys_exit()s itself on panic(), instead of sys_abort(). RS also talks in endpoints instead of process numbers.
2006-03-03 11:20:58 +01:00
}
2005-04-21 16:53:53 +02:00
/* Call the task. */
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
if (r != OK) return(r);
2005-04-21 16:53:53 +02:00
if (op == DEV_OPEN && dev_style_asyn(dp->dmap_style)) {
2012-02-13 16:28:04 +01:00
/* Wait for reply when driver is asynchronous */
fp->fp_task = dp->dmap_driver;
worker_wait();
}
2005-04-21 16:53:53 +02:00
if (op == DEV_OPEN && dev_mess.REP_STATUS >= 0) {
2012-02-13 16:28:04 +01:00
if (dev_mess.REP_STATUS != minor_dev) {
struct vnode *vp;
struct node_details res;
2007-08-07 14:52:47 +02:00
/* A new minor device number has been returned.
2012-02-13 16:28:04 +01:00
* Request PFS to create a temporary device file to hold it.
*/
2012-02-13 16:28:04 +01:00
/* Device number of the new device. */
dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR);
/* Issue request */
r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid,
2007-08-07 14:52:47 +02:00
ALL_MODES | I_CHAR_SPECIAL, dev, &res);
if (r != OK) {
2012-02-13 16:28:04 +01:00
(void) clone_opcl(DEV_CLOSE, dev, proc_e, 0);
return r;
}
/* Drop old node and use the new values */
2012-02-13 16:28:04 +01:00
assert(FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_filp_inuse));
vp = fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno;
unlock_vnode(vp);
put_vnode(vp);
2012-02-13 16:28:04 +01:00
if ((vp = get_free_vnode()) == NULL)
return(err_code);
lock_vnode(vp, VNODE_OPCL);
vp->v_fs_e = res.fs_e;
vp->v_vmnt = NULL;
2012-02-13 16:28:04 +01:00
vp->v_dev = NO_DEV;
2007-08-07 14:52:47 +02:00
vp->v_fs_e = res.fs_e;
vp->v_inode_nr = res.inode_nr;
2012-02-13 16:28:04 +01:00
vp->v_mode = res.fmode;
vp->v_sdev = dev;
2007-01-05 17:36:55 +01:00
vp->v_fs_count = 1;
vp->v_ref_count = 1;
2012-02-13 16:28:04 +01:00
fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno = vp;
2005-04-21 16:53:53 +02:00
}
dev_mess.REP_STATUS = OK;
}
return(dev_mess.REP_STATUS);
}
2007-08-07 14:52:47 +02: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
* bdev_up *
*===========================================================================*/
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
PUBLIC void bdev_up(int maj)
{
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
/* A new block device driver has been mapped in. This may affect both mounted
* file systems and open block-special files.
*/
int r, found, bits;
2012-02-13 16:28:04 +01:00
struct filp *rfilp;
struct vmnt *vmp;
struct vnode *vp;
char *label;
2012-02-13 16:28:04 +01:00
if (maj < 0 || maj >= NR_DEVICES) panic("VFS: out-of-bound major");
label = dmap[maj].dmap_label;
2012-02-13 16:28:04 +01:00
/* Tell each affected mounted file system about the new endpoint. This code
* is currently useless, as driver endpoints do not change across restarts.
*/
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
if (major(vmp->m_dev) != maj) continue;
/* Send the driver label to the mounted file system. */
if (OK != req_newdriver(vmp->m_fs_e, vmp->m_dev, label))
2012-02-13 16:28:04 +01:00
printf("VFS dev_up: error sending new driver label to %d\n",
vmp->m_fs_e);
}
/* For each block-special file that was previously opened on the affected
* device, we need to reopen it on the new driver.
*/
found = 0;
2012-02-13 16:28:04 +01:00
for (rfilp = filp; rfilp < &filp[NR_FILPS]; rfilp++) {
if (rfilp->filp_count < 1 || !(vp = rfilp->filp_vno)) continue;
if (major(vp->v_sdev) != maj) continue;
if (!S_ISBLK(vp->v_mode)) continue;
/* Reopen the device on the driver, once per filp. */
2012-02-13 16:28:04 +01:00
bits = mode_map[rfilp->filp_mode & O_ACCMODE];
if ((r = bdev_open(vp->v_sdev, bits)) != OK)
printf("VFS: mounted dev %d/%d re-open failed: %d.\n",
maj, minor(vp->v_sdev), r);
found = 1;
}
/* If any block-special file was open for this major at all, also inform the
2012-02-13 16:28:04 +01:00
* root file system about the new driver. We do this even if the
* block-special file is linked to another mounted file system, merely
* because it is more work to check for that case.
*/
if (found) {
if (OK != req_newdriver(ROOT_FS_E, makedev(maj, 0), label))
printf("VFSdev_up: error sending new driver label to %d\n",
2012-02-13 16:28:04 +01:00
ROOT_FS_E);
}
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
}
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
/*===========================================================================*
* cdev_up *
*===========================================================================*/
PUBLIC void cdev_up(int maj)
{
/* A new character device driver has been mapped in.
2012-02-13 16:28:04 +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
int needs_reopen, fd_nr;
2012-02-13 16:28:04 +01:00
struct filp *rfilp;
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
struct fproc *rfp;
struct vnode *vp;
2012-02-13 16:28:04 +01:00
/* Look for processes that are suspened in an OPEN call. Set FP_SUSP_REOPEN
* to indicate that this process was suspended before the call to dev_up.
*/
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
if(rfp->fp_pid == PID_FREE) continue;
if(rfp->fp_blocked_on != FP_BLOCKED_ON_DOPEN) continue;
2012-02-13 16:28:04 +01:00
fd_nr = scratch(rfp).file.fd_nr;
printf("VFS: dev_up: found process in FP_BLOCKED_ON_DOPEN, fd %d\n",
fd_nr);
rfilp = rfp->fp_filp[fd_nr];
vp = rfilp->filp_vno;
if (!vp) panic("VFS: cdev_up: no vp");
if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
2012-02-13 16:28:04 +01:00
if (major(vp->v_sdev) != maj) continue;
2012-02-13 16:28:04 +01:00
rfp->fp_flags |= FP_SUSP_REOPEN;
}
needs_reopen= FALSE;
2012-02-13 16:28:04 +01:00
for (rfilp = filp; rfilp < &filp[NR_FILPS]; rfilp++) {
if (rfilp->filp_count < 1 || !(vp = rfilp->filp_vno)) continue;
if (major(vp->v_sdev) != maj) continue;
if (!S_ISCHR(vp->v_mode)) continue;
2012-02-13 16:28:04 +01:00
rfilp->filp_state = FS_NEEDS_REOPEN;
needs_reopen = TRUE;
}
if (needs_reopen)
restart_reopen(maj);
}
2012-02-13 16:28:04 +01:00
/*===========================================================================*
* open_reply *
*===========================================================================*/
PUBLIC void open_reply(void)
{
struct fproc *rfp;
endpoint_t proc_e;
int slot;
proc_e = m_in.REP_ENDPT;
if (isokendpt(proc_e, &slot) != OK) return;
rfp = &fproc[slot];
*rfp->fp_sendrec = m_in;
worker_signal(worker_get(rfp->fp_wtid)); /* Continue open */
}
/*===========================================================================*
* restart_reopen *
*===========================================================================*/
PRIVATE void restart_reopen(maj)
int maj;
{
2012-02-13 16:28:04 +01:00
int n, r, minor_dev, major_dev, fd_nr;
endpoint_t driver_e;
struct vnode *vp;
2012-02-13 16:28:04 +01:00
struct filp *rfilp;
struct fproc *rfp;
2012-02-13 16:28:04 +01:00
if (maj < 0 || maj >= NR_DEVICES) panic("VFS: out-of-bound major");
for (rfilp = filp; rfilp < &filp[NR_FILPS]; rfilp++) {
if (rfilp->filp_count < 1 || !(vp = rfilp->filp_vno)) continue;
if (rfilp->filp_state != FS_NEEDS_REOPEN) continue;
if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
2012-02-13 16:28:04 +01:00
major_dev = major(vp->v_sdev);
minor_dev = minor(vp->v_sdev);
if (major_dev != maj) continue;
if (!(rfilp->filp_flags & O_REOPEN)) {
/* File descriptor is to be closed when driver restarts. */
2012-02-13 16:28:04 +01:00
n = invalidate_filp(rfilp);
if (n != rfilp->filp_count) {
printf("VFS: warning: invalidate/count "
2012-02-13 16:28:04 +01:00
"discrepancy (%d, %d)\n", n, rfilp->filp_count);
}
2012-02-13 16:28:04 +01:00
rfilp->filp_count = 0;
continue;
}
2012-02-13 16:28:04 +01:00
r = dev_reopen(vp->v_sdev, rfilp-filp, vp->v_mode & (R_BIT|W_BIT));
if (r == OK) return;
/* Device could not be reopened. Invalidate all filps on that device.*/
2012-02-13 16:28:04 +01:00
n = invalidate_filp(rfilp);
if (n != rfilp->filp_count) {
printf("VFS: warning: invalidate/count "
2012-02-13 16:28:04 +01:00
"discrepancy (%d, %d)\n", n, rfilp->filp_count);
}
2012-02-13 16:28:04 +01:00
rfilp->filp_count = 0;
printf("VFS: file on dev %d/%d re-open failed: %d; "
2012-02-13 16:28:04 +01:00
"invalidated %d fd's.\n", major_dev, minor_dev, r, n);
}
/* Nothing more to re-open. Restart suspended processes */
2012-02-13 16:28:04 +01:00
driver_e = dmap[maj].dmap_driver;
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
if(rfp->fp_pid == PID_FREE) continue;
if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER &&
2012-02-13 16:28:04 +01:00
rfp->fp_task == driver_e && (rfp->fp_flags & FP_SUSP_REOPEN)) {
rfp->fp_flags &= ~FP_SUSP_REOPEN;
rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
reply(rfp->fp_endpoint, ERESTART);
}
}
/* Look for processes that are suspened in an OPEN call */
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
if (rfp->fp_pid == PID_FREE) continue;
if (rfp->fp_blocked_on == FP_BLOCKED_ON_DOPEN ||
2012-02-13 16:28:04 +01:00
!(rfp->fp_flags & FP_SUSP_REOPEN)) continue;
2012-02-13 16:28:04 +01:00
fd_nr = scratch(rfp).file.fd_nr;
printf("VFS: restart_reopen: process in FP_BLOCKED_ON_DOPEN fd=%d\n",
fd_nr);
rfilp = rfp->fp_filp[fd_nr];
2012-02-13 16:28:04 +01:00
if (!rfilp) {
/* Open failed, and automatic reopen was not requested */
rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
FD_CLR(fd_nr, &rfp->fp_filp_inuse);
reply(rfp->fp_endpoint, EIO);
continue;
}
2012-02-13 16:28:04 +01:00
vp = rfilp->filp_vno;
if (!vp) panic("VFS: restart_reopen: no vp");
if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
2012-02-13 16:28:04 +01:00
if (major(vp->v_sdev) != maj) continue;
rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
reply(rfp->fp_endpoint, fd_nr);
}
}
/*===========================================================================*
* reopen_reply *
*===========================================================================*/
PUBLIC void reopen_reply()
{
endpoint_t driver_e;
int filp_no, status, maj;
2012-02-13 16:28:04 +01:00
struct filp *rfilp;
struct vnode *vp;
struct dmap *dp;
driver_e = m_in.m_source;
filp_no = m_in.REP_ENDPT;
status = m_in.REP_STATUS;
if (filp_no < 0 || filp_no >= NR_FILPS) {
2012-02-13 16:28:04 +01:00
printf("VFS: reopen_reply: bad filp number %d from driver %d\n",
filp_no, driver_e);
return;
}
2012-02-13 16:28:04 +01:00
rfilp = &filp[filp_no];
if (rfilp->filp_count < 1) {
printf("VFS: reopen_reply: filp number %d not inuse (from driver %d)\n",
filp_no, driver_e);
return;
}
2012-02-13 16:28:04 +01:00
vp = rfilp->filp_vno;
if (!vp) {
2012-02-13 16:28:04 +01:00
printf("VFS: reopen_reply: no vnode for filp number %d (from driver "
"%d)\n", filp_no, driver_e);
return;
}
2012-02-13 16:28:04 +01:00
if (rfilp->filp_state != FS_NEEDS_REOPEN) {
printf("VFS: reopen_reply: bad state %d for filp number %d"
" (from driver %d)\n", rfilp->filp_state, filp_no, driver_e);
return;
}
if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) {
2012-02-13 16:28:04 +01:00
printf("VFS: reopen_reply: bad mode 0%o for filp number %d"
" (from driver %d)\n", vp->v_mode, filp_no, driver_e);
return;
}
2012-02-13 16:28:04 +01:00
maj = major(vp->v_sdev);
dp = &dmap[maj];
if (dp->dmap_driver != driver_e) {
2012-02-13 16:28:04 +01:00
printf("VFS: reopen_reply: bad major %d for filp number %d "
"(from driver %d, current driver is %d)\n", maj, filp_no,
driver_e, dp->dmap_driver);
return;
}
if (status == OK) {
2012-02-13 16:28:04 +01:00
rfilp->filp_state= FS_NORMAL;
} else {
2012-02-13 16:28:04 +01:00
printf("VFS: reopen_reply: should handle error status\n");
return;
}
restart_reopen(maj);
}