diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-12 15:55:27 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-12 15:55:27 +0200 |
commit | 81392d0937737682bbbbfa462a185dcb2dc8dd62 (patch) | |
tree | 9225ff62560850aaf53212e946bd15c0ff710d66 | |
parent | cef7f9f811be1b5201f8fd68c78747119a066245 (diff) |
add ext2fs-nodehash-lock.patch
-rw-r--r-- | debian/patches/ext2fs-nodehash-lock.patch | 147 | ||||
-rw-r--r-- | debian/patches/series | 1 |
2 files changed, 148 insertions, 0 deletions
diff --git a/debian/patches/ext2fs-nodehash-lock.patch b/debian/patches/ext2fs-nodehash-lock.patch new file mode 100644 index 00000000..2c63643c --- /dev/null +++ b/debian/patches/ext2fs-nodehash-lock.patch @@ -0,0 +1,147 @@ +diff --git a/ext2fs/inode.c b/ext2fs/inode.c +index ed78265..2264034 100644 +--- a/ext2fs/inode.c ++++ b/ext2fs/inode.c +@@ -48,6 +48,7 @@ + + static struct node *nodehash[INOHSZ]; + static size_t nodehash_nr_items; ++static pthread_mutex_t nodehash_lock = PTHREAD_MUTEX_INITIALIZER; + + static error_t read_node (struct node *np); + +@@ -71,12 +72,12 @@ diskfs_cached_lookup (ino_t inum, struct node **npp) + struct node *np; + struct disknode *dn; + +- pthread_spin_lock (&diskfs_node_refcnt_lock); ++ pthread_mutex_lock (&nodehash_lock); + for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) + if (np->cache_id == inum) + { +- np->references++; +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ diskfs_nref (np); ++ pthread_mutex_unlock (&nodehash_lock); + pthread_mutex_lock (&np->lock); + *npp = np; + return 0; +@@ -86,7 +87,7 @@ diskfs_cached_lookup (ino_t inum, struct node **npp) + dn = malloc (sizeof (struct disknode)); + if (! dn) + { +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ pthread_mutex_unlock (&nodehash_lock); + return ENOMEM; + } + dn->dirents = 0; +@@ -107,9 +108,10 @@ diskfs_cached_lookup (ino_t inum, struct node **npp) + dn->hnext->dn->hprevp = &dn->hnext; + dn->hprevp = &nodehash[INOHASH(inum)]; + nodehash[INOHASH(inum)] = np; ++ diskfs_nref_light (np); + nodehash_nr_items += 1; + +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ pthread_mutex_unlock (&nodehash_lock); + + /* Get the contents of NP off disk. */ + err = read_node (np); +@@ -140,14 +142,13 @@ ifind (ino_t inum) + { + struct node *np; + +- pthread_spin_lock (&diskfs_node_refcnt_lock); ++ pthread_mutex_lock (&nodehash_lock); + for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) + { + if (np->cache_id != inum) + continue; + +- assert (np->references); +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ pthread_mutex_unlock (&nodehash_lock); + return np; + } + assert (0); +@@ -158,11 +159,6 @@ ifind (ino_t inum) + void + diskfs_node_norefs (struct node *np) + { +- *np->dn->hprevp = np->dn->hnext; +- if (np->dn->hnext) +- np->dn->hnext->dn->hprevp = np->dn->hprevp; +- nodehash_nr_items -= 1; +- + if (np->dn->dirents) + free (np->dn->dirents); + assert (!np->dn->pager); +@@ -180,6 +176,31 @@ diskfs_node_norefs (struct node *np) + void + diskfs_try_dropping_softrefs (struct node *np) + { ++ pthread_mutex_lock (&nodehash_lock); ++ if (np->dn->hnext != NULL) ++ { ++ /* Check if someone reacquired a reference through the ++ nodehash. */ ++ unsigned int references; ++ pthread_spin_lock (&diskfs_node_refcnt_lock); ++ references = np->references; ++ pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ ++ if (references > 0) ++ { ++ pthread_mutex_unlock (&nodehash_lock); ++ return; ++ } ++ ++ *np->dn->hprevp = np->dn->hnext; ++ if (np->dn->hnext) ++ np->dn->hnext->dn->hprevp = np->dn->hprevp; ++ np->dn->hnext = NULL; ++ nodehash_nr_items -= 1; ++ diskfs_nrele_light (np); ++ } ++ pthread_mutex_unlock (&nodehash_lock); ++ + drop_pager_softrefs (np); + } + +@@ -556,12 +577,12 @@ diskfs_node_iterate (error_t (*fun)(struct node *)) + size_t num_nodes; + struct node *node, **node_list, **p; + +- pthread_spin_lock (&diskfs_node_refcnt_lock); ++ pthread_mutex_lock (&nodehash_lock); + + /* We must copy everything from the hash table into another data structure + to avoid running into any problems with the hash-table being modified + during processing (normally we delegate access to hash-table with +- diskfs_node_refcnt_lock, but we can't hold this while locking the ++ nodehash_lock, but we can't hold this while locking the + individual node locks). */ + num_nodes = nodehash_nr_items; + +@@ -570,7 +591,7 @@ diskfs_node_iterate (error_t (*fun)(struct node *)) + node_list = malloc (num_nodes * sizeof (struct node *)); + if (node_list == NULL) + { +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ pthread_mutex_unlock (&nodehash_lock); + ext2_debug ("unable to allocate temporary node table"); + return ENOMEM; + } +@@ -580,10 +601,10 @@ diskfs_node_iterate (error_t (*fun)(struct node *)) + for (node = nodehash[n]; node; node = node->dn->hnext) + { + *p++ = node; +- node->references++; ++ diskfs_nref (node); + } + +- pthread_spin_unlock (&diskfs_node_refcnt_lock); ++ pthread_mutex_unlock (&nodehash_lock); + + p = node_list; + while (num_nodes-- > 0) diff --git a/debian/patches/series b/debian/patches/series index 1c6ce664..7189b96c 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -52,3 +52,4 @@ ext2fs-cache-superblock.patch 0009-ext2fs-improve-enable-disable-_caching.patch 0010-fatfs-improve-enable-disable-_caching.patch +ext2fs-nodehash-lock.patch |