]> Zhao Yanbai Git Server - minix.git/commitdiff
Fix locking issues with back calls from FSes
authorThomas Veerman <thomas@minix3.org>
Fri, 19 Aug 2011 14:12:07 +0000 (14:12 +0000)
committerThomas Veerman <thomas@minix3.org>
Fri, 19 Aug 2011 14:17:35 +0000 (14:17 +0000)
servers/avfs/link.c
servers/avfs/main.c
servers/avfs/misc.c
servers/avfs/mount.c
servers/avfs/open.c
servers/avfs/path.c
servers/avfs/pipe.c
servers/avfs/proto.h
servers/avfs/read.c
servers/avfs/vmnt.c

index 90bf4a1486dfbea7b4eb185dc14f3db26ed03ae5..d0e1c762fac94c9a0281e6342c7919c3d12daccf 100644 (file)
@@ -417,7 +417,7 @@ struct fproc *rfp;
 }
 
 /*===========================================================================*
- *                             do_rdlink                                    *
+ *                             do_rdlink                                    *
  *===========================================================================*/
 PUBLIC int do_rdlink()
 {
index 2e548b80b684235d12853b8a8dc96ca878be07d8..0f70e41dd1e9bd763673732f052ae8eed872b6b8 100644 (file)
@@ -385,6 +385,10 @@ PRIVATE void *do_work(void *arg)
 
   lock_proc(fp, 0); /* This proc is busy */
 
+  if (verbose) {
+       printf("Doing call_nr = %d for %d\n", call_nr, who_e);
+  }
+
   if (call_nr == MAPDRIVER) {
        error = do_mapdriver();
   } else if (call_nr == COMMON_GETSYSINFO) {
index 0f0cba7cde48b54ac4c2341f2b819d02e9648145..53b19b533aed1913f0ae72d337bd06875fe451c0 100644 (file)
@@ -284,14 +284,19 @@ PUBLIC int do_fcntl()
 PUBLIC int do_sync()
 {
   struct vmnt *vmp;
+  int r = OK;
+
   for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
-       lock_vmnt(vmp, VMNT_EXCL);
-       if (vmp->m_dev != NO_DEV && vmp->m_fs_e != NONE)
+       if (vmp->m_dev != NO_DEV && vmp->m_fs_e != NONE &&
+                vmp->m_root_node != NULL) {
+               if ((r = lock_vmnt(vmp, VMNT_EXCL)) != OK)
+                       break;
                req_sync(vmp->m_fs_e);
-       unlock_vmnt(vmp);
+               unlock_vmnt(vmp);
+       }
   }
 
-  return(OK);
+  return(r);
 }
 
 /*===========================================================================*
@@ -299,23 +304,28 @@ PUBLIC int do_sync()
  *===========================================================================*/
 PUBLIC int do_fsync()
 {
-/* Perform the fsync() system call. For now, don't be unnecessarily smart. */
+/* Perform the fsync() system call. */
   struct filp *rfilp;
   struct vmnt *vmp;
   dev_t dev;
+  int r = OK;
 
   if ((rfilp = get_filp(m_in.m1_i1, VNODE_READ)) == NULL) return(err_code);
   dev = rfilp->filp_vno->v_dev;
   for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
-       lock_vmnt(vmp, VMNT_EXCL);
-       if (vmp->m_dev != NO_DEV && vmp->m_dev == dev && vmp->m_fs_e != NONE)
+       if (vmp->m_dev != NO_DEV && vmp->m_dev == dev &&
+               vmp->m_fs_e != NONE && vmp->m_root_node != NULL) {
+
+               if ((r = lock_vmnt(vmp, VMNT_EXCL)) != OK)
+                       break;
                req_sync(vmp->m_fs_e);
-       unlock_vmnt(vmp);
+               unlock_vmnt(vmp);
+       }
   }
 
   unlock_filp(rfilp);
 
-  return(OK);
+  return(r);
 }
 
 /*===========================================================================*
@@ -344,6 +354,7 @@ PUBLIC void pm_reboot()
        }
   }
 
+  do_sync();
   unmount_all();
 }
 
index 00f8c8258f7f3451c236b67cd174b1531e617474..9842fd0e8975b542d658c29084f5841653b17627 100644 (file)
@@ -43,7 +43,6 @@ PRIVATE bitchunk_t nonedev[BITMAP_CHUNKS(NR_NONEDEVS)] = { 0 };
 
 FORWARD _PROTOTYPE( dev_t name_to_dev, (int allow_mountpt,
                                        char path[PATH_MAX+1])          );
-FORWARD _PROTOTYPE( int is_nonedev, (dev_t dev)                                );
 FORWARD _PROTOTYPE( dev_t find_free_nonedev, (void)                    );
 FORWARD _PROTOTYPE( void update_bspec, (dev_t dev, endpoint_t fs_e,
                                      int send_drv_e)                   );
@@ -153,7 +152,8 @@ PUBLIC int do_mount()
        return(err_code);
 
   /* Do the actual job */
