xref: /aosp_15_r20/external/e2fsprogs/lib/ext2fs/fallocate.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * fallocate.c -- Allocate large chunks of file.
3*6a54128fSAndroid Build Coastguard Worker  *
4*6a54128fSAndroid Build Coastguard Worker  * Copyright (C) 2014 Oracle.
5*6a54128fSAndroid Build Coastguard Worker  *
6*6a54128fSAndroid Build Coastguard Worker  * %Begin-Header%
7*6a54128fSAndroid Build Coastguard Worker  * This file may be redistributed under the terms of the GNU Library
8*6a54128fSAndroid Build Coastguard Worker  * General Public License, version 2.
9*6a54128fSAndroid Build Coastguard Worker  * %End-Header%
10*6a54128fSAndroid Build Coastguard Worker  */
11*6a54128fSAndroid Build Coastguard Worker 
12*6a54128fSAndroid Build Coastguard Worker #include "config.h"
13*6a54128fSAndroid Build Coastguard Worker 
14*6a54128fSAndroid Build Coastguard Worker #if HAVE_SYS_TYPES_H
15*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
16*6a54128fSAndroid Build Coastguard Worker #endif
17*6a54128fSAndroid Build Coastguard Worker 
18*6a54128fSAndroid Build Coastguard Worker #include "ext2_fs.h"
19*6a54128fSAndroid Build Coastguard Worker #include "ext2fs.h"
20*6a54128fSAndroid Build Coastguard Worker #define min(a, b) ((a) < (b) ? (a) : (b))
21*6a54128fSAndroid Build Coastguard Worker 
22*6a54128fSAndroid Build Coastguard Worker #undef DEBUG
23*6a54128fSAndroid Build Coastguard Worker 
24*6a54128fSAndroid Build Coastguard Worker #ifdef DEBUG
25*6a54128fSAndroid Build Coastguard Worker # define dbg_printf(f, a...)  do {printf(f, ## a); fflush(stdout); } while (0)
26*6a54128fSAndroid Build Coastguard Worker #else
27*6a54128fSAndroid Build Coastguard Worker # define dbg_printf(f, a...)
28*6a54128fSAndroid Build Coastguard Worker #endif
29*6a54128fSAndroid Build Coastguard Worker 
30*6a54128fSAndroid Build Coastguard Worker /*
31*6a54128fSAndroid Build Coastguard Worker  * Extent-based fallocate code.
32*6a54128fSAndroid Build Coastguard Worker  *
33*6a54128fSAndroid Build Coastguard Worker  * Find runs of unmapped logical blocks by starting at start and walking the
34*6a54128fSAndroid Build Coastguard Worker  * extents until we reach the end of the range we want.
35*6a54128fSAndroid Build Coastguard Worker  *
36*6a54128fSAndroid Build Coastguard Worker  * For each run of unmapped blocks, try to find the extents on either side of
37*6a54128fSAndroid Build Coastguard Worker  * the range.  If there's a left extent that can grow by at least a cluster and
38*6a54128fSAndroid Build Coastguard Worker  * there are lblocks between start and the next lcluster after start, see if
39*6a54128fSAndroid Build Coastguard Worker  * there's an implied cluster allocation; if so, zero the blocks (if the left
40*6a54128fSAndroid Build Coastguard Worker  * extent is initialized) and adjust the extent.  Ditto for the blocks between
41*6a54128fSAndroid Build Coastguard Worker  * the end of the last full lcluster and end, if there's a right extent.
42*6a54128fSAndroid Build Coastguard Worker  *
43*6a54128fSAndroid Build Coastguard Worker  * Try to attach as much as we can to the left extent, then try to attach as
44*6a54128fSAndroid Build Coastguard Worker  * much as we can to the right extent.  For the remainder, try to allocate the
45*6a54128fSAndroid Build Coastguard Worker  * whole range; map in whatever we get; and repeat until we're done.
46*6a54128fSAndroid Build Coastguard Worker  *
47*6a54128fSAndroid Build Coastguard Worker  * To attach to a left extent, figure out the maximum amount we can add to the
48*6a54128fSAndroid Build Coastguard Worker  * extent and try to allocate that much, and append if successful.  To attach
49*6a54128fSAndroid Build Coastguard Worker  * to a right extent, figure out the max we can add to the extent, try to
50*6a54128fSAndroid Build Coastguard Worker  * allocate that much, and prepend if successful.
51*6a54128fSAndroid Build Coastguard Worker  *
52*6a54128fSAndroid Build Coastguard Worker  * We need an alloc_range function that tells us how much we can allocate given
53*6a54128fSAndroid Build Coastguard Worker  * a maximum length and one of a suggested start, a fixed start, or a fixed end
54*6a54128fSAndroid Build Coastguard Worker  * point.
55*6a54128fSAndroid Build Coastguard Worker  *
56*6a54128fSAndroid Build Coastguard Worker  * Every time we modify the extent tree we also need to update the block stats.
57*6a54128fSAndroid Build Coastguard Worker  *
58*6a54128fSAndroid Build Coastguard Worker  * At the end, update i_blocks and i_size appropriately.
59*6a54128fSAndroid Build Coastguard Worker  */
60*6a54128fSAndroid Build Coastguard Worker 
dbg_print_extent(const char * desc EXT2FS_ATTR ((unused)),const struct ext2fs_extent * extent EXT2FS_ATTR ((unused)))61*6a54128fSAndroid Build Coastguard Worker static void dbg_print_extent(const char *desc EXT2FS_ATTR((unused)),
62*6a54128fSAndroid Build Coastguard Worker 		const struct ext2fs_extent *extent EXT2FS_ATTR((unused)))
63*6a54128fSAndroid Build Coastguard Worker {
64*6a54128fSAndroid Build Coastguard Worker #ifdef DEBUG
65*6a54128fSAndroid Build Coastguard Worker 	if (desc)
66*6a54128fSAndroid Build Coastguard Worker 		printf("%s: ", desc);
67*6a54128fSAndroid Build Coastguard Worker 	printf("extent: lblk %llu--%llu, len %u, pblk %llu, flags: ",
68*6a54128fSAndroid Build Coastguard Worker 	       extent->e_lblk, extent->e_lblk + extent->e_len - 1,
69*6a54128fSAndroid Build Coastguard Worker 	       extent->e_len, extent->e_pblk);
70*6a54128fSAndroid Build Coastguard Worker 	if (extent->e_flags & EXT2_EXTENT_FLAGS_LEAF)
71*6a54128fSAndroid Build Coastguard Worker 		fputs("LEAF ", stdout);
72*6a54128fSAndroid Build Coastguard Worker 	if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
73*6a54128fSAndroid Build Coastguard Worker 		fputs("UNINIT ", stdout);
74*6a54128fSAndroid Build Coastguard Worker 	if (extent->e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)
75*6a54128fSAndroid Build Coastguard Worker 		fputs("2ND_VISIT ", stdout);
76*6a54128fSAndroid Build Coastguard Worker 	if (!extent->e_flags)
77*6a54128fSAndroid Build Coastguard Worker 		fputs("(none)", stdout);
78*6a54128fSAndroid Build Coastguard Worker 	fputc('\n', stdout);
79*6a54128fSAndroid Build Coastguard Worker 	fflush(stdout);
80*6a54128fSAndroid Build Coastguard Worker #endif
81*6a54128fSAndroid Build Coastguard Worker }
82*6a54128fSAndroid Build Coastguard Worker 
claim_range(ext2_filsys fs,struct ext2_inode * inode,blk64_t blk,blk64_t len)83*6a54128fSAndroid Build Coastguard Worker static errcode_t claim_range(ext2_filsys fs, struct ext2_inode *inode,
84*6a54128fSAndroid Build Coastguard Worker 			     blk64_t blk, blk64_t len)
85*6a54128fSAndroid Build Coastguard Worker {
86*6a54128fSAndroid Build Coastguard Worker 	blk64_t	clusters;
87*6a54128fSAndroid Build Coastguard Worker 
88*6a54128fSAndroid Build Coastguard Worker 	clusters = (len + EXT2FS_CLUSTER_RATIO(fs) - 1) /
89*6a54128fSAndroid Build Coastguard Worker 		   EXT2FS_CLUSTER_RATIO(fs);
90*6a54128fSAndroid Build Coastguard Worker 	ext2fs_block_alloc_stats_range(fs, blk,
91*6a54128fSAndroid Build Coastguard Worker 			clusters * EXT2FS_CLUSTER_RATIO(fs), +1);
92*6a54128fSAndroid Build Coastguard Worker 	return ext2fs_iblk_add_blocks(fs, inode, clusters);
93*6a54128fSAndroid Build Coastguard Worker }
94*6a54128fSAndroid Build Coastguard Worker 
ext_falloc_helper(ext2_filsys fs,int flags,ext2_ino_t ino,struct ext2_inode * inode,ext2_extent_handle_t handle,struct ext2fs_extent * left_ext,struct ext2fs_extent * right_ext,blk64_t range_start,blk64_t range_len,blk64_t alloc_goal)95*6a54128fSAndroid Build Coastguard Worker static errcode_t ext_falloc_helper(ext2_filsys fs,
96*6a54128fSAndroid Build Coastguard Worker 				   int flags,
97*6a54128fSAndroid Build Coastguard Worker 				   ext2_ino_t ino,
98*6a54128fSAndroid Build Coastguard Worker 				   struct ext2_inode *inode,
99*6a54128fSAndroid Build Coastguard Worker 				   ext2_extent_handle_t handle,
100*6a54128fSAndroid Build Coastguard Worker 				   struct ext2fs_extent *left_ext,
101*6a54128fSAndroid Build Coastguard Worker 				   struct ext2fs_extent *right_ext,
102*6a54128fSAndroid Build Coastguard Worker 				   blk64_t range_start, blk64_t range_len,
103*6a54128fSAndroid Build Coastguard Worker 				   blk64_t alloc_goal)
104*6a54128fSAndroid Build Coastguard Worker {
105*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_extent	newex, ex;
106*6a54128fSAndroid Build Coastguard Worker 	int			op;
107*6a54128fSAndroid Build Coastguard Worker 	blk64_t			fillable, pblk, plen, x, y;
108*6a54128fSAndroid Build Coastguard Worker 	blk64_t			eof_blk = 0, cluster_fill = 0;
109*6a54128fSAndroid Build Coastguard Worker 	errcode_t		err;
110*6a54128fSAndroid Build Coastguard Worker 	blk_t			max_extent_len, max_uninit_len, max_init_len;
111*6a54128fSAndroid Build Coastguard Worker 
112*6a54128fSAndroid Build Coastguard Worker #ifdef DEBUG
113*6a54128fSAndroid Build Coastguard Worker 	printf("%s: ", __func__);
114*6a54128fSAndroid Build Coastguard Worker 	if (left_ext)
115*6a54128fSAndroid Build Coastguard Worker 		printf("left_ext=%llu--%llu, ", left_ext->e_lblk,
116*6a54128fSAndroid Build Coastguard Worker 		       left_ext->e_lblk + left_ext->e_len - 1);
117*6a54128fSAndroid Build Coastguard Worker 	if (right_ext)
118*6a54128fSAndroid Build Coastguard Worker 		printf("right_ext=%llu--%llu, ", right_ext->e_lblk,
119*6a54128fSAndroid Build Coastguard Worker 		       right_ext->e_lblk + right_ext->e_len - 1);
120*6a54128fSAndroid Build Coastguard Worker 	printf("start=%llu len=%llu, goal=%llu\n", range_start, range_len,
121*6a54128fSAndroid Build Coastguard Worker 	       alloc_goal);
122*6a54128fSAndroid Build Coastguard Worker 	fflush(stdout);
123*6a54128fSAndroid Build Coastguard Worker #endif
124*6a54128fSAndroid Build Coastguard Worker 	/* Can't create initialized extents past EOF? */
125*6a54128fSAndroid Build Coastguard Worker 	if (!(flags & EXT2_FALLOCATE_INIT_BEYOND_EOF))
126*6a54128fSAndroid Build Coastguard Worker 		eof_blk = EXT2_I_SIZE(inode) / fs->blocksize;
127*6a54128fSAndroid Build Coastguard Worker 
128*6a54128fSAndroid Build Coastguard Worker 	/* The allocation goal must be as far into a cluster as range_start. */
129*6a54128fSAndroid Build Coastguard Worker 	alloc_goal = (alloc_goal & ~EXT2FS_CLUSTER_MASK(fs)) |
130*6a54128fSAndroid Build Coastguard Worker 		     (range_start & EXT2FS_CLUSTER_MASK(fs));
131*6a54128fSAndroid Build Coastguard Worker 
132*6a54128fSAndroid Build Coastguard Worker 	max_uninit_len = EXT_UNINIT_MAX_LEN & ~EXT2FS_CLUSTER_MASK(fs);
133*6a54128fSAndroid Build Coastguard Worker 	max_init_len = EXT_INIT_MAX_LEN & ~EXT2FS_CLUSTER_MASK(fs);
134*6a54128fSAndroid Build Coastguard Worker 
135*6a54128fSAndroid Build Coastguard Worker 	/* We must lengthen the left extent to the end of the cluster */
136*6a54128fSAndroid Build Coastguard Worker 	if (left_ext && EXT2FS_CLUSTER_RATIO(fs) > 1) {
137*6a54128fSAndroid Build Coastguard Worker 		/* How many more blocks can be attached to left_ext? */
138*6a54128fSAndroid Build Coastguard Worker 		if (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
139*6a54128fSAndroid Build Coastguard Worker 			fillable = max_uninit_len - left_ext->e_len;
140*6a54128fSAndroid Build Coastguard Worker 		else
141*6a54128fSAndroid Build Coastguard Worker 			fillable = max_init_len - left_ext->e_len;
142*6a54128fSAndroid Build Coastguard Worker 
143*6a54128fSAndroid Build Coastguard Worker 		if (fillable > range_len)
144*6a54128fSAndroid Build Coastguard Worker 			fillable = range_len;
145*6a54128fSAndroid Build Coastguard Worker 		if (fillable == 0)
146*6a54128fSAndroid Build Coastguard Worker 			goto expand_right;
147*6a54128fSAndroid Build Coastguard Worker 
148*6a54128fSAndroid Build Coastguard Worker 		/*
149*6a54128fSAndroid Build Coastguard Worker 		 * If range_start isn't on a cluster boundary, try an
150*6a54128fSAndroid Build Coastguard Worker 		 * implied cluster allocation for left_ext.
151*6a54128fSAndroid Build Coastguard Worker 		 */
152*6a54128fSAndroid Build Coastguard Worker 		cluster_fill = EXT2FS_CLUSTER_RATIO(fs) -
153*6a54128fSAndroid Build Coastguard Worker 			       (range_start & EXT2FS_CLUSTER_MASK(fs));
154*6a54128fSAndroid Build Coastguard Worker 		cluster_fill &= EXT2FS_CLUSTER_MASK(fs);
155*6a54128fSAndroid Build Coastguard Worker 		if (cluster_fill == 0)
156*6a54128fSAndroid Build Coastguard Worker 			goto expand_right;
157*6a54128fSAndroid Build Coastguard Worker 
158*6a54128fSAndroid Build Coastguard Worker 		if (cluster_fill > fillable)
159*6a54128fSAndroid Build Coastguard Worker 			cluster_fill = fillable;
160*6a54128fSAndroid Build Coastguard Worker 
161*6a54128fSAndroid Build Coastguard Worker 		/* Don't expand an initialized left_ext beyond EOF */
162*6a54128fSAndroid Build Coastguard Worker 		if (!(flags & EXT2_FALLOCATE_INIT_BEYOND_EOF)) {
163*6a54128fSAndroid Build Coastguard Worker 			x = left_ext->e_lblk + left_ext->e_len - 1;
164*6a54128fSAndroid Build Coastguard Worker 			dbg_printf("%s: lend=%llu newlend=%llu eofblk=%llu\n",
165*6a54128fSAndroid Build Coastguard Worker 				   __func__, x, x + cluster_fill, eof_blk);
166*6a54128fSAndroid Build Coastguard Worker 			if (eof_blk >= x && eof_blk <= x + cluster_fill)
167*6a54128fSAndroid Build Coastguard Worker 				cluster_fill = eof_blk - x;
168*6a54128fSAndroid Build Coastguard Worker 			if (cluster_fill == 0)
169*6a54128fSAndroid Build Coastguard Worker 				goto expand_right;
170*6a54128fSAndroid Build Coastguard Worker 		}
171*6a54128fSAndroid Build Coastguard Worker 
172*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_goto(handle, left_ext->e_lblk);
173*6a54128fSAndroid Build Coastguard Worker 		if (err)
174*6a54128fSAndroid Build Coastguard Worker 			goto expand_right;
175*6a54128fSAndroid Build Coastguard Worker 		left_ext->e_len += cluster_fill;
176*6a54128fSAndroid Build Coastguard Worker 		range_start += cluster_fill;
177*6a54128fSAndroid Build Coastguard Worker 		range_len -= cluster_fill;
178*6a54128fSAndroid Build Coastguard Worker 		alloc_goal += cluster_fill;
179*6a54128fSAndroid Build Coastguard Worker 
180*6a54128fSAndroid Build Coastguard Worker 		dbg_print_extent("ext_falloc clus left+", left_ext);
181*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_replace(handle, 0, left_ext);
182*6a54128fSAndroid Build Coastguard Worker 		if (err)
183*6a54128fSAndroid Build Coastguard Worker 			goto out;
184*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_fix_parents(handle);
185*6a54128fSAndroid Build Coastguard Worker 		if (err)
186*6a54128fSAndroid Build Coastguard Worker 			goto out;
187*6a54128fSAndroid Build Coastguard Worker 
188*6a54128fSAndroid Build Coastguard Worker 		/* Zero blocks */
189*6a54128fSAndroid Build Coastguard Worker 		if (!(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) {
190*6a54128fSAndroid Build Coastguard Worker 			err = ext2fs_zero_blocks2(fs, left_ext->e_pblk +
191*6a54128fSAndroid Build Coastguard Worker 						  left_ext->e_len -
192*6a54128fSAndroid Build Coastguard Worker 						  cluster_fill, cluster_fill,
193*6a54128fSAndroid Build Coastguard Worker 						  NULL, NULL);
194*6a54128fSAndroid Build Coastguard Worker 			if (err)
195*6a54128fSAndroid Build Coastguard Worker 				goto out;
196*6a54128fSAndroid Build Coastguard Worker 		}
197*6a54128fSAndroid Build Coastguard Worker 	}
198*6a54128fSAndroid Build Coastguard Worker 
199*6a54128fSAndroid Build Coastguard Worker expand_right:
200*6a54128fSAndroid Build Coastguard Worker 	/* We must lengthen the right extent to the beginning of the cluster */
201*6a54128fSAndroid Build Coastguard Worker 	if (right_ext && EXT2FS_CLUSTER_RATIO(fs) > 1) {
202*6a54128fSAndroid Build Coastguard Worker 		/* How much can we attach to right_ext? */
203*6a54128fSAndroid Build Coastguard Worker 		if (right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
204*6a54128fSAndroid Build Coastguard Worker 			fillable = max_uninit_len - right_ext->e_len;
205*6a54128fSAndroid Build Coastguard Worker 		else
206*6a54128fSAndroid Build Coastguard Worker 			fillable = max_init_len - right_ext->e_len;
207*6a54128fSAndroid Build Coastguard Worker 
208*6a54128fSAndroid Build Coastguard Worker 		if (fillable > range_len)
209*6a54128fSAndroid Build Coastguard Worker 			fillable = range_len;
210*6a54128fSAndroid Build Coastguard Worker 		if (fillable == 0)
211*6a54128fSAndroid Build Coastguard Worker 			goto try_merge;
212*6a54128fSAndroid Build Coastguard Worker 
213*6a54128fSAndroid Build Coastguard Worker 		/*
214*6a54128fSAndroid Build Coastguard Worker 		 * If range_end isn't on a cluster boundary, try an implied
215*6a54128fSAndroid Build Coastguard Worker 		 * cluster allocation for right_ext.
216*6a54128fSAndroid Build Coastguard Worker 		 */
217*6a54128fSAndroid Build Coastguard Worker 		cluster_fill = right_ext->e_lblk & EXT2FS_CLUSTER_MASK(fs);
218*6a54128fSAndroid Build Coastguard Worker 		if (cluster_fill == 0)
219*6a54128fSAndroid Build Coastguard Worker 			goto try_merge;
220*6a54128fSAndroid Build Coastguard Worker 
221*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_goto(handle, right_ext->e_lblk);
222*6a54128fSAndroid Build Coastguard Worker 		if (err)
223*6a54128fSAndroid Build Coastguard Worker 			goto out;
224*6a54128fSAndroid Build Coastguard Worker 
225*6a54128fSAndroid Build Coastguard Worker 		if (cluster_fill > fillable)
226*6a54128fSAndroid Build Coastguard Worker 			cluster_fill = fillable;
227*6a54128fSAndroid Build Coastguard Worker 		right_ext->e_lblk -= cluster_fill;
228*6a54128fSAndroid Build Coastguard Worker 		right_ext->e_pblk -= cluster_fill;
229*6a54128fSAndroid Build Coastguard Worker 		right_ext->e_len += cluster_fill;
230*6a54128fSAndroid Build Coastguard Worker 		range_len -= cluster_fill;
231*6a54128fSAndroid Build Coastguard Worker 
232*6a54128fSAndroid Build Coastguard Worker 		dbg_print_extent("ext_falloc clus right+", right_ext);
233*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_replace(handle, 0, right_ext);
234*6a54128fSAndroid Build Coastguard Worker 		if (err)
235*6a54128fSAndroid Build Coastguard Worker 			goto out;
236*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_fix_parents(handle);
237*6a54128fSAndroid Build Coastguard Worker 		if (err)
238*6a54128fSAndroid Build Coastguard Worker 			goto out;
239*6a54128fSAndroid Build Coastguard Worker 
240*6a54128fSAndroid Build Coastguard Worker 		/* Zero blocks if necessary */
241*6a54128fSAndroid Build Coastguard Worker 		if (!(right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) {
242*6a54128fSAndroid Build Coastguard Worker 			err = ext2fs_zero_blocks2(fs, right_ext->e_pblk,
243*6a54128fSAndroid Build Coastguard Worker 						  cluster_fill, NULL, NULL);
244*6a54128fSAndroid Build Coastguard Worker 			if (err)
245*6a54128fSAndroid Build Coastguard Worker 				goto out;
246*6a54128fSAndroid Build Coastguard Worker 		}
247*6a54128fSAndroid Build Coastguard Worker 	}
248*6a54128fSAndroid Build Coastguard Worker 
249*6a54128fSAndroid Build Coastguard Worker try_merge:
250*6a54128fSAndroid Build Coastguard Worker 	/* Merge both extents together, perhaps? */
251*6a54128fSAndroid Build Coastguard Worker 	if (left_ext && right_ext) {
252*6a54128fSAndroid Build Coastguard Worker 		/* Are the two extents mergeable? */
253*6a54128fSAndroid Build Coastguard Worker 		if ((left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) !=
254*6a54128fSAndroid Build Coastguard Worker 		    (right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT))
255*6a54128fSAndroid Build Coastguard Worker 			goto try_left;
256*6a54128fSAndroid Build Coastguard Worker 
257*6a54128fSAndroid Build Coastguard Worker 		/* User requires init/uninit but extent is uninit/init. */
258*6a54128fSAndroid Build Coastguard Worker 		if (((flags & EXT2_FALLOCATE_FORCE_INIT) &&
259*6a54128fSAndroid Build Coastguard Worker 		     (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) ||
260*6a54128fSAndroid Build Coastguard Worker 		    ((flags & EXT2_FALLOCATE_FORCE_UNINIT) &&
261*6a54128fSAndroid Build Coastguard Worker 		     !(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)))
262*6a54128fSAndroid Build Coastguard Worker 			goto try_left;
263*6a54128fSAndroid Build Coastguard Worker 
264*6a54128fSAndroid Build Coastguard Worker 		/*
265*6a54128fSAndroid Build Coastguard Worker 		 * Skip initialized extent unless user wants to zero blocks
266*6a54128fSAndroid Build Coastguard Worker 		 * or requires init extent.
267*6a54128fSAndroid Build Coastguard Worker 		 */
268*6a54128fSAndroid Build Coastguard Worker 		if (!(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
269*6a54128fSAndroid Build Coastguard Worker 		    (!(flags & EXT2_FALLOCATE_ZERO_BLOCKS) ||
270*6a54128fSAndroid Build Coastguard Worker 		     !(flags & EXT2_FALLOCATE_FORCE_INIT)))
271*6a54128fSAndroid Build Coastguard Worker 			goto try_left;
272*6a54128fSAndroid Build Coastguard Worker 
273*6a54128fSAndroid Build Coastguard Worker 		/* Will it even fit? */
274*6a54128fSAndroid Build Coastguard Worker 		x = left_ext->e_len + range_len + right_ext->e_len;
275*6a54128fSAndroid Build Coastguard Worker 		if (x > (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT ?
276*6a54128fSAndroid Build Coastguard Worker 				max_uninit_len : max_init_len))
277*6a54128fSAndroid Build Coastguard Worker 			goto try_left;
278*6a54128fSAndroid Build Coastguard Worker 
279*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_goto(handle, left_ext->e_lblk);
280*6a54128fSAndroid Build Coastguard Worker 		if (err)
281*6a54128fSAndroid Build Coastguard Worker 			goto try_left;
282*6a54128fSAndroid Build Coastguard Worker 
283*6a54128fSAndroid Build Coastguard Worker 		/* Allocate blocks */
284*6a54128fSAndroid Build Coastguard Worker 		y = left_ext->e_pblk + left_ext->e_len;
285*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_new_range(fs, EXT2_NEWRANGE_FIXED_GOAL |
286*6a54128fSAndroid Build Coastguard Worker 				       EXT2_NEWRANGE_MIN_LENGTH, y,
287*6a54128fSAndroid Build Coastguard Worker 				       right_ext->e_pblk - y + 1, NULL,
288*6a54128fSAndroid Build Coastguard Worker 				       &pblk, &plen);
289*6a54128fSAndroid Build Coastguard Worker 		if (err)
290*6a54128fSAndroid Build Coastguard Worker 			goto try_left;
291*6a54128fSAndroid Build Coastguard Worker 		if (pblk + plen != right_ext->e_pblk)
292*6a54128fSAndroid Build Coastguard Worker 			goto try_left;
293*6a54128fSAndroid Build Coastguard Worker 		err = claim_range(fs, inode, pblk, plen);
294*6a54128fSAndroid Build Coastguard Worker 		if (err)
295*6a54128fSAndroid Build Coastguard Worker 			goto out;
296*6a54128fSAndroid Build Coastguard Worker 
297*6a54128fSAndroid Build Coastguard Worker 		/* Modify extents */
298*6a54128fSAndroid Build Coastguard Worker 		left_ext->e_len = x;
299*6a54128fSAndroid Build Coastguard Worker 		dbg_print_extent("ext_falloc merge", left_ext);
300*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_replace(handle, 0, left_ext);
301*6a54128fSAndroid Build Coastguard Worker 		if (err)
302*6a54128fSAndroid Build Coastguard Worker 			goto out;
303*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_fix_parents(handle);
304*6a54128fSAndroid Build Coastguard Worker 		if (err)
305*6a54128fSAndroid Build Coastguard Worker 			goto out;
306*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_LEAF, &newex);
307*6a54128fSAndroid Build Coastguard Worker 		if (err)
308*6a54128fSAndroid Build Coastguard Worker 			goto out;
309*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_delete(handle, 0);
310*6a54128fSAndroid Build Coastguard Worker 		if (err)
311*6a54128fSAndroid Build Coastguard Worker 			goto out;
312*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_fix_parents(handle);
313*6a54128fSAndroid Build Coastguard Worker 		if (err)
314*6a54128fSAndroid Build Coastguard Worker 			goto out;
315*6a54128fSAndroid Build Coastguard Worker 		*right_ext = *left_ext;
316*6a54128fSAndroid Build Coastguard Worker 
317*6a54128fSAndroid Build Coastguard Worker 		/* Zero blocks */
318*6a54128fSAndroid Build Coastguard Worker 		if (!(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
319*6a54128fSAndroid Build Coastguard Worker 		    (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) {
320*6a54128fSAndroid Build Coastguard Worker 			err = ext2fs_zero_blocks2(fs, range_start, range_len,
321*6a54128fSAndroid Build Coastguard Worker 						  NULL, NULL);
322*6a54128fSAndroid Build Coastguard Worker 			if (err)
323*6a54128fSAndroid Build Coastguard Worker 				goto out;
324*6a54128fSAndroid Build Coastguard Worker 		}
325*6a54128fSAndroid Build Coastguard Worker 
326*6a54128fSAndroid Build Coastguard Worker 		return 0;
327*6a54128fSAndroid Build Coastguard Worker 	}
328*6a54128fSAndroid Build Coastguard Worker 
329*6a54128fSAndroid Build Coastguard Worker try_left:
330*6a54128fSAndroid Build Coastguard Worker 	/* Extend the left extent */
331*6a54128fSAndroid Build Coastguard Worker 	if (left_ext) {
332*6a54128fSAndroid Build Coastguard Worker 		/* How many more blocks can be attached to left_ext? */
333*6a54128fSAndroid Build Coastguard Worker 		if (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
334*6a54128fSAndroid Build Coastguard Worker 			fillable = max_uninit_len - left_ext->e_len;
335*6a54128fSAndroid Build Coastguard Worker 		else if (flags & EXT2_FALLOCATE_ZERO_BLOCKS)
336*6a54128fSAndroid Build Coastguard Worker 			fillable = max_init_len - left_ext->e_len;
337*6a54128fSAndroid Build Coastguard Worker 		else
338*6a54128fSAndroid Build Coastguard Worker 			fillable = 0;
339*6a54128fSAndroid Build Coastguard Worker 
340*6a54128fSAndroid Build Coastguard Worker 		/* User requires init/uninit but extent is uninit/init. */
341*6a54128fSAndroid Build Coastguard Worker 		if (((flags & EXT2_FALLOCATE_FORCE_INIT) &&
342*6a54128fSAndroid Build Coastguard Worker 		     (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) ||
343*6a54128fSAndroid Build Coastguard Worker 		    ((flags & EXT2_FALLOCATE_FORCE_UNINIT) &&
344*6a54128fSAndroid Build Coastguard Worker 		     !(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)))
345*6a54128fSAndroid Build Coastguard Worker 			goto try_right;
346*6a54128fSAndroid Build Coastguard Worker 
347*6a54128fSAndroid Build Coastguard Worker 		if (fillable > range_len)
348*6a54128fSAndroid Build Coastguard Worker 			fillable = range_len;
349*6a54128fSAndroid Build Coastguard Worker 
350*6a54128fSAndroid Build Coastguard Worker 		/* Don't expand an initialized left_ext beyond EOF */
351*6a54128fSAndroid Build Coastguard Worker 		x = left_ext->e_lblk + left_ext->e_len - 1;
352*6a54128fSAndroid Build Coastguard Worker 		if (!(flags & EXT2_FALLOCATE_INIT_BEYOND_EOF)) {
353*6a54128fSAndroid Build Coastguard Worker 			dbg_printf("%s: lend=%llu newlend=%llu eofblk=%llu\n",
354*6a54128fSAndroid Build Coastguard Worker 				   __func__, x, x + fillable, eof_blk);
355*6a54128fSAndroid Build Coastguard Worker 			if (eof_blk >= x && eof_blk <= x + fillable)
356*6a54128fSAndroid Build Coastguard Worker 				fillable = eof_blk - x;
357*6a54128fSAndroid Build Coastguard Worker 		}
358*6a54128fSAndroid Build Coastguard Worker 
359*6a54128fSAndroid Build Coastguard Worker 		if (fillable == 0)
360*6a54128fSAndroid Build Coastguard Worker 			goto try_right;
361*6a54128fSAndroid Build Coastguard Worker 
362*6a54128fSAndroid Build Coastguard Worker 		/* Test if the right edge of the range is already mapped? */
363*6a54128fSAndroid Build Coastguard Worker 		if (EXT2FS_CLUSTER_RATIO(fs) > 1) {
364*6a54128fSAndroid Build Coastguard Worker 			err = ext2fs_map_cluster_block(fs, ino, inode,
365*6a54128fSAndroid Build Coastguard Worker 					x + fillable, &pblk);
366*6a54128fSAndroid Build Coastguard Worker 			if (err)
367*6a54128fSAndroid Build Coastguard Worker 				goto out;
368*6a54128fSAndroid Build Coastguard Worker 			if (pblk)
369*6a54128fSAndroid Build Coastguard Worker 				fillable -= 1 + ((x + fillable)
370*6a54128fSAndroid Build Coastguard Worker 						 & EXT2FS_CLUSTER_MASK(fs));
371*6a54128fSAndroid Build Coastguard Worker 			if (fillable == 0)
372*6a54128fSAndroid Build Coastguard Worker 				goto try_right;
373*6a54128fSAndroid Build Coastguard Worker 		}
374*6a54128fSAndroid Build Coastguard Worker 
375*6a54128fSAndroid Build Coastguard Worker 		/* Allocate range of blocks */
376*6a54128fSAndroid Build Coastguard Worker 		x = left_ext->e_pblk + left_ext->e_len;
377*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_new_range(fs, EXT2_NEWRANGE_FIXED_GOAL |
378*6a54128fSAndroid Build Coastguard Worker 				EXT2_NEWRANGE_MIN_LENGTH,
379*6a54128fSAndroid Build Coastguard Worker 				x, fillable, NULL, &pblk, &plen);
380*6a54128fSAndroid Build Coastguard Worker 		if (err)
381*6a54128fSAndroid Build Coastguard Worker 			goto try_right;
382*6a54128fSAndroid Build Coastguard Worker 		err = claim_range(fs, inode, pblk, plen);
383*6a54128fSAndroid Build Coastguard Worker 		if (err)
384*6a54128fSAndroid Build Coastguard Worker 			goto out;
385*6a54128fSAndroid Build Coastguard Worker 
386*6a54128fSAndroid Build Coastguard Worker 		/* Modify left_ext */
387*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_goto(handle, left_ext->e_lblk);
388*6a54128fSAndroid Build Coastguard Worker 		if (err)
389*6a54128fSAndroid Build Coastguard Worker 			goto out;
390*6a54128fSAndroid Build Coastguard Worker 		range_start += plen;
391*6a54128fSAndroid Build Coastguard Worker 		range_len -= plen;
392*6a54128fSAndroid Build Coastguard Worker 		left_ext->e_len += plen;
393*6a54128fSAndroid Build Coastguard Worker 		dbg_print_extent("ext_falloc left+", left_ext);
394*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_replace(handle, 0, left_ext);
395*6a54128fSAndroid Build Coastguard Worker 		if (err)
396*6a54128fSAndroid Build Coastguard Worker 			goto out;
397*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_fix_parents(handle);
398*6a54128fSAndroid Build Coastguard Worker 		if (err)
399*6a54128fSAndroid Build Coastguard Worker 			goto out;
400*6a54128fSAndroid Build Coastguard Worker 
401*6a54128fSAndroid Build Coastguard Worker 		/* Zero blocks if necessary */
402*6a54128fSAndroid Build Coastguard Worker 		if (!(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
403*6a54128fSAndroid Build Coastguard Worker 		    (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) {
404*6a54128fSAndroid Build Coastguard Worker 			err = ext2fs_zero_blocks2(fs, pblk, plen, NULL, NULL);
405*6a54128fSAndroid Build Coastguard Worker 			if (err)
406*6a54128fSAndroid Build Coastguard Worker 				goto out;
407*6a54128fSAndroid Build Coastguard Worker 		}
408*6a54128fSAndroid Build Coastguard Worker 	}
409*6a54128fSAndroid Build Coastguard Worker 
410*6a54128fSAndroid Build Coastguard Worker try_right:
411*6a54128fSAndroid Build Coastguard Worker 	/* Extend the right extent */
412*6a54128fSAndroid Build Coastguard Worker 	if (right_ext) {
413*6a54128fSAndroid Build Coastguard Worker 		/* How much can we attach to right_ext? */
414*6a54128fSAndroid Build Coastguard Worker 		if (right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
415*6a54128fSAndroid Build Coastguard Worker 			fillable = max_uninit_len - right_ext->e_len;
416*6a54128fSAndroid Build Coastguard Worker 		else if (flags & EXT2_FALLOCATE_ZERO_BLOCKS)
417*6a54128fSAndroid Build Coastguard Worker 			fillable = max_init_len - right_ext->e_len;
418*6a54128fSAndroid Build Coastguard Worker 		else
419*6a54128fSAndroid Build Coastguard Worker 			fillable = 0;
420*6a54128fSAndroid Build Coastguard Worker 
421*6a54128fSAndroid Build Coastguard Worker 		/* User requires init/uninit but extent is uninit/init. */
422*6a54128fSAndroid Build Coastguard Worker 		if (((flags & EXT2_FALLOCATE_FORCE_INIT) &&
423*6a54128fSAndroid Build Coastguard Worker 		     (right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) ||
424*6a54128fSAndroid Build Coastguard Worker 		    ((flags & EXT2_FALLOCATE_FORCE_UNINIT) &&
425*6a54128fSAndroid Build Coastguard Worker 		     !(right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)))
426*6a54128fSAndroid Build Coastguard Worker 			goto try_anywhere;
427*6a54128fSAndroid Build Coastguard Worker 
428*6a54128fSAndroid Build Coastguard Worker 		if (fillable > range_len)
429*6a54128fSAndroid Build Coastguard Worker 			fillable = range_len;
430*6a54128fSAndroid Build Coastguard Worker 		if (fillable == 0)
431*6a54128fSAndroid Build Coastguard Worker 			goto try_anywhere;
432*6a54128fSAndroid Build Coastguard Worker 
433*6a54128fSAndroid Build Coastguard Worker 		/* Test if the left edge of the range is already mapped? */
434*6a54128fSAndroid Build Coastguard Worker 		if (EXT2FS_CLUSTER_RATIO(fs) > 1) {
435*6a54128fSAndroid Build Coastguard Worker 			err = ext2fs_map_cluster_block(fs, ino, inode,
436*6a54128fSAndroid Build Coastguard Worker 					right_ext->e_lblk - fillable, &pblk);
437*6a54128fSAndroid Build Coastguard Worker 			if (err)
438*6a54128fSAndroid Build Coastguard Worker 				goto out;
439*6a54128fSAndroid Build Coastguard Worker 			if (pblk)
440*6a54128fSAndroid Build Coastguard Worker 				fillable -= EXT2FS_CLUSTER_RATIO(fs) -
441*6a54128fSAndroid Build Coastguard Worker 						((right_ext->e_lblk - fillable)
442*6a54128fSAndroid Build Coastguard Worker 						 & EXT2FS_CLUSTER_MASK(fs));
443*6a54128fSAndroid Build Coastguard Worker 			if (fillable == 0)
444*6a54128fSAndroid Build Coastguard Worker 				goto try_anywhere;
445*6a54128fSAndroid Build Coastguard Worker 		}
446*6a54128fSAndroid Build Coastguard Worker 
447*6a54128fSAndroid Build Coastguard Worker 		/*
448*6a54128fSAndroid Build Coastguard Worker 		 * FIXME: It would be nice if we could handle allocating a
449*6a54128fSAndroid Build Coastguard Worker 		 * variable range from a fixed end point instead of just
450*6a54128fSAndroid Build Coastguard Worker 		 * skipping to the general allocator if the whole range is
451*6a54128fSAndroid Build Coastguard Worker 		 * unavailable.
452*6a54128fSAndroid Build Coastguard Worker 		 */
453*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_new_range(fs, EXT2_NEWRANGE_FIXED_GOAL |
454*6a54128fSAndroid Build Coastguard Worker 				EXT2_NEWRANGE_MIN_LENGTH,
455*6a54128fSAndroid Build Coastguard Worker 				right_ext->e_pblk - fillable,
456*6a54128fSAndroid Build Coastguard Worker 				fillable, NULL, &pblk, &plen);
457*6a54128fSAndroid Build Coastguard Worker 		if (err)
458*6a54128fSAndroid Build Coastguard Worker 			goto try_anywhere;
459*6a54128fSAndroid Build Coastguard Worker 		err = claim_range(fs, inode,
460*6a54128fSAndroid Build Coastguard Worker 			      pblk & ~EXT2FS_CLUSTER_MASK(fs),
461*6a54128fSAndroid Build Coastguard Worker 			      plen + (pblk & EXT2FS_CLUSTER_MASK(fs)));
462*6a54128fSAndroid Build Coastguard Worker 		if (err)
463*6a54128fSAndroid Build Coastguard Worker 			goto out;
464*6a54128fSAndroid Build Coastguard Worker 
465*6a54128fSAndroid Build Coastguard Worker 		/* Modify right_ext */
466*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_goto(handle, right_ext->e_lblk);
467*6a54128fSAndroid Build Coastguard Worker 		if (err)
468*6a54128fSAndroid Build Coastguard Worker 			goto out;
469*6a54128fSAndroid Build Coastguard Worker 		range_len -= plen;
470*6a54128fSAndroid Build Coastguard Worker 		right_ext->e_lblk -= plen;
471*6a54128fSAndroid Build Coastguard Worker 		right_ext->e_pblk -= plen;
472*6a54128fSAndroid Build Coastguard Worker 		right_ext->e_len += plen;
473*6a54128fSAndroid Build Coastguard Worker 		dbg_print_extent("ext_falloc right+", right_ext);
474*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_replace(handle, 0, right_ext);
475*6a54128fSAndroid Build Coastguard Worker 		if (err)
476*6a54128fSAndroid Build Coastguard Worker 			goto out;
477*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_fix_parents(handle);
478*6a54128fSAndroid Build Coastguard Worker 		if (err)
479*6a54128fSAndroid Build Coastguard Worker 			goto out;
480*6a54128fSAndroid Build Coastguard Worker 
481*6a54128fSAndroid Build Coastguard Worker 		/* Zero blocks if necessary */
482*6a54128fSAndroid Build Coastguard Worker 		if (!(right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
483*6a54128fSAndroid Build Coastguard Worker 		    (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) {
484*6a54128fSAndroid Build Coastguard Worker 			err = ext2fs_zero_blocks2(fs, pblk,
485*6a54128fSAndroid Build Coastguard Worker 					plen + cluster_fill, NULL, NULL);
486*6a54128fSAndroid Build Coastguard Worker 			if (err)
487*6a54128fSAndroid Build Coastguard Worker 				goto out;
488*6a54128fSAndroid Build Coastguard Worker 		}
489*6a54128fSAndroid Build Coastguard Worker 	}
490*6a54128fSAndroid Build Coastguard Worker 
491*6a54128fSAndroid Build Coastguard Worker try_anywhere:
492*6a54128fSAndroid Build Coastguard Worker 	/* Try implied cluster alloc on the left and right ends */
493*6a54128fSAndroid Build Coastguard Worker 	if (range_len > 0 && (range_start & EXT2FS_CLUSTER_MASK(fs))) {
494*6a54128fSAndroid Build Coastguard Worker 		cluster_fill = EXT2FS_CLUSTER_RATIO(fs) -
495*6a54128fSAndroid Build Coastguard Worker 			       (range_start & EXT2FS_CLUSTER_MASK(fs));
496*6a54128fSAndroid Build Coastguard Worker 		cluster_fill &= EXT2FS_CLUSTER_MASK(fs);
497*6a54128fSAndroid Build Coastguard Worker 		if (cluster_fill > range_len)
498*6a54128fSAndroid Build Coastguard Worker 			cluster_fill = range_len;
499*6a54128fSAndroid Build Coastguard Worker 		newex.e_lblk = range_start;
500*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_map_cluster_block(fs, ino, inode, newex.e_lblk,
501*6a54128fSAndroid Build Coastguard Worker 					       &pblk);
502*6a54128fSAndroid Build Coastguard Worker 		if (err)
503*6a54128fSAndroid Build Coastguard Worker 			goto out;
504*6a54128fSAndroid Build Coastguard Worker 		if (pblk == 0)
505*6a54128fSAndroid Build Coastguard Worker 			goto try_right_implied;
506*6a54128fSAndroid Build Coastguard Worker 		newex.e_pblk = pblk;
507*6a54128fSAndroid Build Coastguard Worker 		newex.e_len = cluster_fill;
508*6a54128fSAndroid Build Coastguard Worker 		newex.e_flags = (flags & EXT2_FALLOCATE_FORCE_INIT ? 0 :
509*6a54128fSAndroid Build Coastguard Worker 				 EXT2_EXTENT_FLAGS_UNINIT);
510*6a54128fSAndroid Build Coastguard Worker 		dbg_print_extent("ext_falloc iclus left+", &newex);
511*6a54128fSAndroid Build Coastguard Worker 		ext2fs_extent_goto(handle, newex.e_lblk);
512*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT,
513*6a54128fSAndroid Build Coastguard Worker 					&ex);
514*6a54128fSAndroid Build Coastguard Worker 		if (err == EXT2_ET_NO_CURRENT_NODE)
515*6a54128fSAndroid Build Coastguard Worker 			ex.e_lblk = 0;
516*6a54128fSAndroid Build Coastguard Worker 		else if (err)
517*6a54128fSAndroid Build Coastguard Worker 			goto out;
518*6a54128fSAndroid Build Coastguard Worker 
519*6a54128fSAndroid Build Coastguard Worker 		if (ex.e_lblk > newex.e_lblk)
520*6a54128fSAndroid Build Coastguard Worker 			op = 0; /* insert before */
521*6a54128fSAndroid Build Coastguard Worker 		else
522*6a54128fSAndroid Build Coastguard Worker 			op = EXT2_EXTENT_INSERT_AFTER;
523*6a54128fSAndroid Build Coastguard Worker 		dbg_printf("%s: inserting %s lblk %llu newex=%llu\n",
524*6a54128fSAndroid Build Coastguard Worker 			   __func__, op ? "after" : "before", ex.e_lblk,
525*6a54128fSAndroid Build Coastguard Worker 			   newex.e_lblk);
526*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_insert(handle, op, &newex);
527*6a54128fSAndroid Build Coastguard Worker 		if (err)
528*6a54128fSAndroid Build Coastguard Worker 			goto out;
529*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_fix_parents(handle);
530*6a54128fSAndroid Build Coastguard Worker 		if (err)
531*6a54128fSAndroid Build Coastguard Worker 			goto out;
532*6a54128fSAndroid Build Coastguard Worker 
533*6a54128fSAndroid Build Coastguard Worker 		if (!(newex.e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
534*6a54128fSAndroid Build Coastguard Worker 		    (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) {
535*6a54128fSAndroid Build Coastguard Worker 			err = ext2fs_zero_blocks2(fs, newex.e_pblk,
536*6a54128fSAndroid Build Coastguard Worker 						  newex.e_len, NULL, NULL);
537*6a54128fSAndroid Build Coastguard Worker 			if (err)
538*6a54128fSAndroid Build Coastguard Worker 				goto out;
539*6a54128fSAndroid Build Coastguard Worker 		}
540*6a54128fSAndroid Build Coastguard Worker 
541*6a54128fSAndroid Build Coastguard Worker 		range_start += cluster_fill;
542*6a54128fSAndroid Build Coastguard Worker 		range_len -= cluster_fill;
543*6a54128fSAndroid Build Coastguard Worker 	}
544*6a54128fSAndroid Build Coastguard Worker 
545*6a54128fSAndroid Build Coastguard Worker try_right_implied:
546*6a54128fSAndroid Build Coastguard Worker 	y = range_start + range_len;
547*6a54128fSAndroid Build Coastguard Worker 	if (range_len > 0 && (y & EXT2FS_CLUSTER_MASK(fs))) {
548*6a54128fSAndroid Build Coastguard Worker 		cluster_fill = y & EXT2FS_CLUSTER_MASK(fs);
549*6a54128fSAndroid Build Coastguard Worker 		if (cluster_fill > range_len)
550*6a54128fSAndroid Build Coastguard Worker 			cluster_fill = range_len;
551*6a54128fSAndroid Build Coastguard Worker 		newex.e_lblk = y & ~EXT2FS_CLUSTER_MASK(fs);
552*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_map_cluster_block(fs, ino, inode, newex.e_lblk,
553*6a54128fSAndroid Build Coastguard Worker 					       &pblk);
554*6a54128fSAndroid Build Coastguard Worker 		if (err)
555*6a54128fSAndroid Build Coastguard Worker 			goto out;
556*6a54128fSAndroid Build Coastguard Worker 		if (pblk == 0)
557*6a54128fSAndroid Build Coastguard Worker 			goto no_implied;
558*6a54128fSAndroid Build Coastguard Worker 		newex.e_pblk = pblk;
559*6a54128fSAndroid Build Coastguard Worker 		newex.e_len = cluster_fill;
560*6a54128fSAndroid Build Coastguard Worker 		newex.e_flags = (flags & EXT2_FALLOCATE_FORCE_INIT ? 0 :
561*6a54128fSAndroid Build Coastguard Worker 				 EXT2_EXTENT_FLAGS_UNINIT);
562*6a54128fSAndroid Build Coastguard Worker 		dbg_print_extent("ext_falloc iclus right+", &newex);
563*6a54128fSAndroid Build Coastguard Worker 		ext2fs_extent_goto(handle, newex.e_lblk);
564*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT,
565*6a54128fSAndroid Build Coastguard Worker 					&ex);
566*6a54128fSAndroid Build Coastguard Worker 		if (err == EXT2_ET_NO_CURRENT_NODE)
567*6a54128fSAndroid Build Coastguard Worker 			ex.e_lblk = 0;
568*6a54128fSAndroid Build Coastguard Worker 		else if (err)
569*6a54128fSAndroid Build Coastguard Worker 			goto out;
570*6a54128fSAndroid Build Coastguard Worker 
571*6a54128fSAndroid Build Coastguard Worker 		if (ex.e_lblk > newex.e_lblk)
572*6a54128fSAndroid Build Coastguard Worker 			op = 0; /* insert before */
573*6a54128fSAndroid Build Coastguard Worker 		else
574*6a54128fSAndroid Build Coastguard Worker 			op = EXT2_EXTENT_INSERT_AFTER;
575*6a54128fSAndroid Build Coastguard Worker 		dbg_printf("%s: inserting %s lblk %llu newex=%llu\n",
576*6a54128fSAndroid Build Coastguard Worker 			   __func__, op ? "after" : "before", ex.e_lblk,
577*6a54128fSAndroid Build Coastguard Worker 			   newex.e_lblk);
578*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_insert(handle, op, &newex);
579*6a54128fSAndroid Build Coastguard Worker 		if (err)
580*6a54128fSAndroid Build Coastguard Worker 			goto out;
581*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_fix_parents(handle);
582*6a54128fSAndroid Build Coastguard Worker 		if (err)
583*6a54128fSAndroid Build Coastguard Worker 			goto out;
584*6a54128fSAndroid Build Coastguard Worker 
585*6a54128fSAndroid Build Coastguard Worker 		if (!(newex.e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
586*6a54128fSAndroid Build Coastguard Worker 		    (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) {
587*6a54128fSAndroid Build Coastguard Worker 			err = ext2fs_zero_blocks2(fs, newex.e_pblk,
588*6a54128fSAndroid Build Coastguard Worker 						  newex.e_len, NULL, NULL);
589*6a54128fSAndroid Build Coastguard Worker 			if (err)
590*6a54128fSAndroid Build Coastguard Worker 				goto out;
591*6a54128fSAndroid Build Coastguard Worker 		}
592*6a54128fSAndroid Build Coastguard Worker 
593*6a54128fSAndroid Build Coastguard Worker 		range_len -= cluster_fill;
594*6a54128fSAndroid Build Coastguard Worker 	}
595*6a54128fSAndroid Build Coastguard Worker 
596*6a54128fSAndroid Build Coastguard Worker no_implied:
597*6a54128fSAndroid Build Coastguard Worker 	if (range_len == 0)
598*6a54128fSAndroid Build Coastguard Worker 		return 0;
599*6a54128fSAndroid Build Coastguard Worker 
600*6a54128fSAndroid Build Coastguard Worker 	newex.e_lblk = range_start;
601*6a54128fSAndroid Build Coastguard Worker 	if (flags & EXT2_FALLOCATE_FORCE_INIT) {
602*6a54128fSAndroid Build Coastguard Worker 		max_extent_len = max_init_len;
603*6a54128fSAndroid Build Coastguard Worker 		newex.e_flags = 0;
604*6a54128fSAndroid Build Coastguard Worker 	} else {
605*6a54128fSAndroid Build Coastguard Worker 		max_extent_len = max_uninit_len;
606*6a54128fSAndroid Build Coastguard Worker 		newex.e_flags = EXT2_EXTENT_FLAGS_UNINIT;
607*6a54128fSAndroid Build Coastguard Worker 	}
608*6a54128fSAndroid Build Coastguard Worker 	pblk = alloc_goal;
609*6a54128fSAndroid Build Coastguard Worker 	y = range_len;
610*6a54128fSAndroid Build Coastguard Worker 	for (x = 0; x < y;) {
611*6a54128fSAndroid Build Coastguard Worker 		cluster_fill = newex.e_lblk & EXT2FS_CLUSTER_MASK(fs);
612*6a54128fSAndroid Build Coastguard Worker 		fillable = min(range_len + cluster_fill, max_extent_len);
613*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_new_range(fs, 0, pblk & ~EXT2FS_CLUSTER_MASK(fs),
614*6a54128fSAndroid Build Coastguard Worker 				       fillable,
615*6a54128fSAndroid Build Coastguard Worker 				       NULL, &pblk, &plen);
616*6a54128fSAndroid Build Coastguard Worker 		if (err)
617*6a54128fSAndroid Build Coastguard Worker 			goto out;
618*6a54128fSAndroid Build Coastguard Worker 		err = claim_range(fs, inode, pblk, plen);
619*6a54128fSAndroid Build Coastguard Worker 		if (err)
620*6a54128fSAndroid Build Coastguard Worker 			goto out;
621*6a54128fSAndroid Build Coastguard Worker 
622*6a54128fSAndroid Build Coastguard Worker 		/* Create extent */
623*6a54128fSAndroid Build Coastguard Worker 		newex.e_pblk = pblk + cluster_fill;
624*6a54128fSAndroid Build Coastguard Worker 		newex.e_len = plen - cluster_fill;
625*6a54128fSAndroid Build Coastguard Worker 		dbg_print_extent("ext_falloc create", &newex);
626*6a54128fSAndroid Build Coastguard Worker 		ext2fs_extent_goto(handle, newex.e_lblk);
627*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT,
628*6a54128fSAndroid Build Coastguard Worker 					&ex);
629*6a54128fSAndroid Build Coastguard Worker 		if (err == EXT2_ET_NO_CURRENT_NODE)
630*6a54128fSAndroid Build Coastguard Worker 			ex.e_lblk = 0;
631*6a54128fSAndroid Build Coastguard Worker 		else if (err)
632*6a54128fSAndroid Build Coastguard Worker 			goto out;
633*6a54128fSAndroid Build Coastguard Worker 
634*6a54128fSAndroid Build Coastguard Worker 		if (ex.e_lblk > newex.e_lblk)
635*6a54128fSAndroid Build Coastguard Worker 			op = 0; /* insert before */
636*6a54128fSAndroid Build Coastguard Worker 		else
637*6a54128fSAndroid Build Coastguard Worker 			op = EXT2_EXTENT_INSERT_AFTER;
638*6a54128fSAndroid Build Coastguard Worker 		dbg_printf("%s: inserting %s lblk %llu newex=%llu\n",
639*6a54128fSAndroid Build Coastguard Worker 			   __func__, op ? "after" : "before", ex.e_lblk,
640*6a54128fSAndroid Build Coastguard Worker 			   newex.e_lblk);
641*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_insert(handle, op, &newex);
642*6a54128fSAndroid Build Coastguard Worker 		if (err)
643*6a54128fSAndroid Build Coastguard Worker 			goto out;
644*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_fix_parents(handle);
645*6a54128fSAndroid Build Coastguard Worker 		if (err)
646*6a54128fSAndroid Build Coastguard Worker 			goto out;
647*6a54128fSAndroid Build Coastguard Worker 
648*6a54128fSAndroid Build Coastguard Worker 		if (!(newex.e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
649*6a54128fSAndroid Build Coastguard Worker 		    (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) {
650*6a54128fSAndroid Build Coastguard Worker 			err = ext2fs_zero_blocks2(fs, pblk, plen, NULL, NULL);
651*6a54128fSAndroid Build Coastguard Worker 			if (err)
652*6a54128fSAndroid Build Coastguard Worker 				goto out;
653*6a54128fSAndroid Build Coastguard Worker 		}
654*6a54128fSAndroid Build Coastguard Worker 
655*6a54128fSAndroid Build Coastguard Worker 		/* Update variables at end of loop */
656*6a54128fSAndroid Build Coastguard Worker 		x += plen - cluster_fill;
657*6a54128fSAndroid Build Coastguard Worker 		range_len -= plen - cluster_fill;
658*6a54128fSAndroid Build Coastguard Worker 		newex.e_lblk += plen - cluster_fill;
659*6a54128fSAndroid Build Coastguard Worker 		pblk += plen - cluster_fill;
660*6a54128fSAndroid Build Coastguard Worker 		if (pblk >= ext2fs_blocks_count(fs->super))
661*6a54128fSAndroid Build Coastguard Worker 			pblk = fs->super->s_first_data_block;
662*6a54128fSAndroid Build Coastguard Worker 	}
663*6a54128fSAndroid Build Coastguard Worker 
664*6a54128fSAndroid Build Coastguard Worker out:
665*6a54128fSAndroid Build Coastguard Worker 	return err;
666*6a54128fSAndroid Build Coastguard Worker }
667*6a54128fSAndroid Build Coastguard Worker 
extent_fallocate(ext2_filsys fs,int flags,ext2_ino_t ino,struct ext2_inode * inode,blk64_t goal,blk64_t start,blk64_t len)668*6a54128fSAndroid Build Coastguard Worker static errcode_t extent_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino,
669*6a54128fSAndroid Build Coastguard Worker 				      struct ext2_inode *inode, blk64_t goal,
670*6a54128fSAndroid Build Coastguard Worker 				      blk64_t start, blk64_t len)
671*6a54128fSAndroid Build Coastguard Worker {
672*6a54128fSAndroid Build Coastguard Worker 	ext2_extent_handle_t	handle;
673*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_extent	left_extent, right_extent;
674*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_extent	*left_adjacent, *right_adjacent;
675*6a54128fSAndroid Build Coastguard Worker 	errcode_t		err;
676*6a54128fSAndroid Build Coastguard Worker 	blk64_t			range_start, range_end = 0, end, next;
677*6a54128fSAndroid Build Coastguard Worker 	blk64_t			count, goal_distance;
678*6a54128fSAndroid Build Coastguard Worker 
679*6a54128fSAndroid Build Coastguard Worker 	end = start + len - 1;
680*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_extent_open2(fs, ino, inode, &handle);
681*6a54128fSAndroid Build Coastguard Worker 	if (err)
682*6a54128fSAndroid Build Coastguard Worker 		return err;
683*6a54128fSAndroid Build Coastguard Worker 
684*6a54128fSAndroid Build Coastguard Worker 	/*
685*6a54128fSAndroid Build Coastguard Worker 	 * Find the extent closest to the start of the alloc range.  We don't
686*6a54128fSAndroid Build Coastguard Worker 	 * check the return value because _goto() sets the current node to the
687*6a54128fSAndroid Build Coastguard Worker 	 * next-lowest extent if 'start' is in a hole; or the next-highest
688*6a54128fSAndroid Build Coastguard Worker 	 * extent if there aren't any lower ones; or doesn't set a current node
689*6a54128fSAndroid Build Coastguard Worker 	 * if there was a real error reading the extent tree.  In that case,
690*6a54128fSAndroid Build Coastguard Worker 	 * _get() will error out.
691*6a54128fSAndroid Build Coastguard Worker 	 */
692*6a54128fSAndroid Build Coastguard Worker start_again:
693*6a54128fSAndroid Build Coastguard Worker 	ext2fs_extent_goto(handle, start);
694*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &left_extent);
695*6a54128fSAndroid Build Coastguard Worker 	if (err == EXT2_ET_NO_CURRENT_NODE) {
696*6a54128fSAndroid Build Coastguard Worker 		blk64_t max_blocks = ext2fs_blocks_count(fs->super);
697*6a54128fSAndroid Build Coastguard Worker 
698*6a54128fSAndroid Build Coastguard Worker 		if (goal == ~0ULL)
699*6a54128fSAndroid Build Coastguard Worker 			goal = ext2fs_find_inode_goal(fs, ino, inode, start);
700*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
701*6a54128fSAndroid Build Coastguard Worker 						goal, max_blocks - 1, &goal);
702*6a54128fSAndroid Build Coastguard Worker 		goal += start;
703*6a54128fSAndroid Build Coastguard Worker 		err = ext_falloc_helper(fs, flags, ino, inode, handle, NULL,
704*6a54128fSAndroid Build Coastguard Worker 					NULL, start, len, goal);
705*6a54128fSAndroid Build Coastguard Worker 		goto errout;
706*6a54128fSAndroid Build Coastguard Worker 	} else if (err)
707*6a54128fSAndroid Build Coastguard Worker 		goto errout;
708*6a54128fSAndroid Build Coastguard Worker 
709*6a54128fSAndroid Build Coastguard Worker 	dbg_print_extent("ext_falloc initial", &left_extent);
710*6a54128fSAndroid Build Coastguard Worker 	next = left_extent.e_lblk + left_extent.e_len;
711*6a54128fSAndroid Build Coastguard Worker 	if (left_extent.e_lblk > start) {
712*6a54128fSAndroid Build Coastguard Worker 		/* The nearest extent we found was beyond start??? */
713*6a54128fSAndroid Build Coastguard Worker 		goal = left_extent.e_pblk - (left_extent.e_lblk - start);
714*6a54128fSAndroid Build Coastguard Worker 		err = ext_falloc_helper(fs, flags, ino, inode, handle, NULL,
715*6a54128fSAndroid Build Coastguard Worker 					&left_extent, start,
716*6a54128fSAndroid Build Coastguard Worker 					left_extent.e_lblk - start, goal);
717*6a54128fSAndroid Build Coastguard Worker 		if (err)
718*6a54128fSAndroid Build Coastguard Worker 			goto errout;
719*6a54128fSAndroid Build Coastguard Worker 
720*6a54128fSAndroid Build Coastguard Worker 		goto start_again;
721*6a54128fSAndroid Build Coastguard Worker 	} else if (next >= start) {
722*6a54128fSAndroid Build Coastguard Worker 		range_start = next;
723*6a54128fSAndroid Build Coastguard Worker 		left_adjacent = &left_extent;
724*6a54128fSAndroid Build Coastguard Worker 	} else {
725*6a54128fSAndroid Build Coastguard Worker 		range_start = start;
726*6a54128fSAndroid Build Coastguard Worker 		left_adjacent = NULL;
727*6a54128fSAndroid Build Coastguard Worker 	}
728*6a54128fSAndroid Build Coastguard Worker 	goal = left_extent.e_pblk + (range_start - left_extent.e_lblk);
729*6a54128fSAndroid Build Coastguard Worker 
730*6a54128fSAndroid Build Coastguard Worker 	do {
731*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_LEAF,
732*6a54128fSAndroid Build Coastguard Worker 					   &right_extent);
733*6a54128fSAndroid Build Coastguard Worker 		dbg_printf("%s: ino=%d get next =%d\n", __func__, ino,
734*6a54128fSAndroid Build Coastguard Worker 			   (int)err);
735*6a54128fSAndroid Build Coastguard Worker 		dbg_print_extent("ext_falloc next", &right_extent);
736*6a54128fSAndroid Build Coastguard Worker 		/* Stop if we've seen this extent before */
737*6a54128fSAndroid Build Coastguard Worker 		if (!err && right_extent.e_lblk <= left_extent.e_lblk)
738*6a54128fSAndroid Build Coastguard Worker 			err = EXT2_ET_EXTENT_NO_NEXT;
739*6a54128fSAndroid Build Coastguard Worker 
740*6a54128fSAndroid Build Coastguard Worker 		if (err && err != EXT2_ET_EXTENT_NO_NEXT)
741*6a54128fSAndroid Build Coastguard Worker 			goto errout;
742*6a54128fSAndroid Build Coastguard Worker 		if (err == EXT2_ET_EXTENT_NO_NEXT ||
743*6a54128fSAndroid Build Coastguard Worker 		    right_extent.e_lblk > end + 1) {
744*6a54128fSAndroid Build Coastguard Worker 			range_end = end;
745*6a54128fSAndroid Build Coastguard Worker 			right_adjacent = NULL;
746*6a54128fSAndroid Build Coastguard Worker 		} else {
747*6a54128fSAndroid Build Coastguard Worker 			/* Handle right_extent.e_lblk <= end */
748*6a54128fSAndroid Build Coastguard Worker 			range_end = right_extent.e_lblk - 1;
749*6a54128fSAndroid Build Coastguard Worker 			right_adjacent = &right_extent;
750*6a54128fSAndroid Build Coastguard Worker 		}
751*6a54128fSAndroid Build Coastguard Worker 		goal_distance = range_start - next;
752*6a54128fSAndroid Build Coastguard Worker 		if (err != EXT2_ET_EXTENT_NO_NEXT &&
753*6a54128fSAndroid Build Coastguard Worker 		    goal_distance > (range_end - right_extent.e_lblk))
754*6a54128fSAndroid Build Coastguard Worker 			goal = right_extent.e_pblk -
755*6a54128fSAndroid Build Coastguard Worker 					(right_extent.e_lblk - range_start);
756*6a54128fSAndroid Build Coastguard Worker 
757*6a54128fSAndroid Build Coastguard Worker 		dbg_printf("%s: ino=%d rstart=%llu rend=%llu\n", __func__, ino,
758*6a54128fSAndroid Build Coastguard Worker 			   range_start, range_end);
759*6a54128fSAndroid Build Coastguard Worker 		err = 0;
760*6a54128fSAndroid Build Coastguard Worker 		if (range_start <= range_end) {
761*6a54128fSAndroid Build Coastguard Worker 			count = range_end - range_start + 1;
762*6a54128fSAndroid Build Coastguard Worker 			err = ext_falloc_helper(fs, flags, ino, inode, handle,
763*6a54128fSAndroid Build Coastguard Worker 						left_adjacent, right_adjacent,
764*6a54128fSAndroid Build Coastguard Worker 						range_start, count, goal);
765*6a54128fSAndroid Build Coastguard Worker 			if (err)
766*6a54128fSAndroid Build Coastguard Worker 				goto errout;
767*6a54128fSAndroid Build Coastguard Worker 		}
768*6a54128fSAndroid Build Coastguard Worker 
769*6a54128fSAndroid Build Coastguard Worker 		if (range_end == end)
770*6a54128fSAndroid Build Coastguard Worker 			break;
771*6a54128fSAndroid Build Coastguard Worker 
772*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_extent_goto(handle, right_extent.e_lblk);
773*6a54128fSAndroid Build Coastguard Worker 		if (err)
774*6a54128fSAndroid Build Coastguard Worker 			goto errout;
775*6a54128fSAndroid Build Coastguard Worker 		next = right_extent.e_lblk + right_extent.e_len;
776*6a54128fSAndroid Build Coastguard Worker 		left_extent = right_extent;
777*6a54128fSAndroid Build Coastguard Worker 		left_adjacent = &left_extent;
778*6a54128fSAndroid Build Coastguard Worker 		range_start = next;
779*6a54128fSAndroid Build Coastguard Worker 		goal = left_extent.e_pblk + (range_start - left_extent.e_lblk);
780*6a54128fSAndroid Build Coastguard Worker 	} while (range_end < end);
781*6a54128fSAndroid Build Coastguard Worker 
782*6a54128fSAndroid Build Coastguard Worker errout:
783*6a54128fSAndroid Build Coastguard Worker 	ext2fs_extent_free(handle);
784*6a54128fSAndroid Build Coastguard Worker 	return err;
785*6a54128fSAndroid Build Coastguard Worker }
786*6a54128fSAndroid Build Coastguard Worker 
787*6a54128fSAndroid Build Coastguard Worker /*
788*6a54128fSAndroid Build Coastguard Worker  * Map physical blocks to a range of logical blocks within a file.  The range
789*6a54128fSAndroid Build Coastguard Worker  * of logical blocks are (start, start + len).  If there are already extents,
790*6a54128fSAndroid Build Coastguard Worker  * the mappings will try to extend the mappings; otherwise, it will try to map
791*6a54128fSAndroid Build Coastguard Worker  * start as if logical block 0 points to goal.  If goal is ~0ULL, then the goal
792*6a54128fSAndroid Build Coastguard Worker  * is calculated based on the inode group.
793*6a54128fSAndroid Build Coastguard Worker  *
794*6a54128fSAndroid Build Coastguard Worker  * Flags:
795*6a54128fSAndroid Build Coastguard Worker  * - EXT2_FALLOCATE_ZERO_BLOCKS: Zero the blocks that are allocated.
796*6a54128fSAndroid Build Coastguard Worker  * - EXT2_FALLOCATE_FORCE_INIT: Create only initialized extents.
797*6a54128fSAndroid Build Coastguard Worker  * - EXT2_FALLOCATE_FORCE_UNINIT: Create only uninitialized extents.
798*6a54128fSAndroid Build Coastguard Worker  * - EXT2_FALLOCATE_INIT_BEYOND_EOF: Create extents beyond EOF.
799*6a54128fSAndroid Build Coastguard Worker  *
800*6a54128fSAndroid Build Coastguard Worker  * If neither FORCE_INIT nor FORCE_UNINIT are specified, this function will
801*6a54128fSAndroid Build Coastguard Worker  * try to expand any extents it finds, zeroing blocks as necessary.
802*6a54128fSAndroid Build Coastguard Worker  */
ext2fs_fallocate(ext2_filsys fs,int flags,ext2_ino_t ino,struct ext2_inode * inode,blk64_t goal,blk64_t start,blk64_t len)803*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino,
804*6a54128fSAndroid Build Coastguard Worker 			   struct ext2_inode *inode, blk64_t goal,
805*6a54128fSAndroid Build Coastguard Worker 			   blk64_t start, blk64_t len)
806*6a54128fSAndroid Build Coastguard Worker {
807*6a54128fSAndroid Build Coastguard Worker 	struct ext2_inode	inode_buf;
808*6a54128fSAndroid Build Coastguard Worker 	blk64_t			blk, x, zero_blk, last = 0;
809*6a54128fSAndroid Build Coastguard Worker 	int			zero_len = 0;
810*6a54128fSAndroid Build Coastguard Worker 	errcode_t		err;
811*6a54128fSAndroid Build Coastguard Worker 
812*6a54128fSAndroid Build Coastguard Worker 	if (((flags & EXT2_FALLOCATE_FORCE_INIT) &&
813*6a54128fSAndroid Build Coastguard Worker 	    (flags & EXT2_FALLOCATE_FORCE_UNINIT)) ||
814*6a54128fSAndroid Build Coastguard Worker 	   (flags & ~EXT2_FALLOCATE_ALL_FLAGS))
815*6a54128fSAndroid Build Coastguard Worker 		return EXT2_ET_INVALID_ARGUMENT;
816*6a54128fSAndroid Build Coastguard Worker 
817*6a54128fSAndroid Build Coastguard Worker 	if (len > ext2fs_blocks_count(fs->super))
818*6a54128fSAndroid Build Coastguard Worker 		return EXT2_ET_BLOCK_ALLOC_FAIL;
819*6a54128fSAndroid Build Coastguard Worker 	else if (len == 0)
820*6a54128fSAndroid Build Coastguard Worker 		return 0;
821*6a54128fSAndroid Build Coastguard Worker 
822*6a54128fSAndroid Build Coastguard Worker 	/* Read inode structure if necessary */
823*6a54128fSAndroid Build Coastguard Worker 	if (!inode) {
824*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_read_inode(fs, ino, &inode_buf);
825*6a54128fSAndroid Build Coastguard Worker 		if (err)
826*6a54128fSAndroid Build Coastguard Worker 			return err;
827*6a54128fSAndroid Build Coastguard Worker 		inode = &inode_buf;
828*6a54128fSAndroid Build Coastguard Worker 	}
829*6a54128fSAndroid Build Coastguard Worker 	dbg_printf("%s: ino=%d start=%llu len=%llu goal=%llu\n", __func__, ino,
830*6a54128fSAndroid Build Coastguard Worker 		   start, len, goal);
831*6a54128fSAndroid Build Coastguard Worker 
832*6a54128fSAndroid Build Coastguard Worker 	if (inode->i_flags & EXT4_EXTENTS_FL) {
833*6a54128fSAndroid Build Coastguard Worker 		err = extent_fallocate(fs, flags, ino, inode, goal, start, len);
834*6a54128fSAndroid Build Coastguard Worker 		goto out;
835*6a54128fSAndroid Build Coastguard Worker 	}
836*6a54128fSAndroid Build Coastguard Worker 
837*6a54128fSAndroid Build Coastguard Worker 	/* XXX: Allocate a bunch of blocks the slow way */
838*6a54128fSAndroid Build Coastguard Worker 	for (blk = start; blk < start + len; blk++) {
839*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_bmap2(fs, ino, inode, NULL, 0, blk, 0, &x);
840*6a54128fSAndroid Build Coastguard Worker 		if (err)
841*6a54128fSAndroid Build Coastguard Worker 			return err;
842*6a54128fSAndroid Build Coastguard Worker 		if (x)
843*6a54128fSAndroid Build Coastguard Worker 			continue;
844*6a54128fSAndroid Build Coastguard Worker 
845*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_bmap2(fs, ino, inode, NULL, BMAP_ALLOC,
846*6a54128fSAndroid Build Coastguard Worker 				   blk, 0, &x);
847*6a54128fSAndroid Build Coastguard Worker 		if (err)
848*6a54128fSAndroid Build Coastguard Worker 			goto errout;
849*6a54128fSAndroid Build Coastguard Worker 		if ((zero_len && (x != last+1)) ||
850*6a54128fSAndroid Build Coastguard Worker 		    (zero_len >= 65536)) {
851*6a54128fSAndroid Build Coastguard Worker 			err = ext2fs_zero_blocks2(fs, zero_blk, zero_len,
852*6a54128fSAndroid Build Coastguard Worker 						  NULL, NULL);
853*6a54128fSAndroid Build Coastguard Worker 			zero_len = 0;
854*6a54128fSAndroid Build Coastguard Worker 			if (err)
855*6a54128fSAndroid Build Coastguard Worker 				goto errout;
856*6a54128fSAndroid Build Coastguard Worker 		}
857*6a54128fSAndroid Build Coastguard Worker 		if (zero_len == 0) {
858*6a54128fSAndroid Build Coastguard Worker 			zero_blk = x;
859*6a54128fSAndroid Build Coastguard Worker 			zero_len = 1;
860*6a54128fSAndroid Build Coastguard Worker 		} else {
861*6a54128fSAndroid Build Coastguard Worker 			zero_len++;
862*6a54128fSAndroid Build Coastguard Worker 		}
863*6a54128fSAndroid Build Coastguard Worker 		last = x;
864*6a54128fSAndroid Build Coastguard Worker 	}
865*6a54128fSAndroid Build Coastguard Worker 
866*6a54128fSAndroid Build Coastguard Worker out:
867*6a54128fSAndroid Build Coastguard Worker 	if (inode == &inode_buf)
868*6a54128fSAndroid Build Coastguard Worker 		ext2fs_write_inode(fs, ino, inode);
869*6a54128fSAndroid Build Coastguard Worker errout:
870*6a54128fSAndroid Build Coastguard Worker 	if (zero_len)
871*6a54128fSAndroid Build Coastguard Worker 		ext2fs_zero_blocks2(fs, zero_blk, zero_len, NULL, NULL);
872*6a54128fSAndroid Build Coastguard Worker 	return err;
873*6a54128fSAndroid Build Coastguard Worker }
874