David van Moolenbroek 289b04677a libfsdriver: prefill st_dev for stat requests
This obviates the need for several file system implementations to
remember the device on which they are mounted.

Change-Id: Ida8325cf4bcf072e61761cfee34e3f7ed2d750b9
2014-11-14 15:54:16 +00:00

98 lines
2.1 KiB
C

#include "fsdriver.h"
/* Library-local variables. */
dev_t fsdriver_device;
ino_t fsdriver_root;
int fsdriver_mounted = FALSE;
static int fsdriver_running;
/*
* Process an incoming VFS request, and send a reply. If the message is not
* a file system request from VFS, pass it on to the generic message handler.
* Multithreaded file systems should indicate that the reply is to be sent to
* VFS asynchronously.
*/
void
fsdriver_process(const struct fsdriver * __restrict fdp,
const message * __restrict m_ptr, int ipc_status, int asyn_reply)
{
message m_out;
unsigned int call_nr;
int r, transid;
/* Is this a file system request at all? */
if (is_ipc_notify(ipc_status) || m_ptr->m_source != VFS_PROC_NR) {
if (fdp->fdr_other != NULL)
fdp->fdr_other(m_ptr, ipc_status);
return; /* do not send a reply */
}
/* Call the appropriate function. */
transid = TRNS_GET_ID(m_ptr->m_type);
call_nr = TRNS_DEL_ID(m_ptr->m_type);
memset(&m_out, 0, sizeof(m_out));
if (fsdriver_mounted || call_nr == REQ_READSUPER) {
call_nr -= FS_BASE; /* unsigned; wrapping is intended */
if (call_nr < NREQS && fsdriver_callvec[call_nr] != NULL)
r = (fsdriver_callvec[call_nr])(fdp, m_ptr, &m_out);
else
r = ENOSYS;
} else
r = EINVAL;
/* Send a reply. */
m_out.m_type = TRNS_ADD_ID(r, transid);
if (asyn_reply)
r = asynsend(m_ptr->m_source, &m_out);
else
r = ipc_send(m_ptr->m_source, &m_out);
if (r != OK)
printf("fsdriver: sending reply failed (%d)\n", r);
if (fdp->fdr_postcall != NULL)
fdp->fdr_postcall();
}
/*
* Terminate the file server as soon as the file system has been unmounted.
*/
void
fsdriver_terminate(void)
{
fsdriver_running = FALSE;
sef_cancel();
}
/*
* Main program of any file server task.
*/
void
fsdriver_task(struct fsdriver * fdp)
{
message mess;
int r, ipc_status;
fsdriver_running = TRUE;
while (fsdriver_running || fsdriver_mounted) {
if ((r = sef_receive_status(ANY, &mess, &ipc_status)) != OK) {
if (r == EINTR)
continue; /* sef_cancel() was called */
panic("fsdriver: sef_receive_status failed: %d", r);
}
fsdriver_process(fdp, &mess, ipc_status, FALSE /*asyn_reply*/);
}
}