summaryrefslogtreecommitdiff
path: root/isofs
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2015-04-15 16:26:31 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2015-04-17 22:16:14 +0200
commit4266bb02b1f3342d3fc4920c07c71592a14acdd9 (patch)
treea8312d2209709d962cd3f71cc3cf0b3641a6b951 /isofs
parentc234e34ad80801acd902c6d4892a7722fd084a87 (diff)
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.
Diffstat (limited to 'isofs')
-rw-r--r--isofs/inode.c326
-rw-r--r--isofs/isofs.h13
-rw-r--r--isofs/lookup.c18
-rw-r--r--isofs/main.c15
4 files changed, 70 insertions, 302 deletions
diff --git a/isofs/inode.c b/isofs/inode.c
index e79ebddb..eef2a6a4 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 68a94e93..3f6690be 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 e51b9cb1..f375212a 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 4f531f7e..95c90fe8 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);