indirect.c revision 8642b7fba54727a38f751516bcdc452fb09ef610
14f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/* 24f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Copyright (C) 2010 The Android Open Source Project 34f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * 44f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 54f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * you may not use this file except in compliance with the License. 64f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * You may obtain a copy of the License at 74f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * 84f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 94f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * 104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * See the License for the specific language governing permissions and 144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * limitations under the License. 154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */ 164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdlib.h> 184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdio.h> 194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "ext4_utils.h" 214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "ext4.h" 224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "ext4_extents.h" 234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "backed_block.h" 244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "indirect.h" 254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "allocate.h" 264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/* Creates data buffers for the first backing_len bytes of a block allocation 284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project and queues them to be written */ 294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic u8 *create_backing(struct block_allocation *alloc, 304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project unsigned long backing_len) 314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{ 324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (DIV_ROUND_UP(backing_len, info.block_size) > EXT4_NDIR_BLOCKS) 334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project critical_error("indirect backing larger than %d blocks", EXT4_NDIR_BLOCKS); 34982a815c10cc28707d81c46112fc45b1c10df3beColin Cross 354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u8 *data = calloc(backing_len, 1); 364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (!data) 37b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross critical_error_errno("calloc"); 38ed8a7d84428ec945c48b6b53dc5a3a18fabaf683Colin Cross 39ed8a7d84428ec945c48b6b53dc5a3a18fabaf683Colin Cross u8 *ptr = data; 404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project for (; alloc != NULL && backing_len > 0; get_next_region(alloc)) { 414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 region_block; 4202863b957cfbfc302d3136ed78c0cba86accacd8Brian Swetland u32 region_len; 4302863b957cfbfc302d3136ed78c0cba86accacd8Brian Swetland u32 len; 444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project get_region(alloc, ®ion_block, ®ion_len); 450dd7ca6e87abb689700c5e3a816a949b03b1154bColin Cross 460dd7ca6e87abb689700c5e3a816a949b03b1154bColin Cross len = min(region_len * info.block_size, backing_len); 474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project queue_data_block(ptr, len, region_block); 494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project ptr += len; 504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project backing_len -= len; 514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 52b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 53b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return data; 544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void reserve_indirect_block(struct block_allocation *alloc, int len) 574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{ 584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (reserve_oob_blocks(alloc, 1)) { 594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to reserve oob block"); 604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return; 614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 625f5d5c8cef10f28950fa108a8bd86d55f11b7ef4Nick Kralevich 634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (advance_blocks(alloc, len)) { 644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to advance %d blocks", len); 654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return; 664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void reserve_dindirect_block(struct block_allocation *alloc, int len) 704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{ 714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (reserve_oob_blocks(alloc, 1)) { 724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to reserve oob block"); 734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return; 744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 755f5d5c8cef10f28950fa108a8bd86d55f11b7ef4Nick Kralevich 764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project while (len > 0) { 774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project int ind_block_len = min((int)aux_info.blocks_per_ind, len); 784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project reserve_indirect_block(alloc, ind_block_len); 804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project len -= ind_block_len; 824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void reserve_tindirect_block(struct block_allocation *alloc, int len) 874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{ 884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (reserve_oob_blocks(alloc, 1)) { 894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to reserve oob block"); 904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return; 914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project while (len > 0) { 944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project int dind_block_len = min((int)aux_info.blocks_per_dind, len); 954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project reserve_dindirect_block(alloc, dind_block_len); 9744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross 984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project len -= dind_block_len; 994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 1004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 1014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 1024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void fill_indirect_block(u32 *ind_block, int len, struct block_allocation *alloc) 10344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross{ 10444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross int i; 1054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project for (i = 0; i < len; i++) { 10644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross ind_block[i] = get_block(alloc, i); 1074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 1084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 1094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 1104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void fill_dindirect_block(u32 *dind_block, int len, struct block_allocation *alloc) 1114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{ 1124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project int i; 1134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 ind_block; 1144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 1154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project for (i = 0; len > 0; i++) { 1164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project ind_block = get_oob_block(alloc, 0); 1174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (advance_oob_blocks(alloc, 1)) { 1184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to reserve oob block"); 1194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return; 1204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 12144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross 1224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project dind_block[i] = ind_block; 1234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 1244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 *ind_block_data = calloc(info.block_size, 1); 1254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project queue_data_block((u8*)ind_block_data, info.block_size, ind_block); 1264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project int ind_block_len = min((int)aux_info.blocks_per_ind, len); 1274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 1284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project fill_indirect_block(ind_block_data, ind_block_len, alloc); 1294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 1304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (advance_blocks(alloc, ind_block_len)) { 1314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to advance %d blocks", ind_block_len); 1324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return; 1334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 1344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 1354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project len -= ind_block_len; 1364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 1374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 1384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 1394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void fill_tindirect_block(u32 *tind_block, int len, struct block_allocation *alloc) 1404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{ 1414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project int i; 1424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 dind_block; 1434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 1444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project for (i = 0; len > 0; i++) { 1454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project dind_block = get_oob_block(alloc, 0); 1464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (advance_oob_blocks(alloc, 1)) { 1474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to reserve oob block"); 1484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return; 1494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 15044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross 15144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross tind_block[i] = dind_block; 15244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross 15344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross u32 *dind_block_data = calloc(info.block_size, 1); 15444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross queue_data_block((u8*)dind_block_data, info.block_size, dind_block); 15544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross int dind_block_len = min((int)aux_info.blocks_per_dind, len); 15644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross 15744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross fill_dindirect_block(dind_block_data, dind_block_len, alloc); 15844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross 15944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross len -= dind_block_len; 16044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross } 16144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross} 16244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross 16344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross/* Given an allocation, attach as many blocks as possible to direct inode 16444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross blocks, and return the rest */ 16544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Crossstatic int inode_attach_direct_blocks(struct ext4_inode *inode, 16644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross struct block_allocation *alloc, u32 *block_len) 1674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{ 16844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross int len = min(*block_len, EXT4_NDIR_BLOCKS); 16944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross int i; 17044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross 1714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project for (i = 0; i < len; i++) { 17244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross inode->i_block[i] = get_block(alloc, i); 17344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross } 17444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross 17544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross if (advance_blocks(alloc, len)) { 1764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to advance %d blocks", len); 1774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return -1; 1784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 1794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 1804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *block_len -= len; 1814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return 0; 1824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 1834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 1844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/* Given an allocation, attach as many blocks as possible to indirect blocks, 1854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project and return the rest 18617dcc5c57dcffb919f3de65ff7a0134ffa3bd874Colin Cross Assumes that the blocks necessary to hold the indirect blocks were included 1876405c6953fa02d41d9f6377f4cdb947604f481c4Nick Pelly as part of the allocation */ 1886405c6953fa02d41d9f6377f4cdb947604f481c4Nick Pellystatic int inode_attach_indirect_blocks(struct ext4_inode *inode, 1896405c6953fa02d41d9f6377f4cdb947604f481c4Nick Pelly struct block_allocation *alloc, u32 *block_len) 1906405c6953fa02d41d9f6377f4cdb947604f481c4Nick Pelly{ 1916405c6953fa02d41d9f6377f4cdb947604f481c4Nick Pelly int len = min(*block_len, aux_info.blocks_per_ind); 1926405c6953fa02d41d9f6377f4cdb947604f481c4Nick Pelly 1934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project int ind_block = get_oob_block(alloc, 0); 1946405c6953fa02d41d9f6377f4cdb947604f481c4Nick Pelly inode->i_block[EXT4_IND_BLOCK] = ind_block; 1956405c6953fa02d41d9f6377f4cdb947604f481c4Nick Pelly 1964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (advance_oob_blocks(alloc, 1)) { 1974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to advance oob block"); 1981e070846f8908dff15086efa12fbba01ab7eae15Chuck Tuffli return -1; 1994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 2004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 *ind_block_data = calloc(info.block_size, 1); 2024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project queue_data_block((u8*)ind_block_data, info.block_size, ind_block); 2034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project fill_indirect_block(ind_block_data, len, alloc); 2054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (advance_blocks(alloc, len)) { 2074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to advance %d blocks", len); 2084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return -1; 2094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 2104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *block_len -= len; 2124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return 0; 2134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 2144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/* Given an allocation, attach as many blocks as possible to doubly indirect 2164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project blocks, and return the rest. 2174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project Assumes that the blocks necessary to hold the indirect and doubly indirect 2184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project blocks were included as part of the allocation */ 2194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int inode_attach_dindirect_blocks(struct ext4_inode *inode, 2204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project struct block_allocation *alloc, u32 *block_len) 2214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{ 2224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project int len = min(*block_len, aux_info.blocks_per_dind); 2234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 224b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross int dind_block = get_oob_block(alloc, 0); 225b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross inode->i_block[EXT4_DIND_BLOCK] = dind_block; 2264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (advance_oob_blocks(alloc, 1)) { 2284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to advance oob block"); 2294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return -1; 2304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 2314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 *dind_block_data = calloc(info.block_size, 1); 2334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project queue_data_block((u8*)dind_block_data, info.block_size, dind_block); 2344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project fill_dindirect_block(dind_block_data, len, alloc); 2364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (advance_blocks(alloc, len)) { 2384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to advance %d blocks", len); 2394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return -1; 2404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 2414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *block_len -= len; 2434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return 0; 2444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 2454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/* Given an allocation, attach as many blocks as possible to triply indirect 247b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross blocks, and return the rest. 248b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross Assumes that the blocks necessary to hold the indirect, doubly indirect and 249b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross triply indirect blocks were included as part of the allocation */ 250b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossstatic int inode_attach_tindirect_blocks(struct ext4_inode *inode, 251b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross struct block_allocation *alloc, u32 *block_len) 252b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{ 2534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project int len = min(*block_len, aux_info.blocks_per_tind); 2544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project int tind_block = get_oob_block(alloc, 0); 2564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project inode->i_block[EXT4_TIND_BLOCK] = tind_block; 2574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (advance_oob_blocks(alloc, 1)) { 2594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to advance oob block"); 2604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return -1; 2614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 2624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 2634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 *tind_block_data = calloc(info.block_size, 1); 2644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project queue_data_block((u8*)tind_block_data, info.block_size, tind_block); 265b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 266b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross fill_tindirect_block(tind_block_data, len, alloc); 267b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 268b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (advance_blocks(alloc, len)) { 269b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross error("failed to advance %d blocks", len); 270b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return -1; 271b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross } 272b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 273b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross *block_len -= len; 274b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return 0; 275b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross} 276b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 277b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossstatic void reserve_all_indirect_blocks(struct block_allocation *alloc, u32 len) 278b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{ 279b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (len <= EXT4_NDIR_BLOCKS) 280b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return; 281b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 282b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross len -= EXT4_NDIR_BLOCKS; 283b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross advance_blocks(alloc, EXT4_NDIR_BLOCKS); 284b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 285b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross u32 ind_block_len = min(aux_info.blocks_per_ind, len); 286b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross reserve_indirect_block(alloc, ind_block_len); 287b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 288b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross len -= ind_block_len; 289b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (len == 0) 290b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return; 291b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 292b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross u32 dind_block_len = min(aux_info.blocks_per_dind, len); 293b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross reserve_dindirect_block(alloc, dind_block_len); 294b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 295b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross len -= dind_block_len; 296b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (len == 0) 297b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return; 298b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 299b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross u32 tind_block_len = min(aux_info.blocks_per_tind, len); 300b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross reserve_tindirect_block(alloc, tind_block_len); 301b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 302b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross len -= tind_block_len; 303b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (len == 0) 304b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return; 305b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 306b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross error("%d blocks remaining", len); 307b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross} 308b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 309b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossstatic u32 indirect_blocks_needed(u32 len) 310b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{ 311b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross u32 ind = 0; 312b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 313b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (len <= EXT4_NDIR_BLOCKS) 314b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return ind; 315b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 316b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross len -= EXT4_NDIR_BLOCKS; 317b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 318b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross /* We will need an indirect block for the rest of the blocks */ 319b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ind += DIV_ROUND_UP(len, aux_info.blocks_per_ind); 320b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 321b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (len <= aux_info.blocks_per_ind) 322b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return ind; 323b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 324b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross len -= aux_info.blocks_per_ind; 325b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 326b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ind += DIV_ROUND_UP(len, aux_info.blocks_per_dind); 327b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 3284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (len <= aux_info.blocks_per_dind) 3294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return ind; 3304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 33193ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood len -= aux_info.blocks_per_dind; 3324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 333b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ind += DIV_ROUND_UP(len, aux_info.blocks_per_tind); 3344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 335b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (len <= aux_info.blocks_per_tind) 3364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return ind; 3374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 3384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project critical_error("request too large"); 3394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return 0; 3404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 3414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 3424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int do_inode_attach_indirect(struct ext4_inode *inode, 3434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project struct block_allocation *alloc, u32 block_len) 3444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{ 3454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 count = block_len; 3464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 3474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (inode_attach_direct_blocks(inode, alloc, &count)) { 3484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to attach direct blocks to inode"); 3494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return -1; 3504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 3514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 35235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project if (count > 0) { 3534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (inode_attach_indirect_blocks(inode, alloc, &count)) { 3544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to attach indirect blocks to inode"); 3554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return -1; 356b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross } 357b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross } 3584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 3594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (count > 0) { 3604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (inode_attach_dindirect_blocks(inode, alloc, &count)) { 36193ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood error("failed to attach dindirect blocks to inode"); 36293ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood return -1; 36393ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood } 36493ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood } 36593ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood 36693ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood if (count > 0) { 36793ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood if (inode_attach_tindirect_blocks(inode, alloc, &count)) { 36893ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood error("failed to attach tindirect blocks to inode"); 36993ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood return -1; 37093ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood } 37193ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood } 37293ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood 37393ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood if (count) { 37493ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood error("blocks left after triply-indirect allocation"); 37593ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood return -1; 37693ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood } 37793ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood 37893ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood rewind_alloc(alloc); 37993ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood 38093ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood return 0; 3814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 3824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 38335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Projectstatic struct block_allocation *do_inode_allocate_indirect( 3844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project struct ext4_inode *inode, u32 block_len) 3854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{ 38635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project u32 indirect_len = indirect_blocks_needed(block_len); 3874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 3884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project struct block_allocation *alloc = allocate_blocks(block_len + indirect_len); 389fc0182eb1db0620eb71fb6ca219b15a17dcd912fIliyan Malchev 390fc0182eb1db0620eb71fb6ca219b15a17dcd912fIliyan Malchev if (alloc == NULL) { 391fc0182eb1db0620eb71fb6ca219b15a17dcd912fIliyan Malchev error("Failed to allocate %d blocks", block_len + indirect_len); 392fc0182eb1db0620eb71fb6ca219b15a17dcd912fIliyan Malchev return NULL; 3934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 3944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 39535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project return alloc; 3964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 3974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 3985bb44c8ea2bc513fefc526918980ab3d17494eccXiaopeng Yang/* Allocates enough blocks to hold len bytes and connects them to an inode */ 3995bb44c8ea2bc513fefc526918980ab3d17494eccXiaopeng Yangvoid inode_allocate_indirect(struct ext4_inode *inode, unsigned long len) 4005bb44c8ea2bc513fefc526918980ab3d17494eccXiaopeng Yang{ 40135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project struct block_allocation *alloc; 4024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 block_len = DIV_ROUND_UP(len, info.block_size); 4034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 indirect_len = indirect_blocks_needed(block_len); 4044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project alloc = do_inode_allocate_indirect(inode, block_len); 4064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (alloc == NULL) { 4074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to allocate extents for %lu bytes", len); 4084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return; 4094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 41093ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood 41193ac1559b8c7ad3125ddcd896082b030faadbbd4Mike Lockwood reserve_all_indirect_blocks(alloc, block_len); 4124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project rewind_alloc(alloc); 4134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (do_inode_attach_indirect(inode, alloc, block_len)) 415b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross error("failed to attach blocks to indirect inode"); 416b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 417b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross inode->i_flags = 0; 418b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross inode->i_blocks_lo = (block_len + indirect_len) * info.block_size / 512; 4194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project inode->i_size_lo = len; 4204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project free_alloc(alloc); 422b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross} 423b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 424b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossvoid inode_attach_resize(struct ext4_inode *inode, 425b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross struct block_allocation *alloc) 4264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{ 427b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross u32 block_len = block_allocation_len(alloc); 428b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross u32 superblocks = block_len / aux_info.bg_desc_reserve_blocks; 429b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross u32 i, j; 430b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross u64 blocks; 431b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross u64 size; 432b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 4334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (block_len % aux_info.bg_desc_reserve_blocks) 4344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project critical_error("reserved blocks not a multiple of %d", 4354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project aux_info.bg_desc_reserve_blocks); 4364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project append_oob_allocation(alloc, 1); 4384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 dind_block = get_oob_block(alloc, 0); 4394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 *dind_block_data = calloc(info.block_size, 1); 4414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (!dind_block_data) 4424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project critical_error_errno("calloc"); 4434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project queue_data_block((u8 *)dind_block_data, info.block_size, dind_block); 4444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 *ind_block_data = calloc(info.block_size, aux_info.bg_desc_reserve_blocks); 4464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (!ind_block_data) 4474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project critical_error_errno("calloc"); 4484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project queue_data_block((u8 *)ind_block_data, 4494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project info.block_size * aux_info.bg_desc_reserve_blocks, 4504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project get_block(alloc, 0)); 4514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project for (i = 0; i < aux_info.bg_desc_reserve_blocks; i++) { 4534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project int r = (i - aux_info.bg_desc_blocks) % aux_info.bg_desc_reserve_blocks; 4544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (r < 0) 4554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project r += aux_info.bg_desc_reserve_blocks; 4564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project dind_block_data[i] = get_block(alloc, r); 4584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project for (j = 1; j < superblocks; j++) { 4604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 b = j * aux_info.bg_desc_reserve_blocks + r; 4614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project ind_block_data[r * aux_info.blocks_per_ind + j - 1] = get_block(alloc, b); 4624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 4634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 4644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u32 last_block = EXT4_NDIR_BLOCKS + aux_info.blocks_per_ind + 4664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project aux_info.blocks_per_ind * (aux_info.bg_desc_reserve_blocks - 1) + 4674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project superblocks - 2; 4684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project blocks = ((u64)block_len + 1) * info.block_size / 512; 4704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project size = (u64)last_block * info.block_size; 4714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project inode->i_block[EXT4_DIND_BLOCK] = dind_block; 4734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project inode->i_flags = 0; 4744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project inode->i_blocks_lo = blocks; 4754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project inode->osd2.linux2.l_i_blocks_high = blocks >> 32; 4764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project inode->i_size_lo = size; 4774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project inode->i_size_high = size >> 32; 4784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} 4794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/* Allocates enough blocks to hold len bytes, with backing_len bytes in a data 4814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project buffer, and connects them to an inode. Returns a pointer to the data 4824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project buffer. */ 4834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectu8 *inode_allocate_data_indirect(struct ext4_inode *inode, unsigned long len, 48402863b957cfbfc302d3136ed78c0cba86accacd8Brian Swetland unsigned long backing_len) 4854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{ 4864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project struct block_allocation *alloc; 4874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project u8 *data = NULL; 4884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project alloc = do_inode_allocate_indirect(inode, len); 4904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (alloc == NULL) { 4914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to allocate extents for %lu bytes", len); 4924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project return NULL; 4934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 4944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 4954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (backing_len) { 4964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project data = create_backing(alloc, backing_len); 4974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project if (!data) 4984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project error("failed to create backing for %lu bytes", backing_len); 4994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project } 5004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project 5014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project free_alloc(alloc); 50202863b957cfbfc302d3136ed78c0cba86accacd8Brian Swetland 50302863b957cfbfc302d3136ed78c0cba86accacd8Brian Swetland return data; 50402863b957cfbfc302d3136ed78c0cba86accacd8Brian Swetland} 50502863b957cfbfc302d3136ed78c0cba86accacd8Brian Swetland