bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] tmpfs: now working


From: Neal H Walfield
Subject: [PATCH] tmpfs: now working
Date: Sun, 15 Apr 2001 18:06:56 +0200
User-agent: Mutt/1.3.15i

This patch makes tmpfs work.  Well, mostly.  If you attempt to create
files too quickly on the tmpfs (e.g. extract a tar file), vm_map (when
passed memory objects, it works fine mapping anonymously) maps bad
memory regions into the server address space which cause the server to
stall during the memcpy in pager_memcpy.  Note that once this happens,
_no_ process can successfully use vm_map with a memory object.  As such,
I suspect that there is a race in the implementation of
default_pager_object_create in the default pager.

In implementing this patch, I found several bugs in libdiskfs, that patch
is also required to make tmpfs happy.

2001-04-15  Neal H Walfield  <neal@cs.uml.edu>

        * tmpfs.c (main): Do not deallocate the underlying node;
        servers deallocate nodes based only on the number of outstanding
        protids.
        * dir.c (diskfs_get_directs): Total rewrite.
        (diskfs_lookup_hard): Likewise.
        (diskfs_enter_hard): Count node size the size of the dirent so
        diskfs_get_directs does not have to guess; this is only a few
        bytes different.  Check the amount of space correctly, i.e.
        we cannot compare bytes and pages.
        * node.c: (diskfs_free_node): We already hold
        diskfs_node_refcnt_lock; do not try to lock it again.
        (diskfs_cached_lookup): Use diskfs_nref, that is why we have it.
        Link the nodes correctly.
        (diskfs_node_iterate):  Check the return of alloca.
        (diskfs_set_translator): Add or remove S_IPTRANS from
        np->dn_stat.st_mode as appropriate.
        (diskfs_truncate): We can truncate objects when they are being
        truncated to a size of zero.  Set the new np->dn_stat.st_size.
        (diskfs_grow): Move the assert up.

diff --exclude CVS --exclude configure -urN hurd-20010412-snapshot/tmpfs/dir.c 
hurd-20010412/tmpfs/dir.c
--- hurd-20010412-snapshot/tmpfs/dir.c  Mon Feb 26 11:43:08 2001
+++ hurd-20010412/tmpfs/dir.c   Sun Apr 15 12:03:02 2001
@@ -62,7 +62,8 @@
          >= offsetof (struct dirent, d_name));
 
   if (bufsiz == 0)
