blob: b259190087e9cad5a25228b0d97bdd0d133c3970 [file] [log] [blame]
Colin Cross28fa5bc2012-05-20 13:28:05 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Colin Crossb55dcee2012-04-24 23:07:49 -070017#include <assert.h>
18#include <errno.h>
19#include <stdint.h>
Colin Cross28fa5bc2012-05-20 13:28:05 -070020#include <stdlib.h>
21#include <string.h>
22
23#include "backed_block.h"
Colin Cross28fa5bc2012-05-20 13:28:05 -070024
Colin Crossb55dcee2012-04-24 23:07:49 -070025struct backed_block {
26 unsigned int block;
27 unsigned int len;
28 enum backed_block_type type;
29 union {
30 struct {
31 void *data;
32 } data;
33 struct {
34 char *filename;
35 int64_t offset;
36 } file;
37 struct {
38 uint32_t val;
39 } fill;
40 };
41 struct backed_block *next;
Colin Cross28fa5bc2012-05-20 13:28:05 -070042};
43
Colin Cross411619e2012-04-24 18:51:42 -070044struct backed_block_list {
Colin Crossb55dcee2012-04-24 23:07:49 -070045 struct backed_block *data_blocks;
46 struct backed_block *last_used;
Colin Cross411619e2012-04-24 18:51:42 -070047};
Colin Cross28fa5bc2012-05-20 13:28:05 -070048
Colin Crossb55dcee2012-04-24 23:07:49 -070049struct backed_block *backed_block_iter_new(struct backed_block_list *bbl)
50{
51 return bbl->data_blocks;
52}
53
54struct backed_block *backed_block_iter_next(struct backed_block *bb)
55{
56 return bb->next;
57}
58
59unsigned int backed_block_len(struct backed_block *bb)
60{
61 return bb->len;
62}
63
64unsigned int backed_block_block(struct backed_block *bb)
65{
66 return bb->block;
67}
68
69void *backed_block_data(struct backed_block *bb)
70{
71 assert(bb->type == BACKED_BLOCK_DATA);
72 return bb->data.data;
73}
74
75const char *backed_block_filename(struct backed_block *bb)
76{
77 assert(bb->type == BACKED_BLOCK_FILE);
78 return bb->file.filename;
79}
80
81int64_t backed_block_file_offset(struct backed_block *bb)
82{
83 assert(bb->type == BACKED_BLOCK_FILE);
84 return bb->file.offset;
85}
86
87uint32_t backed_block_fill_val(struct backed_block *bb)
88{
89 assert(bb->type == BACKED_BLOCK_FILL);
90 return bb->fill.val;
91}
92
93enum backed_block_type backed_block_type(struct backed_block *bb)
94{
95 return bb->type;
96}
97
Colin Cross411619e2012-04-24 18:51:42 -070098struct backed_block_list *backed_block_list_new(void)
99{
100 struct backed_block_list *b = calloc(sizeof(struct backed_block_list), 1);
101
102 return b;
103}
104
Colin Crossb55dcee2012-04-24 23:07:49 -0700105void backed_block_list_destroy(struct backed_block_list *bbl)
Colin Cross411619e2012-04-24 18:51:42 -0700106{
Colin Crossb55dcee2012-04-24 23:07:49 -0700107 if (bbl->data_blocks) {
108 struct backed_block *bb = bbl->data_blocks;
109 while (bb) {
110 struct backed_block *next = bb->next;
111 if (bb->type == BACKED_BLOCK_FILE) {
112 free(bb->file.filename);
113 }
Colin Cross411619e2012-04-24 18:51:42 -0700114
Colin Crossb55dcee2012-04-24 23:07:49 -0700115 free(bb);
116 bb = next;
Colin Cross411619e2012-04-24 18:51:42 -0700117 }
118 }
119
Colin Crossb55dcee2012-04-24 23:07:49 -0700120 free(bbl);
Colin Cross411619e2012-04-24 18:51:42 -0700121}
122
Colin Crossb55dcee2012-04-24 23:07:49 -0700123static int queue_bb(struct backed_block_list *bbl, struct backed_block *new_bb)
Colin Cross28fa5bc2012-05-20 13:28:05 -0700124{
Colin Crossb55dcee2012-04-24 23:07:49 -0700125 struct backed_block *bb;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700126
Colin Crossb55dcee2012-04-24 23:07:49 -0700127 if (bbl->data_blocks == NULL) {
128 bbl->data_blocks = new_bb;
129 return 0;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700130 }
131
Colin Crossb55dcee2012-04-24 23:07:49 -0700132 if (bbl->data_blocks->block > new_bb->block) {
133 new_bb->next = bbl->data_blocks;
134 bbl->data_blocks = new_bb;
135 return 0;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700136 }
137
138 /* Optimization: blocks are mostly queued in sequence, so save the
Colin Crossb55dcee2012-04-24 23:07:49 -0700139 pointer to the last bb that was added, and start searching from
Colin Cross28fa5bc2012-05-20 13:28:05 -0700140 there if the next block number is higher */
Colin Crossb55dcee2012-04-24 23:07:49 -0700141 if (bbl->last_used && new_bb->block > bbl->last_used->block)
142 bb = bbl->last_used;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700143 else
Colin Crossb55dcee2012-04-24 23:07:49 -0700144 bb = bbl->data_blocks;
145 bbl->last_used = new_bb;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700146
Colin Crossb55dcee2012-04-24 23:07:49 -0700147 for (; bb->next && bb->next->block < new_bb->block; bb = bb->next)
Colin Cross28fa5bc2012-05-20 13:28:05 -0700148 ;
149
Colin Crossb55dcee2012-04-24 23:07:49 -0700150 if (bb->next == NULL) {
151 bb->next = new_bb;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700152 } else {
Colin Crossb55dcee2012-04-24 23:07:49 -0700153 new_bb->next = bb->next;
154 bb->next = new_bb;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700155 }
Colin Crossb55dcee2012-04-24 23:07:49 -0700156
157 return 0;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700158}
159
160/* Queues a fill block of memory to be written to the specified data blocks */
Colin Crossb55dcee2012-04-24 23:07:49 -0700161int backed_block_add_fill(struct backed_block_list *bbl, unsigned int fill_val,
Colin Cross411619e2012-04-24 18:51:42 -0700162 unsigned int len, unsigned int block)
Colin Cross28fa5bc2012-05-20 13:28:05 -0700163{
Colin Crossb55dcee2012-04-24 23:07:49 -0700164 struct backed_block *bb = calloc(1, sizeof(struct backed_block));
165 if (bb == NULL) {
166 return -ENOMEM;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700167 }
168
Colin Crossb55dcee2012-04-24 23:07:49 -0700169 bb->block = block;
170 bb->len = len;
171 bb->type = BACKED_BLOCK_FILL;
172 bb->fill.val = fill_val;
173 bb->next = NULL;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700174
Colin Crossb55dcee2012-04-24 23:07:49 -0700175 return queue_bb(bbl, bb);
Colin Cross28fa5bc2012-05-20 13:28:05 -0700176}
177
178/* Queues a block of memory to be written to the specified data blocks */
Colin Crossb55dcee2012-04-24 23:07:49 -0700179int backed_block_add_data(struct backed_block_list *bbl, void *data,
180 unsigned int len, unsigned int block)
Colin Cross28fa5bc2012-05-20 13:28:05 -0700181{
Colin Crossb55dcee2012-04-24 23:07:49 -0700182 struct backed_block *bb = calloc(1, sizeof(struct backed_block));
183 if (bb == NULL) {
184 return -ENOMEM;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700185 }
186
Colin Crossb55dcee2012-04-24 23:07:49 -0700187 bb->block = block;
188 bb->len = len;
189 bb->type = BACKED_BLOCK_DATA;
190 bb->data.data = data;
191 bb->next = NULL;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700192
Colin Crossb55dcee2012-04-24 23:07:49 -0700193 return queue_bb(bbl, bb);
Colin Cross28fa5bc2012-05-20 13:28:05 -0700194}
195
196/* Queues a chunk of a file on disk to be written to the specified data blocks */
Colin Crossb55dcee2012-04-24 23:07:49 -0700197int backed_block_add_file(struct backed_block_list *bbl, const char *filename,
Colin Cross411619e2012-04-24 18:51:42 -0700198 int64_t offset, unsigned int len, unsigned int block)
Colin Cross28fa5bc2012-05-20 13:28:05 -0700199{
Colin Crossb55dcee2012-04-24 23:07:49 -0700200 struct backed_block *bb = calloc(1, sizeof(struct backed_block));
201 if (bb == NULL) {
202 return -ENOMEM;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700203 }
204
Colin Crossb55dcee2012-04-24 23:07:49 -0700205 bb->block = block;
206 bb->len = len;
207 bb->type = BACKED_BLOCK_FILE;
208 bb->file.filename = strdup(filename);
209 bb->file.offset = offset;
210 bb->next = NULL;
Colin Cross28fa5bc2012-05-20 13:28:05 -0700211
Colin Crossb55dcee2012-04-24 23:07:49 -0700212 return queue_bb(bbl, bb);
Colin Cross28fa5bc2012-05-20 13:28:05 -0700213}