/*===========================================================================* * do_fs_reply * *===========================================================================*/ static void *do_fs_reply(struct job *job) { struct vmnt *vmp; struct fproc *rfp; if ((vmp = find_vmnt(who_e)) == NULL) panic("Couldn't find vmnt for endpoint %d", who_e); rfp = job->j_fp; if (rfp == NULL || rfp->fp_endpoint == NONE) { printf("VFS: spurious reply from %d\n", who_e); return(NULL); } if (rfp->fp_task != who_e) printf("VFS: expected %d to reply, not %d\n", rfp->fp_task, who_e); *rfp->fp_sendrec = m_in; rfp->fp_task = NONE; vmp->m_comm.c_cur_reqs--; /* We've got our reply, make room for others */ if (rfp->fp_wtid != invalid_thread_id) worker_signal(worker_get(rfp->fp_wtid)); /* Continue this thread */ else printf("VFS: consistency error: reply for finished job\n"); return(NULL); }
/*===========================================================================* * worker_self * *===========================================================================*/ PUBLIC struct worker_thread *worker_self(void) { struct worker_thread *worker; worker = worker_get(mthread_self()); assert(worker != NULL); return(worker); }
/*===========================================================================* * do_fs_reply * *===========================================================================*/ static void *do_fs_reply(struct job *job) { struct vmnt *vmp; struct worker_thread *wp; if ((vmp = find_vmnt(who_e)) == NULL) panic("Couldn't find vmnt for endpoint %d", who_e); wp = worker_get(job->j_fp->fp_wtid); if (wp == NULL) { printf("VFS: spurious reply from %d\n", who_e); return(NULL); } if (wp->w_task != who_e) { printf("VFS: expected %d to reply, not %d\n", wp->w_task, who_e); return(NULL); } *wp->w_fs_sendrec = m_in; wp->w_task = NONE; vmp->m_comm.c_cur_reqs--; /* We've got our reply, make room for others */ worker_signal(wp); /* Continue this thread */ return(NULL); }
/*===========================================================================* * worker_getjob * *===========================================================================*/ PUBLIC struct job *worker_getjob(thread_t worker_tid) { struct worker_thread *worker; if ((worker = worker_get(worker_tid)) != NULL) return(&worker->w_job); return(NULL); }
/*===========================================================================* * dmap_endpt_up * *===========================================================================*/ void dmap_endpt_up(endpoint_t proc_e, int is_blk) { /* A device driver with endpoint proc_e has been restarted. Go tell everyone * that might be blocking on it that this device is 'up'. */ devmajor_t major; struct dmap *dp; struct worker_thread *worker; if (proc_e == NONE) return; for (major = 0; major < NR_DEVICES; major++) { if ((dp = get_dmap_by_major(major)) == NULL) continue; if (dp->dmap_driver == proc_e) { if (is_blk) { if (dp->dmap_recovering) { printf("VFS: driver recovery failure for" " major %d\n", major); if (dp->dmap_servicing != INVALID_THREAD) { worker = worker_get(dp->dmap_servicing); worker_stop(worker); } dp->dmap_recovering = 0; continue; } dp->dmap_recovering = 1; bdev_up(major); dp->dmap_recovering = 0; } else { if (dp->dmap_servicing != INVALID_THREAD) { worker = worker_get(dp->dmap_servicing); worker_stop(worker); } invalidate_filp_by_char_major(major); } } } }
/*===========================================================================* * main * *===========================================================================*/ int main(void) { /* This is the main program of the file system. The main loop consists of * three major activities: getting new work, processing the work, and sending * the reply. This loop never terminates as long as the file system runs. */ int transid; struct worker_thread *wp; /* SEF local startup. */ sef_local_startup(); printf("Started VFS: %d worker thread(s)\n", NR_WTHREADS); /* This is the main loop that gets work, processes it, and sends replies. */ while (TRUE) { worker_yield(); /* let other threads run */ send_work(); /* The get_work() function returns TRUE if we have a new message to * process. It returns FALSE if it spawned other thread activities. */ if (!get_work()) continue; transid = TRNS_GET_ID(m_in.m_type); if (IS_VFS_FS_TRANSID(transid)) { wp = worker_get((thread_t) transid - VFS_TRANSID); if (wp == NULL || wp->w_fp == NULL) { printf("VFS: spurious message %d from endpoint %d\n", m_in.m_type, m_in.m_source); continue; } m_in.m_type = TRNS_DEL_ID(m_in.m_type); do_reply(wp); continue; } else if (who_e == PM_PROC_NR) { /* Calls from PM */ /* Special control messages from PM */ service_pm(); continue; } else if (is_notify(call_nr)) { /* A task ipc_notify()ed us */ switch (who_e) { case DS_PROC_NR: /* Start a thread to handle DS events, if no thread * is pending or active for it already. DS is not * supposed to issue calls to VFS or be the subject of * postponed PM requests, so this should be no problem. */ if (worker_can_start(fp)) handle_work(ds_event); break; case KERNEL: mthread_stacktraces(); break; case CLOCK: /* Timer expired. Used only for select(). Check it. */ expire_timers(m_in.m_notify.timestamp); break; default: printf("VFS: ignoring notification from %d\n", who_e); } continue; } else if (who_p < 0) { /* i.e., message comes from a task */ /* We're going to ignore this message. Tasks should * send ipc_notify()s only. */ printf("VFS: ignoring message from %d (%d)\n", who_e, call_nr); continue; } if (IS_BDEV_RS(call_nr)) { /* We've got results for a block device request. */ bdev_reply(); } else if (IS_CDEV_RS(call_nr)) { /* We've got results for a character device request. */ cdev_reply(); } else { /* Normal syscall. This spawns a new thread. */ handle_work(do_work); } } return(OK); /* shouldn't come here */ }