indirect.c revision 22742ce739a046a079b2e1b03342a25472dfa352
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 <stdlib.h> 18ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <stdio.h> 19ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 20ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "ext4_utils.h" 21ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "ext4.h" 22ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "ext4_extents.h" 23ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "backed_block.h" 24ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "indirect.h" 25ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "allocate.h" 26ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 27ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Creates data buffers for the first backing_len bytes of a block allocation 28ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross and queues them to be written */ 29ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u8 *create_backing(struct block_allocation *alloc, 30ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross unsigned long backing_len) 31ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 32ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (DIV_ROUND_UP(backing_len, info.block_size) > EXT4_NDIR_BLOCKS) 33ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error("indirect backing larger than %d blocks", EXT4_NDIR_BLOCKS); 34ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 35ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u8 *data = calloc(backing_len, 1); 36ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (!data) 37ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error_errno("calloc"); 38ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 39ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u8 *ptr = data; 40ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (; alloc != NULL && backing_len > 0; get_next_region(alloc)) { 41ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 region_block; 42ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 region_len; 43ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 len; 44ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross get_region(alloc, ®ion_block, ®ion_len); 45ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 46ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len = min(region_len * info.block_size, backing_len); 47ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 48ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross queue_data_block(ptr, len, region_block); 49ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ptr += len; 50ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross backing_len -= len; 51ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 52ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 53ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return data; 54ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 55ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 56ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void reserve_indirect_block(struct block_allocation *alloc, int len) 57ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 58ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (reserve_oob_blocks(alloc, 1)) { 598aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to reserve oob block"); 608aef66d2125af8de7672a12895276802fcc1948fColin Cross return; 618aef66d2125af8de7672a12895276802fcc1948fColin Cross } 62ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 63ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (advance_blocks(alloc, len)) { 64ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to advance %d blocks", len); 65ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 66ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 67ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 68ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 69ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void reserve_dindirect_block(struct block_allocation *alloc, int len) 70ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 71ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (reserve_oob_blocks(alloc, 1)) { 728aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to reserve oob block"); 738aef66d2125af8de7672a12895276802fcc1948fColin Cross return; 748aef66d2125af8de7672a12895276802fcc1948fColin Cross } 75ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 76ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross while (len > 0) { 77ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int ind_block_len = min((int)aux_info.blocks_per_ind, len); 78ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 79ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_indirect_block(alloc, ind_block_len); 80ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 81ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= ind_block_len; 82ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 83ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 84ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 85ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 86ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void reserve_tindirect_block(struct block_allocation *alloc, int len) 87ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 88ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (reserve_oob_blocks(alloc, 1)) { 898aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to reserve oob block"); 908aef66d2125af8de7672a12895276802fcc1948fColin Cross return; 918aef66d2125af8de7672a12895276802fcc1948fColin Cross } 92ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 93ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross while (len > 0) { 94ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int dind_block_len = min((int)aux_info.blocks_per_dind, len); 95ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 96ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_dindirect_block(alloc, dind_block_len); 97ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 98ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= dind_block_len; 99ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 100ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 101ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 102ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void fill_indirect_block(u32 *ind_block, int len, struct block_allocation *alloc) 103ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 104ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int i; 105ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; i < len; i++) { 106ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ind_block[i] = get_block(alloc, i); 107ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 108ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 109ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 110ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void fill_dindirect_block(u32 *dind_block, int len, struct block_allocation *alloc) 111ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 112ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int i; 113ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 ind_block; 114ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 115ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; len > 0; i++) { 116ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ind_block = get_oob_block(alloc, 0); 117ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (advance_oob_blocks(alloc, 1)) { 1188aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to reserve oob block"); 1198aef66d2125af8de7672a12895276802fcc1948fColin Cross return; 1208aef66d2125af8de7672a12895276802fcc1948fColin Cross } 121ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 122ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dind_block[i] = ind_block; 123ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 124ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 *ind_block_data = calloc(info.block_size, 1); 125ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross queue_data_block((u8*)ind_block_data, info.block_size, ind_block); 126ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int ind_block_len = min((int)aux_info.blocks_per_ind, len); 127ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 128ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fill_indirect_block(ind_block_data, ind_block_len, alloc); 129ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 130ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (advance_blocks(alloc, ind_block_len)) { 131ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to advance %d blocks", ind_block_len); 132ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 133ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 134ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 135ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= ind_block_len; 136ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 137ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 138ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 139ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void fill_tindirect_block(u32 *tind_block, int len, struct block_allocation *alloc) 140ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 141ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int i; 142ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 dind_block; 143ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 144ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; len > 0; i++) { 145ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dind_block = get_oob_block(alloc, 0); 146ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (advance_oob_blocks(alloc, 1)) { 1478aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to reserve oob block"); 1488aef66d2125af8de7672a12895276802fcc1948fColin Cross return; 1498aef66d2125af8de7672a12895276802fcc1948fColin Cross } 150ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 1518aef66d2125af8de7672a12895276802fcc1948fColin Cross tind_block[i] = dind_block; 152ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 153ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 *dind_block_data = calloc(info.block_size, 1); 154ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross queue_data_block((u8*)dind_block_data, info.block_size, dind_block); 155ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int dind_block_len = min((int)aux_info.blocks_per_dind, len); 156ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 157ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fill_dindirect_block(dind_block_data, dind_block_len, alloc); 158ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 1598aef66d2125af8de7672a12895276802fcc1948fColin Cross len -= dind_block_len; 160ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 161ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 162ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 163ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Given an allocation, attach as many blocks as possible to direct inode 164ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross blocks, and return the rest */ 165ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic int inode_attach_direct_blocks(struct ext4_inode *inode, 166ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc, u32 *block_len) 167ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 168ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int len = min(*block_len, EXT4_NDIR_BLOCKS); 169ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int i; 170ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 171ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; i < len; i++) { 172ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_block[i] = get_block(alloc, i); 173ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 174ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 1758aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_blocks(alloc, len)) { 1768aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance %d blocks", len); 1778aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 1788aef66d2125af8de7672a12895276802fcc1948fColin Cross } 179ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 1808aef66d2125af8de7672a12895276802fcc1948fColin Cross *block_len -= len; 1818aef66d2125af8de7672a12895276802fcc1948fColin Cross return 0; 182ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 183ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 184ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Given an allocation, attach as many blocks as possible to indirect blocks, 185ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross and return the rest 186ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross Assumes that the blocks necessary to hold the indirect blocks were included 187ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross as part of the allocation */ 188ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic int inode_attach_indirect_blocks(struct ext4_inode *inode, 189ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc, u32 *block_len) 190ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 191ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int len = min(*block_len, aux_info.blocks_per_ind); 192ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 193ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int ind_block = get_oob_block(alloc, 0); 194ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_block[EXT4_IND_BLOCK] = ind_block; 195ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 1968aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_oob_blocks(alloc, 1)) { 1978aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance oob block"); 1988aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 1998aef66d2125af8de7672a12895276802fcc1948fColin Cross } 200ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 201ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 *ind_block_data = calloc(info.block_size, 1); 202ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross queue_data_block((u8*)ind_block_data, info.block_size, ind_block); 203ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 204ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fill_indirect_block(ind_block_data, len, alloc); 205ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2068aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_blocks(alloc, len)) { 2078aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance %d blocks", len); 2088aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 2098aef66d2125af8de7672a12895276802fcc1948fColin Cross } 210ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2118aef66d2125af8de7672a12895276802fcc1948fColin Cross *block_len -= len; 2128aef66d2125af8de7672a12895276802fcc1948fColin Cross return 0; 213ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 214ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 215ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Given an allocation, attach as many blocks as possible to doubly indirect 216ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross blocks, and return the rest. 217ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross Assumes that the blocks necessary to hold the indirect and doubly indirect 218ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross blocks were included as part of the allocation */ 219ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic int inode_attach_dindirect_blocks(struct ext4_inode *inode, 220ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc, u32 *block_len) 221ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 222ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int len = min(*block_len, aux_info.blocks_per_dind); 223ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 224ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int dind_block = get_oob_block(alloc, 0); 225ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_block[EXT4_DIND_BLOCK] = dind_block; 226ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2278aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_oob_blocks(alloc, 1)) { 2288aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance oob block"); 2298aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 2308aef66d2125af8de7672a12895276802fcc1948fColin Cross } 231ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 232ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 *dind_block_data = calloc(info.block_size, 1); 233ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross queue_data_block((u8*)dind_block_data, info.block_size, dind_block); 234ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 235ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fill_dindirect_block(dind_block_data, len, alloc); 236ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2378aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_blocks(alloc, len)) { 2388aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance %d blocks", len); 2398aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 2408aef66d2125af8de7672a12895276802fcc1948fColin Cross } 241ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2428aef66d2125af8de7672a12895276802fcc1948fColin Cross *block_len -= len; 243ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 0; 244ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 245ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 246ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Given an allocation, attach as many blocks as possible to triply indirect 247ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross blocks, and return the rest. 248ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross Assumes that the blocks necessary to hold the indirect, doubly indirect and 249ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross triply indirect blocks were included as part of the allocation */ 250ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic int inode_attach_tindirect_blocks(struct ext4_inode *inode, 251ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc, u32 *block_len) 252ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 253ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int len = min(*block_len, aux_info.blocks_per_tind); 254ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 255ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int tind_block = get_oob_block(alloc, 0); 256ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_block[EXT4_TIND_BLOCK] = tind_block; 257ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2588aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_oob_blocks(alloc, 1)) { 2598aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance oob block"); 2608aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 2618aef66d2125af8de7672a12895276802fcc1948fColin Cross } 262ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 263ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 *tind_block_data = calloc(info.block_size, 1); 264ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross queue_data_block((u8*)tind_block_data, info.block_size, tind_block); 265ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 266ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fill_tindirect_block(tind_block_data, len, alloc); 267ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2688aef66d2125af8de7672a12895276802fcc1948fColin Cross if (advance_blocks(alloc, len)) { 2698aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to advance %d blocks", len); 2708aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 2718aef66d2125af8de7672a12895276802fcc1948fColin Cross } 272ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 2738aef66d2125af8de7672a12895276802fcc1948fColin Cross *block_len -= len; 2748aef66d2125af8de7672a12895276802fcc1948fColin Cross return 0; 275ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 276ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 277ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void reserve_all_indirect_blocks(struct block_allocation *alloc, u32 len) 278ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 279ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len <= EXT4_NDIR_BLOCKS) 280ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 281ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 282ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= EXT4_NDIR_BLOCKS; 283ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross advance_blocks(alloc, EXT4_NDIR_BLOCKS); 284ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 285ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 ind_block_len = min(aux_info.blocks_per_ind, len); 286ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_indirect_block(alloc, ind_block_len); 287ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 288ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= ind_block_len; 289ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len == 0) 290ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 291ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 292ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 dind_block_len = min(aux_info.blocks_per_dind, len); 293ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_dindirect_block(alloc, dind_block_len); 294ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 295ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= dind_block_len; 296ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len == 0) 297ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 298ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 299ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 tind_block_len = min(aux_info.blocks_per_tind, len); 300ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_tindirect_block(alloc, tind_block_len); 301ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 302ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= tind_block_len; 303ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len == 0) 304ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 305ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 306ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("%d blocks remaining", len); 307ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 308ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 309ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u32 indirect_blocks_needed(u32 len) 310ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 311ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 ind = 0; 312ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 313ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len <= EXT4_NDIR_BLOCKS) 314ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return ind; 315ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 316ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= EXT4_NDIR_BLOCKS; 317ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 318ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross /* We will need an indirect block for the rest of the blocks */ 319ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ind += DIV_ROUND_UP(len, aux_info.blocks_per_ind); 320ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 321ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len <= aux_info.blocks_per_ind) 322ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return ind; 323ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 324ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= aux_info.blocks_per_ind; 325ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 326ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ind += DIV_ROUND_UP(len, aux_info.blocks_per_dind); 327ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 328ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len <= aux_info.blocks_per_dind) 329ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return ind; 330ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 331ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross len -= aux_info.blocks_per_dind; 332ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 333ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ind += DIV_ROUND_UP(len, aux_info.blocks_per_tind); 334ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 335ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (len <= aux_info.blocks_per_tind) 336ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return ind; 337ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 338ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error("request too large"); 339ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 0; 340ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 341ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 342ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic int do_inode_attach_indirect(struct ext4_inode *inode, 343ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc, u32 block_len) 344ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 345ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 count = block_len; 346ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 347ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (inode_attach_direct_blocks(inode, alloc, &count)) { 348ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to attach direct blocks to inode"); 349ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return -1; 350ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 351ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 352ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (count > 0) { 3538aef66d2125af8de7672a12895276802fcc1948fColin Cross if (inode_attach_indirect_blocks(inode, alloc, &count)) { 3548aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to attach indirect blocks to inode"); 3558aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 3568aef66d2125af8de7672a12895276802fcc1948fColin Cross } 3578aef66d2125af8de7672a12895276802fcc1948fColin Cross } 3588aef66d2125af8de7672a12895276802fcc1948fColin Cross 3598aef66d2125af8de7672a12895276802fcc1948fColin Cross if (count > 0) { 3608aef66d2125af8de7672a12895276802fcc1948fColin Cross if (inode_attach_dindirect_blocks(inode, alloc, &count)) { 3618aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to attach dindirect blocks to inode"); 3628aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 3638aef66d2125af8de7672a12895276802fcc1948fColin Cross } 364ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 365ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 3668aef66d2125af8de7672a12895276802fcc1948fColin Cross if (count > 0) { 3678aef66d2125af8de7672a12895276802fcc1948fColin Cross if (inode_attach_tindirect_blocks(inode, alloc, &count)) { 3688aef66d2125af8de7672a12895276802fcc1948fColin Cross error("failed to attach tindirect blocks to inode"); 3698aef66d2125af8de7672a12895276802fcc1948fColin Cross return -1; 3708aef66d2125af8de7672a12895276802fcc1948fColin Cross } 3718aef66d2125af8de7672a12895276802fcc1948fColin Cross } 3728aef66d2125af8de7672a12895276802fcc1948fColin Cross 3738aef66d2125af8de7672a12895276802fcc1948fColin Cross if (count) { 374ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("blocks left after triply-indirect allocation"); 375ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return -1; 3768aef66d2125af8de7672a12895276802fcc1948fColin Cross } 377ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 378ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross rewind_alloc(alloc); 379ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 380ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 0; 381ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 382ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 383ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic struct block_allocation *do_inode_allocate_indirect( 384ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct ext4_inode *inode, u32 block_len) 385ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 386ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 indirect_len = indirect_blocks_needed(block_len); 387ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 388ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc = allocate_blocks(block_len + indirect_len); 389ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 390ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (alloc == NULL) { 391ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("Failed to allocate %d blocks", block_len + indirect_len); 392ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return NULL; 393ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 394ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 395ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return alloc; 396ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 397ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 398ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Allocates enough blocks to hold len bytes and connects them to an inode */ 399ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossvoid inode_allocate_indirect(struct ext4_inode *inode, unsigned long len) 400ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 401ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc; 402ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 block_len = DIV_ROUND_UP(len, info.block_size); 403ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 indirect_len = indirect_blocks_needed(block_len); 404ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 405ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross alloc = do_inode_allocate_indirect(inode, block_len); 406ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (alloc == NULL) { 407ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to allocate extents for %lu bytes", len); 408ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 409ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 410ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 411ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_all_indirect_blocks(alloc, block_len); 412ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross rewind_alloc(alloc); 413ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 414ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (do_inode_attach_indirect(inode, alloc, block_len)) 415ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to attach blocks to indirect inode"); 416ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 417ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_flags = 0; 418ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_blocks_lo = (block_len + indirect_len) * info.block_size / 512; 419ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_size_lo = len; 420ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 421ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free_alloc(alloc); 422ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 423ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 424ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossvoid inode_attach_resize(struct ext4_inode *inode, 425ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc) 426ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 427ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 block_len = block_allocation_len(alloc); 42822742ce739a046a079b2e1b03342a25472dfa352Colin Cross u32 superblocks = block_len / info.bg_desc_reserve_blocks; 429ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 i, j; 430ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u64 blocks; 431ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u64 size; 432ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 43322742ce739a046a079b2e1b03342a25472dfa352Colin Cross if (block_len % info.bg_desc_reserve_blocks) 434ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error("reserved blocks not a multiple of %d", 43522742ce739a046a079b2e1b03342a25472dfa352Colin Cross info.bg_desc_reserve_blocks); 436ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 437ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross append_oob_allocation(alloc, 1); 438ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 dind_block = get_oob_block(alloc, 0); 439ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 440ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 *dind_block_data = calloc(info.block_size, 1); 441ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (!dind_block_data) 442ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error_errno("calloc"); 443ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross queue_data_block((u8 *)dind_block_data, info.block_size, dind_block); 444ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 44522742ce739a046a079b2e1b03342a25472dfa352Colin Cross u32 *ind_block_data = calloc(info.block_size, info.bg_desc_reserve_blocks); 446ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (!ind_block_data) 447ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error_errno("calloc"); 448ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross queue_data_block((u8 *)ind_block_data, 44922742ce739a046a079b2e1b03342a25472dfa352Colin Cross info.block_size * info.bg_desc_reserve_blocks, 450ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross get_block(alloc, 0)); 451ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 45222742ce739a046a079b2e1b03342a25472dfa352Colin Cross for (i = 0; i < info.bg_desc_reserve_blocks; i++) { 45322742ce739a046a079b2e1b03342a25472dfa352Colin Cross int r = (i - aux_info.bg_desc_blocks) % info.bg_desc_reserve_blocks; 454ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (r < 0) 45522742ce739a046a079b2e1b03342a25472dfa352Colin Cross r += info.bg_desc_reserve_blocks; 456ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 457ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dind_block_data[i] = get_block(alloc, r); 458ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 459ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (j = 1; j < superblocks; j++) { 46022742ce739a046a079b2e1b03342a25472dfa352Colin Cross u32 b = j * info.bg_desc_reserve_blocks + r; 461ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ind_block_data[r * aux_info.blocks_per_ind + j - 1] = get_block(alloc, b); 462ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 463ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 464ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 465ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 last_block = EXT4_NDIR_BLOCKS + aux_info.blocks_per_ind + 46622742ce739a046a079b2e1b03342a25472dfa352Colin Cross aux_info.blocks_per_ind * (info.bg_desc_reserve_blocks - 1) + 467ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross superblocks - 2; 468ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 469ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross blocks = ((u64)block_len + 1) * info.block_size / 512; 470ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross size = (u64)last_block * info.block_size; 471ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 472ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_block[EXT4_DIND_BLOCK] = dind_block; 473ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_flags = 0; 474ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_blocks_lo = blocks; 475ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->osd2.linux2.l_i_blocks_high = blocks >> 32; 476ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_size_lo = size; 477ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_size_high = size >> 32; 478ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 479ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 480ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Allocates enough blocks to hold len bytes, with backing_len bytes in a data 481ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross buffer, and connects them to an inode. Returns a pointer to the data 482ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross buffer. */ 483ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossu8 *inode_allocate_data_indirect(struct ext4_inode *inode, unsigned long len, 484ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross unsigned long backing_len) 485ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 486ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *alloc; 487ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u8 *data = NULL; 488ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 489ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross alloc = do_inode_allocate_indirect(inode, len); 490ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (alloc == NULL) { 491ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to allocate extents for %lu bytes", len); 492ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return NULL; 493ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 494ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 495ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (backing_len) { 496ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross data = create_backing(alloc, backing_len); 497ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (!data) 498ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to create backing for %lu bytes", backing_len); 499ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 500ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 501ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free_alloc(alloc); 502ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 503ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return data; 504ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 505