commit-hurd
[Top][All Lists]
Advanced

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

[hurd] 12/20: isofs: port to libdiskfs' node cache


From: Samuel Thibault
Subject: [hurd] 12/20: isofs: port to libdiskfs' node cache
Date: Sat, 23 May 2015 05:09:42 +0000

This is an automated email from the git hooks/post-receive script.

sthibault pushed a commit to branch upstream
in repository hurd.

commit 4266bb02b1f3342d3fc4920c07c71592a14acdd9
Author: Justus Winter <address@hidden>
Date:   Wed Apr 15 16:26:31 2015 +0200

    isofs: port to libdiskfs' node cache
    
    * isofs/inode.c: Drop all cache-related code.
    (diskfs_user_make_node): New function.
    (calculate_file_start): Check for `record' being null.
    (cache_id): New function.
    (read_node): Rename to diskfs_user_read_node and adopt accordingly.
    (diskfs_try_dropping_softrefs): Rename to diskfs_user_try_dropping_softrefs.
    * isofs/isofs.h (struct lookup_context): New definition.
    (cache_id): New declaration.
    * isofs/lookup.c (diskfs_lookup_hard): Adjust accordingly.
    * isofs/main.c (fetch_root): Likewise.
---
 isofs/inode.c  | 326 +++++++--------------------------------------------------
 isofs/isofs.h  |  13 ++-
 isofs/lookup.c |  18 ++--
 isofs/main.c   |  15 +--
 4 files changed, 70 insertions(+), 302 deletions(-)

diff --git a/isofs/inode.c b/isofs/inode.c
index e79ebdd..eef2a6a 100644
--- a/isofs/inode.c
+++ b/isofs/inode.c
@@ -31,72 +31,6 @@
    record for symlinks and zero length files, and file_start otherwise.
    Only for hard links to zero length files we get extra inodes.  */
 
-#define        INOHSZ  512
-#if    ((INOHSZ&(INOHSZ-1)) == 0)
-#define        INOHASH(ino)    ((ino>>8)&(INOHSZ-1))
-#else
-#define        INOHASH(ino)    (((unsigned)(ino>>8))%INOHSZ)
-#endif
-
-struct node_cache
-{
-  struct dirrect *dr;          /* somewhere in disk_image */
-  off_t file_start;            /* start of file */
-
-  off_t id;                    /* UNIQUE identifier.  */
-
-  struct node *np;             /* if live */
-};
-
-/* The node_cache is a cache of nodes.
-
-   Access to node_cache, node_cache_size, and node_cache_alloced is
-   protected by nodecache_lock.
-
-   Every node in the node_cache carries a light reference.  When we
-   are asked to give up that light reference, we reacquire our lock
-   momentarily to check whether someone else reacquired a reference
-   through the node_cache.  */
-static int node_cache_size = 0;
-static int node_cache_alloced = 0;
-struct node_cache *node_cache = 0;
-static pthread_rwlock_t nodecache_lock = PTHREAD_RWLOCK_INITIALIZER;
-
-/* Forward */
-static error_t read_disknode (struct node *,
-                             struct dirrect *, struct rrip_lookup *);
-
-
-/* Lookup node with id ID.  Returns NULL if the node is not found in
-   the node cache.  */
-static struct node *
-lookup (off_t id)
-{
-  int i;
-  for (i = 0; i < node_cache_size; i++)
-    if (node_cache[i].id == id
-       && node_cache[i].np)
-      return node_cache[i].np;
-  return NULL;
-}
-
-/* See if node with identifier ID is in the cache.  If so, return it,
-   with one additional reference. nodecache_lock must be held
-   on entry to the call, and will be released iff the node was found
-   in the cache. */
-void
-inode_cache_find (off_t id, struct node **npp)
-{
-  *npp = lookup (id);
-  if (*npp)
-    {
-      diskfs_nref (*npp);
-      pthread_rwlock_unlock (&nodecache_lock);
-      pthread_mutex_lock (&(*npp)->lock);
-    }
-}
-
-
 /* Determine if we use file_start or struct dirrect * as node id.  */
 int
 use_file_start_id (struct dirrect *record, struct rrip_lookup *rr)
@@ -108,140 +42,35 @@ use_file_start_id (struct dirrect *record, struct 
rrip_lookup *rr)
   return 1;
 }
 
-/* Enter NP into the cache.  The directory entry we used is DR, the
-   cached Rock-Ridge info RR. nodecache_lock must be held. */
-void
-cache_inode (struct node *np, struct dirrect *record,
-           struct rrip_lookup *rr)
-{
-  int i;
-  struct node_cache *c = 0;
-  off_t id;
-
-  if (use_file_start_id (record, rr))
-    id = np->dn->file_start << store->log2_block_size;
-  else
-    id = (off_t) ((void *) record - (void *) disk_image);
-
-  /* First see if there's already an entry. */
-  for (i = 0; i < node_cache_size; i++)
-    if (node_cache[i].id == id)
-      break;
-
-  if (i == node_cache_size)
-    {
-      if (node_cache_size >= node_cache_alloced)
-       {
-         if (!node_cache_alloced)
-           {
-             /* Initialize */
-             node_cache_alloced = 10;
-             node_cache = malloc (sizeof (struct node_cache) * 10);
-           }
-         else
-           {
-             node_cache_alloced *= 2;
-             node_cache = realloc (node_cache,
-                                   sizeof (struct node_cache)
-                                   * node_cache_alloced);
-           }
-         assert (node_cache);
-       }
-      node_cache_size++;
-    }
-
-  c = &node_cache[i];
-  c->id = id;
-  c->dr = record;
-  c->file_start = np->dn->file_start;
-  diskfs_nref_light (np);
-  c->np = np;
-
-  /* PLUS 1 so that we don't store zero cache ID's (not allowed by diskfs) */
-  np->cache_id = i + 1;
-}
-
-/* Fetch inode with cache id ID; set *NPP to the node structure;
-   gain one user reference and lock the node. */
+/* The user must define this function if she wants to use the node
+   cache.  Create and initialize a node.  */
 error_t
-diskfs_cached_lookup (ino_t id, struct node **npp)
+diskfs_user_make_node (struct node **npp, struct lookup_context *ctx)
 {
-  struct node *np;
   error_t err;
+  struct node *np;
+  struct disknode *dn;
 
-  /* Cache ID's are incremented when presented to diskfs
-     to avoid presenting zero cache ID's. */
-  id--;
-
-  pthread_rwlock_rdlock (&nodecache_lock);
-  assert (id < node_cache_size);
-
-  np = node_cache[id].np;
+  /* Create the new node.  */
+  np = diskfs_make_node_alloc (sizeof *dn);
+  if (np == NULL)
+    return ENOMEM;
 
-  if (!np)
+  /* Format specific data for the new node.  */
+  dn = diskfs_node_disknode (np);
+  dn->fileinfo = 0;
+  dn->dr = ctx->dr;
+  err = calculate_file_start (ctx->dr, &dn->file_start, &ctx->rr);
+  if (err)
     {
-      struct node_cache *c = &node_cache[id];
-      struct rrip_lookup rr;
-      struct disknode *dn;
-
-      pthread_rwlock_unlock (&nodecache_lock);
-
-      rrip_lookup (node_cache[id].dr, &rr, 1);
-
-      /* We should never cache the wrong directory entry */
-      assert (!(rr.valid & VALID_CL));
-
-      dn = malloc (sizeof (struct disknode));
-      if (!dn)
-       {
-         pthread_rwlock_unlock (&nodecache_lock);
-         release_rrip (&rr);
-         return ENOMEM;
-       }
-      dn->fileinfo = 0;
-      dn->dr = c->dr;
-      dn->file_start = c->file_start;
-      np = diskfs_make_node (dn);
-      if (!np)
-       {
-         free (dn);
-         pthread_rwlock_unlock (&nodecache_lock);
-         release_rrip (&rr);
-         return ENOMEM;
-       }
-      np->cache_id = id + 1;   /* see above for rationale for increment */
-      pthread_mutex_lock (&np->lock);
-
-      pthread_rwlock_wrlock (&nodecache_lock);
-      if (c->np != NULL)
-        {
-          /* We lost a race.  */
-          diskfs_nput (np);
-          np = c->np;
-          goto gotit;
-        }
-      c->np = np;
-      diskfs_nref_light (np);
-      pthread_rwlock_unlock (&nodecache_lock);
-
-      err = read_disknode (np, dn->dr, &rr);
-      if (!err)
-       *npp = np;
-
-      release_rrip (&rr);
-
+      diskfs_nrele (np);
       return err;
     }
 
- gotit:
-  diskfs_nref (np);
-  pthread_rwlock_unlock (&nodecache_lock);
-  pthread_mutex_lock (&np->lock);
   *npp = np;
   return 0;
 }
 
-
 /* Return Epoch-based time from a seven byte according to 9.1.5 */
 char *
 isodate_915 (char *c, struct timespec *ts)
@@ -315,6 +144,9 @@ calculate_file_start (struct dirrect *record, off_t 
*file_start,
     *file_start = rr->realfilestart;
   else
     {
+      if (record == NULL)
+        return ENOENT;
+
       err = diskfs_catch_exception ();
       if (err)
        return err;
@@ -327,90 +159,40 @@ calculate_file_start (struct dirrect *record, off_t 
*file_start,
   return 0;
 }
 
-
-/* Load the inode with directory entry RECORD and cached Rock-Ridge
-   info RR into NP.  The directory entry is at OFFSET in BLOCK.  */
+/* Given RECORD and RR, calculate the cache id.  */
 error_t
-load_inode (struct node **npp, struct dirrect *record,
-           struct rrip_lookup *rr)
+cache_id (struct dirrect *record, struct rrip_lookup *rr, ino_t *idp)
 {
   error_t err;
   off_t file_start;
-  struct disknode *dn;
-  struct node *np, *tmp;
-  off_t id;
-
   err = calculate_file_start (record, &file_start, rr);
   if (err)
     return err;
+
   if (rr->valid & VALID_CL)
     record = rr->realdirent;
 
-  /* First check the cache */
   if (use_file_start_id (record, rr))
-    id = file_start << store->log2_block_size;
+    *idp = file_start << store->log2_block_size;
   else
-    id = (off_t) ((void *) record - (void *) disk_image);
-
-  pthread_rwlock_rdlock (&nodecache_lock);
-  inode_cache_find (id, npp);
-  pthread_rwlock_unlock (&nodecache_lock);
-  if (*npp)
-    return 0;
-
-  /* Create a new node */
-  dn = malloc (sizeof (struct disknode));
-  if (!dn)
-    return ENOMEM;
-
-  dn->fileinfo = 0;
-  dn->dr = record;
-  dn->file_start = file_start;
-
-  np = diskfs_make_node (dn);
-  if (!np)
-    {
-      free (dn);
-      return ENOMEM;
-    }
-
-  pthread_mutex_lock (&np->lock);
-
-  pthread_rwlock_wrlock (&nodecache_lock);
-  tmp = lookup (id);
-  if (tmp)
-    {
-      /* We lost a race.  */
-      diskfs_nput (np);
-      diskfs_nref (tmp);
-      *npp = tmp;
-      pthread_rwlock_unlock (&nodecache_lock);
-      return 0;
-    }
-
-  cache_inode (np, record, rr);
-  pthread_rwlock_unlock (&nodecache_lock);
-
-  err = read_disknode (np, record, rr);
-  *npp = np;
-  return err;
+    *idp = (off_t) ((void *) record - (void *) disk_image);
+  return 0;
 }
 
-
-/* Read stat information from the directory entry at DR and the
-   contents of RL. */
-static error_t
-read_disknode (struct node *np, struct dirrect *dr,
-              struct rrip_lookup *rl)
+/* The user must define this function if she wants to use the node
+   cache.  Read stat information out of the on-disk node.  */
+error_t
+diskfs_user_read_node (struct node *np, struct lookup_context *ctx)
 {
   error_t err;
   struct stat *st = &np->dn_stat;
+  /* Read stat information from the directory entry at DR and the
+     contents of RL. */
+  struct dirrect *dr = ctx->dr;
+  struct rrip_lookup *rl = &ctx->rr;
   st->st_fstype = FSTYPE_ISO9660;
   st->st_fsid = getpid ();
-  if (use_file_start_id (dr, rl))
-    st->st_ino = (ino_t) np->dn->file_start << store->log2_block_size;
-  else
-    st->st_ino = (ino_t) ((void *) dr - (void *) disk_image);
+  st->st_ino = np->cache_id;
   st->st_gen = 0;
   st->st_rdev = 0;
 
@@ -547,39 +329,15 @@ diskfs_node_norefs (struct node *np)
     free (np->dn->translator);
 
   assert (!np->dn->fileinfo);
-  free (np->dn);
   free (np);
 }
 
-/* The last hard reference to a node has gone away; arrange to have
-   all the weak references dropped that can be.  */
+/* The user must define this function if she wants to use the node
+   cache.  The last hard reference to a node has gone away; arrange to
+   have all the weak references dropped that can be.  */
 void
-diskfs_try_dropping_softrefs (struct node *np)
+diskfs_user_try_dropping_softrefs (struct node *np)
 {
-  pthread_rwlock_wrlock (&nodecache_lock);
-  if (np->cache_id != 0)
-    {
-      assert (node_cache[np->cache_id - 1].np == np);
-
-      /* Check if someone reacquired a reference through the
-        node_cache.  */
-      struct references result;
-      refcounts_references (&np->refcounts, &result);
-
-      if (result.hard > 0)
-       {
-         /* A reference was reacquired through a hash table lookup.
-            It's fine, we didn't touch anything yet. */
-         pthread_rwlock_unlock (&nodecache_lock);
-         return;
-       }
-
-      node_cache[np->cache_id - 1].np = 0;
-      np->cache_id = 0;
-      diskfs_nrele_light (np);
-    }
-  pthread_rwlock_unlock (&nodecache_lock);
-
   drop_pager_softrefs (np);
 }
 
@@ -640,14 +398,6 @@ diskfs_validate_author_change (struct node *np, uid_t 
author)
   return EROFS;
 }
 
-error_t
-diskfs_node_iterate (error_t (*fun)(struct node *))
-{
-  /* We never actually have to do anything, because this function
-     is only used for things that have to do with read-write media. */
-  return 0;
-}
-
 void
 diskfs_write_disknode (struct node *np, int wait)
 {
diff --git a/isofs/isofs.h b/isofs/isofs.h
index 68a94e9..3f6690b 100644
--- a/isofs/isofs.h
+++ b/isofs/isofs.h
@@ -56,6 +56,15 @@ struct user_pager_info
     struct pager *p;
 };
 
+struct lookup_context
+{
+  /* The directory record.  Points somewhere into the disk_image.  */
+  struct dirrect *dr;
+
+  /* The results of an rrip_scan_lookup call for this node.  */
+  struct rrip_lookup rr;
+};
+
 /* The physical media */
 extern struct store *store;
 
@@ -87,7 +96,9 @@ void drop_pager_softrefs (struct node *);
 void allow_pager_softrefs (struct node *);
 void create_disk_pager (void);
 
-error_t load_inode (struct node **, struct dirrect *, struct rrip_lookup *);
+/* Given RECORD and RR, calculate the cache id.  */
+error_t cache_id (struct dirrect *record, struct rrip_lookup *rr, ino_t *idp);
+
 error_t calculate_file_start (struct dirrect *, off_t *, struct rrip_lookup *);
 
 char *isodate_915 (char *, struct timespec *);
diff --git a/isofs/lookup.c b/isofs/lookup.c
index e51b9cb..f375212 100644
--- a/isofs/lookup.c
+++ b/isofs/lookup.c
@@ -70,12 +70,12 @@ diskfs_lookup_hard (struct node *dp, const char *name, enum 
lookup_type type,
                    struct node **npp, struct dirstat *ds, struct protid *cred)
 {
   error_t err = 0;
-  struct dirrect *record;
+  struct lookup_context ctx;
   int namelen;
   int spec_dotdot;
   void *buf;
   void *blockaddr;
-  struct rrip_lookup rr;
+  ino_t id;
 
   if ((type == REMOVE) || (type == RENAME))
     assert (npp);
@@ -99,7 +99,7 @@ diskfs_lookup_hard (struct node *dp, const char *name, enum 
lookup_type type,
        blockaddr < buf + dp->dn_stat.st_size;
        blockaddr += logical_sector_size)
     {
-      err = dirscanblock (blockaddr, name, namelen, &record, &rr);
+      err = dirscanblock (blockaddr, name, namelen, &ctx.dr, &ctx.rr);
 
       if (!err)
        break;
@@ -115,6 +115,10 @@ diskfs_lookup_hard (struct node *dp, const char *name, 
enum lookup_type type,
   if (err)
     return err;
 
+  err = cache_id (ctx.dr, &ctx.rr, &id);
+  if (err)
+    return err;
+
   /* Load the inode */
   if (namelen == 2 && name[0] == '.' && name[1] == '.')
     {
@@ -125,7 +129,7 @@ diskfs_lookup_hard (struct node *dp, const char *name, enum 
lookup_type type,
          /* renames and removes can't get this far. */
          assert (type == LOOKUP);
          diskfs_nput (dp);
-         err = load_inode (npp, record, &rr);
+         err = diskfs_cached_lookup_context (id, npp, &ctx);
        }
       else
        {
@@ -133,7 +137,7 @@ diskfs_lookup_hard (struct node *dp, const char *name, enum 
lookup_type type,
             we are permanently read-only, so things are necessarily
             quiescent.  Just be careful to honor the locking order. */
          pthread_mutex_unlock (&dp->lock);
-         err = load_inode (npp, record, &rr);
+         err = diskfs_cached_lookup_context (id, npp, &ctx);
          pthread_mutex_lock (&dp->lock);
        }
     }
@@ -143,9 +147,9 @@ diskfs_lookup_hard (struct node *dp, const char *name, enum 
lookup_type type,
       diskfs_nref (dp);
     }
   else
-    err = load_inode (npp, record, &rr);
+    err = diskfs_cached_lookup_context (id, npp, &ctx);
 
-  release_rrip (&rr);
+  release_rrip (&ctx.rr);
   return err;
 }
 
diff --git a/isofs/main.c b/isofs/main.c
index 4f531f7..95c90fe 100644
--- a/isofs/main.c
+++ b/isofs/main.c
@@ -44,20 +44,23 @@ int diskfs_maxsymlinks = 8;
 static void
 fetch_root ()
 {
-  struct rrip_lookup rl;
-  struct dirrect *dr;
+  struct lookup_context ctx;
+  ino_t id;
   error_t err;
 
-  dr = (struct dirrect *) sblock->root;
+  ctx.dr = (struct dirrect *) sblock->root;
 
   /* First check for SUSP and all relevant extensions */
-  rrip_initialize (dr);
+  rrip_initialize (ctx.dr);
 
   /* Now rescan the node for real */
-  rrip_lookup (dr, &rl, 1);
+  rrip_lookup (ctx.dr, &ctx.rr, 1);
+
+  err = cache_id (ctx.dr, &ctx.rr, &id);
+  assert_perror (err);
 
   /* And fetch the node. */
-  err = load_inode (&diskfs_root_node, dr, &rl);
+  err = diskfs_cached_lookup_context (id, &diskfs_root_node, &ctx);
   assert_perror (err);
 
   pthread_mutex_unlock (&diskfs_root_node->lock);

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-hurd/hurd.git



reply via email to

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