dm space map disk: cache a small number of index entries
The disk space map stores it's index entries in a btree, these are accessed very frequently, so having a few cached makes a big difference to performance. With this change provisioning a new block takes roughly 20% less cpu. Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
parent
be500ed721
commit
6b06dd5a97
@ -7,6 +7,7 @@
|
|||||||
#include "dm-space-map-common.h"
|
#include "dm-space-map-common.h"
|
||||||
#include "dm-transaction-manager.h"
|
#include "dm-transaction-manager.h"
|
||||||
#include "dm-btree-internal.h"
|
#include "dm-btree-internal.h"
|
||||||
|
#include "dm-persistent-data-internal.h"
|
||||||
|
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/device-mapper.h>
|
#include <linux/device-mapper.h>
|
||||||
@ -1083,28 +1084,92 @@ int sm_ll_open_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm,
|
|||||||
|
|
||||||
/*----------------------------------------------------------------*/
|
/*----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static inline int ie_cache_writeback(struct ll_disk *ll, struct ie_cache *iec)
|
||||||
|
{
|
||||||
|
iec->dirty = false;
|
||||||
|
__dm_bless_for_disk(iec->ie);
|
||||||
|
return dm_btree_insert(&ll->bitmap_info, ll->bitmap_root,
|
||||||
|
&iec->index, &iec->ie, &ll->bitmap_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned hash_index(dm_block_t index)
|
||||||
|
{
|
||||||
|
return dm_hash_block(index, IE_CACHE_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
static int disk_ll_load_ie(struct ll_disk *ll, dm_block_t index,
|
static int disk_ll_load_ie(struct ll_disk *ll, dm_block_t index,
|
||||||
struct disk_index_entry *ie)
|
struct disk_index_entry *ie)
|
||||||
{
|
{
|
||||||
return dm_btree_lookup(&ll->bitmap_info, ll->bitmap_root, &index, ie);
|
int r;
|
||||||
|
unsigned h = hash_index(index);
|
||||||
|
struct ie_cache *iec = ll->ie_cache + h;
|
||||||
|
|
||||||
|
if (iec->valid) {
|
||||||
|
if (iec->index == index) {
|
||||||
|
memcpy(ie, &iec->ie, sizeof(*ie));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iec->dirty) {
|
||||||
|
r = ie_cache_writeback(ll, iec);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = dm_btree_lookup(&ll->bitmap_info, ll->bitmap_root, &index, ie);
|
||||||
|
if (!r) {
|
||||||
|
iec->valid = true;
|
||||||
|
iec->dirty = false;
|
||||||
|
iec->index = index;
|
||||||
|
memcpy(&iec->ie, ie, sizeof(*ie));
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int disk_ll_save_ie(struct ll_disk *ll, dm_block_t index,
|
static int disk_ll_save_ie(struct ll_disk *ll, dm_block_t index,
|
||||||
struct disk_index_entry *ie)
|
struct disk_index_entry *ie)
|
||||||
{
|
{
|
||||||
__dm_bless_for_disk(ie);
|
int r;
|
||||||
return dm_btree_insert(&ll->bitmap_info, ll->bitmap_root,
|
unsigned h = hash_index(index);
|
||||||
&index, ie, &ll->bitmap_root);
|
struct ie_cache *iec = ll->ie_cache + h;
|
||||||
|
|
||||||
|
ll->bitmap_index_changed = true;
|
||||||
|
if (iec->valid) {
|
||||||
|
if (iec->index == index) {
|
||||||
|
memcpy(&iec->ie, ie, sizeof(*ie));
|
||||||
|
iec->dirty = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iec->dirty) {
|
||||||
|
r = ie_cache_writeback(ll, iec);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iec->valid = true;
|
||||||
|
iec->dirty = true;
|
||||||
|
iec->index = index;
|
||||||
|
memcpy(&iec->ie, ie, sizeof(*ie));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int disk_ll_init_index(struct ll_disk *ll)
|
static int disk_ll_init_index(struct ll_disk *ll)
|
||||||
{
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < IE_CACHE_SIZE; i++) {
|
||||||
|
struct ie_cache *iec = ll->ie_cache + i;
|
||||||
|
iec->valid = false;
|
||||||
|
iec->dirty = false;
|
||||||
|
}
|
||||||
return dm_btree_empty(&ll->bitmap_info, &ll->bitmap_root);
|
return dm_btree_empty(&ll->bitmap_info, &ll->bitmap_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int disk_ll_open(struct ll_disk *ll)
|
static int disk_ll_open(struct ll_disk *ll)
|
||||||
{
|
{
|
||||||
/* nothing to do */
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1115,7 +1180,16 @@ static dm_block_t disk_ll_max_entries(struct ll_disk *ll)
|
|||||||
|
|
||||||
static int disk_ll_commit(struct ll_disk *ll)
|
static int disk_ll_commit(struct ll_disk *ll)
|
||||||
{
|
{
|
||||||
return 0;
|
int r = 0;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < IE_CACHE_SIZE; i++) {
|
||||||
|
struct ie_cache *iec = ll->ie_cache + i;
|
||||||
|
if (iec->valid && iec->dirty)
|
||||||
|
r = ie_cache_writeback(ll, iec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sm_ll_new_disk(struct ll_disk *ll, struct dm_transaction_manager *tm)
|
int sm_ll_new_disk(struct ll_disk *ll, struct dm_transaction_manager *tm)
|
||||||
|
@ -54,6 +54,20 @@ typedef int (*open_index_fn)(struct ll_disk *ll);
|
|||||||
typedef dm_block_t (*max_index_entries_fn)(struct ll_disk *ll);
|
typedef dm_block_t (*max_index_entries_fn)(struct ll_disk *ll);
|
||||||
typedef int (*commit_fn)(struct ll_disk *ll);
|
typedef int (*commit_fn)(struct ll_disk *ll);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A lot of time can be wasted reading and writing the same
|
||||||
|
* index entry. So we cache a few entries.
|
||||||
|
*/
|
||||||
|
#define IE_CACHE_SIZE 64
|
||||||
|
#define IE_CACHE_MASK (IE_CACHE_SIZE - 1)
|
||||||
|
|
||||||
|
struct ie_cache {
|
||||||
|
bool valid;
|
||||||
|
bool dirty;
|
||||||
|
dm_block_t index;
|
||||||
|
struct disk_index_entry ie;
|
||||||
|
};
|
||||||
|
|
||||||
struct ll_disk {
|
struct ll_disk {
|
||||||
struct dm_transaction_manager *tm;
|
struct dm_transaction_manager *tm;
|
||||||
struct dm_btree_info bitmap_info;
|
struct dm_btree_info bitmap_info;
|
||||||
@ -79,6 +93,8 @@ struct ll_disk {
|
|||||||
max_index_entries_fn max_entries;
|
max_index_entries_fn max_entries;
|
||||||
commit_fn commit;
|
commit_fn commit;
|
||||||
bool bitmap_index_changed:1;
|
bool bitmap_index_changed:1;
|
||||||
|
|
||||||
|
struct ie_cache ie_cache[IE_CACHE_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct disk_sm_root {
|
struct disk_sm_root {
|
||||||
|
Loading…
Reference in New Issue
Block a user