]> Zhao Yanbai Git Server - minix.git/commitdiff
allow resizing of ramdisks.
authorBen Gras <ben@minix3.org>
Tue, 22 Sep 2009 13:57:21 +0000 (13:57 +0000)
committerBen Gras <ben@minix3.org>
Tue, 22 Sep 2009 13:57:21 +0000 (13:57 +0000)
drivers/memory/memory.c

index 4b57ade429fa682e030c2b11fe2f8497280e909d..63ff16c71ef22418c5e5ba9301670eab801609da 100644 (file)
@@ -46,11 +46,14 @@ PRIVATE struct kinfo kinfo;         /* kernel information */
 
 extern int errno;                      /* error number for PM calls */
 
+PRIVATE int openct[NR_DEVS];
+
 FORWARD _PROTOTYPE( char *m_name, (void)                               );
 FORWARD _PROTOTYPE( struct device *m_prepare, (int device)             );
 FORWARD _PROTOTYPE( int m_transfer, (int proc_nr, int opcode, u64_t position,
                                iovec_t *iov, unsigned nr_req, int safe));
 FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr)         );
+FORWARD _PROTOTYPE( int m_do_close, (struct driver *dp, message *m_ptr)        );
 FORWARD _PROTOTYPE( void m_init, (void) );
 FORWARD _PROTOTYPE( int m_ioctl, (struct driver *dp, message *m_ptr, int safe));
 FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry)                 );
@@ -59,7 +62,7 @@ FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry)                );
 PRIVATE struct driver m_dtab = {
   m_name,      /* current device's name */
   m_do_open,   /* open or mount */
-  do_nop,      /* nothing on a close */
+  m_do_close,  /* nothing on a close */
   m_ioctl,     /* specify ram disk geometry */
   m_prepare,   /* prepare for I/O on a given minor device */
   m_transfer,  /* do the I/O */
@@ -307,9 +310,40 @@ message *m_ptr;
                return r;
        }
   }
+
+  if(m_device < 0 || m_device >= NR_DEVS) {
+      panic("MEM","wrong m_device",m_device);
+  }
+
+  openct[m_device]++;
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *                             m_do_close                                   *
+ *===========================================================================*/
+PRIVATE int m_do_close(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+  int r;
+
+  if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
+
+  if(m_device < 0 || m_device >= NR_DEVS) {
+      panic("MEM","wrong m_device",m_device);
+  }
+
+  if(openct[m_device] < 1) {
+      panic("MEM","closed too often",NO_NUM);
+  }
+  openct[m_device]--;
+
   return(OK);
 }
 
+
 /*===========================================================================*
  *                             m_init                                       *
  *===========================================================================*/
@@ -343,6 +377,9 @@ PRIVATE void m_init()
        dev_zero[i] = '\0';
   }
 
+  for(i = 0; i < NR_DEVS; i++)
+       openct[i] = 0;
+
   /* Set up memory range for /dev/mem. */
   m_geom[MEM_DEV].dv_base = cvul64(0);
   m_geom[MEM_DEV].dv_size = cvul64(0xffffffff);
@@ -393,9 +430,20 @@ int safe;
        if(m_vaddrs[dev] && !cmp64(dv->dv_size, cvul64(ramdev_size))) {
                return(OK);
        }
+       /* openct is 1 for the ioctl(). */
+       if(openct[dev] != 1) {
+               printf("MEM: MIOCRAMSIZE: %d in use (count %d)\n",
+                       dev, openct[dev]);
+               return(EBUSY);
+       }
        if(m_vaddrs[dev]) {
-               printf("MEM: MIOCRAMSIZE: %d already has a ramdisk\n", dev);
-               return(EPERM);
+               u32_t size;
+               if(ex64hi(dv->dv_size)) {
+                       panic("MEM","huge old ramdisk", NO_NUM);
+               }
+               size = ex64lo(dv->dv_size);
+               munmap((void *) m_vaddrs[dev], size);
+               m_vaddrs[dev] = (vir_bytes) NULL;
        }
 
 #if DEBUG