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