Make AVFS deal intelligently with back calling FSes
PUFFS file systems need to make back calls for every operation we send to them. Consequently, they cannot handle block reads and writes themselves. Instead, the root file system has to do it (for now). When the mount operation causes an FS to make a back call, AVFS now concludes that every block read and write for that FS has to go through the root file system.
This commit is contained in:
parent
b1c2329954
commit
823e42c3e3
@ -82,6 +82,7 @@ PUBLIC int fs_sendrec(endpoint_t fs_e, message *reqmp)
|
||||
|
||||
if ((vmp = find_vmnt(fs_e)) == NULL)
|
||||
panic("Trying to talk to non-existent FS");
|
||||
if (fs_e == fp->fp_endpoint) return(EDEADLK);
|
||||
|
||||
if (!force_sync) {
|
||||
fp->fp_sendrec = reqmp; /* Where to store request and reply */
|
||||
|
@ -144,17 +144,23 @@ PRIVATE void handle_work(void *(*func)(void *arg))
|
||||
|
||||
if ((vmp = find_vmnt(who_e)) != NULL) {
|
||||
/* A back call or dev result from an FS endpoint */
|
||||
|
||||
/* When an FS point has to make a callback in order to mount, force
|
||||
* its device to a "none device" so block reads/writes will be handled
|
||||
* by ROOT_FS_E.
|
||||
*/
|
||||
if (vmp->m_flags & VMNT_MOUNTING)
|
||||
vmp->m_flags |= VMNT_FORCEROOTBSF;
|
||||
|
||||
if (worker_available() == 0) {
|
||||
/* No worker threads available to handle call */
|
||||
if (deadlock_resolving) {
|
||||
/* Already trying to resolve a deadlock, can't
|
||||
* handle more, sorry */
|
||||
|
||||
reply(who_e, EAGAIN);
|
||||
return;
|
||||
}
|
||||
deadlock_resolving = 1;
|
||||
vmp->m_flags |= VMNT_BACKCALL;
|
||||
dl_worker_start(func);
|
||||
return;
|
||||
}
|
||||
@ -198,10 +204,6 @@ PRIVATE void *do_async_dev_result(void *arg)
|
||||
select_reply2(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
|
||||
|
||||
if (deadlock_resolving) {
|
||||
struct vmnt *vmp;
|
||||
if ((vmp = find_vmnt(who_e)) != NULL)
|
||||
vmp->m_flags &= ~VMNT_BACKCALL;
|
||||
|
||||
if (fp != NULL && fp->fp_wtid == dl_worker.w_tid)
|
||||
deadlock_resolving = 0;
|
||||
}
|
||||
@ -380,7 +382,6 @@ PRIVATE void *do_work(void *arg)
|
||||
int error, i;
|
||||
struct job my_job;
|
||||
struct fproc *rfp;
|
||||
struct vmnt *vmp;
|
||||
|
||||
my_job = *((struct job *) arg);
|
||||
fp = my_job.j_fp;
|
||||
@ -425,9 +426,6 @@ PRIVATE void *do_work(void *arg)
|
||||
/* Copy the results back to the user and send reply. */
|
||||
if (error != SUSPEND) {
|
||||
if (deadlock_resolving) {
|
||||
if ((vmp = find_vmnt(who_e)) != NULL)
|
||||
vmp->m_flags &= ~VMNT_BACKCALL;
|
||||
|
||||
if (fp->fp_wtid == dl_worker.w_tid)
|
||||
deadlock_resolving = 0;
|
||||
}
|
||||
|
@ -241,11 +241,9 @@ char mount_label[LABEL_MAX] )
|
||||
/* XXX: move this upwards before lookup after proper locking. */
|
||||
/* We'll need a vnode for the root inode */
|
||||
if ((root_node = get_free_vnode()) == NULL || dev == 266) {
|
||||
if (vp != NULL) {
|
||||
unlock_vnode(vp);
|
||||
put_vnode(vp);
|
||||
}
|
||||
unlock_vnode(vp);
|
||||
unlock_vmnt(new_vmp);
|
||||
put_vnode(vp);
|
||||
return(err_code);
|
||||
}
|
||||
|
||||
@ -258,19 +256,22 @@ char mount_label[LABEL_MAX] )
|
||||
else new_vmp->m_flags &= ~VMNT_READONLY;
|
||||
|
||||
/* Tell FS which device to mount */
|
||||
new_vmp->m_flags |= VMNT_MOUNTING;
|
||||
r = req_readsuper(fs_e, label, dev, rdonly, isroot, &res, &con_reqs);
|
||||
new_vmp->m_flags &= ~VMNT_MOUNTING;
|
||||
|
||||
if (r != OK) {
|
||||
if (vp != NULL) {
|
||||
unlock_vnode(vp);
|
||||
put_vnode(vp);
|
||||
}
|
||||
new_vmp->m_fs_e = NONE;
|
||||
new_vmp->m_dev = NO_DEV;
|
||||
unlock_vnode(root_node);
|
||||
unlock_vnode(vp);
|
||||
unlock_vmnt(new_vmp);
|
||||
put_vnode(vp);
|
||||
return(r);
|
||||
}
|
||||
|
||||
lock_bsf();
|
||||
|
||||
/* Fill in root node's fields */
|
||||
root_node->v_fs_e = res.fs_e;
|
||||
root_node->v_inode_nr = res.inode_nr;
|
||||
@ -291,8 +292,6 @@ char mount_label[LABEL_MAX] )
|
||||
new_vmp->m_comm.c_max_reqs = con_reqs;
|
||||
new_vmp->m_comm.c_cur_reqs = 0;
|
||||
|
||||
lock_bsf();
|
||||
|
||||
if (mount_root) {
|
||||
/* Superblock and root node already read.
|
||||
* Nothing else can go wrong. Perform the mount. */
|
||||
@ -340,6 +339,7 @@ char mount_label[LABEL_MAX] )
|
||||
put_vnode(vp);
|
||||
put_vnode(root_node);
|
||||
new_vmp->m_dev = NO_DEV;
|
||||
new_vmp->m_flags = 0;
|
||||
unlock_bsf();
|
||||
return(r);
|
||||
}
|
||||
@ -353,14 +353,15 @@ char mount_label[LABEL_MAX] )
|
||||
if (is_nonedev(dev)) alloc_nonedev(dev);
|
||||
|
||||
/* The new FS will handle block I/O requests for its device now. */
|
||||
update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */);
|
||||
if (!(new_vmp->m_flags & VMNT_FORCEROOTBSF))
|
||||
update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */);
|
||||
|
||||
unlock_vnode(vp);
|
||||
unlock_vnode(root_node);
|
||||
unlock_vmnt(new_vmp);
|
||||
unlock_bsf();
|
||||
|
||||
return(r);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
|
@ -181,8 +181,9 @@ PRIVATE int common_open(char path[PATH_MAX], int oflags, mode_t omode)
|
||||
vp->v_bfs_e = ROOT_FS_E; /* By default */
|
||||
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp)
|
||||
if (vmp->m_dev == vp->v_sdev &&
|
||||
!is_nonedev(vmp->m_dev))
|
||||
!(vmp->m_flags & VMNT_FORCEROOTBSF)) {
|
||||
vp->v_bfs_e = vmp->m_fs_e;
|
||||
}
|
||||
|
||||
/* Get the driver endpoint of the block spec device */
|
||||
major_dev = major(vp->v_sdev);
|
||||
|
@ -15,6 +15,8 @@ EXTERN struct vmnt {
|
||||
/* vmnt flags */
|
||||
#define VMNT_READONLY 01 /* Device mounted readonly */
|
||||
#define VMNT_BACKCALL 02 /* FS did back call */
|
||||
#define VMNT_MOUNTING 04 /* Device is being mounted */
|
||||
#define VMNT_FORCEROOTBSF 010 /* Force usage of none-device */
|
||||
|
||||
/* vmnt lock types mapping */
|
||||
#define VMNT_READ TLL_READ
|
||||
|
@ -299,7 +299,10 @@ PUBLIC void worker_signal(struct worker_thread *worker)
|
||||
PUBLIC void worker_stop(struct worker_thread *worker)
|
||||
{
|
||||
ASSERTW(worker); /* Make sure we have a valid thread */
|
||||
worker->w_job.j_m_in.m_type = EIO;
|
||||
if (worker->w_job.j_fp)
|
||||
worker->w_job.j_fp->fp_sendrec->m_type = EIO;
|
||||
else
|
||||
worker->w_job.j_m_in.m_type = EIO;
|
||||
worker_wake(worker);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user