13241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber/* 23241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * Copyright (C) 2011 Red Hat, Inc. 33241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * 43241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * This file is released under the GPL. 53241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber */ 63241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 73241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber#include "dm-space-map.h" 83241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber#include "dm-space-map-common.h" 93241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber#include "dm-space-map-metadata.h" 103241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 113241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber#include <linux/list.h> 123241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber#include <linux/slab.h> 133241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber#include <linux/device-mapper.h> 143241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 153241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber#define DM_MSG_PREFIX "space map metadata" 163241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 173241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber/*----------------------------------------------------------------*/ 183241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 193241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber/* 203241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * Space map interface. 213241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * 223241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * The low level disk format is written using the standard btree and 233241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * transaction manager. This means that performing disk operations may 243241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * cause us to recurse into the space map in order to allocate new blocks. 253241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * For this reason we have a pool of pre-allocated blocks large enough to 263241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * service any metadata_ll_disk operation. 273241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber */ 283241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 293241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber/* 303241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * FIXME: we should calculate this based on the size of the device. 313241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * Only the metadata space map needs this functionality. 323241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber */ 333241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber#define MAX_RECURSIVE_ALLOCATIONS 1024 343241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 353241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberenum block_op_type { 363241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber BOP_INC, 373241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber BOP_DEC 383241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber}; 393241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 403241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstruct block_op { 413241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber enum block_op_type type; 423241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber dm_block_t block; 433241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber}; 443241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 453241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstruct sm_metadata { 463241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct dm_space_map sm; 473241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 483241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct ll_disk ll; 493241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct ll_disk old_ll; 503241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 513241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber dm_block_t begin; 523241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 533241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber unsigned recursion_count; 543241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber unsigned allocated_this_transaction; 553241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber unsigned nr_uncommitted; 563241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct block_op uncommitted[MAX_RECURSIVE_ALLOCATIONS]; 573241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber}; 583241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 593241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int add_bop(struct sm_metadata *smm, enum block_op_type type, dm_block_t b) 603241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 613241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct block_op *op; 623241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 633241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (smm->nr_uncommitted == MAX_RECURSIVE_ALLOCATIONS) { 643241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber DMERR("too many recursive allocations"); 653241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return -ENOMEM; 663241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 673241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 683241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber op = smm->uncommitted + smm->nr_uncommitted++; 693241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber op->type = type; 703241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber op->block = b; 713241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 723241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 733241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 743241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 753241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int commit_bop(struct sm_metadata *smm, struct block_op *op) 763241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 773241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber int r = 0; 783241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber enum allocation_event ev; 793241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 803241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber switch (op->type) { 813241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber case BOP_INC: 823241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_inc(&smm->ll, op->block, &ev); 833241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber break; 843241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 853241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber case BOP_DEC: 863241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_dec(&smm->ll, op->block, &ev); 873241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber break; 883241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 893241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 903241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return r; 913241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 923241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 933241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic void in(struct sm_metadata *smm) 943241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 953241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->recursion_count++; 963241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 973241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 983241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int out(struct sm_metadata *smm) 993241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 1003241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber int r = 0; 1013241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1023241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber /* 1033241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * If we're not recursing then very bad things are happening. 1043241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber */ 1053241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (!smm->recursion_count) { 1063241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber DMERR("lost track of recursion depth"); 1073241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return -ENOMEM; 1083241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 1093241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1103241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (smm->recursion_count == 1 && smm->nr_uncommitted) { 1113241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber while (smm->nr_uncommitted && !r) { 1123241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->nr_uncommitted--; 1133241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = commit_bop(smm, smm->uncommitted + 1143241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->nr_uncommitted); 1153241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (r) 1163241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber break; 1173241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 1183241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 1193241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1203241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->recursion_count--; 1213241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1223241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return r; 1233241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 1243241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1253241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber/* 1263241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * When using the out() function above, we often want to combine an error 1273241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * code for the operation run in the recursive context with that from 1283241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * out(). 1293241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber */ 1303241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int combine_errors(int r1, int r2) 1313241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 1323241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return r1 ? r1 : r2; 1333241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 1343241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1353241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int recursing(struct sm_metadata *smm) 1363241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 1373241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return smm->recursion_count; 1383241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 1393241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1403241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic void sm_metadata_destroy(struct dm_space_map *sm) 1413241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 1423241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 1433241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1443241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber kfree(smm); 1453241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 1463241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1473241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks) 1483241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 1493241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber DMERR("doesn't support extend"); 1503241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return -EINVAL; 1513241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 1523241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1533241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count) 1543241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 1553241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 1563241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1573241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber *count = smm->ll.nr_blocks; 1583241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1593241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 1603241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 1613241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1623241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_get_nr_free(struct dm_space_map *sm, dm_block_t *count) 1633241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 1643241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 1653241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1663241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber *count = smm->old_ll.nr_blocks - smm->old_ll.nr_allocated - 1673241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->allocated_this_transaction; 1683241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1693241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 1703241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 1713241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1723241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b, 1733241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber uint32_t *result) 1743241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 1753241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber int r, i; 1763241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 1773241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber unsigned adjustment = 0; 1783241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1793241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber /* 1803241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * We may have some uncommitted adjustments to add. This list 1813241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * should always be really short. 1823241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber */ 1833241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber for (i = 0; i < smm->nr_uncommitted; i++) { 1843241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct block_op *op = smm->uncommitted + i; 1853241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1863241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (op->block != b) 1873241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber continue; 1883241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1893241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber switch (op->type) { 1903241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber case BOP_INC: 1913241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber adjustment++; 1923241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber break; 1933241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 1943241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber case BOP_DEC: 1953241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber adjustment--; 1963241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber break; 1973241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 1983241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 1993241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2003241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_lookup(&smm->ll, b, result); 2013241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (r) 2023241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return r; 2033241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2043241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber *result += adjustment; 2053241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2063241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 2073241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 2083241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2093241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_count_is_more_than_one(struct dm_space_map *sm, 2103241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber dm_block_t b, int *result) 2113241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 2123241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber int r, i, adjustment = 0; 2133241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 2143241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber uint32_t rc; 2153241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2163241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber /* 2173241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * We may have some uncommitted adjustments to add. This list 2183241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * should always be really short. 2193241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber */ 2203241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber for (i = 0; i < smm->nr_uncommitted; i++) { 2213241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct block_op *op = smm->uncommitted + i; 2223241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2233241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (op->block != b) 2243241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber continue; 2253241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2263241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber switch (op->type) { 2273241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber case BOP_INC: 2283241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber adjustment++; 2293241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber break; 2303241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2313241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber case BOP_DEC: 2323241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber adjustment--; 2333241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber break; 2343241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 2353241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 2363241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2373241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (adjustment > 1) { 2383241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber *result = 1; 2393241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 2403241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 2413241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2423241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_lookup_bitmap(&smm->ll, b, &rc); 2433241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (r) 2443241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return r; 2453241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2463241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (rc == 3) 2473241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber /* 2483241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * We err on the side of caution, and always return true. 2493241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber */ 2503241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber *result = 1; 2513241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber else 2523241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber *result = rc + adjustment > 1; 2533241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2543241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 2553241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 2563241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2573241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_set_count(struct dm_space_map *sm, dm_block_t b, 2583241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber uint32_t count) 2593241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 2603241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber int r, r2; 2613241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber enum allocation_event ev; 2623241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 2633241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2643241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (smm->recursion_count) { 2653241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber DMERR("cannot recurse set_count()"); 2663241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return -EINVAL; 2673241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 2683241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2693241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber in(smm); 2703241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_insert(&smm->ll, b, count, &ev); 2713241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r2 = out(smm); 2723241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2733241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return combine_errors(r, r2); 2743241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 2753241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2763241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_inc_block(struct dm_space_map *sm, dm_block_t b) 2773241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 2783241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber int r, r2 = 0; 2793241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber enum allocation_event ev; 2803241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 2813241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2823241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (recursing(smm)) 2833241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = add_bop(smm, BOP_INC, b); 2843241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber else { 2853241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber in(smm); 2863241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_inc(&smm->ll, b, &ev); 2873241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r2 = out(smm); 2883241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 2893241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2903241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return combine_errors(r, r2); 2913241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 2923241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2933241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_dec_block(struct dm_space_map *sm, dm_block_t b) 2943241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 2953241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber int r, r2 = 0; 2963241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber enum allocation_event ev; 2973241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 2983241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 2993241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (recursing(smm)) 3003241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = add_bop(smm, BOP_DEC, b); 3013241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber else { 3023241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber in(smm); 3033241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_dec(&smm->ll, b, &ev); 3043241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r2 = out(smm); 3053241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 3063241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3073241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return combine_errors(r, r2); 3083241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 3093241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3103241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b) 3113241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 3123241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber int r, r2 = 0; 3133241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber enum allocation_event ev; 3143241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 3153241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3163241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_find_free_block(&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b); 3173241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (r) 3183241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return r; 3193241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3203241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->begin = *b + 1; 3213241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3223241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (recursing(smm)) 3233241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = add_bop(smm, BOP_INC, *b); 3243241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber else { 3253241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber in(smm); 3263241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_inc(&smm->ll, *b, &ev); 3273241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r2 = out(smm); 3283241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber } 3293241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3303241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (!r) 3313241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->allocated_this_transaction++; 3323241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3333241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return combine_errors(r, r2); 3343241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 3353241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3363241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b) 3373241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 3383241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber int r = sm_metadata_new_block_(sm, b); 3393241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (r) 3403241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber DMERR("out of metadata space"); 3413241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return r; 3423241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 3433241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3443241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_commit(struct dm_space_map *sm) 3453241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 3463241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber int r; 3473241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 3483241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3493241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_commit(&smm->ll); 3503241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (r) 3513241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return r; 3523241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3533241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll)); 3543241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->begin = 0; 3553241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->allocated_this_transaction = 0; 3563241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3573241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 3583241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 3593241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3603241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_root_size(struct dm_space_map *sm, size_t *result) 3613241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 3623241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber *result = sizeof(struct disk_sm_root); 3633241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3643241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 3653241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 3663241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3673241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_metadata_copy_root(struct dm_space_map *sm, void *where_le, size_t max) 3683241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 3693241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 3703241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct disk_sm_root root_le; 3713241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3723241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber root_le.nr_blocks = cpu_to_le64(smm->ll.nr_blocks); 3733241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber root_le.nr_allocated = cpu_to_le64(smm->ll.nr_allocated); 3743241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber root_le.bitmap_root = cpu_to_le64(smm->ll.bitmap_root); 3753241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber root_le.ref_count_root = cpu_to_le64(smm->ll.ref_count_root); 3763241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3773241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (max < sizeof(root_le)) 3783241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return -ENOSPC; 3793241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3803241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber memcpy(where_le, &root_le, sizeof(root_le)); 3813241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3823241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 3833241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 3843241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 3853241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic struct dm_space_map ops = { 3863241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .destroy = sm_metadata_destroy, 3873241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .extend = sm_metadata_extend, 3883241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .get_nr_blocks = sm_metadata_get_nr_blocks, 3893241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .get_nr_free = sm_metadata_get_nr_free, 3903241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .get_count = sm_metadata_get_count, 3913241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .count_is_more_than_one = sm_metadata_count_is_more_than_one, 3923241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .set_count = sm_metadata_set_count, 3933241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .inc_block = sm_metadata_inc_block, 3943241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .dec_block = sm_metadata_dec_block, 3953241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .new_block = sm_metadata_new_block, 3963241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .commit = sm_metadata_commit, 3973241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .root_size = sm_metadata_root_size, 3983241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .copy_root = sm_metadata_copy_root 3993241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber}; 4003241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4013241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber/*----------------------------------------------------------------*/ 4023241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4033241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber/* 4043241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * When a new space map is created that manages its own space. We use 4053241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * this tiny bootstrap allocator. 4063241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber */ 4073241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic void sm_bootstrap_destroy(struct dm_space_map *sm) 4083241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 4093241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 4103241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4113241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_bootstrap_extend(struct dm_space_map *sm, dm_block_t extra_blocks) 4123241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 4133241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber DMERR("boostrap doesn't support extend"); 4143241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4153241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return -EINVAL; 4163241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 4173241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4183241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_bootstrap_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count) 4193241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 4203241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 4213241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4223241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return smm->ll.nr_blocks; 4233241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 4243241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4253241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_bootstrap_get_nr_free(struct dm_space_map *sm, dm_block_t *count) 4263241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 4273241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 4283241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4293241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber *count = smm->ll.nr_blocks - smm->begin; 4303241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4313241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 4323241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 4333241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4343241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_bootstrap_get_count(struct dm_space_map *sm, dm_block_t b, 4353241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber uint32_t *result) 4363241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 4373241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 4383241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4393241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return b < smm->begin ? 1 : 0; 4403241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 4413241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4423241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_bootstrap_count_is_more_than_one(struct dm_space_map *sm, 4433241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber dm_block_t b, int *result) 4443241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 4453241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber *result = 0; 4463241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4473241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 4483241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 4493241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4503241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_bootstrap_set_count(struct dm_space_map *sm, dm_block_t b, 4513241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber uint32_t count) 4523241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 4533241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber DMERR("boostrap doesn't support set_count"); 4543241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4553241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return -EINVAL; 4563241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 4573241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4583241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_bootstrap_new_block(struct dm_space_map *sm, dm_block_t *b) 4593241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 4603241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 4613241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4623241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber /* 4633241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * We know the entire device is unused. 4643241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber */ 4653241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (smm->begin == smm->ll.nr_blocks) 4663241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return -ENOSPC; 4673241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4683241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber *b = smm->begin++; 4693241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4703241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 4713241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 4723241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4733241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_bootstrap_inc_block(struct dm_space_map *sm, dm_block_t b) 4743241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 4753241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 4763241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4773241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return add_bop(smm, BOP_INC, b); 4783241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 4793241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4803241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_bootstrap_dec_block(struct dm_space_map *sm, dm_block_t b) 4813241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 4823241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 4833241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4843241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return add_bop(smm, BOP_DEC, b); 4853241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 4863241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4873241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_bootstrap_commit(struct dm_space_map *sm) 4883241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 4893241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 4903241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 4913241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4923241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_bootstrap_root_size(struct dm_space_map *sm, size_t *result) 4933241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 4943241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber DMERR("boostrap doesn't support root_size"); 4953241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4963241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return -EINVAL; 4973241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 4983241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 4993241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic int sm_bootstrap_copy_root(struct dm_space_map *sm, void *where, 5003241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber size_t max) 5013241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 5023241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber DMERR("boostrap doesn't support copy_root"); 5033241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5043241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return -EINVAL; 5053241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 5063241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5073241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstatic struct dm_space_map bootstrap_ops = { 5083241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .destroy = sm_bootstrap_destroy, 5093241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .extend = sm_bootstrap_extend, 5103241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .get_nr_blocks = sm_bootstrap_get_nr_blocks, 5113241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .get_nr_free = sm_bootstrap_get_nr_free, 5123241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .get_count = sm_bootstrap_get_count, 5133241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .count_is_more_than_one = sm_bootstrap_count_is_more_than_one, 5143241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .set_count = sm_bootstrap_set_count, 5153241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .inc_block = sm_bootstrap_inc_block, 5163241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .dec_block = sm_bootstrap_dec_block, 5173241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .new_block = sm_bootstrap_new_block, 5183241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .commit = sm_bootstrap_commit, 5193241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .root_size = sm_bootstrap_root_size, 5203241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber .copy_root = sm_bootstrap_copy_root 5213241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber}; 5223241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5233241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber/*----------------------------------------------------------------*/ 5243241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5253241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberstruct dm_space_map *dm_sm_metadata_init(void) 5263241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 5273241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm; 5283241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5293241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm = kmalloc(sizeof(*smm), GFP_KERNEL); 5303241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (!smm) 5313241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return ERR_PTR(-ENOMEM); 5323241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5333241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber memcpy(&smm->sm, &ops, sizeof(smm->sm)); 5343241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5353241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return &smm->sm; 5363241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 5373241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5383241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberint dm_sm_metadata_create(struct dm_space_map *sm, 5393241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct dm_transaction_manager *tm, 5403241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber dm_block_t nr_blocks, 5413241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber dm_block_t superblock) 5423241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 5433241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber int r; 5443241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber dm_block_t i; 5453241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber enum allocation_event ev; 5463241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 5473241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5483241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->begin = superblock + 1; 5493241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->recursion_count = 0; 5503241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->allocated_this_transaction = 0; 5513241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->nr_uncommitted = 0; 5523241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5533241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm)); 5543241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5553241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_new_metadata(&smm->ll, tm); 5563241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (r) 5573241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return r; 5583241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5593241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_extend(&smm->ll, nr_blocks); 5603241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (r) 5613241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return r; 5623241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5633241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber memcpy(&smm->sm, &ops, sizeof(smm->sm)); 5643241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5653241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber /* 5663241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * Now we need to update the newly created data structures with the 5673241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber * allocated blocks that they were built from. 5683241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber */ 5693241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber for (i = superblock; !r && i < smm->begin; i++) 5703241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_inc(&smm->ll, i, &ev); 5713241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5723241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (r) 5733241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return r; 5743241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5753241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return sm_metadata_commit(sm); 5763241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 5773241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5783241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornberint dm_sm_metadata_open(struct dm_space_map *sm, 5793241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct dm_transaction_manager *tm, 5803241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber void *root_le, size_t len) 5813241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber{ 5823241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber int r; 5833241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 5843241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5853241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber r = sm_ll_open_metadata(&smm->ll, tm, root_le, len); 5863241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber if (r) 5873241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return r; 5883241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5893241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->begin = 0; 5903241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->recursion_count = 0; 5913241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->allocated_this_transaction = 0; 5923241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber smm->nr_uncommitted = 0; 5933241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber 5943241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll)); 5953241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber return 0; 5963241b1d3e0aaafbfcd320f4d71ade629728cc4f4Joe Thornber} 597