-  return mount_fs(dev, fullpath, fs_e, rdonly, mount_label);
+  r = mount_fs(dev, fullpath, fs_e, rdonly, mount_label);
+  return(r);
 }
 
 
@@ -191,32 +191,18 @@ char mount_label[LABEL_MAX] )
        assert(strlen(label) > 0);
   }
 
-  lock_bsf();
-
-  /* Check whether there is a block special file open which uses the
-   * same device (partition) */
-  for (bspec = &vnode[0]; bspec < &vnode[NR_VNODES]; ++bspec) {
-       if (bspec->v_ref_count > 0 && bspec->v_sdev == dev) {
-               /* Found, flush and invalidate any blocks for this device. */
-               req_flush(bspec->v_fs_e, dev);
-               break;
-       }
-  }
-
   /* Scan vmnt table to see if dev already mounted. If not, find a free slot.*/
   found = FALSE;
   for (i = 0; i < NR_MNTS; ++i) {
        if (vmnt[i].m_dev == dev) found = TRUE;
   }
   if (found) {
-       unlock_bsf();
        return(EBUSY);
   } else if ((new_vmp = get_free_vmnt()) == NULL) {
-       unlock_bsf();
        return(ENOMEM);
   }
 
-  lock_vmnt(new_vmp, VMNT_EXCL);
+  if ((r = lock_vmnt(new_vmp, VMNT_EXCL)) != OK) return(r);
 
   isroot = (strcmp(mountpoint, "/") == 0);
   mount_root = (isroot && have_root < 2); /* Root can be mounted twice:
@@ -237,14 +223,15 @@ char mount_label[LABEL_MAX] )
        } else
                r = EBUSY;
 
+       if (vp != NULL)
+               unlock_vmnt(parent_vmp);
+
        if (r != OK) {
                if (vp != NULL) {
                        unlock_vnode(vp);
-                       unlock_vmnt(parent_vmp);
                        put_vnode(vp);
                }
                unlock_vmnt(new_vmp);
-               unlock_bsf();
                return(r);
        }
   }
@@ -254,11 +241,9 @@ char mount_label[LABEL_MAX] )
   if ((root_node = get_free_vnode()) == NULL || dev == 266) {
        if (vp != NULL) {
                unlock_vnode(vp);
-               unlock_vmnt(parent_vmp);
                put_vnode(vp);
        }
        unlock_vmnt(new_vmp);
-       unlock_bsf();
        return(err_code);
   }
 
@@ -271,19 +256,21 @@ char mount_label[LABEL_MAX] )
   else new_vmp->m_flags &= ~VMNT_READONLY;
 
   /* Tell FS which device to mount */
+  if (verbose)
+       printf("Tell FS %d to mount device %s %d\n", fs_e, label, dev);
   if ((r = req_readsuper(fs_e, label, dev, rdonly, isroot, &res)) != OK) {
+       if (verbose) printf("Failed: %d\n", r);
        if (vp != NULL) {
                unlock_vnode(vp);
-               unlock_vmnt(parent_vmp);
                put_vnode(vp);
        }
        new_vmp->m_fs_e = NONE;
        new_vmp->m_dev = NO_DEV;
        unlock_vnode(root_node);
        unlock_vmnt(new_vmp);
-       unlock_bsf();
        return(r);
   }
+  if (verbose) printf("Ok done: r=%d\n", r);
 
   /* Fill in root node's fields */
   root_node->v_fs_e = res.fs_e;
@@ -300,7 +287,9 @@ char mount_label[LABEL_MAX] )
   root_node->v_vmnt = new_vmp;
   root_node->v_dev = new_vmp->m_dev;
 
