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