sparse.c revision f1ec8ac84a8540b92a16f187bfa92b2f3c63917e
128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* 228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * Copyright (C) 2012 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> 1828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <stdlib.h> 1928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 2028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sparse/sparse.h> 2128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 2228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_file.h" 2328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 2428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "output_file.h" 2528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "backed_block.h" 2628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_defs.h" 27bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross#include "sparse_format.h" 2828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 2928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct sparse_file *sparse_file_new(unsigned int block_size, int64_t len) 3028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 3128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross struct sparse_file *s = calloc(sizeof(struct sparse_file), 1); 3228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (!s) { 3328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return NULL; 3428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 3528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 36be8ddcb35a459481c0bcf5bfe645c1fefe963f5cColin Cross s->backed_block_list = backed_block_list_new(block_size); 37411619e921904b896eddae81c086c1f687c8304dColin Cross if (!s->backed_block_list) { 38411619e921904b896eddae81c086c1f687c8304dColin Cross free(s); 39411619e921904b896eddae81c086c1f687c8304dColin Cross return NULL; 40411619e921904b896eddae81c086c1f687c8304dColin Cross } 4128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross s->block_size = block_size; 4328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross s->len = len; 4428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return s; 4628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 4728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4828fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossvoid sparse_file_destroy(struct sparse_file *s) 4928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 50411619e921904b896eddae81c086c1f687c8304dColin Cross backed_block_list_destroy(s->backed_block_list); 5128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross free(s); 5228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 5328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 5428fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_data(struct sparse_file *s, 5528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross void *data, unsigned int len, unsigned int block) 5628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 57b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return backed_block_add_data(s->backed_block_list, data, len, block); 5828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 5928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 6028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_fill(struct sparse_file *s, 6128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross uint32_t fill_val, unsigned int len, unsigned int block) 6228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 63b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return backed_block_add_fill(s->backed_block_list, fill_val, len, block); 6428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 6528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 6628fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_file(struct sparse_file *s, 6728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross const char *filename, int64_t file_offset, unsigned int len, 6828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross unsigned int block) 6928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 70b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return backed_block_add_file(s->backed_block_list, filename, file_offset, 71b55dceea986ab24f8b836b5116b389ed619c816eColin Cross len, block); 7228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 7328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 749e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Crossint sparse_file_add_fd(struct sparse_file *s, 759e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross int fd, int64_t file_offset, unsigned int len, unsigned int block) 769e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross{ 779e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return backed_block_add_fd(s->backed_block_list, fd, file_offset, 789e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross len, block); 799e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross} 80b55dceea986ab24f8b836b5116b389ed619c816eColin Crossunsigned int sparse_count_chunks(struct sparse_file *s) 8128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 82b55dceea986ab24f8b836b5116b389ed619c816eColin Cross struct backed_block *bb; 83b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int last_block = 0; 84b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int chunks = 0; 85b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 86b55dceea986ab24f8b836b5116b389ed619c816eColin Cross for (bb = backed_block_iter_new(s->backed_block_list); bb; 87b55dceea986ab24f8b836b5116b389ed619c816eColin Cross bb = backed_block_iter_next(bb)) { 88b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (backed_block_block(bb) > last_block) { 89b55dceea986ab24f8b836b5116b389ed619c816eColin Cross /* If there is a gap between chunks, add a skip chunk */ 90b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunks++; 91b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 92b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunks++; 93b55dceea986ab24f8b836b5116b389ed619c816eColin Cross last_block = backed_block_block(bb) + 94b55dceea986ab24f8b836b5116b389ed619c816eColin Cross DIV_ROUND_UP(backed_block_len(bb), s->block_size); 95b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 96b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (last_block < DIV_ROUND_UP(s->len, s->block_size)) { 97b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunks++; 98b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 9928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 100b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return chunks; 10128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 10228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 1031e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic void sparse_file_write_block(struct output_file *out, 1041e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct backed_block *bb) 1051e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 1061e17b313a6257b7b5081e178e81435c09d60378eColin Cross switch (backed_block_type(bb)) { 1071e17b313a6257b7b5081e178e81435c09d60378eColin Cross case BACKED_BLOCK_DATA: 1081e17b313a6257b7b5081e178e81435c09d60378eColin Cross write_data_chunk(out, backed_block_len(bb), backed_block_data(bb)); 1091e17b313a6257b7b5081e178e81435c09d60378eColin Cross break; 1101e17b313a6257b7b5081e178e81435c09d60378eColin Cross case BACKED_BLOCK_FILE: 1111e17b313a6257b7b5081e178e81435c09d60378eColin Cross write_file_chunk(out, backed_block_len(bb), 1121e17b313a6257b7b5081e178e81435c09d60378eColin Cross backed_block_filename(bb), backed_block_file_offset(bb)); 1131e17b313a6257b7b5081e178e81435c09d60378eColin Cross break; 1141e17b313a6257b7b5081e178e81435c09d60378eColin Cross case BACKED_BLOCK_FD: 1151e17b313a6257b7b5081e178e81435c09d60378eColin Cross write_fd_chunk(out, backed_block_len(bb), 1161e17b313a6257b7b5081e178e81435c09d60378eColin Cross backed_block_fd(bb), backed_block_file_offset(bb)); 1171e17b313a6257b7b5081e178e81435c09d60378eColin Cross break; 1181e17b313a6257b7b5081e178e81435c09d60378eColin Cross case BACKED_BLOCK_FILL: 1191e17b313a6257b7b5081e178e81435c09d60378eColin Cross write_fill_chunk(out, backed_block_len(bb), 1201e17b313a6257b7b5081e178e81435c09d60378eColin Cross backed_block_fill_val(bb)); 1211e17b313a6257b7b5081e178e81435c09d60378eColin Cross break; 1221e17b313a6257b7b5081e178e81435c09d60378eColin Cross } 1231e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 1241e17b313a6257b7b5081e178e81435c09d60378eColin Cross 1251e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic int write_all_blocks(struct sparse_file *s, struct output_file *out) 12628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 127b55dceea986ab24f8b836b5116b389ed619c816eColin Cross struct backed_block *bb; 128b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int last_block = 0; 129b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int64_t pad; 13028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 131b55dceea986ab24f8b836b5116b389ed619c816eColin Cross for (bb = backed_block_iter_new(s->backed_block_list); bb; 132b55dceea986ab24f8b836b5116b389ed619c816eColin Cross bb = backed_block_iter_next(bb)) { 133b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (backed_block_block(bb) > last_block) { 134b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int blocks = backed_block_block(bb) - last_block; 135b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_skip_chunk(out, (int64_t)blocks * s->block_size); 136b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 1371e17b313a6257b7b5081e178e81435c09d60378eColin Cross sparse_file_write_block(out, bb); 138b55dceea986ab24f8b836b5116b389ed619c816eColin Cross last_block = backed_block_block(bb) + 139b55dceea986ab24f8b836b5116b389ed619c816eColin Cross DIV_ROUND_UP(backed_block_len(bb), s->block_size); 140b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 14128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 142f1ec8ac84a8540b92a16f187bfa92b2f3c63917eColin Cross pad = s->len - (int64_t)last_block * s->block_size; 143b55dceea986ab24f8b836b5116b389ed619c816eColin Cross assert(pad >= 0); 144b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (pad > 0) { 145b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_skip_chunk(out, pad); 146b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 14728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 1481e17b313a6257b7b5081e178e81435c09d60378eColin Cross return 0; 1491e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 1501e17b313a6257b7b5081e178e81435c09d60378eColin Cross 1511e17b313a6257b7b5081e178e81435c09d60378eColin Crossint sparse_file_write(struct sparse_file *s, int fd, bool gz, bool sparse, 1521e17b313a6257b7b5081e178e81435c09d60378eColin Cross bool crc) 1531e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 1541e17b313a6257b7b5081e178e81435c09d60378eColin Cross int ret; 1551e17b313a6257b7b5081e178e81435c09d60378eColin Cross int chunks; 1561e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct output_file *out; 1571e17b313a6257b7b5081e178e81435c09d60378eColin Cross 1581e17b313a6257b7b5081e178e81435c09d60378eColin Cross chunks = sparse_count_chunks(s); 159b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross out = output_file_open_fd(fd, s->block_size, s->len, gz, sparse, chunks, crc); 1601e17b313a6257b7b5081e178e81435c09d60378eColin Cross 1611e17b313a6257b7b5081e178e81435c09d60378eColin Cross if (!out) 1621e17b313a6257b7b5081e178e81435c09d60378eColin Cross return -ENOMEM; 1631e17b313a6257b7b5081e178e81435c09d60378eColin Cross 1641e17b313a6257b7b5081e178e81435c09d60378eColin Cross ret = write_all_blocks(s, out); 1651e17b313a6257b7b5081e178e81435c09d60378eColin Cross 166b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross output_file_close(out); 16728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 1681e17b313a6257b7b5081e178e81435c09d60378eColin Cross return ret; 1691e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 1701e17b313a6257b7b5081e178e81435c09d60378eColin Cross 1711e17b313a6257b7b5081e178e81435c09d60378eColin Crossint sparse_file_callback(struct sparse_file *s, bool sparse, bool crc, 1721e17b313a6257b7b5081e178e81435c09d60378eColin Cross int (*write)(void *priv, const void *data, int len), void *priv) 1731e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 1741e17b313a6257b7b5081e178e81435c09d60378eColin Cross int ret; 1751e17b313a6257b7b5081e178e81435c09d60378eColin Cross int chunks; 1761e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct output_file *out; 1771e17b313a6257b7b5081e178e81435c09d60378eColin Cross 1781e17b313a6257b7b5081e178e81435c09d60378eColin Cross chunks = sparse_count_chunks(s); 179b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross out = output_file_open_callback(write, priv, s->block_size, s->len, false, 1801e17b313a6257b7b5081e178e81435c09d60378eColin Cross sparse, chunks, crc); 1811e17b313a6257b7b5081e178e81435c09d60378eColin Cross 1821e17b313a6257b7b5081e178e81435c09d60378eColin Cross if (!out) 1831e17b313a6257b7b5081e178e81435c09d60378eColin Cross return -ENOMEM; 1841e17b313a6257b7b5081e178e81435c09d60378eColin Cross 1851e17b313a6257b7b5081e178e81435c09d60378eColin Cross ret = write_all_blocks(s, out); 1861e17b313a6257b7b5081e178e81435c09d60378eColin Cross 187b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross output_file_close(out); 1881e17b313a6257b7b5081e178e81435c09d60378eColin Cross 1891e17b313a6257b7b5081e178e81435c09d60378eColin Cross return ret; 19028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 191a21930b6b0dbb04a52948566d58fb48c6db58babColin Cross 192bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Crossstatic int out_counter_write(void *priv, const void *data, int len) 193bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross{ 194bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross int64_t *count = priv; 195bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross *count += len; 196bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross return 0; 197bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross} 198bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 199317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Crossint64_t sparse_file_len(struct sparse_file *s, bool sparse, bool crc) 200317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross{ 201317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross int ret; 202317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross int chunks = sparse_count_chunks(s); 203317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross int64_t count = 0; 204317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross struct output_file *out; 205317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross 206b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross out = output_file_open_callback(out_counter_write, &count, 207317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross s->block_size, s->len, false, sparse, chunks, crc); 208317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross if (!out) { 209317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross return -1; 210317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross } 211317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross 212317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross ret = write_all_blocks(s, out); 213317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross 214b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross output_file_close(out); 215317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross 216317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross if (ret < 0) { 217317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross return -1; 218317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross } 219317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross 220317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross return count; 221317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross} 222317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross 223bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Crossstatic struct backed_block *move_chunks_up_to_len(struct sparse_file *from, 224bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross struct sparse_file *to, unsigned int len) 225bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross{ 226bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross int64_t count = 0; 227bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross struct output_file *out_counter; 228bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross struct backed_block *last_bb = NULL; 229bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross struct backed_block *bb; 230bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross struct backed_block *start; 231bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross int64_t file_len = 0; 232bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 233bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross /* 234bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross * overhead is sparse file header, initial skip chunk, split chunk, end 235bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross * skip chunk, and crc chunk. 236bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross */ 237bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross int overhead = sizeof(sparse_header_t) + 4 * sizeof(chunk_header_t) + 238bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross sizeof(uint32_t); 239bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross len -= overhead; 240bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 241bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross start = backed_block_iter_new(from->backed_block_list); 242b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross out_counter = output_file_open_callback(out_counter_write, &count, 243bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross to->block_size, to->len, false, true, 0, false); 244bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross if (!out_counter) { 245bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross return NULL; 246bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross } 247bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 248bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross for (bb = start; bb; bb = backed_block_iter_next(bb)) { 249bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross count = 0; 250bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross /* will call out_counter_write to update count */ 251bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross sparse_file_write_block(out_counter, bb); 252bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross if (file_len + count > len) { 253bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross /* 254bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross * If the remaining available size is more than 1/8th of the 255bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross * requested size, split the chunk. Results in sparse files that 256bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross * are at least 7/8ths of the requested size 257bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross */ 258bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross if (!last_bb || (len - file_len > (len / 8))) { 259bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross backed_block_split(from->backed_block_list, bb, len - file_len); 260bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross last_bb = bb; 261bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross } 262bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross goto out; 263bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross } 264bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross file_len += count; 265bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross last_bb = bb; 266bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross } 267bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 268bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Crossout: 269bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross backed_block_list_move(from->backed_block_list, 270bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross to->backed_block_list, start, last_bb); 271bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 272b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross output_file_close(out_counter); 273bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 274bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross return bb; 275bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross} 276bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 277bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Crossint sparse_file_resparse(struct sparse_file *in_s, unsigned int max_len, 278bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross struct sparse_file **out_s, int out_s_count) 279bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross{ 280bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross struct backed_block *bb; 281bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross unsigned int overhead; 282bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross struct sparse_file *s; 283bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross struct sparse_file *tmp; 284bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross int c = 0; 285bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 286bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross tmp = sparse_file_new(in_s->block_size, in_s->len); 287bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross if (!tmp) { 288bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross return -ENOMEM; 289bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross } 290bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 291bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross do { 292bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross s = sparse_file_new(in_s->block_size, in_s->len); 293bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 294bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross bb = move_chunks_up_to_len(in_s, s, max_len); 295bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 296bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross if (c < out_s_count) { 297bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross out_s[c] = s; 298bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross } else { 299bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross backed_block_list_move(s->backed_block_list, tmp->backed_block_list, 300bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross NULL, NULL); 301bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross sparse_file_destroy(s); 302bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross } 303bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross c++; 304bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross } while (bb); 305bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 306bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross backed_block_list_move(tmp->backed_block_list, in_s->backed_block_list, 307bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross NULL, NULL); 308bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 309bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross sparse_file_destroy(tmp); 310bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 311bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross return c; 312bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross} 313bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross 314a21930b6b0dbb04a52948566d58fb48c6db58babColin Crossvoid sparse_file_verbose(struct sparse_file *s) 315a21930b6b0dbb04a52948566d58fb48c6db58babColin Cross{ 316a21930b6b0dbb04a52948566d58fb48c6db58babColin Cross s->verbose = true; 317a21930b6b0dbb04a52948566d58fb48c6db58babColin Cross} 318