4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * Areas are maintained in size order, largest first.
27 * FIXME Cope with overlap.
29 static void _insert_area(struct dm_list
*head
, struct pv_area
*a
)
33 dm_list_iterate_items(pva
, head
) {
34 if (a
->count
> pva
->count
)
38 dm_list_add(&pva
->list
, &a
->list
);
39 a
->map
->pe_count
+= a
->count
;
42 static int _create_single_area(struct dm_pool
*mem
, struct pv_map
*pvm
,
43 uint32_t start
, uint32_t length
)
47 if (!(pva
= dm_pool_zalloc(mem
, sizeof(*pva
))))
50 log_debug("Allowing allocation on %s start PE %" PRIu32
" length %"
51 PRIu32
, pv_dev_name(pvm
->pv
), start
, length
);
55 _insert_area(&pvm
->areas
, pva
);
60 static int _create_alloc_areas_for_pv(struct dm_pool
*mem
, struct pv_map
*pvm
,
61 uint32_t start
, uint32_t count
)
63 struct pv_segment
*peg
;
64 uint32_t pe
, end
, area_len
;
66 /* Only select extents from start to end inclusive */
67 end
= start
+ count
- 1;
68 if (end
> pvm
->pv
->pe_count
- 1)
69 end
= pvm
->pv
->pe_count
- 1;
73 /* Walk through complete ordered list of device segments */
74 dm_list_iterate_items(peg
, &pvm
->pv
->segments
) {
75 /* pe holds the next extent we want to check */
77 /* Beyond the range we're interested in? */
81 /* Skip if we haven't reached the first seg we want yet */
82 if (pe
> peg
->pe
+ peg
->len
- 1)
89 /* How much of this peg do we need? */
90 area_len
= (end
>= peg
->pe
+ peg
->len
- 1) ?
91 peg
->len
- (pe
- peg
->pe
) : end
- pe
+ 1;
93 if (!_create_single_area(mem
, pvm
, pe
, area_len
))
97 pe
= peg
->pe
+ peg
->len
;
103 static int _create_all_areas_for_pv(struct dm_pool
*mem
, struct pv_map
*pvm
,
104 struct dm_list
*pe_ranges
)
110 if (!_create_alloc_areas_for_pv(mem
, pvm
, UINT32_C(0),
117 dm_list_iterate_items(aa
, pe_ranges
) {
118 if (!_create_alloc_areas_for_pv(mem
, pvm
, aa
->start
,
126 static int _create_maps(struct dm_pool
*mem
, struct dm_list
*pvs
, struct dm_list
*pvms
)
128 struct pv_map
*pvm
, *pvm2
;
131 dm_list_iterate_items(pvl
, pvs
) {
132 if (!(pvl
->pv
->status
& ALLOCATABLE_PV
))
134 if (pvl
->pv
->status
& MISSING_PV
)
136 assert(pvl
->pv
->dev
);
140 dm_list_iterate_items(pvm2
, pvms
)
141 if (pvm2
->pv
->dev
== pvl
->pv
->dev
) {
147 if (!(pvm
= dm_pool_zalloc(mem
, sizeof(*pvm
))))
151 dm_list_init(&pvm
->areas
);
152 dm_list_add(pvms
, &pvm
->list
);
155 if (!_create_all_areas_for_pv(mem
, pvm
, pvl
->pe_ranges
))
163 * Create list of PV areas available for this particular allocation
165 struct dm_list
*create_pv_maps(struct dm_pool
*mem
, struct volume_group
*vg
,
166 struct dm_list
*allocatable_pvs
)
168 struct dm_list
*pvms
;
170 if (!(pvms
= dm_pool_zalloc(mem
, sizeof(*pvms
)))) {
171 log_error("create_pv_maps alloc failed");
177 if (!_create_maps(mem
, allocatable_pvs
, pvms
)) {
178 log_error("Couldn't create physical volume maps in %s",
180 dm_pool_free(mem
, pvms
);
187 void consume_pv_area(struct pv_area
*pva
, uint32_t to_go
)
189 dm_list_del(&pva
->list
);
190 pva
->map
->pe_count
-= pva
->count
;
192 assert(to_go
<= pva
->count
);
194 if (to_go
< pva
->count
) {
198 _insert_area(&pva
->map
->areas
, pva
);
202 uint32_t pv_maps_size(struct dm_list
*pvms
)
205 uint32_t pe_count
= 0;
207 dm_list_iterate_items(pvm
, pvms
)
208 pe_count
+= pvm
->pe_count
;