-    bufsiz = dp->dn_stat.st_size + 2 * offsetof (struct dirent, d_name[4]);
+    bufsiz = dp->dn_stat.st_size
+            + 2 * ((offsetof (struct dirent, d_name[3]) + 7) & ~7);
   if (bufsiz > *datacnt)
     {
       *data = mmap (0, bufsiz, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
@@ -108,19 +109,26 @@
   for (d = dp->dn->u.dir.entries; i < entry && d != 0; d = d->next)
     ++i;
 
+  if (i < entry)
+    {
+      assert (d == 0);
+      *datacnt = 0;
+      *amt = 0;
+      return 0;
+    }
+
   /* Now fill in the buffer with real entries.  */
-  for (; d != 0; d = d->next)
+  for (; d != 0; d = d->next, i++)
     {
-      if ((char *) entp - *data >= bufsiz || (n >= 0 && ++i > n))
+      size_t rlen = (offsetof (struct dirent, d_name[1]) + d->namelen + 7) & 
~7;
+      if (rlen + (char *) entp - *data > bufsiz || (n >= 0 && i > n))
        break;
       entp->d_fileno = (ino_t) d->dn;
       entp->d_type = DT_UNKNOWN;
       entp->d_namlen = d->namelen;
       memcpy (entp->d_name, d->name, d->namelen + 1);
-      entp->d_reclen = ((&entp->d_name[d->namelen + 1] - (char *) entp + 7)
-                       & ~7);
-      entp = (void *) entp + entp->d_reclen;
-      ++i;
+      entp->d_reclen = rlen;
+      entp = (void *) entp + rlen;
     }
 
   *datacnt = (char *) entp - *data;
@@ -158,6 +166,9 @@
   const size_t namelen = strlen (name);
   struct tmpfs_dirent *d, **prevp;
 
+  if (type == REMOVE || type == RENAME)
+    assert (np);
+
   if (namelen == 1 && name[0] == '.')
     {
       if (np != 0)
@@ -170,40 +181,54 @@
   if (namelen == 2 && name[0] == '.' && name[1] == '.')
     {
       struct disknode *dddn = dp->dn->u.dir.dotdot;
-      struct node *ddnp = 0;
       error_t err;
 
       assert (np != 0);
       if (dddn == 0)           /* root directory */
        return EAGAIN;
 
-      err = diskfs_cached_lookup ((int) dddn, &ddnp);
-      switch (type)
-       {
-       case LOOKUP|SPEC_DOTDOT:
-         diskfs_nput (dp);
-       default:
-         if (!err)
-           {
-             diskfs_nref (ddnp);
-             mutex_lock (&ddnp->lock);
-           }
-       case REMOVE|SPEC_DOTDOT:
-       case RENAME|SPEC_DOTDOT:
-         *np = ddnp;
+      if (type == (REMOVE|SPEC_DOTDOT) || type == (RENAME|SPEC_DOTDOT))
+        {
+         *np = *dddn->hprevp;
+         assert (*np);
+         assert ((*np)->dn == dddn);
+         assert (*dddn->hprevp == *np);
+         return 0;
+       }
+      else
+        {
+         mutex_unlock (&dp->lock);
+          err = diskfs_cached_lookup ((int) dddn, np);
+
+         if (type == (LOOKUP|SPEC_DOTDOT))
+           diskfs_nrele (dp);
+         else
+           mutex_lock (&dp->lock);
+
+         if (err)
+           *np = 0;
+
+          return err;
        }
-      return err;
     }
 
   for (d = *(prevp = &dp->dn->u.dir.entries); d != 0;
        d = *(prevp = &d->next))
     if (d->namelen == namelen && !memcmp (d->name, name, namelen))
       {
-       ds->prevp = prevp;
-       return diskfs_cached_lookup ((ino_t) d->dn, np);
+       if (ds)
+         ds->prevp = prevp;
+
+       if (np)
+         return diskfs_cached_lookup ((ino_t) d->dn, np);
+       else
+         return 0;
       }
 
-  ds->prevp = prevp;
+  if (ds)
+    ds->prevp = prevp;
+  if (np)
+    *np = 0;
   return ENOENT;
 }
 
@@ -214,10 +239,12 @@
                      struct protid *cred)
 {
   const size_t namelen = strlen (name);
-  const size_t entsize = offsetof (struct tmpfs_dirent, name) + namelen + 1;
+  const size_t entsize
+         = (offsetof (struct dirent, d_name[1]) + namelen + 7) & ~7;
   struct tmpfs_dirent *new;
 
-  if (round_page (tmpfs_space_used + entsize) > tmpfs_page_limit)
+  if (round_page (tmpfs_space_used + entsize) / vm_page_size
+      > tmpfs_page_limit)
     return ENOSPC;
 
   new = malloc (entsize);
@@ -251,7 +278,8 @@
 diskfs_dirremove_hard (struct node *dp, struct dirstat *ds)
 {
   struct tmpfs_dirent *d = *ds->prevp;
-  const size_t entsize = &d->name[d->namelen + 1] - (char *) d;
+  const size_t entsize
+         = (offsetof (struct dirent, d_name[1]) + d->namelen + 7) & ~7;
 
   *ds->prevp = d->next;
 
diff --exclude CVS --exclude configure -urN hurd-20010412-snapshot/tmpfs/node.c 
hurd-20010412/tmpfs/node.c
--- hurd-20010412-snapshot/tmpfs/node.c Mon Feb 26 12:03:15 2001
+++ hurd-20010412/tmpfs/node.c  Sun Apr 15 16:46:25 2001
@@ -74,10 +74,8 @@
   free (np->dn);
   np->dn = 0;
 
-  spin_lock (&diskfs_node_refcnt_lock);
   --num_files;
   tmpfs_space_used -= sizeof *np->dn;
-  spin_unlock (&diskfs_node_refcnt_lock);
 }
 
 void
@@ -150,31 +148,36 @@
   st->st_blocks = (st->st_blocks + 511) / 512;
 }
 
+/* Fetch inode INUM, set *NPP to the node structure;
+   gain one user reference and lock the node.  */
 error_t
 diskfs_cached_lookup (int inum, struct node **npp)
 {
   struct disknode *dn = (void *) inum;
   struct node *np;
 
+  assert (npp);
+
   if (dn->hprevp != 0)         /* There is already a node.  */
     {
       np = *dn->hprevp;
       assert (np->dn == dn);
       assert (*dn->hprevp == np);
-      spin_lock (&diskfs_node_refcnt_lock);
-      np->references++;
-      spin_unlock (&diskfs_node_refcnt_lock);
+
+      diskfs_nref (np);
     }
   else
+    /* Create the new node.  */
     {
       struct stat *st;
 
-      /* Create the new node.  */
       np = diskfs_make_node (dn);
       np->cache_id = (ino_t) dn;
 
       spin_lock (&diskfs_node_refcnt_lock);
       dn->hnext = all_nodes;
+      if (dn->hnext)
+       dn->hnext->dn->hprevp = &dn->hnext;
       dn->hprevp = &all_nodes;
       all_nodes = np;
       spin_unlock (&diskfs_node_refcnt_lock);
@@ -228,6 +231,9 @@
     num_nodes++;
 
   p = node_list = alloca (num_nodes * sizeof (struct node *));
+  if (! p)
+    return ENOMEM;
+
   for (node = all_nodes; node != 0; node = node->dn->hnext)
     {
       *p++ = node;
@@ -303,6 +309,7 @@
     {
       free (np->dn->trans);
       new = 0;
+      np->dn_stat.st_mode &= ~S_IPTRANS;
     }
   else
     {
@@ -310,6 +317,7 @@
       if (new == 0)
        return ENOSPC;
       memcpy (new, name, namelen);
+      np->dn_stat.st_mode |= S_IPTRANS;
     }
   adjust_used (namelen - np->dn->translen);
   np->dn->trans = new;
@@ -393,13 +401,22 @@
 
   if (np->dn->u.reg.memobj != MACH_PORT_NULL)
     {
-      /* XXX  We have no way to truncate the memory object.  */
-      return 0;
+      if (size == 0)
+        {
+         mach_port_deallocate (mach_task_self (), np->dn->u.reg.memobj);
+         np->dn->u.reg.memobj = MACH_PORT_NULL;
+       }
+      else
+        {
+          /* XXX  We have no way to truncate the memory object.  */
+          return 0;
+       }
     }
   /* Otherwise it never had any real contents.  */
 
   adjust_used (size - np->allocsize);
   np->dn_stat.st_blocks += (size - np->allocsize) / 512;
+  np->dn_stat.st_size = size;
   np->allocsize = size;
 
   return 0;
@@ -412,10 +429,10 @@
 error_t
 diskfs_grow (struct node *np, off_t size, struct protid *cred)
 {
+  assert (np->dn->type == DT_REG);
+
   if (np->allocsize >= size)
     return 0;
-
-  assert (np->dn->type == DT_REG);
 
   size = round_page (size);
   if (round_page (tmpfs_space_used + size) / vm_page_size > tmpfs_page_limit)
diff --exclude CVS --exclude configure -urN 
hurd-20010412-snapshot/tmpfs/tmpfs.c hurd-20010412/tmpfs/tmpfs.c
--- hurd-20010412-snapshot/tmpfs/tmpfs.c        Sun Apr 15 13:16:04 2001
+++ hurd-20010412/tmpfs/tmpfs.c Sat Apr 14 15:30:05 2001
@@ -265,7 +265,6 @@
   /* Propagate permissions, owner, etc. from underlying node to
      the root directory of the new (empty) filesystem.  */
   err = io_stat (realnode, &st);
-  mach_port_deallocate (mach_task_self (), realnode);
   if (err)
     {
       error (0, err, "cannot stat underlying node");

Attachment: pgp7Td8TA_J2n.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]