| 1024 | } |
| 1025 | |
| 1026 | int bcache_write(struct filemgr *file, |
| 1027 | bid_t bid, |
| 1028 | void *buf, |
| 1029 | bcache_dirty_t dirty, |
| 1030 | bool final_write) |
| 1031 | { |
| 1032 | struct hash_elem *h = NULL; |
| 1033 | struct bcache_item *item; |
| 1034 | struct bcache_item query; |
| 1035 | struct fnamedic_item *fname_new; |
| 1036 | |
| 1037 | fname_new = file->bcache; |
| 1038 | if (fname_new == NULL) { |
| 1039 | spin_lock(&bcache_lock); |
| 1040 | fname_new = file->bcache; |
| 1041 | if (fname_new == NULL) { |
| 1042 | // filename doesn't exist in filename dictionary .. create |
| 1043 | fname_new = _fname_create(file); |
| 1044 | } |
| 1045 | spin_unlock(&bcache_lock); |
| 1046 | } |
| 1047 | |
| 1048 | // Update the access timestamp. |
| 1049 | struct timeval tp; |
| 1050 | gettimeofday(&tp, NULL); |
| 1051 | atomic_store_uint64_t(&fname_new->access_timestamp, |
| 1052 | (uint64_t) (tp.tv_sec * 1000000 + tp.tv_usec)); |
| 1053 | |
| 1054 | size_t shard_num = bid % fname_new->num_shards; |
| 1055 | // set query |
| 1056 | query.bid = bid; |
| 1057 | |
| 1058 | spin_lock(&fname_new->shards[shard_num].lock); |
| 1059 | |
| 1060 | // search hash table |
| 1061 | h = hash_find(&fname_new->shards[shard_num].hashtable, &query.hash_elem); |
| 1062 | if (h == NULL) { |
| 1063 | // cache miss |
| 1064 | // get a free block |
| 1065 | while ((item = _bcache_alloc_freeblock()) == NULL) { |
| 1066 | // no free block .. perform eviction |
| 1067 | spin_unlock(&fname_new->shards[shard_num].lock); |
| 1068 | |
| 1069 | _bcache_evict(fname_new); |
| 1070 | |
| 1071 | spin_lock(&fname_new->shards[shard_num].lock); |
| 1072 | } |
| 1073 | |
| 1074 | // re-search hash table |
| 1075 | h = hash_find(&fname_new->shards[shard_num].hashtable, &query.hash_elem); |
| 1076 | if (h == NULL) { |
| 1077 | // insert into hash table |
| 1078 | item->bid = bid; |
| 1079 | item->flag = BCACHE_FREE; |
| 1080 | hash_insert(&fname_new->shards[shard_num].hashtable, &item->hash_elem); |
| 1081 | h = &item->hash_elem; |
| 1082 | } else { |
| 1083 | // insert into freelist again |