-  if(mount_root) {
+  lock_bsf();
+
+  if (mount_root) {
        /* Superblock and root node already read.
         * Nothing else can go wrong. Perform the mount. */
        new_vmp->m_root_node = root_node;
@@ -342,7 +331,6 @@ char mount_label[LABEL_MAX] )
   /* If error, return the super block and both inodes; release the vmnt. */
   if (r != OK) {
        unlock_vnode(vp);
-       unlock_vmnt(parent_vmp);
        unlock_vnode(root_node);
        unlock_vmnt(new_vmp);
        put_vnode(vp);
@@ -364,7 +352,6 @@ char mount_label[LABEL_MAX] )
   update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */);
 
   unlock_vnode(vp);
-  unlock_vmnt(parent_vmp);
   unlock_vnode(root_node);
   unlock_vmnt(new_vmp);
   unlock_bsf();
@@ -454,7 +441,10 @@ PUBLIC int unmount(
 
   lock_bsf();
 
-  assert(lock_vmnt(vmp, VMNT_EXCL) == OK);
+  if ((r = lock_vmnt(vmp, VMNT_EXCL)) != OK) {
+       unlock_bsf();
+       return(r);
+  }
 
   /* See if the mounted device is busy.  Only 1 vnode using it should be
    * open -- the root vnode -- and that inode only 1 time. */
@@ -577,7 +567,7 @@ PRIVATE dev_t name_to_dev(int allow_mountpt, char path[PATH_MAX+1])
 /*===========================================================================*
  *                              is_nonedev                                  *
  *===========================================================================*/
-PRIVATE int is_nonedev(dev_t dev)
+PUBLIC int is_nonedev(dev_t dev)
 {
 /* Return whether the given device is a "none" pseudo device.
  */
index 54b69a43b46df7a5ff203b086b8e1ef554b7c340..23e8cfb5f92b63ff33d2ddfc62a3f4411c210889 100644 (file)
@@ -180,7 +180,8 @@ PRIVATE int common_open(char path[PATH_MAX+1], int oflags, mode_t omode)
                         * we default to ROOT_FS. */
                        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)
+                               if (vmp->m_dev == vp->v_sdev &&
+                                   !is_nonedev(vmp->m_dev))
                                        vp->v_bfs_e = vmp->m_fs_e;
 
                        /* Get the driver endpoint of the block spec device */
index 1be54d9efe5f5f96efcbd64a6eed3ea90a59f539..213ae27cf452bd65e2880c01965da9bc75525c56 100644 (file)
@@ -169,6 +169,10 @@ struct fproc *rfp;
   char *cp;
   char dir_entry[PATH_MAX+1];
   struct vnode *start_dir, *res;
+  int r;
+
+  *resolve->l_vnode = NULL;
+  *resolve->l_vmp = NULL;
 
   /* Is the path absolute or relative? Initialize 'start_dir' accordingly. */
   start_dir = (resolve->l_path[0] == '/' ? rfp->fp_rd : rfp->fp_wd);
@@ -195,8 +199,12 @@ struct fproc *rfp;
        struct vmnt *vmp;
 
        vmp = find_vmnt(start_dir->v_fs_e);
-       if (lock_vmnt(vmp, resolve->l_vmnt_lock) != EBUSY)
+       r = lock_vmnt(vmp, resolve->l_vmnt_lock);
+       if (r == EDEADLK)
+               return(NULL);
+       else if (r == OK)
                *resolve->l_vmp = vmp;
+
        lock_vnode(start_dir, resolve->l_vnode_lock);
        *resolve->l_vnode = start_dir;
        dup_vnode(start_dir);
@@ -285,6 +293,8 @@ struct fproc *rfp;
   if ((r = lock_vmnt(vmpres, resolve->l_vmnt_lock)) != OK) {
        if (r == EBUSY) /* vmnt already locked */
                vmpres = NULL;
+       else
+               return(r);
   }
   *(resolve->l_vmp) = vmpres;
 
@@ -320,7 +330,7 @@ struct fproc *rfp;
                vmp = NULL;
        } else if (r == EENTERMOUNT) {
                /* Entering a new partition */
-               dir_vp = 0;
+               dir_vp = NULL;
                /* Start node is now the mounted partition's root node */
                for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) {
                        if (vmp->m_dev != NO_DEV && vmp->m_mounted_on) {
@@ -374,6 +384,8 @@ struct fproc *rfp;
        if ((r = lock_vmnt(vmpres, resolve->l_vmnt_lock)) != OK) {
                if (r == EBUSY)
                        vmpres = NULL;  /* Already locked */
+               else
+                       return(r);
        }
        *(resolve->l_vmp) = vmpres;
 
index de21280698411c543706f3e7a3f85d2405216895..bfc918153d2d47d4a8a33dfe1fe06f2f50749f35 100644 (file)
@@ -50,14 +50,14 @@ PUBLIC int do_pipe()
   struct vmnt *vmp;
   struct node_details res;
 
+  /* Get a lock on PFS */
+  if ((vmp = find_vmnt(PFS_PROC_NR)) == NULL) panic("PFS gone");
+  if ((r = lock_vmnt(vmp, VMNT_WRITE)) != OK) return(r);
+
   /* See if a free vnode is available */
   if ((vp = get_free_vnode()) == NULL) return(err_code);
   lock_vnode(vp, VNODE_OPCL);
 
-  /* Get a lock on PFS */
-  if ((vmp = find_vmnt(PFS_PROC_NR)) == NULL) panic("PFS gone");
-  lock_vmnt(vmp, VMNT_WRITE);
-
   /* Acquire two file descriptors. */
   rfp = fp;
   if ((r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) {
@@ -147,8 +147,13 @@ endpoint_t map_to_fs_e;
 
   if ((vmp = find_vmnt(map_to_fs_e)) == NULL)
        panic("Can't map to unknown endpoint");
-  if (lock_vmnt(vmp, VMNT_WRITE) == EBUSY)
-       vmp = NULL;     /* Already locked, do not unlock */
+  if ((r = lock_vmnt(vmp, VMNT_WRITE)) != OK) {
+       if (r == EBUSY)
+               vmp = NULL;     /* Already locked, do not unlock */
+       else
+               return(r);
+
+  }
 
   /* Create a temporary mapping of this inode to another FS. Read and write
    * operations on data will be handled by that FS. The rest by the 'original'
index 31f7ca2b92b41997c7b1702cbd7c59d47efdf2e4..0fa5761bdf19f17d6515afe95faf66714db2e1de 100644 (file)
@@ -141,6 +141,7 @@ _PROTOTYPE( void ds_event, (void)                                   );
 _PROTOTYPE( int do_fsready, (void)                                      );
 _PROTOTYPE( int do_mount, (void)                                       );
 _PROTOTYPE( int do_umount, (void)                                      );
+_PROTOTYPE( int is_nonedev, (dev_t dev)                                        );
 _PROTOTYPE( void mount_pfs, (void)                                     );
 _PROTOTYPE( int mount_fs, (dev_t dev, char fullpath[PATH_MAX+1],
                                   endpoint_t fs_e, int rdonly,
index ffde1f9dbc7165ac3576182530986e1dfd2d1889..8de5eeb8690259f190707171ac96176eb58054fb 100644 (file)
@@ -137,12 +137,17 @@ int rw_flag;                      /* READING or WRITING */
   } else if (block_spec) {             /* Block special files. */
        lock_bsf();
 
+       printf("Doing block read_write(%d) from dev %d/ep=%d\n",
+               rw_flag == READING,
+               vp->v_sdev, vp->v_bfs_e);
        r = req_breadwrite(vp->v_bfs_e, who_e, vp->v_sdev, position,
                m_in.nbytes, m_in.buffer, rw_flag, &res_pos, &res_cum_io);
        if (r == OK) {
+               printf("OK res_cum_io = %d\n", res_cum_io);
                position = res_pos;
                cum_io += res_cum_io;
-       }
+       } else
+               printf("Failed with %d\n", r);
 
        unlock_bsf();
   } else {                             /* Regular files */
index cbb517f7f5c7561a37578138d23252454cc39cd2..f391aa9635fed339b6c1a608b4f36f3ed487447c 100644 (file)
@@ -129,6 +129,8 @@ PUBLIC int lock_vmnt(struct vmnt *vmp, tll_access_t locktype)
 
   initial_locktype = (locktype == VMNT_EXCL) ? VMNT_WRITE : locktype;
 
+  if (vmp->m_fs_e == who_e) return(EDEADLK);
+
   r = tll_lock(&vmp->m_lock, initial_locktype);
 
   if (r == EBUSY) return(r);