xref: /linux/drivers/md/persistent-data/dm-block-manager.h (revision 49f154c7327139c275c9392b5fd69cad82f106bc)
13241b1d3SJoe Thornber /*
23241b1d3SJoe Thornber  * Copyright (C) 2011 Red Hat, Inc.
33241b1d3SJoe Thornber  *
43241b1d3SJoe Thornber  * This file is released under the GPL.
53241b1d3SJoe Thornber  */
63241b1d3SJoe Thornber 
73241b1d3SJoe Thornber #ifndef _LINUX_DM_BLOCK_MANAGER_H
83241b1d3SJoe Thornber #define _LINUX_DM_BLOCK_MANAGER_H
93241b1d3SJoe Thornber 
103241b1d3SJoe Thornber #include <linux/types.h>
113241b1d3SJoe Thornber #include <linux/blkdev.h>
123241b1d3SJoe Thornber 
133241b1d3SJoe Thornber /*----------------------------------------------------------------*/
143241b1d3SJoe Thornber 
153241b1d3SJoe Thornber /*
163241b1d3SJoe Thornber  * Block number.
173241b1d3SJoe Thornber  */
183241b1d3SJoe Thornber typedef uint64_t dm_block_t;
193241b1d3SJoe Thornber struct dm_block;
203241b1d3SJoe Thornber 
213241b1d3SJoe Thornber dm_block_t dm_block_location(struct dm_block *b);
223241b1d3SJoe Thornber void *dm_block_data(struct dm_block *b);
233241b1d3SJoe Thornber 
243241b1d3SJoe Thornber /*----------------------------------------------------------------*/
253241b1d3SJoe Thornber 
263241b1d3SJoe Thornber /*
273241b1d3SJoe Thornber  * @name should be a unique identifier for the block manager, no longer
283241b1d3SJoe Thornber  * than 32 chars.
293241b1d3SJoe Thornber  *
303241b1d3SJoe Thornber  * @max_held_per_thread should be the maximum number of locks, read or
313241b1d3SJoe Thornber  * write, that an individual thread holds at any one time.
323241b1d3SJoe Thornber  */
333241b1d3SJoe Thornber struct dm_block_manager;
343241b1d3SJoe Thornber struct dm_block_manager *dm_block_manager_create(
353241b1d3SJoe Thornber 	struct block_device *bdev, unsigned block_size,
363241b1d3SJoe Thornber 	unsigned cache_size, unsigned max_held_per_thread);
373241b1d3SJoe Thornber void dm_block_manager_destroy(struct dm_block_manager *bm);
383241b1d3SJoe Thornber 
393241b1d3SJoe Thornber unsigned dm_bm_block_size(struct dm_block_manager *bm);
403241b1d3SJoe Thornber dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm);
413241b1d3SJoe Thornber 
423241b1d3SJoe Thornber /*----------------------------------------------------------------*/
433241b1d3SJoe Thornber 
443241b1d3SJoe Thornber /*
453241b1d3SJoe Thornber  * The validator allows the caller to verify newly-read data and modify
463241b1d3SJoe Thornber  * the data just before writing, e.g. to calculate checksums.  It's
473241b1d3SJoe Thornber  * important to be consistent with your use of validators.  The only time
483241b1d3SJoe Thornber  * you can change validators is if you call dm_bm_write_lock_zero.
493241b1d3SJoe Thornber  */
503241b1d3SJoe Thornber struct dm_block_validator {
513241b1d3SJoe Thornber 	const char *name;
523241b1d3SJoe Thornber 	void (*prepare_for_write)(struct dm_block_validator *v, struct dm_block *b, size_t block_size);
533241b1d3SJoe Thornber 
543241b1d3SJoe Thornber 	/*
553241b1d3SJoe Thornber 	 * Return 0 if the checksum is valid or < 0 on error.
563241b1d3SJoe Thornber 	 */
573241b1d3SJoe Thornber 	int (*check)(struct dm_block_validator *v, struct dm_block *b, size_t block_size);
583241b1d3SJoe Thornber };
593241b1d3SJoe Thornber 
603241b1d3SJoe Thornber /*----------------------------------------------------------------*/
613241b1d3SJoe Thornber 
623241b1d3SJoe Thornber /*
633241b1d3SJoe Thornber  * You can have multiple concurrent readers or a single writer holding a
643241b1d3SJoe Thornber  * block lock.
653241b1d3SJoe Thornber  */
663241b1d3SJoe Thornber 
673241b1d3SJoe Thornber /*
683241b1d3SJoe Thornber  * dm_bm_lock() locks a block and returns through @result a pointer to
693241b1d3SJoe Thornber  * memory that holds a copy of that block.  If you have write-locked the
703241b1d3SJoe Thornber  * block then any changes you make to memory pointed to by @result will be
713241b1d3SJoe Thornber  * written back to the disk sometime after dm_bm_unlock is called.
723241b1d3SJoe Thornber  */
733241b1d3SJoe Thornber int dm_bm_read_lock(struct dm_block_manager *bm, dm_block_t b,
743241b1d3SJoe Thornber 		    struct dm_block_validator *v,
753241b1d3SJoe Thornber 		    struct dm_block **result);
763241b1d3SJoe Thornber 
773241b1d3SJoe Thornber int dm_bm_write_lock(struct dm_block_manager *bm, dm_block_t b,
783241b1d3SJoe Thornber 		     struct dm_block_validator *v,
793241b1d3SJoe Thornber 		     struct dm_block **result);
803241b1d3SJoe Thornber 
813241b1d3SJoe Thornber /*
823241b1d3SJoe Thornber  * The *_try_lock variants return -EWOULDBLOCK if the block isn't
833241b1d3SJoe Thornber  * available immediately.
843241b1d3SJoe Thornber  */
853241b1d3SJoe Thornber int dm_bm_read_try_lock(struct dm_block_manager *bm, dm_block_t b,
863241b1d3SJoe Thornber 			struct dm_block_validator *v,
873241b1d3SJoe Thornber 			struct dm_block **result);
883241b1d3SJoe Thornber 
893241b1d3SJoe Thornber /*
903241b1d3SJoe Thornber  * Use dm_bm_write_lock_zero() when you know you're going to
913241b1d3SJoe Thornber  * overwrite the block completely.  It saves a disk read.
923241b1d3SJoe Thornber  */
933241b1d3SJoe Thornber int dm_bm_write_lock_zero(struct dm_block_manager *bm, dm_block_t b,
943241b1d3SJoe Thornber 			  struct dm_block_validator *v,
953241b1d3SJoe Thornber 			  struct dm_block **result);
963241b1d3SJoe Thornber 
973241b1d3SJoe Thornber int dm_bm_unlock(struct dm_block *b);
983241b1d3SJoe Thornber 
993241b1d3SJoe Thornber /*
1003241b1d3SJoe Thornber  * It's a common idiom to have a superblock that should be committed last.
1013241b1d3SJoe Thornber  *
1023241b1d3SJoe Thornber  * @superblock should be write-locked on entry. It will be unlocked during
1033241b1d3SJoe Thornber  * this function.  All dirty blocks are guaranteed to be written and flushed
1043241b1d3SJoe Thornber  * before the superblock.
1053241b1d3SJoe Thornber  *
1063241b1d3SJoe Thornber  * This method always blocks.
1073241b1d3SJoe Thornber  */
108a9d45396SJoe Thornber int dm_bm_flush(struct dm_block_manager *bm);
1093241b1d3SJoe Thornber 
11004f17c80SJoe Thornber /*
1119b7aaa64SJoe Thornber  * Request data is prefetched into the cache.
11204f17c80SJoe Thornber  */
11304f17c80SJoe Thornber void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b);
11404f17c80SJoe Thornber 
11531097557SJoe Thornber /*
11631097557SJoe Thornber  * Switches the bm to a read only mode.  Once read-only mode
11731097557SJoe Thornber  * has been entered the following functions will return -EPERM.
11831097557SJoe Thornber  *
11931097557SJoe Thornber  *   dm_bm_write_lock
12031097557SJoe Thornber  *   dm_bm_write_lock_zero
12131097557SJoe Thornber  *   dm_bm_flush_and_unlock
12231097557SJoe Thornber  *
12331097557SJoe Thornber  * Additionally you should not use dm_bm_unlock_move, however no error will
12431097557SJoe Thornber  * be returned if you do.
12531097557SJoe Thornber  */
126*49f154c7SMike Snitzer bool dm_bm_is_read_only(struct dm_block_manager *bm);
12731097557SJoe Thornber void dm_bm_set_read_only(struct dm_block_manager *bm);
1289b7aaa64SJoe Thornber void dm_bm_set_read_write(struct dm_block_manager *bm);
12931097557SJoe Thornber 
1303241b1d3SJoe Thornber u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor);
1313241b1d3SJoe Thornber 
1323241b1d3SJoe Thornber /*----------------------------------------------------------------*/
1333241b1d3SJoe Thornber 
1343241b1d3SJoe Thornber #endif	/* _LINUX_DM_BLOCK_MANAGER_H */
135