]> Zhao Yanbai Git Server - minix.git/commitdiff
Make AVFS deal intelligently with back calling FSes
authorThomas Veerman <thomas@minix3.org>
Wed, 26 Oct 2011 13:28:41 +0000 (13:28 +0000)
committerThomas Veerman <thomas@minix3.org>
Thu, 27 Oct 2011 15:29:23 +0000 (15:29 +0000)
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.

servers/avfs/comm.c
servers/avfs/main.c
servers/avfs/mount.c
servers/avfs/open.c
servers/avfs/vmnt.h
servers/avfs/worker.c

index 06c08e49bf1ad8927a68e73cd2fe6f8e95b5a8a7..8546622ac17fb03116fcca2d7a0bfc642406da96 100644 (file)
@@ -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 */
index 61e3ac525325c5c96eedc31d4fd22281b8712cad..135ab38d870fbe1c8511465fdb6b8f6f0dc2e8da 100644 (file)
@@ -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;
        }
index 151e63a7d37312c02f9071d87a36aa79e97c03b7..65699573213345010ddc67edccdc223095dc71d0 100644 (file)
@@ -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);
 }
 
 
index 1655fd2f6f50f082595e0781d6d4098422403e56..dd88fed06b1a731e73a623b878768a3450575e04 100644 (file)
@@ -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);
index 3143f045e652cbee1bdea5f95d831afe43e15066..510502c0102296444973b40d7e841ee1c143057f 100644 (file)
@@ -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
index 01ce6705bcd3ae006e7cad249296474ccd7b4693..f179892761bdbbba73bd4ccc8c410336635af205 100644 (file)
@@ -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);
 }