diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
commit | 78c388aed2b7184182c08428db1de6c872d815f5 (patch) | |
tree | 4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /fs/hfs/catalog.c | |
parent | eb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff) |
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'fs/hfs/catalog.c')
-rw-r--r-- | fs/hfs/catalog.c | 134 |
1 files changed, 72 insertions, 62 deletions
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c index 2435ceb31..306c018e7 100644 --- a/fs/hfs/catalog.c +++ b/fs/hfs/catalog.c @@ -127,17 +127,15 @@ static inline hfs_u32 brec_to_id(struct hfs_brec *brec) * * hash an (struct mdb *) and a (struct hfs_cat_key *) to an integer. */ -static inline unsigned long hashfn(const struct hfs_mdb *mdb, +static inline unsigned int hashfn(const struct hfs_mdb *mdb, const struct hfs_cat_key *key) { -#define LSB(X) (((unsigned char *)(&X))[3]) - unsigned long hash; + unsigned int hash; - hash = (unsigned long) mdb | (unsigned long) key->ParID[3] | - hfs_strhash(&key->CName); + hash = (unsigned long) mdb | (unsigned long) key->ParID[3] | + hfs_strhash(key->CName.Name, key->CName.Len); hash = hash ^ (hash >> C_HASHBITS) ^ (hash >> C_HASHBITS*2); return hash & C_HASHMASK; -#undef LSB } /* @@ -533,7 +531,6 @@ add_new_entry: HFS_BKEY(key), HFS_BFIND_READ_EQ)) { /* uh oh. we failed to read the record. * the entry doesn't actually exist. */ - entry->state |= HFS_DELETED; goto read_fail; } @@ -564,12 +561,14 @@ add_new_entry: return NULL; read_fail: - /* spinlock unlocked already. we don't need to mark the entry - * dirty here because we know that it doesn't exist. */ - remove_hash(entry); - entry->state &= ~HFS_LOCK; - hfs_wake_up(&entry->wait); - hfs_cat_put(entry); + /* short-cut hfs_cat_put by doing everything here. */ + spin_lock(&entry_lock); + list_del(&entry->hash); + list_del(&entry->list); + init_entry(entry); + list_add(&entry->list, &entry_unused); + entries_stat.nr_free_entries++; + spin_unlock(&entry_lock); return NULL; } @@ -586,6 +585,11 @@ static struct hfs_cat_entry *get_entry(struct hfs_mdb *mdb, { struct hfs_cat_entry * entry; +#if defined(DEBUG_CATALOG) || defined(DEBUG_ALL) + hfs_warn("hfs_get_entry: mdb=%p key=%s read=%d\n", + mdb, key->CName.Name, read); +#endif + spin_lock(&entry_lock); entry = find_entry(mdb, key); if (!entry) { @@ -759,6 +763,7 @@ static int create_entry(struct hfs_cat_entry *parent, struct hfs_cat_key *key, /* complete the cache entry and return success */ __read_entry(entry, record); unlock_entry(entry); + if (result) { *result = entry; } else { @@ -786,17 +791,7 @@ done: * * Release an entry we aren't using anymore. * - * NOTE: We must be careful any time we sleep on a non-deleted - * entry that the entry is in a consistent state, since another - * process may get the entry while we sleep. That is why we - * 'goto repeat' after each operation that might sleep. - * - * ADDITIONAL NOTE: the sys_entries will remove themselves from - * the sys_entry list on the final iput, so we don't need - * to worry about them here. - * - * nothing in hfs_cat_put goes to sleep now except - * on the initial entry. + * nothing in hfs_cat_put goes to sleep now except on the initial entry. */ void hfs_cat_put(struct hfs_cat_entry * entry) { @@ -810,9 +805,13 @@ void hfs_cat_put(struct hfs_cat_entry * entry) return; } +#if defined(DEBUG_CATALOG) || defined(DEBUG_ALL) + hfs_warn("hfs_cat_put: %p(%u) type=%d state=%lu\n", + entry, entry->count, entry->type, entry->state); +#endif spin_lock(&entry_lock); if (!--entry->count) { - if ((entry->state & HFS_DELETED)) + if ((entry->state & HFS_DELETED)) goto entry_deleted; if ((entry->type == HFS_CDR_FIL)) { @@ -840,10 +839,7 @@ entry_deleted: /* deleted entries have already been removed HFS_DELETE(entry); entries_stat.nr_entries--; } else { - spin_unlock(&entry_lock); - wait_on_entry(entry); init_entry(entry); - spin_lock(&entry_lock); list_add(&entry->list, &entry_unused); entries_stat.nr_free_entries++; } @@ -919,7 +915,7 @@ static void delete_list(struct list_head *head) * hfs_cat_invalidate() * * Called by hfs_mdb_put() to remove all the entries - * in the cache which are associated with a given MDB. + * in the cache that are associated with a given MDB. */ void hfs_cat_invalidate(struct hfs_mdb *mdb) { @@ -931,6 +927,11 @@ void hfs_cat_invalidate(struct hfs_mdb *mdb) spin_unlock(&entry_lock); delete_list(&throw_away); +#if defined(DEBUG_CATALOG) || defined(DEBUG_ALL) + hfs_warn("hfs_cat_invalidate: free=%d total=%d\n", + entries_stat.nr_free_entries, + entries_stat.nr_entries); +#endif } /* @@ -941,7 +942,7 @@ void hfs_cat_invalidate(struct hfs_mdb *mdb) void hfs_cat_commit(struct hfs_mdb *mdb) { struct list_head *tmp, *head = &mdb->entry_dirty; - struct hfs_cat_entry * entry; + struct hfs_cat_entry *entry; spin_lock(&entry_lock); while ((tmp = head->prev) != head) { @@ -1018,7 +1019,8 @@ int hfs_cat_compare(const struct hfs_cat_key *key1, if (parents != 0) { retval = (int)parents; } else { - retval = hfs_strcmp(&key1->CName, &key2->CName); + retval = hfs_strcmp(key1->CName.Name, key1->CName.Len, + key2->CName.Name, key2->CName.Len); } return retval; } @@ -1170,9 +1172,6 @@ struct hfs_cat_entry *hfs_cat_parent(struct hfs_cat_entry *entry) * Create a new file with the indicated name in the indicated directory. * The file will have the indicated flags, type and creator. * If successful an (struct hfs_cat_entry) is returned in '*result'. - * - * XXX: the presence of "record" probably means that the following two - * aren't currently SMP safe and need spinlocks. */ int hfs_cat_create(struct hfs_cat_entry *parent, struct hfs_cat_key *key, hfs_u8 flags, hfs_u32 type, hfs_u32 creator, @@ -1182,6 +1181,10 @@ int hfs_cat_create(struct hfs_cat_entry *parent, struct hfs_cat_key *key, hfs_u32 id = new_cnid(parent->mdb); hfs_u32 mtime = hfs_time(); +#if defined(DEBUG_CATALOG) || defined(DEBUG_ALL) + hfs_warn("hfs_cat_create: %p/%s flags=%d res=%p\n", + parent, key->CName.Name, flags, result); +#endif /* init some fields for the file record */ memset(&record, 0, sizeof(record)); record.cdrType = HFS_CDR_FIL; @@ -1209,6 +1212,11 @@ int hfs_cat_mkdir(struct hfs_cat_entry *parent, struct hfs_cat_key *key, hfs_u32 id = new_cnid(parent->mdb); hfs_u32 mtime = hfs_time(); +#if defined(DEBUG_CATALOG) || defined(DEBUG_ALL) + hfs_warn("hfs_cat_mkdir: %p/%s res=%p\n", parent, key->CName.Name, + result); +#endif + /* init some fields for the directory record */ memset(&record, 0, sizeof(record)); record.cdrType = HFS_CDR_DIR; @@ -1234,6 +1242,10 @@ int hfs_cat_delete(struct hfs_cat_entry *parent, struct hfs_cat_entry *entry, struct hfs_mdb *mdb = parent->mdb; int is_dir, error = 0; +#if defined(DEBUG_CATALOG) || defined(DEBUG_ALL) + hfs_warn("hfs_cat_delete: %p/%p type=%d state=%lu, thread=%d\n", + parent, entry, entry->type, entry->state, with_thread); +#endif if (parent->mdb != entry->mdb) { return -EINVAL; } @@ -1252,39 +1264,39 @@ int hfs_cat_delete(struct hfs_cat_entry *parent, struct hfs_cat_entry *entry, if (entry->type == HFS_CDR_DIR) { start_read(entry); - if (entry->u.dir.files || entry->u.dir.dirs) { - error = -ENOTEMPTY; - } + error = -ENOTEMPTY; + if (entry->u.dir.files || entry->u.dir.dirs) + goto hfs_delete_end; } /* try to delete the file or directory */ - if (!error) { - lock_entry(entry); - if ((entry->state & HFS_DELETED)) { - /* somebody beat us to it */ - error = -ENOENT; - } else { - error = hfs_bdelete(mdb->cat_tree, - HFS_BKEY(&entry->key)); - } - unlock_entry(entry); + lock_entry(entry); + error = -ENOENT; + if ((entry->state & HFS_DELETED)) { + /* somebody beat us to it. */ + goto hfs_delete_unlock; + } + + /* delete the catalog record */ + if ((error = hfs_bdelete(mdb->cat_tree, HFS_BKEY(&entry->key)))) { + goto hfs_delete_unlock; } - if (!error) { - /* Mark the entry deleted and remove it from the cache */ - lock_entry(entry); - delete_entry(entry); - - /* try to delete the thread entry if it exists */ - if (with_thread) { - hfs_cat_build_key(entry->cnid, NULL, &key); - (void)hfs_bdelete(mdb->cat_tree, HFS_BKEY(&key)); - } + /* Mark the entry deleted and remove it from the cache */ + delete_entry(entry); - unlock_entry(entry); - update_dir(mdb, parent, is_dir, -1); + /* try to delete the thread entry if it exists */ + if (with_thread) { + hfs_cat_build_key(entry->cnid, NULL, &key); + (void)hfs_bdelete(mdb->cat_tree, HFS_BKEY(&key)); } + + update_dir(mdb, parent, is_dir, -1); + +hfs_delete_unlock: + unlock_entry(entry); +hfs_delete_end: if (entry->type == HFS_CDR_DIR) { end_read(entry); } @@ -1332,10 +1344,10 @@ int hfs_cat_move(struct hfs_cat_entry *old_dir, struct hfs_cat_entry *new_dir, return -EINVAL; } - spin_lock(&entry_lock); while (mdb->rename_lock) { hfs_sleep_on(&mdb->rename_wait); } + spin_lock(&entry_lock); mdb->rename_lock = 1; spin_unlock(&entry_lock); @@ -1575,5 +1587,3 @@ void hfs_cat_init(void) i--; } while (i); } - - |