backed_block.c revision 9e1f17e926fa20255c5f4b4d2f68aa98a964253a
128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/*
228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * Copyright (C) 2010 The Android Open Source Project
328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross *
428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * Licensed under the Apache License, Version 2.0 (the "License");
528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * you may not use this file except in compliance with the License.
628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * You may obtain a copy of the License at
728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross *
828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross *      http://www.apache.org/licenses/LICENSE-2.0
928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross *
1028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * Unless required by applicable law or agreed to in writing, software
1128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * distributed under the License is distributed on an "AS IS" BASIS,
1228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * See the License for the specific language governing permissions and
1428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * limitations under the License.
1528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross */
1628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
17b55dceea986ab24f8b836b5116b389ed619c816eColin Cross#include <assert.h>
18b55dceea986ab24f8b836b5116b389ed619c816eColin Cross#include <errno.h>
19b55dceea986ab24f8b836b5116b389ed619c816eColin Cross#include <stdint.h>
2028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <stdlib.h>
2128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <string.h>
2228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
2328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "backed_block.h"
24b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
25b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstruct backed_block {
26b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	unsigned int block;
27b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	unsigned int len;
28b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	enum backed_block_type type;
29b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	union {
30b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		struct {
31b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			void *data;
32b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		} data;
33b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		struct {
34b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			char *filename;
35b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			int64_t offset;
36b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		} file;
37b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		struct {
389e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross			int fd;
399e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross			int64_t offset;
409e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross		} fd;
419e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross		struct {
42b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			uint32_t val;
43b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		} fill;
44b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	};
45b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	struct backed_block *next;
4628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross};
4728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
48411619e921904b896eddae81c086c1f687c8304dColin Crossstruct backed_block_list {
49b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	struct backed_block *data_blocks;
50b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	struct backed_block *last_used;
51411619e921904b896eddae81c086c1f687c8304dColin Cross};
52411619e921904b896eddae81c086c1f687c8304dColin Cross
53b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstruct backed_block *backed_block_iter_new(struct backed_block_list *bbl)
54b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{
55b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return bbl->data_blocks;
56b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}
57b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
58b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstruct backed_block *backed_block_iter_next(struct backed_block *bb)
59b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{
60b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return bb->next;
61b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}
62b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
63b55dceea986ab24f8b836b5116b389ed619c816eColin Crossunsigned int backed_block_len(struct backed_block *bb)
64b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{
65b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return bb->len;
66b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}
67b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
68b55dceea986ab24f8b836b5116b389ed619c816eColin Crossunsigned int backed_block_block(struct backed_block *bb)
69b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{
70b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return bb->block;
71b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}
72b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
73b55dceea986ab24f8b836b5116b389ed619c816eColin Crossvoid *backed_block_data(struct backed_block *bb)
74b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{
75b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	assert(bb->type == BACKED_BLOCK_DATA);
76b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return bb->data.data;
77b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}
78b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
79b55dceea986ab24f8b836b5116b389ed619c816eColin Crossconst char *backed_block_filename(struct backed_block *bb)
80b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{
81b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	assert(bb->type == BACKED_BLOCK_FILE);
82b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return bb->file.filename;
83b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}
84b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
859e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Crossint backed_block_fd(struct backed_block *bb)
869e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross{
879e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	assert(bb->type == BACKED_BLOCK_FD);
889e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	return bb->fd.fd;
899e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross}
909e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross
91b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint64_t backed_block_file_offset(struct backed_block *bb)
92b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{
939e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	assert(bb->type == BACKED_BLOCK_FILE || bb->type == BACKED_BLOCK_FD);
949e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	if (bb->type == BACKED_BLOCK_FILE) {
959e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross		return bb->file.offset;
969e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	} else { /* bb->type == BACKED_BLOCK_FD */
979e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross		return bb->fd.offset;
989e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	}
99b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}
100b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
101b55dceea986ab24f8b836b5116b389ed619c816eColin Crossuint32_t backed_block_fill_val(struct backed_block *bb)
102b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{
103b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	assert(bb->type == BACKED_BLOCK_FILL);
104b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return bb->fill.val;
105b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}
106b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
107b55dceea986ab24f8b836b5116b389ed619c816eColin Crossenum backed_block_type backed_block_type(struct backed_block *bb)
108b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{
109b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return bb->type;
110b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}
111b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
112411619e921904b896eddae81c086c1f687c8304dColin Crossstruct backed_block_list *backed_block_list_new(void)
113411619e921904b896eddae81c086c1f687c8304dColin Cross{
114411619e921904b896eddae81c086c1f687c8304dColin Cross	struct backed_block_list *b = calloc(sizeof(struct backed_block_list), 1);
115411619e921904b896eddae81c086c1f687c8304dColin Cross
116411619e921904b896eddae81c086c1f687c8304dColin Cross	return b;
117411619e921904b896eddae81c086c1f687c8304dColin Cross}
11828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
119b55dceea986ab24f8b836b5116b389ed619c816eColin Crossvoid backed_block_list_destroy(struct backed_block_list *bbl)
120411619e921904b896eddae81c086c1f687c8304dColin Cross{
121b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	if (bbl->data_blocks) {
122b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		struct backed_block *bb = bbl->data_blocks;
123b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		while (bb) {
124b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			struct backed_block *next = bb->next;
125b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			if (bb->type == BACKED_BLOCK_FILE) {
126b55dceea986ab24f8b836b5116b389ed619c816eColin Cross				free(bb->file.filename);
127b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			}
128b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
129b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			free(bb);
130b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			bb = next;
131411619e921904b896eddae81c086c1f687c8304dColin Cross		}
132411619e921904b896eddae81c086c1f687c8304dColin Cross	}
133411619e921904b896eddae81c086c1f687c8304dColin Cross
134b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	free(bbl);
135411619e921904b896eddae81c086c1f687c8304dColin Cross}
136411619e921904b896eddae81c086c1f687c8304dColin Cross
137b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int queue_bb(struct backed_block_list *bbl, struct backed_block *new_bb)
13828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
139b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	struct backed_block *bb;
14028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
141b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	if (bbl->data_blocks == NULL) {
142b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		bbl->data_blocks = new_bb;
143b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		return 0;
14428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
14528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
146b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	if (bbl->data_blocks->block > new_bb->block) {
147b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		new_bb->next = bbl->data_blocks;
148b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		bbl->data_blocks = new_bb;
149b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		return 0;
15028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
15128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
15228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	/* Optimization: blocks are mostly queued in sequence, so save the
153b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	   pointer to the last bb that was added, and start searching from
15428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	   there if the next block number is higher */
155b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	if (bbl->last_used && new_bb->block > bbl->last_used->block)
156b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		bb = bbl->last_used;
15728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	else
158b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		bb = bbl->data_blocks;
159b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bbl->last_used = new_bb;
16028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
161b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	for (; bb->next && bb->next->block < new_bb->block; bb = bb->next)
16228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		;
16328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
164b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	if (bb->next == NULL) {
165b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		bb->next = new_bb;
16628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	} else {
167b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		new_bb->next = bb->next;
168b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		bb->next = new_bb;
16928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
170b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
171b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return 0;
17228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
17328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
17428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* Queues a fill block of memory to be written to the specified data blocks */
175b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint backed_block_add_fill(struct backed_block_list *bbl, unsigned int fill_val,
176411619e921904b896eddae81c086c1f687c8304dColin Cross		unsigned int len, unsigned int block)
17728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
178b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	struct backed_block *bb = calloc(1, sizeof(struct backed_block));
179b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	if (bb == NULL) {
180b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		return -ENOMEM;
18128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
18228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
183b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->block = block;
184b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->len = len;
185b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->type = BACKED_BLOCK_FILL;
186b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->fill.val = fill_val;
187b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->next = NULL;
18828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
189b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return queue_bb(bbl, bb);
19028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
19128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
19228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* Queues a block of memory to be written to the specified data blocks */
193b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint backed_block_add_data(struct backed_block_list *bbl, void *data,
194b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		unsigned int len, unsigned int block)
19528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
196b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	struct backed_block *bb = calloc(1, sizeof(struct backed_block));
197b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	if (bb == NULL) {
198b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		return -ENOMEM;
19928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
20028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
201b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->block = block;
202b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->len = len;
203b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->type = BACKED_BLOCK_DATA;
204b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->data.data = data;
205b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->next = NULL;
20628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
207b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return queue_bb(bbl, bb);
20828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
20928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
21028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* Queues a chunk of a file on disk to be written to the specified data blocks */
211b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint backed_block_add_file(struct backed_block_list *bbl, const char *filename,
212411619e921904b896eddae81c086c1f687c8304dColin Cross		int64_t offset, unsigned int len, unsigned int block)
21328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
214b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	struct backed_block *bb = calloc(1, sizeof(struct backed_block));
215b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	if (bb == NULL) {
216b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		return -ENOMEM;
21728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
21828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
219b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->block = block;
220b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->len = len;
221b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->type = BACKED_BLOCK_FILE;
222b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->file.filename = strdup(filename);
223b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->file.offset = offset;
224b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	bb->next = NULL;
22528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
226b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return queue_bb(bbl, bb);
22728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
2289e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross
2299e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross/* Queues a chunk of a fd to be written to the specified data blocks */
2309e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Crossint backed_block_add_fd(struct backed_block_list *bbl, int fd, int64_t offset,
2319e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross		unsigned int len, unsigned int block)
2329e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross{
2339e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	struct backed_block *bb = calloc(1, sizeof(struct backed_block));
2349e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	if (bb == NULL) {
2359e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross		return -ENOMEM;
2369e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	}
2379e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross
2389e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	bb->block = block;
2399e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	bb->len = len;
2409e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	bb->type = BACKED_BLOCK_FD;
2419e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	bb->fd.fd = fd;
2429e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	bb->fd.offset = offset;
2439e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	bb->next = NULL;
2449e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross
2459e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	return queue_bb(bbl, bb);
2469e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross}
247