| The Möbius Operating System: Driver Book | ||||
| HOME | DOWNLOAD | DOCUMENTATION | SCREENSHOTS | |
File SystemsBack: Device Drivers | Next: Example: PS/2 Mouse This document specifies the interface that the kernel uses to access file system drivers. If you write a file system driver, you need to implement the functions in this specification (or, at least the ones that make sense for your file system). The interface is designed such that file system drivers can be written in either C or C++. The interface is centred around the fsd_t structure: each file system device (i.e. each mount point controlled by your file system driver) is represented by a memory object whose contents start with an fsd_t structure. In short, you need to substitute your own structure or class -- containing any per-instance file system data -- for fsd_t, while keeping an fsd_t structure at the beginning. C++ handles this for you automatically by allowing you to inherit a class from fsd_t; if you are using C, you need to define your own structure type whose first field is of type fsd_t. File System/FSD InteractionAs their name suggests, file system drivers are contained within driver files, as device drivers are; the entry point to the driver is still DrvEntry (or however you name it). A file system driver is a driver where the fs_mount field of the driver_t object is valid; this points to the FSD's mount function. The file system will nearly always call the FSD; there are only a couple of calls the other way (relating to asynchronous I/O completion). The first call the kernel makes to your driver is to the FSD mount function, which looks like this:
fsd_t *FsdMount(driver_t *drv,
const wchar_t *dest);
You can name the function any way you want; the FsdMount name is just a placeholder. Your FsdMount function needs to:
Every file and directory maintained by the FSD is represented by a cookie. A cookie is a object which is allocated and freed by the FSD; the kernel doesn't read or modify it, but passes it unchanged to the FSD where relevant. Cookies can be anything that can be represented by a void* pointer; usually it is most convenient for the FSD to allocate a structure and use a pointer to the structure as the cookie. The FSD needs to allocate a file cookie when a file is opened or created; it does this in create_file and lookup_file. create_file is called in response to a call to FsCreate; lookup_file is called not only from FsOpen but also functions such as FsQueryFile which need to look up a file name before manipulating it. The cookie from create_file or lookup_file gets passed in the fsd_cookie member of the file_t structure passed to read_write_file, ioctl_file and passthrough; the kernel calls free_cookie when the cookie is no longer needed. Directory cookies are similar to file cookies, except that they are allocated in opendir, passed to readdir, and freed in free_dir_cookie. FSD Definition
struct vtbl_fsd_t
{
void (*dismount)(fsd_t *this);
void (*get_fs_info)(fsd_t *this,
fs_info_t *info);
status_t (*parse_element)(fsd_t *this,
const wchar_t *name,
wchar_t **new_path,
vnode_t *node);
status_t (*create_file)(fsd_t *this,
vnode_id_t dir,
const wchar_t *name,
void **cookie);
status_t (*lookup_file)(fsd_t *this,
vnode_id_t node,
uint32_t open_flags,
void **cookie);
status_t (*get_file_info)(fsd_t *this,
void *cookie,
uint32_t type,
void *buf);
status_t (*set_file_info)(fsd_t *this,
void *cookie,
uint32_t type,
const void *buf);
void (*free_cookie)(fsd_t *this,
void *cookie);
bool (*read_write_file)(fsd_t *this,
const fs_request_t *req,
size_t *bytes);
bool (*ioctl_file)(fsd_t *this,
file_t *file,
uint32_t code,
void *buf,
size_t length,
fs_asyncio_t *io);
bool (*passthrough)(fsd_t *this,
file_t *file,
uint32_t code,
void *buf,
size_t length,
fs_asyncio_t *io);
status_t (*mkdir)(fsd_t *this,
vnode_id_t dir,
const wchar_t *name,
void **dir_cookie);
status_t (*opendir)(fsd_t *this,
vnode_id_t node,
void **dir_cookie);
status_t (*readdir)(fsd_t *this,
void *dir_cookie,
dirent_t *buf);
void (*free_dir_cookie)(fsd_t *this,
void *dir_cookie);
void (*finishio)(fsd_t *this,
request_t *req);
void (*flush_cache)(fsd_t *this,
file_t *fd);
};
dismountvoid dismount(fsd_t *fsd); Called when the file system is dismounted and the last file has been closed. Your driver should free any resources it allocated for the file system here. get_fs_infovoid get_fs_info(fsd_t *fsd, fs_info_t *info); Called to obtain information on the file system as a whole. fs_info_t looks like this: struct fs_info_t
{
uint32_t flags;
uint64_t cache_block_size;
uint64_t space_total;
uint64_t space_free;
};
parse_elementstatus_t parse_element(fsd_t *fsd, const wchar_t *name, wchar_t **new_path, vnode_t *node); Called to translate a file or directory name into a vnode ID. On entry
On exit
create_filestatus_t create_file(fsd_t *fsd, vnode_id_t dir, const wchar_t *name, void **cookie); Called to create a new file, called name, in the directory dir. Your code should:
lookup_filestatus_t lookup_file(fsd_t *fsd, vnode_id_t node, uint32_t open_flags, void **cookie); Called to open an existing file. specifies the flags originally passed to FsOpen. Your code should:
get_file_infostatus_t get_file_info(fsd_t *fsd, void *cookie, uint32_t type, void *buf); Called to retrieve information on a file. type can be one of the following, or some privately-defined value:
set_file_infostatus_t set_file_info(fsd_t *fsd, void *cookie, uint32_t type, const void *buf); Called to update a file's information. See get_file_info for details. free_cookievoid free_cookie(fsd_t *fsd, void *cookie); Called to free a file's cookie, when the file is closed. read_write_filestatus_t read_write_file(fsd_t *fsd, const fs_request_t *req, size_t *bytes); Called by the implementation of FsReadAsync and FsWriteAsync to initiate an asynchronous read or write operation. Parameters:
Synchronous or asynchronous operation
Asynchronous operation
Synchronous operation
ioctl_filebool ioctl_file(fsd_t *fsd, file_t *file, uint32_t code, void *buf, size_t length, fs_asyncio_t *io); ...todo... passthroughbool passthrough(fsd_t *fsd, file_t *file, uint32_t code, void *buf, size_t length, fs_asyncio_t *io); ...todo... mkdirstatus_t mkdir(fsd_t *fsd, vnode_id_t dir, const wchar_t *name, void **dir_cookie); ...todo... opendirstatus_t opendir(fsd_t *fsd, vnode_id_t node, void **dir_cookie); Called to open a directory for use with the readdir function. Your code should:
readdirstatus_t readdir(fsd_t *fsd, void *dir_cookie, dirent_t *buf); Called to read the next entry from the directory at dir_cookie. Your code should return the directory entry through buf and return zero if available, or return EEOF if not. free_dir_cookievoid free_dir_cookie(fsd_t *fsd, void *dir_cookie); Called to free a directory cookie allocated by opendir. finishiovoid finishio(fsd_t *fsd, request_t *req); Called when any I/O queued on a device completes. flush_cachevoid flush_cache(fsd_t *fsd, file_t *fd); ...todo... Back: Device Drivers | Next: Example: PS/2 Mouse |
||||