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_TRANSACTION_MANAGER_H 83241b1d3SJoe Thornber #define _LINUX_DM_TRANSACTION_MANAGER_H 93241b1d3SJoe Thornber 103241b1d3SJoe Thornber #include "dm-block-manager.h" 113241b1d3SJoe Thornber 123241b1d3SJoe Thornber struct dm_transaction_manager; 133241b1d3SJoe Thornber struct dm_space_map; 143241b1d3SJoe Thornber 153241b1d3SJoe Thornber /*----------------------------------------------------------------*/ 163241b1d3SJoe Thornber 173241b1d3SJoe Thornber /* 183241b1d3SJoe Thornber * This manages the scope of a transaction. It also enforces immutability 193241b1d3SJoe Thornber * of the on-disk data structures by limiting access to writeable blocks. 203241b1d3SJoe Thornber * 213241b1d3SJoe Thornber * Clients should not fiddle with the block manager directly. 223241b1d3SJoe Thornber */ 233241b1d3SJoe Thornber 243241b1d3SJoe Thornber void dm_tm_destroy(struct dm_transaction_manager *tm); 253241b1d3SJoe Thornber 263241b1d3SJoe Thornber /* 273241b1d3SJoe Thornber * The non-blocking version of a transaction manager is intended for use in 283241b1d3SJoe Thornber * fast path code that needs to do lookups e.g. a dm mapping function. 293241b1d3SJoe Thornber * You create the non-blocking variant from a normal tm. The interface is 303241b1d3SJoe Thornber * the same, except that most functions will just return -EWOULDBLOCK. 313241b1d3SJoe Thornber * Methods that return void yet may block should not be called on a clone 323241b1d3SJoe Thornber * viz. dm_tm_inc, dm_tm_dec. Call dm_tm_destroy() as you would with a normal 333241b1d3SJoe Thornber * tm when you've finished with it. You may not destroy the original prior 343241b1d3SJoe Thornber * to clones. 353241b1d3SJoe Thornber */ 363241b1d3SJoe Thornber struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transaction_manager *real); 373241b1d3SJoe Thornber 383241b1d3SJoe Thornber /* 393241b1d3SJoe Thornber * We use a 2-phase commit here. 403241b1d3SJoe Thornber * 41a9d45396SJoe Thornber * i) Make all changes for the transaction *except* for the superblock. 42a9d45396SJoe Thornber * Then call dm_tm_pre_commit() to flush them to disk. 433241b1d3SJoe Thornber * 44a9d45396SJoe Thornber * ii) Lock your superblock. Update. Then call dm_tm_commit() which will 45a9d45396SJoe Thornber * unlock the superblock and flush it. No other blocks should be updated 46a9d45396SJoe Thornber * during this period. Care should be taken to never unlock a partially 47a9d45396SJoe Thornber * updated superblock; perform any operations that could fail *before* you 48a9d45396SJoe Thornber * take the superblock lock. 493241b1d3SJoe Thornber */ 503241b1d3SJoe Thornber int dm_tm_pre_commit(struct dm_transaction_manager *tm); 51a9d45396SJoe Thornber int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *superblock); 523241b1d3SJoe Thornber 533241b1d3SJoe Thornber /* 543241b1d3SJoe Thornber * These methods are the only way to get hold of a writeable block. 553241b1d3SJoe Thornber */ 563241b1d3SJoe Thornber 573241b1d3SJoe Thornber /* 583241b1d3SJoe Thornber * dm_tm_new_block() is pretty self-explanatory. Make sure you do actually 593241b1d3SJoe Thornber * write to the whole of @data before you unlock, otherwise you could get 603241b1d3SJoe Thornber * a data leak. (The other option is for tm_new_block() to zero new blocks 613241b1d3SJoe Thornber * before handing them out, which will be redundant in most, if not all, 623241b1d3SJoe Thornber * cases). 633241b1d3SJoe Thornber * Zeroes the new block and returns with write lock held. 643241b1d3SJoe Thornber */ 653241b1d3SJoe Thornber int dm_tm_new_block(struct dm_transaction_manager *tm, 663241b1d3SJoe Thornber struct dm_block_validator *v, 673241b1d3SJoe Thornber struct dm_block **result); 683241b1d3SJoe Thornber 693241b1d3SJoe Thornber /* 703241b1d3SJoe Thornber * dm_tm_shadow_block() allocates a new block and copies the data from @orig 713241b1d3SJoe Thornber * to it. It then decrements the reference count on original block. Use 723241b1d3SJoe Thornber * this to update the contents of a block in a data structure, don't 733241b1d3SJoe Thornber * confuse this with a clone - you shouldn't access the orig block after 743241b1d3SJoe Thornber * this operation. Because the tm knows the scope of the transaction it 753241b1d3SJoe Thornber * can optimise requests for a shadow of a shadow to a no-op. Don't forget 763241b1d3SJoe Thornber * to unlock when you've finished with the shadow. 773241b1d3SJoe Thornber * 783241b1d3SJoe Thornber * The @inc_children flag is used to tell the caller whether it needs to 793241b1d3SJoe Thornber * adjust reference counts for children. (Data in the block may refer to 803241b1d3SJoe Thornber * other blocks.) 813241b1d3SJoe Thornber * 823241b1d3SJoe Thornber * Shadowing implicitly drops a reference on @orig so you must not have 833241b1d3SJoe Thornber * it locked when you call this. 843241b1d3SJoe Thornber */ 853241b1d3SJoe Thornber int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig, 863241b1d3SJoe Thornber struct dm_block_validator *v, 873241b1d3SJoe Thornber struct dm_block **result, int *inc_children); 883241b1d3SJoe Thornber 893241b1d3SJoe Thornber /* 903241b1d3SJoe Thornber * Read access. You can lock any block you want. If there's a write lock 913241b1d3SJoe Thornber * on it outstanding then it'll block. 923241b1d3SJoe Thornber */ 933241b1d3SJoe Thornber int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b, 943241b1d3SJoe Thornber struct dm_block_validator *v, 953241b1d3SJoe Thornber struct dm_block **result); 963241b1d3SJoe Thornber 974c7da06fSMikulas Patocka void dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b); 983241b1d3SJoe Thornber 993241b1d3SJoe Thornber /* 1003241b1d3SJoe Thornber * Functions for altering the reference count of a block directly. 1013241b1d3SJoe Thornber */ 1023241b1d3SJoe Thornber void dm_tm_inc(struct dm_transaction_manager *tm, dm_block_t b); 103*be500ed7SJoe Thornber void dm_tm_inc_range(struct dm_transaction_manager *tm, dm_block_t b, dm_block_t e); 1043241b1d3SJoe Thornber void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b); 105*be500ed7SJoe Thornber void dm_tm_dec_range(struct dm_transaction_manager *tm, dm_block_t b, dm_block_t e); 106*be500ed7SJoe Thornber 107*be500ed7SJoe Thornber /* 108*be500ed7SJoe Thornber * Builds up runs of adjacent blocks, and then calls the given fn 109*be500ed7SJoe Thornber * (typically dm_tm_inc/dec). Very useful when you have to perform 110*be500ed7SJoe Thornber * the same tm operation on all values in a btree leaf. 111*be500ed7SJoe Thornber */ 112*be500ed7SJoe Thornber typedef void (*dm_tm_run_fn)(struct dm_transaction_manager *, dm_block_t, dm_block_t); 113*be500ed7SJoe Thornber void dm_tm_with_runs(struct dm_transaction_manager *tm, 114*be500ed7SJoe Thornber const __le64 *value_le, unsigned count, dm_tm_run_fn fn); 1153241b1d3SJoe Thornber 1164eafdb15SJoe Thornber int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b, uint32_t *result); 1174eafdb15SJoe Thornber 1184eafdb15SJoe Thornber /* 1194eafdb15SJoe Thornber * Finds out if a given block is shared (ie. has a reference count higher 1204eafdb15SJoe Thornber * than one). 1214eafdb15SJoe Thornber */ 1224eafdb15SJoe Thornber int dm_tm_block_is_shared(struct dm_transaction_manager *tm, dm_block_t b, 1234eafdb15SJoe Thornber int *result); 1243241b1d3SJoe Thornber 1253241b1d3SJoe Thornber struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm); 1263241b1d3SJoe Thornber 1273241b1d3SJoe Thornber /* 1284646015dSJoe Thornber * If you're using a non-blocking clone the tm will build up a list of 1294646015dSJoe Thornber * requested blocks that weren't in core. This call will request those 1304646015dSJoe Thornber * blocks to be prefetched. 1314646015dSJoe Thornber */ 1324646015dSJoe Thornber void dm_tm_issue_prefetches(struct dm_transaction_manager *tm); 1334646015dSJoe Thornber 1344646015dSJoe Thornber /* 1353241b1d3SJoe Thornber * A little utility that ties the knot by producing a transaction manager 1363241b1d3SJoe Thornber * that has a space map managed by the transaction manager... 1373241b1d3SJoe Thornber * 1383241b1d3SJoe Thornber * Returns a tm that has an open transaction to write the new disk sm. 1393241b1d3SJoe Thornber * Caller should store the new sm root and commit. 140384ef0e6SJoe Thornber * 141384ef0e6SJoe Thornber * The superblock location is passed so the metadata space map knows it 142384ef0e6SJoe Thornber * shouldn't be used. 1433241b1d3SJoe Thornber */ 1443241b1d3SJoe Thornber int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, 1453241b1d3SJoe Thornber struct dm_transaction_manager **tm, 146384ef0e6SJoe Thornber struct dm_space_map **sm); 1473241b1d3SJoe Thornber 1483241b1d3SJoe Thornber int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, 149384ef0e6SJoe Thornber void *sm_root, size_t root_len, 1503241b1d3SJoe Thornber struct dm_transaction_manager **tm, 151384ef0e6SJoe Thornber struct dm_space_map **sm); 1523241b1d3SJoe Thornber 1533241b1d3SJoe Thornber #endif /* _LINUX_DM_TRANSACTION_MANAGER_H */ 154