1ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* 2ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * Copyright (C) 2010 The Android Open Source Project 3ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * 4ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * Licensed under the Apache License, Version 2.0 (the "License"); 5ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * you may not use this file except in compliance with the License. 6ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * You may obtain a copy of the License at 7ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * 8ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * http://www.apache.org/licenses/LICENSE-2.0 9ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * 10ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * Unless required by applicable law or agreed to in writing, software 11ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * distributed under the License is distributed on an "AS IS" BASIS, 12ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * See the License for the specific language governing permissions and 14ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * limitations under the License. 15ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross */ 16ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 17ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "ext4_utils.h" 18ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "ext4.h" 19ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "ext4_extents.h" 20ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "indirect.h" 21ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "allocate.h" 22ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 23dc5abeee1e6fc4827ee0d5ece12aaed2dd56f4c7Colin Cross#include <sparse/sparse.h> 24dc5abeee1e6fc4827ee0d5ece12aaed2dd56f4c7Colin Cross 2533f96c66e9a1f2e266a75e5e84c091dffa6ef118Colin Cross#include <stdlib.h> 2633f96c66e9a1f2e266a75e5e84c091dffa6ef118Colin Cross#include <stdio.h> 2733f96c66e9a1f2e266a75e5e84c091dffa6ef118Colin Cross 28ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Creates data buffers for the first backing_len bytes of a block allocation 29ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross and queues them to be written */ 30ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u8 *create_backing(struct block_allocation *alloc, 31ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross unsigned long backing_len) 32ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 33ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (DIV_ROUND_UP(backing_len, info.block_size) > EXT4_NDIR_BLOCKS) 34ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error("indirect backing larger than %d blocks", EXT4_NDIR_BLOCKS); 35ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 36ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u8 *data = calloc(backing_len, 1); 37ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (!data) 38ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error_errno("calloc"); 39ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 40ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u8 *ptr = data; 41ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (; alloc != NULL && backing_len > 0; get_next_region(alloc)) { 42ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 region_block; 43ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 region_len; 44ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 len; 45ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross get_region(alloc, ®ion_block, ®ion_len); 46ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 47ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len = min(region_len * info.block_size, backing_len); 48ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 49f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross sparse_file_add_data(info.sparse_file, ptr, len, region_block); 50ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ptr += len; 51ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross backing_len -= len; 52ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 53ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 54ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return data; 55ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 56ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 57ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void reserve_indirect_block(struct block_allocation *alloc, int len) 58ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 59ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (reserve_oob_blocks(alloc, 1)) { 608aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to reserve oob block"); 618aef66d2125af8de7672a12895276802fcc1948fColin Cross return; 628aef66d2125af8de7672a12895276802fcc1948fColin Cross } 63ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 64ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (advance_blocks(alloc, len)) { 65ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to advance %d blocks", len); 66ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 67ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 68ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 69ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 70ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void reserve_dindirect_block(struct block_allocation *alloc, int len) 71ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 72ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (reserve_oob_blocks(alloc, 1)) { 738aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to reserve oob block"); 748aef66d2125af8de7672a12895276802fcc1948fColin Cross return; 758aef66d2125af8de7672a12895276802fcc1948fColin Cross } 76ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 77ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross while (len > 0) { 78ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int ind_block_len = min((int)aux_info.blocks_per_ind, len); 79ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 80ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_indirect_block(alloc, ind_block_len); 81ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 82ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= ind_block_len; 83ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 84ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 85ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 86ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 87ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void reserve_tindirect_block(struct block_allocation *alloc, int len) 88ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 89ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (reserve_oob_blocks(alloc, 1)) { 908aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to reserve oob block"); 918aef66d2125af8de7672a12895276802fcc1948fColin Cross return; 928aef66d2125af8de7672a12895276802fcc1948fColin Cross } 93ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 94ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross while (len > 0) { 95ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int dind_block_len = min((int)aux_info.blocks_per_dind, len); 96ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 97ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_dindirect_block(alloc, dind_block_len); 98ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 99ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= dind_block_len; 100ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 101ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 102ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 103ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void fill_indirect_block(u32 *ind_block, int len, struct block_allocation *alloc) 104ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 105ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int i; 106ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; i < len; i++) { 107ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ind_block[i] = get_block(alloc, i); 108ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 109ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 110ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 111ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void fill_dindirect_block(u32 *dind_block, int len, struct block_allocation *alloc) 112ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 113ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int i; 114ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 ind_block; 115ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 116ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; len > 0; i++) { 117ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ind_block = get_oob_block(alloc, 0); 118ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (advance_oob_blocks(alloc, 1)) { 1198aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to reserve oob block"); 1208aef66d2125af8de7672a12895276802fcc1948fColin Cross return; 1218aef66d2125af8de7672a12895276802fcc1948fColin Cross } 122ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 123ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dind_block[i] = ind_block; 124ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 125ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 *ind_block_data = calloc(info.block_size, 1); 126f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross sparse_file_add_data(info.sparse_file, ind_block_data, info.block_size, 127f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross ind_block); 128ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int ind_block_len = min((int)aux_info.blocks_per_ind, len); 129ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 130ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fill_indirect_block(ind_block_data, ind_block_len, alloc); 131ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 132ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (advance_blocks(alloc, ind_block_len)) { 133ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to advance %d blocks", ind_block_len); 134ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 135ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 136ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 137ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= ind_block_len; 138ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 139ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 140ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 141ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void fill_tindirect_block(u32 *tind_block, int len, struct block_allocation *alloc) 142ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 143ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int i; 144ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 dind_block; 145ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 146ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; len > 0; i++) { 147ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dind_block = get_oob_block(alloc, 0); 148ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (advance_oob_blocks(alloc, 1)) { 1498aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to reserve oob block"); 1508aef66d2125af8de7672a12895276802fcc1948fColin Cross return; 1518aef66d2125af8de7672a12895276802fcc1948fColin Cross } 152ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 1538aef66d2125af8de7672a12895276802fcc1948fColin Cross tind_block[i] = dind_block; 154ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 155ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 *dind_block_data = calloc(info.block_size, 1); 156f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross sparse_file_add_data(info.sparse_file, dind_block_data, info.block_size, 157f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross dind_block); 158ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int dind_block_len = min((int)aux_info.blocks_per_dind, len); 159ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 160ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fill_dindirect_block(dind_block_data, dind_block_len, alloc); 161ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 1628aef66d2125af8de7672a12895276802fcc1948fColin Cross len -= dind_block_len; 163ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 164ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 165ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 166ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Given an allocation, attach as many blocks as possible to direct inode 167ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross blocks, and return the rest */ 168ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic int inode_attach_direct_blocks(struct ext4_inode *inode, 169ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc, u32 *block_len) 170ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 171ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int len = min(*block_len, EXT4_NDIR_BLOCKS); 172ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int i; 173ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 174ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; i < len; i++) { 175ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_block[i] = get_block(alloc, i); 176ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 177ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 1788aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_blocks(alloc, len)) { 1798aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance %d blocks", len); 1808aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 1818aef66d2125af8de7672a12895276802fcc1948fColin Cross } 182ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 1838aef66d2125af8de7672a12895276802fcc1948fColin Cross *block_len -= len; 1848aef66d2125af8de7672a12895276802fcc1948fColin Cross return 0; 185ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 186ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 187ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Given an allocation, attach as many blocks as possible to indirect blocks, 188ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross and return the rest 189ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross Assumes that the blocks necessary to hold the indirect blocks were included 190ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross as part of the allocation */ 191ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic int inode_attach_indirect_blocks(struct ext4_inode *inode, 192ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc, u32 *block_len) 193ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 194ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int len = min(*block_len, aux_info.blocks_per_ind); 195ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 196ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int ind_block = get_oob_block(alloc, 0); 197ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_block[EXT4_IND_BLOCK] = ind_block; 198ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 1998aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_oob_blocks(alloc, 1)) { 2008aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance oob block"); 2018aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 2028aef66d2125af8de7672a12895276802fcc1948fColin Cross } 203ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 204ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 *ind_block_data = calloc(info.block_size, 1); 205f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross sparse_file_add_data(info.sparse_file, ind_block_data, info.block_size, 206f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross ind_block); 207ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 208ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fill_indirect_block(ind_block_data, len, alloc); 209ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2108aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_blocks(alloc, len)) { 2118aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance %d blocks", len); 2128aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 2138aef66d2125af8de7672a12895276802fcc1948fColin Cross } 214ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2158aef66d2125af8de7672a12895276802fcc1948fColin Cross *block_len -= len; 2168aef66d2125af8de7672a12895276802fcc1948fColin Cross return 0; 217ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 218ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 219ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Given an allocation, attach as many blocks as possible to doubly indirect 220ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross blocks, and return the rest. 221ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross Assumes that the blocks necessary to hold the indirect and doubly indirect 222ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross blocks were included as part of the allocation */ 223ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic int inode_attach_dindirect_blocks(struct ext4_inode *inode, 224ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc, u32 *block_len) 225ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 226ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int len = min(*block_len, aux_info.blocks_per_dind); 227ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 228ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int dind_block = get_oob_block(alloc, 0); 229ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_block[EXT4_DIND_BLOCK] = dind_block; 230ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2318aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_oob_blocks(alloc, 1)) { 2328aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance oob block"); 2338aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 2348aef66d2125af8de7672a12895276802fcc1948fColin Cross } 235ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 236ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 *dind_block_data = calloc(info.block_size, 1); 237f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross sparse_file_add_data(info.sparse_file, dind_block_data, info.block_size, 238f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross dind_block); 239ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 240ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fill_dindirect_block(dind_block_data, len, alloc); 241ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2428aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_blocks(alloc, len)) { 2438aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance %d blocks", len); 2448aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 2458aef66d2125af8de7672a12895276802fcc1948fColin Cross } 246ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2478aef66d2125af8de7672a12895276802fcc1948fColin Cross *block_len -= len; 248ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 0; 249ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 250ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 251ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Given an allocation, attach as many blocks as possible to triply indirect 252ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross blocks, and return the rest. 253ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross Assumes that the blocks necessary to hold the indirect, doubly indirect and 254ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross triply indirect blocks were included as part of the allocation */ 255ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic int inode_attach_tindirect_blocks(struct ext4_inode *inode, 256ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc, u32 *block_len) 257ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 258ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int len = min(*block_len, aux_info.blocks_per_tind); 259ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 260ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int tind_block = get_oob_block(alloc, 0); 261ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_block[EXT4_TIND_BLOCK] = tind_block; 262ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2638aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_oob_blocks(alloc, 1)) { 2648aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance oob block"); 2658aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 2668aef66d2125af8de7672a12895276802fcc1948fColin Cross } 267ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 268ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 *tind_block_data = calloc(info.block_size, 1); 269f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross sparse_file_add_data(info.sparse_file, tind_block_data, info.block_size, 270f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross tind_block); 271ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 272ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fill_tindirect_block(tind_block_data, len, alloc); 273ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2748aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_blocks(alloc, len)) { 2758aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance %d blocks", len); 2768aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 2778aef66d2125af8de7672a12895276802fcc1948fColin Cross } 278ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2798aef66d2125af8de7672a12895276802fcc1948fColin Cross *block_len -= len; 2808aef66d2125af8de7672a12895276802fcc1948fColin Cross return 0; 281ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 282ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 283ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void reserve_all_indirect_blocks(struct block_allocation *alloc, u32 len) 284ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 285ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len <= EXT4_NDIR_BLOCKS) 286ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 287ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 288ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= EXT4_NDIR_BLOCKS; 289ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross advance_blocks(alloc, EXT4_NDIR_BLOCKS); 290ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 291ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 ind_block_len = min(aux_info.blocks_per_ind, len); 292ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_indirect_block(alloc, ind_block_len); 293ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 294ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= ind_block_len; 295ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len == 0) 296ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 297ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 298ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 dind_block_len = min(aux_info.blocks_per_dind, len); 299ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_dindirect_block(alloc, dind_block_len); 300ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 301ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= dind_block_len; 302ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len == 0) 303ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 304ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 305ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 tind_block_len = min(aux_info.blocks_per_tind, len); 306ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_tindirect_block(alloc, tind_block_len); 307ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 308ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= tind_block_len; 309ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len == 0) 310ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 311ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 312ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("%d blocks remaining", len); 313ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 314ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 315ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u32 indirect_blocks_needed(u32 len) 316ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 317ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 ind = 0; 318ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 319ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len <= EXT4_NDIR_BLOCKS) 320ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return ind; 321ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 322ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= EXT4_NDIR_BLOCKS; 323ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 324ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross /* We will need an indirect block for the rest of the blocks */ 325ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ind += DIV_ROUND_UP(len, aux_info.blocks_per_ind); 326ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 327ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len <= aux_info.blocks_per_ind) 328ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return ind; 329ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 330ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= aux_info.blocks_per_ind; 331ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 332ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ind += DIV_ROUND_UP(len, aux_info.blocks_per_dind); 333ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 334ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len <= aux_info.blocks_per_dind) 335ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return ind; 336ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 337ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= aux_info.blocks_per_dind; 338ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 339ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ind += DIV_ROUND_UP(len, aux_info.blocks_per_tind); 340ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 341ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len <= aux_info.blocks_per_tind) 342ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return ind; 343ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 344ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error("request too large"); 345ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 0; 346ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 347ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 348ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic int do_inode_attach_indirect(struct ext4_inode *inode, 349ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc, u32 block_len) 350ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 351ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 count = block_len; 352ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 353ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (inode_attach_direct_blocks(inode, alloc, &count)) { 354ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to attach direct blocks to inode"); 355ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return -1; 356ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 357ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 358ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (count > 0) { 3598aef66d2125af8de7672a12895276802fcc1948fColin Cross if (inode_attach_indirect_blocks(inode, alloc, &count)) { 3608aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to attach indirect blocks to inode"); 3618aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 3628aef66d2125af8de7672a12895276802fcc1948fColin Cross } 3638aef66d2125af8de7672a12895276802fcc1948fColin Cross } 3648aef66d2125af8de7672a12895276802fcc1948fColin Cross 3658aef66d2125af8de7672a12895276802fcc1948fColin Cross if (count > 0) { 3668aef66d2125af8de7672a12895276802fcc1948fColin Cross if (inode_attach_dindirect_blocks(inode, alloc, &count)) { 3678aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to attach dindirect blocks to inode"); 3688aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 3698aef66d2125af8de7672a12895276802fcc1948fColin Cross } 370ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 371ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 3728aef66d2125af8de7672a12895276802fcc1948fColin Cross if (count > 0) { 3738aef66d2125af8de7672a12895276802fcc1948fColin Cross if (inode_attach_tindirect_blocks(inode, alloc, &count)) { 3748aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to attach tindirect blocks to inode"); 3758aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 3768aef66d2125af8de7672a12895276802fcc1948fColin Cross } 3778aef66d2125af8de7672a12895276802fcc1948fColin Cross } 3788aef66d2125af8de7672a12895276802fcc1948fColin Cross 3798aef66d2125af8de7672a12895276802fcc1948fColin Cross if (count) { 380ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("blocks left after triply-indirect allocation"); 381ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return -1; 3828aef66d2125af8de7672a12895276802fcc1948fColin Cross } 383ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 384ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross rewind_alloc(alloc); 385ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 386ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 0; 387ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 388ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 389ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic struct block_allocation *do_inode_allocate_indirect( 390ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct ext4_inode *inode, u32 block_len) 391ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 392ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 indirect_len = indirect_blocks_needed(block_len); 393ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 394ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc = allocate_blocks(block_len + indirect_len); 395ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 396ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (alloc == NULL) { 397ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("Failed to allocate %d blocks", block_len + indirect_len); 398ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return NULL; 399ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 400ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 401ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return alloc; 402ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 403ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 404ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Allocates enough blocks to hold len bytes and connects them to an inode */ 405ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossvoid inode_allocate_indirect(struct ext4_inode *inode, unsigned long len) 406ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 407ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc; 408ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 block_len = DIV_ROUND_UP(len, info.block_size); 409ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 indirect_len = indirect_blocks_needed(block_len); 410ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 411ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross alloc = do_inode_allocate_indirect(inode, block_len); 412ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (alloc == NULL) { 413ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to allocate extents for %lu bytes", len); 414ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 415ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 416ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 417ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_all_indirect_blocks(alloc, block_len); 418ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross rewind_alloc(alloc); 419ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 420ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (do_inode_attach_indirect(inode, alloc, block_len)) 421ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to attach blocks to indirect inode"); 422ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 423ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_flags = 0; 424ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_blocks_lo = (block_len + indirect_len) * info.block_size / 512; 425ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_size_lo = len; 426ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 427ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free_alloc(alloc); 428ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 429ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 430ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossvoid inode_attach_resize(struct ext4_inode *inode, 431ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc) 432ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 433ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 block_len = block_allocation_len(alloc); 43422742ce739a046a079b2e1b03342a25472dfa352Colin Cross u32 superblocks = block_len / info.bg_desc_reserve_blocks; 435ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 i, j; 436ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u64 blocks; 437ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u64 size; 438ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 43922742ce739a046a079b2e1b03342a25472dfa352Colin Cross if (block_len % info.bg_desc_reserve_blocks) 440ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error("reserved blocks not a multiple of %d", 44122742ce739a046a079b2e1b03342a25472dfa352Colin Cross info.bg_desc_reserve_blocks); 442ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 443ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross append_oob_allocation(alloc, 1); 444ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 dind_block = get_oob_block(alloc, 0); 445ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 446ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 *dind_block_data = calloc(info.block_size, 1); 447ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (!dind_block_data) 448ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error_errno("calloc"); 449f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross sparse_file_add_data(info.sparse_file, dind_block_data, info.block_size, 450f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross dind_block); 451ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 45222742ce739a046a079b2e1b03342a25472dfa352Colin Cross u32 *ind_block_data = calloc(info.block_size, info.bg_desc_reserve_blocks); 453ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (!ind_block_data) 454ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error_errno("calloc"); 455f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross sparse_file_add_data(info.sparse_file, ind_block_data, 45622742ce739a046a079b2e1b03342a25472dfa352Colin Cross info.block_size * info.bg_desc_reserve_blocks, 457ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross get_block(alloc, 0)); 458ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 45922742ce739a046a079b2e1b03342a25472dfa352Colin Cross for (i = 0; i < info.bg_desc_reserve_blocks; i++) { 46022742ce739a046a079b2e1b03342a25472dfa352Colin Cross int r = (i - aux_info.bg_desc_blocks) % info.bg_desc_reserve_blocks; 461ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (r < 0) 46222742ce739a046a079b2e1b03342a25472dfa352Colin Cross r += info.bg_desc_reserve_blocks; 463ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 464ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dind_block_data[i] = get_block(alloc, r); 465ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 466ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (j = 1; j < superblocks; j++) { 46722742ce739a046a079b2e1b03342a25472dfa352Colin Cross u32 b = j * info.bg_desc_reserve_blocks + r; 468ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ind_block_data[r * aux_info.blocks_per_ind + j - 1] = get_block(alloc, b); 469ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 470ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 471ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 472ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 last_block = EXT4_NDIR_BLOCKS + aux_info.blocks_per_ind + 47322742ce739a046a079b2e1b03342a25472dfa352Colin Cross aux_info.blocks_per_ind * (info.bg_desc_reserve_blocks - 1) + 474ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross superblocks - 2; 475ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 476ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross blocks = ((u64)block_len + 1) * info.block_size / 512; 477ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross size = (u64)last_block * info.block_size; 478ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 479ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_block[EXT4_DIND_BLOCK] = dind_block; 480ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_flags = 0; 481ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_blocks_lo = blocks; 482ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->osd2.linux2.l_i_blocks_high = blocks >> 32; 483ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_size_lo = size; 484ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_size_high = size >> 32; 485ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 486ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 487ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Allocates enough blocks to hold len bytes, with backing_len bytes in a data 488ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross buffer, and connects them to an inode. Returns a pointer to the data 489ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross buffer. */ 490ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossu8 *inode_allocate_data_indirect(struct ext4_inode *inode, unsigned long len, 491ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross unsigned long backing_len) 492ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 493ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc; 49482c18e022db437b22c0d76cca420bfe558bf2ebbJohan Rudholm u32 block_len = DIV_ROUND_UP(len, info.block_size); 495ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u8 *data = NULL; 496ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 49782c18e022db437b22c0d76cca420bfe558bf2ebbJohan Rudholm alloc = do_inode_allocate_indirect(inode, block_len); 498ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (alloc == NULL) { 499ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to allocate extents for %lu bytes", len); 500ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return NULL; 501ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 502ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 503ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (backing_len) { 504ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross data = create_backing(alloc, backing_len); 505ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (!data) 506ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to create backing for %lu bytes", backing_len); 507ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 508ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 50982c18e022db437b22c0d76cca420bfe558bf2ebbJohan Rudholm rewind_alloc(alloc); 51082c18e022db437b22c0d76cca420bfe558bf2ebbJohan Rudholm if (do_inode_attach_indirect(inode, alloc, block_len)) 51182c18e022db437b22c0d76cca420bfe558bf2ebbJohan Rudholm error("failed to attach blocks to indirect inode"); 51282c18e022db437b22c0d76cca420bfe558bf2ebbJohan Rudholm 513ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free_alloc(alloc); 514ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 515ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return data; 516ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 517