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