diff options
Diffstat (limited to 'debian/patches/0003-isofs-use-a-seperate-lock-to-protect-node_cache.patch')
-rw-r--r-- | debian/patches/0003-isofs-use-a-seperate-lock-to-protect-node_cache.patch | 310 |
1 files changed, 0 insertions, 310 deletions
diff --git a/debian/patches/0003-isofs-use-a-seperate-lock-to-protect-node_cache.patch b/debian/patches/0003-isofs-use-a-seperate-lock-to-protect-node_cache.patch deleted file mode 100644 index cd7811b8..00000000 --- a/debian/patches/0003-isofs-use-a-seperate-lock-to-protect-node_cache.patch +++ /dev/null @@ -1,310 +0,0 @@ -From 580ddc597aa7bda6f4941e308482fedd862a43c9 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 3/4] 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 (nodecache_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 | 146 +++++++++++++++++++++++++++++++++++++++++----------------- - 1 file changed, 105 insertions(+), 41 deletions(-) - -diff --git a/isofs/inode.c b/isofs/inode.c -index cdc05ae..3941580 100644 ---- a/isofs/inode.c -+++ b/isofs/inode.c -@@ -48,35 +48,53 @@ 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 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; -+/* nodecache_lock must be acquired before diskfs_node_refcnt_lock. */ -+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. diskfs_node_refcnt_lock must be held -+ 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) - { -- int i; -- -- for (i = 0; i < node_cache_size; i++) -- if (node_cache[i].id == id -- && node_cache[i].np) -- { -- *npp = node_cache[i].np; -- (*npp)->references++; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- pthread_mutex_lock (&(*npp)->lock); -- return; -- } -- *npp = 0; -+ *npp = lookup (id); -+ if (*npp) -+ { -+ diskfs_nref (*npp); -+ pthread_rwlock_unlock (&nodecache_lock); -+ pthread_mutex_lock (&(*npp)->lock); -+ } - } - - -@@ -92,7 +110,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. nodecache_lock must be held. */ - void - cache_inode (struct node *np, struct dirrect *record, - struct rrip_lookup *rr) -@@ -137,6 +155,7 @@ cache_inode (struct node *np, struct dirrect *record, - 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) */ -@@ -155,7 +174,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_rwlock_rdlock (&nodecache_lock); - assert (id < node_cache_size); - - np = node_cache[id].np; -@@ -166,6 +185,8 @@ diskfs_cached_lookup (ino_t id, struct node **npp) - 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 */ -@@ -174,7 +195,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_rwlock_unlock (&nodecache_lock); - release_rrip (&rr); - return ENOMEM; - } -@@ -185,16 +206,26 @@ diskfs_cached_lookup (ino_t id, struct node **npp) - if (!np) - { - free (dn); -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ 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; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ diskfs_nref_light (np); -+ pthread_rwlock_unlock (&nodecache_lock); - -- err = read_disknode (np, node_cache[id].dr, &rr); -+ err = read_disknode (np, dn->dr, &rr); - if (!err) - *npp = np; - -@@ -203,9 +234,9 @@ diskfs_cached_lookup (ino_t id, struct node **npp) - return err; - } - -- -- np->references++; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ gotit: -+ diskfs_nref (np); -+ pthread_rwlock_unlock (&nodecache_lock); - pthread_mutex_lock (&np->lock); - *npp = np; - return 0; -@@ -307,7 +338,8 @@ load_inode (struct node **npp, struct dirrect *record, - error_t err; - off_t file_start; - struct disknode *dn; -- struct node *np; -+ struct node *np, *tmp; -+ off_t id; - - err = calculate_file_start (record, &file_start, rr); - if (err) -@@ -315,27 +347,23 @@ load_inode (struct node **npp, struct dirrect *record, - if (rr->valid & VALID_CL) - record = rr->realdirent; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- - /* First check the cache */ - if (use_file_start_id (record, rr)) -- inode_cache_find (file_start << store->log2_block_size, npp); -+ id = file_start << store->log2_block_size; - else -- inode_cache_find ((off_t) ((void *) record - (void *) disk_image), npp); -+ id = (off_t) ((void *) record - (void *) disk_image); - -+ pthread_rwlock_rdlock (&nodecache_lock); -+ inode_cache_find (id, npp); - if (*npp) -- { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- return 0; -- } -+ return 0; -+ pthread_rwlock_unlock (&nodecache_lock); - - /* Create a new node */ - dn = malloc (sizeof (struct disknode)); - if (!dn) -- { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- return ENOMEM; -- } -+ return ENOMEM; -+ - dn->fileinfo = 0; - dn->dr = record; - dn->file_start = file_start; -@@ -344,14 +372,25 @@ load_inode (struct node **npp, struct dirrect *record, - if (!np) - { - free (dn); -- pthread_spin_unlock (&diskfs_node_refcnt_lock); - 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_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_rwlock_unlock (&nodecache_lock); - - err = read_disknode (np, record, rr); - *npp = np; -@@ -505,9 +544,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 +557,34 @@ diskfs_node_norefs (struct node *np) - void - diskfs_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. */ -+ unsigned int references; -+ pthread_spin_lock (&diskfs_node_refcnt_lock); -+ references = np->references; -+ pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ -+ /* An additional reference is acquired by libdiskfs across calls -+ to diskfs_try_dropping_softrefs. */ -+ if (references > 1) -+ { -+ /* 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); - } - --- -2.0.0.rc2 - |