forked from Minki/linux
dm snapshot: use dm-bufio
Use dm-bufio for initial loading of the exceptions. Introduce a new function dm_bufio_forget that frees the given buffer. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
parent
2cadabd512
commit
55494bf294
@ -238,6 +238,7 @@ config DM_CRYPT
|
|||||||
config DM_SNAPSHOT
|
config DM_SNAPSHOT
|
||||||
tristate "Snapshot target"
|
tristate "Snapshot target"
|
||||||
depends on BLK_DEV_DM
|
depends on BLK_DEV_DM
|
||||||
|
select DM_BUFIO
|
||||||
---help---
|
---help---
|
||||||
Allow volume managers to take writable snapshots of a device.
|
Allow volume managers to take writable snapshots of a device.
|
||||||
|
|
||||||
|
@ -1350,6 +1350,28 @@ retry:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dm_bufio_release_move);
|
EXPORT_SYMBOL_GPL(dm_bufio_release_move);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free the given buffer.
|
||||||
|
*
|
||||||
|
* This is just a hint, if the buffer is in use or dirty, this function
|
||||||
|
* does nothing.
|
||||||
|
*/
|
||||||
|
void dm_bufio_forget(struct dm_bufio_client *c, sector_t block)
|
||||||
|
{
|
||||||
|
struct dm_buffer *b;
|
||||||
|
|
||||||
|
dm_bufio_lock(c);
|
||||||
|
|
||||||
|
b = __find(c, block);
|
||||||
|
if (b && likely(!b->hold_count) && likely(!b->state)) {
|
||||||
|
__unlink_buffer(b);
|
||||||
|
__free_buffer_wake(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
dm_bufio_unlock(c);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dm_bufio_forget);
|
||||||
|
|
||||||
unsigned dm_bufio_get_block_size(struct dm_bufio_client *c)
|
unsigned dm_bufio_get_block_size(struct dm_bufio_client *c)
|
||||||
{
|
{
|
||||||
return c->block_size;
|
return c->block_size;
|
||||||
|
@ -108,6 +108,13 @@ int dm_bufio_issue_flush(struct dm_bufio_client *c);
|
|||||||
*/
|
*/
|
||||||
void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block);
|
void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free the given buffer.
|
||||||
|
* This is just a hint, if the buffer is in use or dirty, this function
|
||||||
|
* does nothing.
|
||||||
|
*/
|
||||||
|
void dm_bufio_forget(struct dm_bufio_client *c, sector_t block);
|
||||||
|
|
||||||
unsigned dm_bufio_get_block_size(struct dm_bufio_client *c);
|
unsigned dm_bufio_get_block_size(struct dm_bufio_client *c);
|
||||||
sector_t dm_bufio_get_device_size(struct dm_bufio_client *c);
|
sector_t dm_bufio_get_device_size(struct dm_bufio_client *c);
|
||||||
sector_t dm_bufio_get_block_number(struct dm_buffer *b);
|
sector_t dm_bufio_get_block_number(struct dm_buffer *b);
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/dm-io.h>
|
#include <linux/dm-io.h>
|
||||||
|
#include "dm-bufio.h"
|
||||||
|
|
||||||
#define DM_MSG_PREFIX "persistent snapshot"
|
#define DM_MSG_PREFIX "persistent snapshot"
|
||||||
#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
|
#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
|
||||||
@ -495,27 +496,51 @@ static int read_exceptions(struct pstore *ps,
|
|||||||
void *callback_context)
|
void *callback_context)
|
||||||
{
|
{
|
||||||
int r, full = 1;
|
int r, full = 1;
|
||||||
|
struct dm_bufio_client *client;
|
||||||
|
|
||||||
|
client = dm_bufio_client_create(dm_snap_cow(ps->store->snap)->bdev,
|
||||||
|
ps->store->chunk_size << SECTOR_SHIFT,
|
||||||
|
1, 0, NULL, NULL);
|
||||||
|
|
||||||
|
if (IS_ERR(client))
|
||||||
|
return PTR_ERR(client);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keeping reading chunks and inserting exceptions until
|
* Keeping reading chunks and inserting exceptions until
|
||||||
* we find a partially full area.
|
* we find a partially full area.
|
||||||
*/
|
*/
|
||||||
for (ps->current_area = 0; full; ps->current_area++) {
|
for (ps->current_area = 0; full; ps->current_area++) {
|
||||||
r = area_io(ps, READ);
|
struct dm_buffer *bp;
|
||||||
if (r)
|
void *area;
|
||||||
return r;
|
chunk_t chunk = area_location(ps, ps->current_area);
|
||||||
|
|
||||||
r = insert_exceptions(ps, ps->area, callback, callback_context,
|
area = dm_bufio_read(client, chunk, &bp);
|
||||||
|
if (unlikely(IS_ERR(area))) {
|
||||||
|
r = PTR_ERR(area);
|
||||||
|
goto ret_destroy_bufio;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = insert_exceptions(ps, area, callback, callback_context,
|
||||||
&full);
|
&full);
|
||||||
if (r)
|
|
||||||
return r;
|
dm_bufio_release(bp);
|
||||||
|
|
||||||
|
dm_bufio_forget(client, chunk);
|
||||||
|
|
||||||
|
if (unlikely(r))
|
||||||
|
goto ret_destroy_bufio;
|
||||||
}
|
}
|
||||||
|
|
||||||
ps->current_area--;
|
ps->current_area--;
|
||||||
|
|
||||||
skip_metadata(ps);
|
skip_metadata(ps);
|
||||||
|
|
||||||
return 0;
|
r = 0;
|
||||||
|
|
||||||
|
ret_destroy_bufio:
|
||||||
|
dm_bufio_client_destroy(client);
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pstore *get_info(struct dm_exception_store *store)
|
static struct pstore *get_info(struct dm_exception_store *store)
|
||||||
|
Loading…
Reference in New Issue
Block a user