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, &region_block, &region_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