diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-16 13:25:36 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-16 13:25:36 +0200 |
commit | 44544936e40a55c6cae9983f1079dd67749347a3 (patch) | |
tree | e8d14a67e361ccc1dcd27a62df6b13155255aa66 /debian/patches/0018-isofs-use-a-seperate-lock-to-protect-node_cache.patch | |
parent | b39a4dca84393407806cb8a8b0630db1993bc38e (diff) |
add patch series
Diffstat (limited to 'debian/patches/0018-isofs-use-a-seperate-lock-to-protect-node_cache.patch')
-rw-r--r-- | debian/patches/0018-isofs-use-a-seperate-lock-to-protect-node_cache.patch | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/debian/patches/0018-isofs-use-a-seperate-lock-to-protect-node_cache.patch b/debian/patches/0018-isofs-use-a-seperate-lock-to-protect-node_cache.patch new file mode 100644 index 00000000..1b5fe5fe --- /dev/null +++ b/debian/patches/0018-isofs-use-a-seperate-lock-to-protect-node_cache.patch @@ -0,0 +1,222 @@ +From 759d9be9624ac9426d1b66ea96999152f5dd60ea Mon Sep 17 00:00:00 2001 +From: Justus Winter <4winter@informatik.uni-hamburg.de> +Date: Tue, 13 May 2014 15:16:31 +0200 +Subject: [PATCH 18/20] isofs: use a seperate lock to protect node_cache + +Previously, isofs used diskfs_node_refcnt_lock to serialize access to +the node_cache. + +Use a separate lock to protect node_cache. Adjust the reference +counting accordingly. 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. + +* isofs/inode.c (node_cache_lock): New lock. +(inode_cache_find): Use a separate lock to protect node_cache. +Adjust the reference counting accordingly. +(diskfs_cached_lookup): Likewise. +(load_inode): Likewise. +(cache_inode): Update comment accordingly. +(diskfs_node_iterate): Likewise. +(diskfs_node_norefs): Move the code removing the node from node_cache... +(diskfs_try_dropping_softrefs): ... here, where we check whether +someone reacquired a reference, and if so hold on to our light +reference. +--- + isofs/inode.c | 72 +++++++++++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 53 insertions(+), 19 deletions(-) + +diff --git a/isofs/inode.c b/isofs/inode.c +index cdc05ae..4f22086 100644 +--- a/isofs/inode.c ++++ b/isofs/inode.c +@@ -48,9 +48,19 @@ struct node_cache + 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 node_cache_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_mutex_t node_cache_lock = PTHREAD_MUTEX_INITIALIZER; + + /* Forward */ + static error_t read_disknode (struct node *, +@@ -58,7 +68,7 @@ static error_t read_disknode (struct node *, + + + /* See if node with identifier ID is in the cache. If so, return it, +- with one additional reference. diskfs_node_refcnt_lock must be held ++ with one additional reference. node_cache_lock must be held + on entry to the call, and will be released iff the node was found + in the cache. */ + void +@@ -71,8 +81,8 @@ inode_cache_find (off_t id, struct node **npp) + && node_cache[i].np) + { + *npp = node_cache[i].np; +- (*npp)->references++; +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ diskfs_nref (*npp); ++ pthread_mutex_unlock (&node_cache_lock); + pthread_mutex_lock (&(*npp)->lock); + return; + } +@@ -92,7 +102,7 @@ use_file_start_id (struct dirrect *record, struct rrip_lookup *rr) + } + + /* Enter NP into the cache. The directory entry we used is DR, the +- cached Rock-Ridge info RR. diskfs_node_refcnt_lock must be held. */ ++ cached Rock-Ridge info RR. node_cache_lock must be held. */ + void + cache_inode (struct node *np, struct dirrect *record, + struct rrip_lookup *rr) +@@ -155,7 +165,7 @@ diskfs_cached_lookup (ino_t id, struct node **npp) + to avoid presenting zero cache ID's. */ + id--; + +- pthread_spin_lock (&diskfs_node_refcnt_lock); ++ pthread_mutex_lock (&node_cache_lock); + assert (id < node_cache_size); + + np = node_cache[id].np; +@@ -174,7 +184,7 @@ diskfs_cached_lookup (ino_t id, struct node **npp) + dn = malloc (sizeof (struct disknode)); + if (!dn) + { +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ pthread_mutex_unlock (&node_cache_lock); + release_rrip (&rr); + return ENOMEM; + } +@@ -185,16 +195,17 @@ diskfs_cached_lookup (ino_t id, struct node **npp) + if (!np) + { + free (dn); +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ pthread_mutex_unlock (&node_cache_lock); + release_rrip (&rr); + return ENOMEM; + } + np->cache_id = id + 1; /* see above for rationale for increment */ + pthread_mutex_lock (&np->lock); + c->np = np; +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ diskfs_nref_light (np); ++ pthread_mutex_unlock (&node_cache_lock); + +- err = read_disknode (np, node_cache[id].dr, &rr); ++ err = read_disknode (np, dn->dr, &rr); + if (!err) + *npp = np; + +@@ -204,8 +215,8 @@ diskfs_cached_lookup (ino_t id, struct node **npp) + } + + +- np->references++; +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ diskfs_nref (np); ++ pthread_mutex_unlock (&node_cache_lock); + pthread_mutex_lock (&np->lock); + *npp = np; + return 0; +@@ -315,7 +326,7 @@ load_inode (struct node **npp, struct dirrect *record, + if (rr->valid & VALID_CL) + record = rr->realdirent; + +- pthread_spin_lock (&diskfs_node_refcnt_lock); ++ pthread_mutex_lock (&node_cache_lock); + + /* First check the cache */ + if (use_file_start_id (record, rr)) +@@ -325,7 +336,7 @@ load_inode (struct node **npp, struct dirrect *record, + + if (*npp) + { +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ pthread_mutex_unlock (&node_cache_lock); + return 0; + } + +@@ -333,7 +344,7 @@ load_inode (struct node **npp, struct dirrect *record, + dn = malloc (sizeof (struct disknode)); + if (!dn) + { +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ pthread_mutex_unlock (&node_cache_lock); + return ENOMEM; + } + dn->fileinfo = 0; +@@ -344,14 +355,14 @@ load_inode (struct node **npp, struct dirrect *record, + if (!np) + { + free (dn); +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ pthread_mutex_unlock (&node_cache_lock); + return ENOMEM; + } + + pthread_mutex_lock (&np->lock); + + cache_inode (np, record, rr); +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ pthread_mutex_unlock (&node_cache_lock); + + err = read_disknode (np, record, rr); + *npp = np; +@@ -505,9 +516,6 @@ error_t (*diskfs_read_symlink_hook) (struct node *, char *) + void + diskfs_node_norefs (struct node *np) + { +- assert (node_cache[np->cache_id - 1].np == np); +- node_cache[np->cache_id - 1].np = 0; +- + if (np->dn->translator) + free (np->dn->translator); + +@@ -521,6 +529,32 @@ diskfs_node_norefs (struct node *np) + void + diskfs_try_dropping_softrefs (struct node *np) + { ++ pthread_mutex_lock (&node_cache_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. */ ++ unsigned int references; ++ pthread_spin_lock (&diskfs_node_refcnt_lock); ++ references = np->references; ++ pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ ++ if (references > 0) ++ { ++ /* A reference was reacquired through a hash table lookup. ++ It's fine, we didn't touch anything yet. */ ++ pthread_mutex_unlock (&node_cache_lock); ++ return; ++ } ++ ++ node_cache[np->cache_id - 1].np = 0; ++ np->cache_id = 0; ++ diskfs_nrele_light (np); ++ } ++ pthread_mutex_unlock (&node_cache_lock); ++ + drop_pager_softrefs (np); + } + +-- +2.0.0.rc0 + |