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 #include "dm-transaction-manager.h" 73241b1d3SJoe Thornber #include "dm-space-map.h" 83241b1d3SJoe Thornber #include "dm-space-map-disk.h" 93241b1d3SJoe Thornber #include "dm-space-map-metadata.h" 103241b1d3SJoe Thornber #include "dm-persistent-data-internal.h" 113241b1d3SJoe Thornber 121944ce60SPaul Gortmaker #include <linux/export.h> 134646015dSJoe Thornber #include <linux/mutex.h> 144646015dSJoe Thornber #include <linux/hash.h> 153241b1d3SJoe Thornber #include <linux/slab.h> 163241b1d3SJoe Thornber #include <linux/device-mapper.h> 173241b1d3SJoe Thornber 183241b1d3SJoe Thornber #define DM_MSG_PREFIX "transaction manager" 193241b1d3SJoe Thornber 203241b1d3SJoe Thornber /*----------------------------------------------------------------*/ 213241b1d3SJoe Thornber 224646015dSJoe Thornber #define PREFETCH_SIZE 128 234646015dSJoe Thornber #define PREFETCH_BITS 7 244646015dSJoe Thornber #define PREFETCH_SENTINEL ((dm_block_t) -1ULL) 254646015dSJoe Thornber 264646015dSJoe Thornber struct prefetch_set { 274646015dSJoe Thornber struct mutex lock; 284646015dSJoe Thornber dm_block_t blocks[PREFETCH_SIZE]; 294646015dSJoe Thornber }; 304646015dSJoe Thornber 314646015dSJoe Thornber static unsigned prefetch_hash(dm_block_t b) 324646015dSJoe Thornber { 334646015dSJoe Thornber return hash_64(b, PREFETCH_BITS); 344646015dSJoe Thornber } 354646015dSJoe Thornber 364646015dSJoe Thornber static void prefetch_wipe(struct prefetch_set *p) 374646015dSJoe Thornber { 384646015dSJoe Thornber unsigned i; 394646015dSJoe Thornber for (i = 0; i < PREFETCH_SIZE; i++) 404646015dSJoe Thornber p->blocks[i] = PREFETCH_SENTINEL; 414646015dSJoe Thornber } 424646015dSJoe Thornber 434646015dSJoe Thornber static void prefetch_init(struct prefetch_set *p) 444646015dSJoe Thornber { 454646015dSJoe Thornber mutex_init(&p->lock); 464646015dSJoe Thornber prefetch_wipe(p); 474646015dSJoe Thornber } 484646015dSJoe Thornber 494646015dSJoe Thornber static void prefetch_add(struct prefetch_set *p, dm_block_t b) 504646015dSJoe Thornber { 514646015dSJoe Thornber unsigned h = prefetch_hash(b); 524646015dSJoe Thornber 534646015dSJoe Thornber mutex_lock(&p->lock); 544646015dSJoe Thornber if (p->blocks[h] == PREFETCH_SENTINEL) 554646015dSJoe Thornber p->blocks[h] = b; 564646015dSJoe Thornber 574646015dSJoe Thornber mutex_unlock(&p->lock); 584646015dSJoe Thornber } 594646015dSJoe Thornber 604646015dSJoe Thornber static void prefetch_issue(struct prefetch_set *p, struct dm_block_manager *bm) 614646015dSJoe Thornber { 624646015dSJoe Thornber unsigned i; 634646015dSJoe Thornber 644646015dSJoe Thornber mutex_lock(&p->lock); 654646015dSJoe Thornber 664646015dSJoe Thornber for (i = 0; i < PREFETCH_SIZE; i++) 674646015dSJoe Thornber if (p->blocks[i] != PREFETCH_SENTINEL) { 684646015dSJoe Thornber dm_bm_prefetch(bm, p->blocks[i]); 694646015dSJoe Thornber p->blocks[i] = PREFETCH_SENTINEL; 704646015dSJoe Thornber } 714646015dSJoe Thornber 724646015dSJoe Thornber mutex_unlock(&p->lock); 734646015dSJoe Thornber } 744646015dSJoe Thornber 754646015dSJoe Thornber /*----------------------------------------------------------------*/ 764646015dSJoe Thornber 773241b1d3SJoe Thornber struct shadow_info { 783241b1d3SJoe Thornber struct hlist_node hlist; 793241b1d3SJoe Thornber dm_block_t where; 803241b1d3SJoe Thornber }; 813241b1d3SJoe Thornber 823241b1d3SJoe Thornber /* 833241b1d3SJoe Thornber * It would be nice if we scaled with the size of transaction. 843241b1d3SJoe Thornber */ 85df855798SAndrew Morton #define DM_HASH_SIZE 256 86df855798SAndrew Morton #define DM_HASH_MASK (DM_HASH_SIZE - 1) 873241b1d3SJoe Thornber 883241b1d3SJoe Thornber struct dm_transaction_manager { 893241b1d3SJoe Thornber int is_clone; 903241b1d3SJoe Thornber struct dm_transaction_manager *real; 913241b1d3SJoe Thornber 923241b1d3SJoe Thornber struct dm_block_manager *bm; 933241b1d3SJoe Thornber struct dm_space_map *sm; 943241b1d3SJoe Thornber 953241b1d3SJoe Thornber spinlock_t lock; 96df855798SAndrew Morton struct hlist_head buckets[DM_HASH_SIZE]; 974646015dSJoe Thornber 984646015dSJoe Thornber struct prefetch_set prefetches; 993241b1d3SJoe Thornber }; 1003241b1d3SJoe Thornber 1013241b1d3SJoe Thornber /*----------------------------------------------------------------*/ 1023241b1d3SJoe Thornber 1033241b1d3SJoe Thornber static int is_shadow(struct dm_transaction_manager *tm, dm_block_t b) 1043241b1d3SJoe Thornber { 1053241b1d3SJoe Thornber int r = 0; 106df855798SAndrew Morton unsigned bucket = dm_hash_block(b, DM_HASH_MASK); 1073241b1d3SJoe Thornber struct shadow_info *si; 1083241b1d3SJoe Thornber 1093241b1d3SJoe Thornber spin_lock(&tm->lock); 110b67bfe0dSSasha Levin hlist_for_each_entry(si, tm->buckets + bucket, hlist) 1113241b1d3SJoe Thornber if (si->where == b) { 1123241b1d3SJoe Thornber r = 1; 1133241b1d3SJoe Thornber break; 1143241b1d3SJoe Thornber } 1153241b1d3SJoe Thornber spin_unlock(&tm->lock); 1163241b1d3SJoe Thornber 1173241b1d3SJoe Thornber return r; 1183241b1d3SJoe Thornber } 1193241b1d3SJoe Thornber 1203241b1d3SJoe Thornber /* 1213241b1d3SJoe Thornber * This can silently fail if there's no memory. We're ok with this since 1223241b1d3SJoe Thornber * creating redundant shadows causes no harm. 1233241b1d3SJoe Thornber */ 1243241b1d3SJoe Thornber static void insert_shadow(struct dm_transaction_manager *tm, dm_block_t b) 1253241b1d3SJoe Thornber { 1263241b1d3SJoe Thornber unsigned bucket; 1273241b1d3SJoe Thornber struct shadow_info *si; 1283241b1d3SJoe Thornber 1293241b1d3SJoe Thornber si = kmalloc(sizeof(*si), GFP_NOIO); 1303241b1d3SJoe Thornber if (si) { 1313241b1d3SJoe Thornber si->where = b; 132df855798SAndrew Morton bucket = dm_hash_block(b, DM_HASH_MASK); 1333241b1d3SJoe Thornber spin_lock(&tm->lock); 1343241b1d3SJoe Thornber hlist_add_head(&si->hlist, tm->buckets + bucket); 1353241b1d3SJoe Thornber spin_unlock(&tm->lock); 1363241b1d3SJoe Thornber } 1373241b1d3SJoe Thornber } 1383241b1d3SJoe Thornber 1393241b1d3SJoe Thornber static void wipe_shadow_table(struct dm_transaction_manager *tm) 1403241b1d3SJoe Thornber { 1413241b1d3SJoe Thornber struct shadow_info *si; 142b67bfe0dSSasha Levin struct hlist_node *tmp; 1433241b1d3SJoe Thornber struct hlist_head *bucket; 1443241b1d3SJoe Thornber int i; 1453241b1d3SJoe Thornber 1463241b1d3SJoe Thornber spin_lock(&tm->lock); 147df855798SAndrew Morton for (i = 0; i < DM_HASH_SIZE; i++) { 1483241b1d3SJoe Thornber bucket = tm->buckets + i; 149b67bfe0dSSasha Levin hlist_for_each_entry_safe(si, tmp, bucket, hlist) 1503241b1d3SJoe Thornber kfree(si); 1513241b1d3SJoe Thornber 1523241b1d3SJoe Thornber INIT_HLIST_HEAD(bucket); 1533241b1d3SJoe Thornber } 1543241b1d3SJoe Thornber 1553241b1d3SJoe Thornber spin_unlock(&tm->lock); 1563241b1d3SJoe Thornber } 1573241b1d3SJoe Thornber 1583241b1d3SJoe Thornber /*----------------------------------------------------------------*/ 1593241b1d3SJoe Thornber 1603241b1d3SJoe Thornber static struct dm_transaction_manager *dm_tm_create(struct dm_block_manager *bm, 1613241b1d3SJoe Thornber struct dm_space_map *sm) 1623241b1d3SJoe Thornber { 1633241b1d3SJoe Thornber int i; 1643241b1d3SJoe Thornber struct dm_transaction_manager *tm; 1653241b1d3SJoe Thornber 1663241b1d3SJoe Thornber tm = kmalloc(sizeof(*tm), GFP_KERNEL); 1673241b1d3SJoe Thornber if (!tm) 1683241b1d3SJoe Thornber return ERR_PTR(-ENOMEM); 1693241b1d3SJoe Thornber 1703241b1d3SJoe Thornber tm->is_clone = 0; 1713241b1d3SJoe Thornber tm->real = NULL; 1723241b1d3SJoe Thornber tm->bm = bm; 1733241b1d3SJoe Thornber tm->sm = sm; 1743241b1d3SJoe Thornber 1753241b1d3SJoe Thornber spin_lock_init(&tm->lock); 176df855798SAndrew Morton for (i = 0; i < DM_HASH_SIZE; i++) 1773241b1d3SJoe Thornber INIT_HLIST_HEAD(tm->buckets + i); 1783241b1d3SJoe Thornber 1794646015dSJoe Thornber prefetch_init(&tm->prefetches); 1804646015dSJoe Thornber 1813241b1d3SJoe Thornber return tm; 1823241b1d3SJoe Thornber } 1833241b1d3SJoe Thornber 1843241b1d3SJoe Thornber struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transaction_manager *real) 1853241b1d3SJoe Thornber { 1863241b1d3SJoe Thornber struct dm_transaction_manager *tm; 1873241b1d3SJoe Thornber 1883241b1d3SJoe Thornber tm = kmalloc(sizeof(*tm), GFP_KERNEL); 1893241b1d3SJoe Thornber if (tm) { 1903241b1d3SJoe Thornber tm->is_clone = 1; 1913241b1d3SJoe Thornber tm->real = real; 1923241b1d3SJoe Thornber } 1933241b1d3SJoe Thornber 1943241b1d3SJoe Thornber return tm; 1953241b1d3SJoe Thornber } 1963241b1d3SJoe Thornber EXPORT_SYMBOL_GPL(dm_tm_create_non_blocking_clone); 1973241b1d3SJoe Thornber 1983241b1d3SJoe Thornber void dm_tm_destroy(struct dm_transaction_manager *tm) 1993241b1d3SJoe Thornber { 20025d7cd6fSMike Snitzer if (!tm->is_clone) 20125d7cd6fSMike Snitzer wipe_shadow_table(tm); 20225d7cd6fSMike Snitzer 2033241b1d3SJoe Thornber kfree(tm); 2043241b1d3SJoe Thornber } 2053241b1d3SJoe Thornber EXPORT_SYMBOL_GPL(dm_tm_destroy); 2063241b1d3SJoe Thornber 2073241b1d3SJoe Thornber int dm_tm_pre_commit(struct dm_transaction_manager *tm) 2083241b1d3SJoe Thornber { 2093241b1d3SJoe Thornber int r; 2103241b1d3SJoe Thornber 2113241b1d3SJoe Thornber if (tm->is_clone) 2123241b1d3SJoe Thornber return -EWOULDBLOCK; 2133241b1d3SJoe Thornber 2143241b1d3SJoe Thornber r = dm_sm_commit(tm->sm); 2153241b1d3SJoe Thornber if (r < 0) 2163241b1d3SJoe Thornber return r; 2173241b1d3SJoe Thornber 218a9d45396SJoe Thornber return dm_bm_flush(tm->bm); 2193241b1d3SJoe Thornber } 2203241b1d3SJoe Thornber EXPORT_SYMBOL_GPL(dm_tm_pre_commit); 2213241b1d3SJoe Thornber 2223241b1d3SJoe Thornber int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root) 2233241b1d3SJoe Thornber { 2243241b1d3SJoe Thornber if (tm->is_clone) 2253241b1d3SJoe Thornber return -EWOULDBLOCK; 2263241b1d3SJoe Thornber 2273241b1d3SJoe Thornber wipe_shadow_table(tm); 228a9d45396SJoe Thornber dm_bm_unlock(root); 2293241b1d3SJoe Thornber 230a9d45396SJoe Thornber return dm_bm_flush(tm->bm); 2313241b1d3SJoe Thornber } 2323241b1d3SJoe Thornber EXPORT_SYMBOL_GPL(dm_tm_commit); 2333241b1d3SJoe Thornber 2343241b1d3SJoe Thornber int dm_tm_new_block(struct dm_transaction_manager *tm, 2353241b1d3SJoe Thornber struct dm_block_validator *v, 2363241b1d3SJoe Thornber struct dm_block **result) 2373241b1d3SJoe Thornber { 2383241b1d3SJoe Thornber int r; 2393241b1d3SJoe Thornber dm_block_t new_block; 2403241b1d3SJoe Thornber 2413241b1d3SJoe Thornber if (tm->is_clone) 2423241b1d3SJoe Thornber return -EWOULDBLOCK; 2433241b1d3SJoe Thornber 2443241b1d3SJoe Thornber r = dm_sm_new_block(tm->sm, &new_block); 2453241b1d3SJoe Thornber if (r < 0) 2463241b1d3SJoe Thornber return r; 2473241b1d3SJoe Thornber 2483241b1d3SJoe Thornber r = dm_bm_write_lock_zero(tm->bm, new_block, v, result); 2493241b1d3SJoe Thornber if (r < 0) { 2503241b1d3SJoe Thornber dm_sm_dec_block(tm->sm, new_block); 2513241b1d3SJoe Thornber return r; 2523241b1d3SJoe Thornber } 2533241b1d3SJoe Thornber 2543241b1d3SJoe Thornber /* 2553241b1d3SJoe Thornber * New blocks count as shadows in that they don't need to be 2563241b1d3SJoe Thornber * shadowed again. 2573241b1d3SJoe Thornber */ 2583241b1d3SJoe Thornber insert_shadow(tm, new_block); 2593241b1d3SJoe Thornber 2603241b1d3SJoe Thornber return 0; 2613241b1d3SJoe Thornber } 2623241b1d3SJoe Thornber 2633241b1d3SJoe Thornber static int __shadow_block(struct dm_transaction_manager *tm, dm_block_t orig, 2643241b1d3SJoe Thornber struct dm_block_validator *v, 2653241b1d3SJoe Thornber struct dm_block **result) 2663241b1d3SJoe Thornber { 2673241b1d3SJoe Thornber int r; 2683241b1d3SJoe Thornber dm_block_t new; 2693241b1d3SJoe Thornber struct dm_block *orig_block; 2703241b1d3SJoe Thornber 2713241b1d3SJoe Thornber r = dm_sm_new_block(tm->sm, &new); 2723241b1d3SJoe Thornber if (r < 0) 2733241b1d3SJoe Thornber return r; 2743241b1d3SJoe Thornber 2753241b1d3SJoe Thornber r = dm_sm_dec_block(tm->sm, orig); 2763241b1d3SJoe Thornber if (r < 0) 2773241b1d3SJoe Thornber return r; 2783241b1d3SJoe Thornber 2793241b1d3SJoe Thornber r = dm_bm_read_lock(tm->bm, orig, v, &orig_block); 2803241b1d3SJoe Thornber if (r < 0) 2813241b1d3SJoe Thornber return r; 2823241b1d3SJoe Thornber 2833c9ad9bdSJoe Thornber /* 2843c9ad9bdSJoe Thornber * It would be tempting to use dm_bm_unlock_move here, but some 2853c9ad9bdSJoe Thornber * code, such as the space maps, keeps using the old data structures 2863c9ad9bdSJoe Thornber * secure in the knowledge they won't be changed until the next 2873c9ad9bdSJoe Thornber * transaction. Using unlock_move would force a synchronous read 2883c9ad9bdSJoe Thornber * since the old block would no longer be in the cache. 2893c9ad9bdSJoe Thornber */ 2903c9ad9bdSJoe Thornber r = dm_bm_write_lock_zero(tm->bm, new, v, result); 2913c9ad9bdSJoe Thornber if (r) { 2923241b1d3SJoe Thornber dm_bm_unlock(orig_block); 2933241b1d3SJoe Thornber return r; 2943241b1d3SJoe Thornber } 2953241b1d3SJoe Thornber 2963c9ad9bdSJoe Thornber memcpy(dm_block_data(*result), dm_block_data(orig_block), 2973c9ad9bdSJoe Thornber dm_bm_block_size(tm->bm)); 2983c9ad9bdSJoe Thornber 2993c9ad9bdSJoe Thornber dm_bm_unlock(orig_block); 3003c9ad9bdSJoe Thornber return r; 3013241b1d3SJoe Thornber } 3023241b1d3SJoe Thornber 3033241b1d3SJoe Thornber int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig, 3043241b1d3SJoe Thornber struct dm_block_validator *v, struct dm_block **result, 3053241b1d3SJoe Thornber int *inc_children) 3063241b1d3SJoe Thornber { 3073241b1d3SJoe Thornber int r; 3083241b1d3SJoe Thornber 3093241b1d3SJoe Thornber if (tm->is_clone) 3103241b1d3SJoe Thornber return -EWOULDBLOCK; 3113241b1d3SJoe Thornber 3123241b1d3SJoe Thornber r = dm_sm_count_is_more_than_one(tm->sm, orig, inc_children); 3133241b1d3SJoe Thornber if (r < 0) 3143241b1d3SJoe Thornber return r; 3153241b1d3SJoe Thornber 3163241b1d3SJoe Thornber if (is_shadow(tm, orig) && !*inc_children) 3173241b1d3SJoe Thornber return dm_bm_write_lock(tm->bm, orig, v, result); 3183241b1d3SJoe Thornber 3193241b1d3SJoe Thornber r = __shadow_block(tm, orig, v, result); 3203241b1d3SJoe Thornber if (r < 0) 3213241b1d3SJoe Thornber return r; 3223241b1d3SJoe Thornber insert_shadow(tm, dm_block_location(*result)); 3233241b1d3SJoe Thornber 3243241b1d3SJoe Thornber return r; 3253241b1d3SJoe Thornber } 326cc8394d8SJoe Thornber EXPORT_SYMBOL_GPL(dm_tm_shadow_block); 3273241b1d3SJoe Thornber 3283241b1d3SJoe Thornber int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b, 3293241b1d3SJoe Thornber struct dm_block_validator *v, 3303241b1d3SJoe Thornber struct dm_block **blk) 3313241b1d3SJoe Thornber { 3324646015dSJoe Thornber if (tm->is_clone) { 3334646015dSJoe Thornber int r = dm_bm_read_try_lock(tm->real->bm, b, v, blk); 3344646015dSJoe Thornber 3354646015dSJoe Thornber if (r == -EWOULDBLOCK) 3364646015dSJoe Thornber prefetch_add(&tm->real->prefetches, b); 3374646015dSJoe Thornber 3384646015dSJoe Thornber return r; 3394646015dSJoe Thornber } 3403241b1d3SJoe Thornber 3413241b1d3SJoe Thornber return dm_bm_read_lock(tm->bm, b, v, blk); 3423241b1d3SJoe Thornber } 343cc8394d8SJoe Thornber EXPORT_SYMBOL_GPL(dm_tm_read_lock); 3443241b1d3SJoe Thornber 345*4c7da06fSMikulas Patocka void dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b) 3463241b1d3SJoe Thornber { 347*4c7da06fSMikulas Patocka dm_bm_unlock(b); 3483241b1d3SJoe Thornber } 3493241b1d3SJoe Thornber EXPORT_SYMBOL_GPL(dm_tm_unlock); 3503241b1d3SJoe Thornber 3513241b1d3SJoe Thornber void dm_tm_inc(struct dm_transaction_manager *tm, dm_block_t b) 3523241b1d3SJoe Thornber { 3533241b1d3SJoe Thornber /* 3543241b1d3SJoe Thornber * The non-blocking clone doesn't support this. 3553241b1d3SJoe Thornber */ 3563241b1d3SJoe Thornber BUG_ON(tm->is_clone); 3573241b1d3SJoe Thornber 3583241b1d3SJoe Thornber dm_sm_inc_block(tm->sm, b); 3593241b1d3SJoe Thornber } 3603241b1d3SJoe Thornber EXPORT_SYMBOL_GPL(dm_tm_inc); 3613241b1d3SJoe Thornber 3623241b1d3SJoe Thornber void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b) 3633241b1d3SJoe Thornber { 3643241b1d3SJoe Thornber /* 3653241b1d3SJoe Thornber * The non-blocking clone doesn't support this. 3663241b1d3SJoe Thornber */ 3673241b1d3SJoe Thornber BUG_ON(tm->is_clone); 3683241b1d3SJoe Thornber 3693241b1d3SJoe Thornber dm_sm_dec_block(tm->sm, b); 3703241b1d3SJoe Thornber } 3713241b1d3SJoe Thornber EXPORT_SYMBOL_GPL(dm_tm_dec); 3723241b1d3SJoe Thornber 3733241b1d3SJoe Thornber int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b, 3743241b1d3SJoe Thornber uint32_t *result) 3753241b1d3SJoe Thornber { 3763241b1d3SJoe Thornber if (tm->is_clone) 3773241b1d3SJoe Thornber return -EWOULDBLOCK; 3783241b1d3SJoe Thornber 3793241b1d3SJoe Thornber return dm_sm_get_count(tm->sm, b, result); 3803241b1d3SJoe Thornber } 3813241b1d3SJoe Thornber 3823241b1d3SJoe Thornber struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm) 3833241b1d3SJoe Thornber { 3843241b1d3SJoe Thornber return tm->bm; 3853241b1d3SJoe Thornber } 3863241b1d3SJoe Thornber 3874646015dSJoe Thornber void dm_tm_issue_prefetches(struct dm_transaction_manager *tm) 3884646015dSJoe Thornber { 3894646015dSJoe Thornber prefetch_issue(&tm->prefetches, tm->bm); 3904646015dSJoe Thornber } 3914646015dSJoe Thornber EXPORT_SYMBOL_GPL(dm_tm_issue_prefetches); 3924646015dSJoe Thornber 3933241b1d3SJoe Thornber /*----------------------------------------------------------------*/ 3943241b1d3SJoe Thornber 3953241b1d3SJoe Thornber static int dm_tm_create_internal(struct dm_block_manager *bm, 3963241b1d3SJoe Thornber dm_block_t sb_location, 3973241b1d3SJoe Thornber struct dm_transaction_manager **tm, 3983241b1d3SJoe Thornber struct dm_space_map **sm, 399384ef0e6SJoe Thornber int create, 400384ef0e6SJoe Thornber void *sm_root, size_t sm_len) 4013241b1d3SJoe Thornber { 4023241b1d3SJoe Thornber int r; 4033241b1d3SJoe Thornber 4043caf6d73SJoe Thornber *sm = dm_sm_metadata_init(); 4053caf6d73SJoe Thornber if (IS_ERR(*sm)) 4063caf6d73SJoe Thornber return PTR_ERR(*sm); 4073241b1d3SJoe Thornber 4083caf6d73SJoe Thornber *tm = dm_tm_create(bm, *sm); 4093241b1d3SJoe Thornber if (IS_ERR(*tm)) { 4103caf6d73SJoe Thornber dm_sm_destroy(*sm); 4113241b1d3SJoe Thornber return PTR_ERR(*tm); 4123241b1d3SJoe Thornber } 4133241b1d3SJoe Thornber 4143241b1d3SJoe Thornber if (create) { 4153caf6d73SJoe Thornber r = dm_sm_metadata_create(*sm, *tm, dm_bm_nr_blocks(bm), 4163241b1d3SJoe Thornber sb_location); 4173241b1d3SJoe Thornber if (r) { 4183241b1d3SJoe Thornber DMERR("couldn't create metadata space map"); 419384ef0e6SJoe Thornber goto bad; 4203241b1d3SJoe Thornber } 4213241b1d3SJoe Thornber 4223241b1d3SJoe Thornber } else { 423384ef0e6SJoe Thornber r = dm_sm_metadata_open(*sm, *tm, sm_root, sm_len); 4243241b1d3SJoe Thornber if (r) { 4253241b1d3SJoe Thornber DMERR("couldn't open metadata space map"); 426384ef0e6SJoe Thornber goto bad; 4273241b1d3SJoe Thornber } 42862662303SMike Snitzer } 4293241b1d3SJoe Thornber 4303241b1d3SJoe Thornber return 0; 4313241b1d3SJoe Thornber 432384ef0e6SJoe Thornber bad: 4333241b1d3SJoe Thornber dm_tm_destroy(*tm); 434384ef0e6SJoe Thornber dm_sm_destroy(*sm); 4353241b1d3SJoe Thornber return r; 4363241b1d3SJoe Thornber } 4373241b1d3SJoe Thornber 4383241b1d3SJoe Thornber int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, 4393241b1d3SJoe Thornber struct dm_transaction_manager **tm, 440384ef0e6SJoe Thornber struct dm_space_map **sm) 4413241b1d3SJoe Thornber { 442384ef0e6SJoe Thornber return dm_tm_create_internal(bm, sb_location, tm, sm, 1, NULL, 0); 4433241b1d3SJoe Thornber } 4443241b1d3SJoe Thornber EXPORT_SYMBOL_GPL(dm_tm_create_with_sm); 4453241b1d3SJoe Thornber 4463241b1d3SJoe Thornber int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, 447384ef0e6SJoe Thornber void *sm_root, size_t root_len, 4483241b1d3SJoe Thornber struct dm_transaction_manager **tm, 449384ef0e6SJoe Thornber struct dm_space_map **sm) 4503241b1d3SJoe Thornber { 451384ef0e6SJoe Thornber return dm_tm_create_internal(bm, sb_location, tm, sm, 0, sm_root, root_len); 4523241b1d3SJoe Thornber } 4533241b1d3SJoe Thornber EXPORT_SYMBOL_GPL(dm_tm_open_with_sm); 4543241b1d3SJoe Thornber 4553241b1d3SJoe Thornber /*----------------------------------------------------------------*/ 456