cache->max_size = max_size;
}
-static struct btrfs_lru_cache_entry *match_entry(struct list_head *head, u64 key)
+static struct btrfs_lru_cache_entry *match_entry(struct list_head *head, u64 key,
+ u64 gen)
{
struct btrfs_lru_cache_entry *entry;
list_for_each_entry(entry, head, list) {
- if (entry->key == key)
+ if (entry->key == key && entry->gen == gen)
return entry;
}
*
* @cache: The cache.
* @key: The key of the entry we are looking for.
+ * @gen: Generation associated to the key.
*
* Returns the entry associated with the key or NULL if none found.
*/
struct btrfs_lru_cache_entry *btrfs_lru_cache_lookup(struct btrfs_lru_cache *cache,
- u64 key)
+ u64 key, u64 gen)
{
struct list_head *head;
struct btrfs_lru_cache_entry *entry;
if (!head)
return NULL;
- entry = match_entry(head, key);
+ entry = match_entry(head, key, gen);
if (entry)
list_move_tail(&entry->lru_list, &cache->lru_list);
kfree(head);
head = mtree_load(&cache->entries, key);
ASSERT(head != NULL);
- if (match_entry(head, key) != NULL)
+ if (match_entry(head, key, new_entry->gen) != NULL)
return -EEXIST;
list_add_tail(&new_entry->list, head);
} else if (ret < 0) {
struct list_head lru_list;
u64 key;
/*
+ * Optional generation associated to a key. Use 0 if not needed/used.
+ * Entries with the same key and different generations are stored in a
+ * linked list, so use this only for cases where there's a small number
+ * of different generations.
+ */
+ u64 gen;
+ /*
* The maple tree uses unsigned long type for the keys, which is 32 bits
* on 32 bits systems, and 64 bits on 64 bits systems. So if we want to
* use something like inode numbers as keys, which are always a u64, we
void btrfs_lru_cache_init(struct btrfs_lru_cache *cache, unsigned int max_size);
struct btrfs_lru_cache_entry *btrfs_lru_cache_lookup(struct btrfs_lru_cache *cache,
- u64 key);
+ u64 key, u64 gen);
int btrfs_lru_cache_store(struct btrfs_lru_cache *cache,
struct btrfs_lru_cache_entry *new_entry,
gfp_t gfp);
/*
* Max number of entries in the cache that stores directories that were already
* created. The cache uses raw struct btrfs_lru_cache_entry entries, so it uses
- * at most 4096 bytes - sizeof(struct btrfs_lru_cache_entry) is 40 bytes, but
+ * at most 4096 bytes - sizeof(struct btrfs_lru_cache_entry) is 48 bytes, but
* the kmalloc-64 slab is used, so we get 4096 bytes (64 bytes * 64).
*/
#define SEND_MAX_DIR_CREATED_CACHE_SIZE 64
return false;
}
- raw_entry = btrfs_lru_cache_lookup(&sctx->backref_cache, key);
+ raw_entry = btrfs_lru_cache_lookup(&sctx->backref_cache, key, 0);
if (!raw_entry)
return false;
return;
new_entry->entry.key = leaf_bytenr >> fs_info->sectorsize_bits;
+ new_entry->entry.gen = 0;
new_entry->num_roots = 0;
ULIST_ITER_INIT(&uiter);
while ((node = ulist_next(root_ids, &uiter)) != NULL) {
return;
entry->key = dir;
+ entry->gen = 0;
ret = btrfs_lru_cache_store(&sctx->dir_created_cache, entry, GFP_KERNEL);
if (ret < 0)
kfree(entry);
struct btrfs_key di_key;
struct btrfs_dir_item *di;
- if (btrfs_lru_cache_lookup(&sctx->dir_created_cache, dir))
+ if (btrfs_lru_cache_lookup(&sctx->dir_created_cache, dir, 0))
return 1;
path = alloc_path_for_send();