diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-04-17 14:17:23 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-04-17 14:17:23 +0200 |
commit | 7f240848cb840544124d08b1a317309d6dc9107e (patch) | |
tree | 1c7eddb9fd1aba2f8822d6f1f1e8b2b07e858ca5 /debian/patches/0013-fatfs-port-to-libdiskfs-node-cache.patch | |
parent | cc37b9eaebce8c8f2b7c00607c7cac5e7eda6a27 (diff) |
add patch series
Diffstat (limited to 'debian/patches/0013-fatfs-port-to-libdiskfs-node-cache.patch')
-rw-r--r-- | debian/patches/0013-fatfs-port-to-libdiskfs-node-cache.patch | 499 |
1 files changed, 499 insertions, 0 deletions
diff --git a/debian/patches/0013-fatfs-port-to-libdiskfs-node-cache.patch b/debian/patches/0013-fatfs-port-to-libdiskfs-node-cache.patch new file mode 100644 index 00000000..07b9e579 --- /dev/null +++ b/debian/patches/0013-fatfs-port-to-libdiskfs-node-cache.patch @@ -0,0 +1,499 @@ +From 23a8f96ebf9430a458fa12c341d790e453cebd8f Mon Sep 17 00:00:00 2001 +From: Justus Winter <4winter@informatik.uni-hamburg.de> +Date: Thu, 16 Apr 2015 16:12:05 +0200 +Subject: [PATCH hurd 13/13] fatfs: port to libdiskfs' node cache + +--- + fatfs/dir.c | 6 +- + fatfs/fatfs.h | 17 ++-- + fatfs/inode.c | 283 +++++----------------------------------------------------- + fatfs/main.c | 6 +- + 4 files changed, 40 insertions(+), 272 deletions(-) + +diff --git a/fatfs/dir.c b/fatfs/dir.c +index 5a38c63..9eea74c 100644 +--- a/fatfs/dir.c ++++ b/fatfs/dir.c +@@ -342,7 +342,7 @@ diskfs_lookup_hard (struct node *dp, const char *name, enum lookup_type type, + + /* Here below are the spec dotdot cases. */ + else if (type == RENAME || type == REMOVE) +- np = ifind (inum); ++ np = diskfs_cached_ifind (inum); + + else if (type == LOOKUP) + { +@@ -395,7 +395,7 @@ diskfs_lookup_hard (struct node *dp, const char *name, enum lookup_type type, + diskfs_nput (np); + } + else if (type == RENAME || type == REMOVE) +- /* We just did ifind to get np; that allocates ++ /* We just did diskfs_cached_ifind to get np; that allocates + no new references, so we don't have anything to do. */ + ; + else if (type == LOOKUP) +@@ -732,7 +732,7 @@ diskfs_dirrewrite_hard (struct node *dp, struct node *np, struct dirstat *ds) + assert (err != EINVAL); + + /* Lookup the node, we already have a reference. */ +- oldnp = ifind (inode); ++ oldnp = diskfs_cached_ifind (inode); + + assert (ds->type == RENAME); + assert (ds->stat == HERE_TIS); +diff --git a/fatfs/fatfs.h b/fatfs/fatfs.h +index 9d38546..04883a1 100644 +--- a/fatfs/fatfs.h ++++ b/fatfs/fatfs.h +@@ -36,9 +36,6 @@ struct disknode + { + cluster_t start_cluster; + +- /* Links on hash list. */ +- struct node *hnext, **hprevp; +- + /* The inode as returned by virtual inode management routines. */ + inode_t inode; + +@@ -71,6 +68,18 @@ struct disknode + int dir_idx; + }; + ++struct lookup_context ++{ ++ /* The inode as returned by virtual inode management routines. */ ++ inode_t inode; ++ ++ /* xxx */ ++ vm_address_t buf; ++ ++ /* xxx */ ++ struct node *dir; ++}; ++ + struct user_pager_info + { + struct node *node; +@@ -117,8 +126,6 @@ void flush_node_pager (struct node *node); + + void write_all_disknodes (); + +-struct node *ifind (ino_t inum); +- + error_t fat_get_next_cluster (cluster_t cluster, cluster_t *next_cluster); + void fat_to_unix_filename (const char *, char *); + +diff --git a/fatfs/inode.c b/fatfs/inode.c +index f228618..a48191b 100644 +--- a/fatfs/inode.c ++++ b/fatfs/inode.c +@@ -37,69 +37,20 @@ + #define UF_IMMUTABLE 0 + #endif + +-#define INOHSZ 512 +-#if ((INOHSZ&(INOHSZ-1)) == 0) +-#define INOHASH(ino) ((ino)&(INOHSZ-1)) +-#else +-#define INOHASH(ino) (((unsigned)(ino))%INOHSZ) +-#endif +- +-/* The nodehash is a cache of nodes. +- +- Access to nodehash and nodehash_nr_items is protected by +- nodecache_lock. +- +- Every node in the nodehash 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 nodehash. */ +-static struct node *nodehash[INOHSZ]; +-static size_t nodehash_nr_items; +-static pthread_rwlock_t nodecache_lock = PTHREAD_RWLOCK_INITIALIZER; +- +-static error_t read_node (struct node *np, vm_address_t buf); +- +-/* Initialize the inode hash table. */ +-void +-inode_init () +-{ +- int n; +- for (n = 0; n < INOHSZ; n++) +- nodehash[n] = 0; +-} +- +-/* Lookup node with inode number INUM. Returns NULL if the node is +- not found in the node cache. */ +-static struct node * +-lookup (ino_t inum) +-{ +- struct node *np; +- for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) +- if (np->cache_id == inum) +- return np; +- return NULL; +-} +- +-/* Fetch inode INUM, set *NPP to the node structure; gain one user +- reference and lock the node. */ ++/* XXX */ + error_t +-diskfs_cached_lookup (ino64_t inum, struct node **npp) ++diskfs_user_make_node (struct node **npp, struct lookup_context *ctx) + { +- error_t err; +- struct node *np, *tmp; ++ struct node *np; + struct disknode *dn; + +- pthread_rwlock_rdlock (&nodecache_lock); +- np = lookup (inum); +- if (np) +- goto gotit; +- pthread_rwlock_unlock (&nodecache_lock); +- +- /* Format specific data for the new node. */ +- dn = malloc (sizeof (struct disknode)); +- if (! dn) ++ /* Create the new node. */ ++ np = diskfs_make_node_alloc (sizeof *dn); ++ if (np == NULL) + return ENOMEM; + ++ /* Format specific data for the new node. */ ++ dn = np->dn; + dn->pager = 0; + dn->first = 0; + dn->last = 0; +@@ -108,49 +59,9 @@ diskfs_cached_lookup (ino64_t inum, struct node **npp) + dn->chain_extension_lock = PTHREAD_SPINLOCK_INITIALIZER; + pthread_rwlock_init (&dn->alloc_lock, NULL); + pthread_rwlock_init (&dn->dirent_lock, NULL); +- +- /* Create the new node. */ +- np = diskfs_make_node (dn); +- np->cache_id = inum; +- np->dn->inode = vi_lookup(inum); + +- pthread_mutex_lock (&np->lock); +- +- /* Put NP in NODEHASH. */ +- pthread_rwlock_wrlock (&nodecache_lock); +- tmp = lookup (inum); +- if (tmp) +- { +- /* We lost a race. */ +- diskfs_nput (np); +- np = tmp; +- goto gotit; +- } +- +- dn->hnext = nodehash[INOHASH(inum)]; +- if (dn->hnext) +- dn->hnext->dn->hprevp = &dn->hnext; +- dn->hprevp = &nodehash[INOHASH(inum)]; +- nodehash[INOHASH(inum)] = np; +- diskfs_nref_light (np); +- nodehash_nr_items += 1; +- pthread_rwlock_unlock (&nodecache_lock); +- +- /* Get the contents of NP off disk. */ +- err = read_node (np, 0); +- +- if (err) +- return err; +- else +- { +- *npp = np; +- return 0; +- } +- +- gotit: +- diskfs_nref (np); +- pthread_rwlock_unlock (&nodecache_lock); +- pthread_mutex_lock (&np->lock); ++ dn->inode = ctx->inode; ++ dn->dirnode = ctx->dir; + *npp = np; + return 0; + } +@@ -162,78 +73,8 @@ error_t + diskfs_cached_lookup_in_dirbuf (int inum, struct node **npp, vm_address_t buf) + { + error_t err; +- struct node *np; +- struct disknode *dn; +- +- pthread_rwlock_rdlock (&nodecache_lock); +- for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) +- if (np->cache_id == inum) +- { +- diskfs_nref (np); +- pthread_rwlock_unlock (&nodecache_lock); +- pthread_mutex_lock (&np->lock); +- *npp = np; +- return 0; +- } +- pthread_rwlock_unlock (&nodecache_lock); +- +- /* Format specific data for the new node. */ +- dn = malloc (sizeof (struct disknode)); +- if (! dn) +- return ENOMEM; +- +- dn->pager = 0; +- dn->first = 0; +- dn->last = 0; +- dn->length_of_chain = 0; +- dn->chain_complete = 0; +- dn->chain_extension_lock = PTHREAD_SPINLOCK_INITIALIZER; +- pthread_rwlock_init (&dn->alloc_lock, NULL); +- pthread_rwlock_init (&dn->dirent_lock, NULL); +- +- /* Create the new node. */ +- np = diskfs_make_node (dn); +- np->cache_id = inum; +- np->dn->inode = vi_lookup(inum); +- +- pthread_mutex_lock (&np->lock); +- +- /* Put NP in NODEHASH. */ +- pthread_rwlock_wrlock (&nodecache_lock); +- dn->hnext = nodehash[INOHASH(inum)]; +- if (dn->hnext) +- dn->hnext->dn->hprevp = &dn->hnext; +- dn->hprevp = &nodehash[INOHASH(inum)]; +- nodehash[INOHASH(inum)] = np; +- diskfs_nref_light (np); +- nodehash_nr_items += 1; +- pthread_rwlock_unlock (&nodecache_lock); +- +- /* Get the contents of NP off disk. */ +- err = read_node (np, buf); +- +- if (err) +- return err; +- else +- { +- *npp = np; +- return 0; +- } +-} +- +-/* Lookup node INUM (which must have a reference already) and return +- it without allocating any new references. */ +-struct node * +-ifind (ino_t inum) +-{ +- struct node *np; +- +- pthread_rwlock_rdlock (&nodecache_lock); +- np = lookup (inum); +- pthread_rwlock_unlock (&nodecache_lock); +- +- assert (np); +- return np; ++ struct lookup_context ctx = { buf: buf, inode: vi_lookup (inum) }; ++ return diskfs_cached_lookup_context (inum, npp, &ctx); + } + + /* The last reference to a node has gone away; drop it from the hash +@@ -258,41 +99,14 @@ diskfs_node_norefs (struct node *np) + + assert (!np->dn->pager); + +- 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. */ + void +-diskfs_try_dropping_softrefs (struct node *np) ++diskfs_user_try_dropping_softrefs (struct node *np) + { +- pthread_rwlock_wrlock (&nodecache_lock); +- if (np->dn->hprevp != NULL) +- { +- /* Check if someone reacquired a reference through the +- nodehash. */ +- 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; +- } +- +- *np->dn->hprevp = np->dn->hnext; +- if (np->dn->hnext) +- np->dn->hnext->dn->hprevp = np->dn->hprevp; +- np->dn->hnext = NULL; +- np->dn->hprevp = NULL; +- nodehash_nr_items -= 1; +- diskfs_nrele_light (np); +- } +- pthread_rwlock_unlock (&nodecache_lock); +- + drop_pager_softrefs (np); + } + +@@ -311,8 +125,8 @@ diskfs_new_hardrefs (struct node *np) + } + + /* Read stat information out of the directory entry. */ +-static error_t +-read_node (struct node *np, vm_address_t buf) ++error_t ++diskfs_user_read_node (struct node *np, struct lookup_context *ctx) + { + /* XXX This needs careful investigation. */ + error_t err; +@@ -323,6 +137,7 @@ read_node (struct node *np, vm_address_t buf) + struct vi_key vk = vi_key(np->dn->inode); + vm_prot_t prot = VM_PROT_READ; + memory_object_t memobj; ++ vm_address_t buf = ctx->buf; + vm_size_t buflen = 0; + int our_buf = 0; + +@@ -359,7 +174,7 @@ read_node (struct node *np, vm_address_t buf) + /* FIXME: We know intimately that the parent dir is locked + by libdiskfs. The only case it is not locked is for NFS + (fsys_getfile) and we disabled that. */ +- dp = ifind (vk.dir_inode); ++ dp = diskfs_cached_ifind (vk.dir_inode); + assert (dp); + + /* Map in the directory contents. */ +@@ -572,7 +387,7 @@ error_t + diskfs_node_reload (struct node *node) + { + struct cluster_chain *last = node->dn->first; +- ++ static struct lookup_context ctx = { buf: 0 }; + while (last) + { + struct cluster_chain *next = last->next; +@@ -580,61 +395,8 @@ diskfs_node_reload (struct node *node) + last = next; + } + flush_node_pager (node); +- read_node (node, 0); + +- return 0; +-} +- +-/* For each active node, call FUN. The node is to be locked around the call +- to FUN. If FUN returns non-zero for any node, then immediately stop, and +- return that value. */ +-error_t +-diskfs_node_iterate (error_t (*fun)(struct node *)) +-{ +- error_t err = 0; +- int n; +- size_t num_nodes; +- struct node *node, **node_list, **p; +- +- pthread_rwlock_rdlock (&nodecache_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 +- nodecache_lock, but we can't hold this while locking the +- individual node locks). */ +- +- num_nodes = nodehash_nr_items; +- +- node_list = alloca (num_nodes * sizeof (struct node *)); +- p = node_list; +- for (n = 0; n < INOHSZ; n++) +- for (node = nodehash[n]; node; node = node->dn->hnext) +- { +- *p++ = node; +- +- /* We acquire a hard reference for node, but without using +- diskfs_nref. We do this so that diskfs_new_hardrefs will not +- get called. */ +- refcounts_ref (&node->refcounts, NULL); +- } +- +- pthread_rwlock_unlock (&nodecache_lock); +- +- p = node_list; +- while (num_nodes-- > 0) +- { +- node = *p++; +- if (!err) +- { +- pthread_mutex_lock (&node->lock); +- err = (*fun)(node); +- pthread_mutex_unlock (&node->lock); +- } +- diskfs_nrele (node); +- } +- +- return err; ++ return diskfs_user_read_node (node, &ctx); + } + + /* Write all active disknodes into the ext2_inode pager. */ +@@ -812,7 +574,8 @@ diskfs_alloc_node (struct node *dir, mode_t mode, struct node **node) + ino_t inum; + inode_t inode; + struct node *np; +- ++ struct lookup_context ctx = { dir: dir }; ++ + assert (!diskfs_readonly); + + /* FIXME: We use a magic key here that signals read_node that we are +@@ -821,12 +584,10 @@ diskfs_alloc_node (struct node *dir, mode_t mode, struct node **node) + if (err) + return err; + +- err = diskfs_cached_lookup (inum, &np); ++ err = diskfs_cached_lookup_context (inum, &np, &ctx); + if (err) + return err; + +- /* FIXME: We know that readnode couldn't put this in. */ +- np->dn->dirnode = dir; + refcounts_ref (&dir->refcounts, NULL); + + *node = np; +diff --git a/fatfs/main.c b/fatfs/main.c +index 2bbcdfa..00c56bc 100644 +--- a/fatfs/main.c ++++ b/fatfs/main.c +@@ -143,7 +143,7 @@ fetch_root () + { + error_t err; + ino_t inum; +- inode_t inode; ++ struct lookup_context ctx; + + memset (&dr_root_node, 0, sizeof(struct dirrect)); + +@@ -196,13 +196,13 @@ fetch_root () + from the vi_zero_key (in the dir_offset value) as well as all + normal virtual inode keys (in the dir_inode value). Enter the + disknode into the inode table. */ +- err = vi_new ((struct vi_key) {0, 1}, &inum, &inode); ++ err = vi_new ((struct vi_key) {0, 1}, &inum, &ctx.inode); + assert_perror (err); + + /* Allocate a node for the root directory disknode in + diskfs_root_node. */ + if (!err) +- err = diskfs_cached_lookup (inum, &diskfs_root_node); ++ err = diskfs_cached_lookup_context (inum, &diskfs_root_node, &ctx); + + assert_perror (err); + +-- +2.1.4 + |