diff options
Diffstat (limited to 'fs/gfs2/bmap.c')
-rw-r--r-- | fs/gfs2/bmap.c | 670 |
1 files changed, 375 insertions, 295 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index e9456ebd3bb6..c19184f2e70e 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -33,6 +33,7 @@ | |||
33 | * keep it small. | 33 | * keep it small. |
34 | */ | 34 | */ |
35 | struct metapath { | 35 | struct metapath { |
36 | struct buffer_head *mp_bh[GFS2_MAX_META_HEIGHT]; | ||
36 | __u16 mp_list[GFS2_MAX_META_HEIGHT]; | 37 | __u16 mp_list[GFS2_MAX_META_HEIGHT]; |
37 | }; | 38 | }; |
38 | 39 | ||
@@ -135,9 +136,10 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) | |||
135 | /* Get a free block, fill it with the stuffed data, | 136 | /* Get a free block, fill it with the stuffed data, |
136 | and write it out to disk */ | 137 | and write it out to disk */ |
137 | 138 | ||
139 | unsigned int n = 1; | ||
140 | block = gfs2_alloc_block(ip, &n); | ||
138 | if (isdir) { | 141 | if (isdir) { |
139 | block = gfs2_alloc_meta(ip); | 142 | gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), block, 1); |
140 | |||
141 | error = gfs2_dir_get_new_buffer(ip, block, &bh); | 143 | error = gfs2_dir_get_new_buffer(ip, block, &bh); |
142 | if (error) | 144 | if (error) |
143 | goto out_brelse; | 145 | goto out_brelse; |
@@ -145,8 +147,6 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) | |||
145 | dibh, sizeof(struct gfs2_dinode)); | 147 | dibh, sizeof(struct gfs2_dinode)); |
146 | brelse(bh); | 148 | brelse(bh); |
147 | } else { | 149 | } else { |
148 | block = gfs2_alloc_data(ip); | ||
149 | |||
150 | error = gfs2_unstuffer_page(ip, dibh, block, page); | 150 | error = gfs2_unstuffer_page(ip, dibh, block, page); |
151 | if (error) | 151 | if (error) |
152 | goto out_brelse; | 152 | goto out_brelse; |
@@ -161,12 +161,11 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) | |||
161 | 161 | ||
162 | if (ip->i_di.di_size) { | 162 | if (ip->i_di.di_size) { |
163 | *(__be64 *)(di + 1) = cpu_to_be64(block); | 163 | *(__be64 *)(di + 1) = cpu_to_be64(block); |
164 | ip->i_di.di_blocks++; | 164 | gfs2_add_inode_blocks(&ip->i_inode, 1); |
165 | gfs2_set_inode_blocks(&ip->i_inode); | 165 | di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode)); |
166 | di->di_blocks = cpu_to_be64(ip->i_di.di_blocks); | ||
167 | } | 166 | } |
168 | 167 | ||
169 | ip->i_di.di_height = 1; | 168 | ip->i_height = 1; |
170 | di->di_height = cpu_to_be16(1); | 169 | di->di_height = cpu_to_be16(1); |
171 | 170 | ||
172 | out_brelse: | 171 | out_brelse: |
@@ -176,114 +175,13 @@ out: | |||
176 | return error; | 175 | return error; |
177 | } | 176 | } |
178 | 177 | ||
179 | /** | ||
180 | * calc_tree_height - Calculate the height of a metadata tree | ||
181 | * @ip: The GFS2 inode | ||
182 | * @size: The proposed size of the file | ||
183 | * | ||
184 | * Work out how tall a metadata tree needs to be in order to accommodate a | ||
185 | * file of a particular size. If size is less than the current size of | ||
186 | * the inode, then the current size of the inode is used instead of the | ||
187 | * supplied one. | ||
188 | * | ||
189 | * Returns: the height the tree should be | ||
190 | */ | ||
191 | |||
192 | static unsigned int calc_tree_height(struct gfs2_inode *ip, u64 size) | ||
193 | { | ||
194 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
195 | u64 *arr; | ||
196 | unsigned int max, height; | ||
197 | |||
198 | if (ip->i_di.di_size > size) | ||
199 | size = ip->i_di.di_size; | ||
200 | |||
201 | if (gfs2_is_dir(ip)) { | ||
202 | arr = sdp->sd_jheightsize; | ||
203 | max = sdp->sd_max_jheight; | ||
204 | } else { | ||
205 | arr = sdp->sd_heightsize; | ||
206 | max = sdp->sd_max_height; | ||
207 | } | ||
208 | |||
209 | for (height = 0; height < max; height++) | ||
210 | if (arr[height] >= size) | ||
211 | break; | ||
212 | |||
213 | return height; | ||
214 | } | ||
215 | |||
216 | /** | ||
217 | * build_height - Build a metadata tree of the requested height | ||
218 | * @ip: The GFS2 inode | ||
219 | * @height: The height to build to | ||
220 | * | ||
221 | * | ||
222 | * Returns: errno | ||
223 | */ | ||
224 | |||
225 | static int build_height(struct inode *inode, unsigned height) | ||
226 | { | ||
227 | struct gfs2_inode *ip = GFS2_I(inode); | ||
228 | unsigned new_height = height - ip->i_di.di_height; | ||
229 | struct buffer_head *dibh; | ||
230 | struct buffer_head *blocks[GFS2_MAX_META_HEIGHT]; | ||
231 | struct gfs2_dinode *di; | ||
232 | int error; | ||
233 | __be64 *bp; | ||
234 | u64 bn; | ||
235 | unsigned n; | ||
236 | |||
237 | if (height <= ip->i_di.di_height) | ||
238 | return 0; | ||
239 | |||
240 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
241 | if (error) | ||
242 | return error; | ||
243 | |||
244 | for(n = 0; n < new_height; n++) { | ||
245 | bn = gfs2_alloc_meta(ip); | ||
246 | blocks[n] = gfs2_meta_new(ip->i_gl, bn); | ||
247 | gfs2_trans_add_bh(ip->i_gl, blocks[n], 1); | ||
248 | } | ||
249 | |||
250 | n = 0; | ||
251 | bn = blocks[0]->b_blocknr; | ||
252 | if (new_height > 1) { | ||
253 | for(; n < new_height-1; n++) { | ||
254 | gfs2_metatype_set(blocks[n], GFS2_METATYPE_IN, | ||
255 | GFS2_FORMAT_IN); | ||
256 | gfs2_buffer_clear_tail(blocks[n], | ||
257 | sizeof(struct gfs2_meta_header)); | ||
258 | bp = (__be64 *)(blocks[n]->b_data + | ||
259 | sizeof(struct gfs2_meta_header)); | ||
260 | *bp = cpu_to_be64(blocks[n+1]->b_blocknr); | ||
261 | brelse(blocks[n]); | ||
262 | blocks[n] = NULL; | ||
263 | } | ||
264 | } | ||
265 | gfs2_metatype_set(blocks[n], GFS2_METATYPE_IN, GFS2_FORMAT_IN); | ||
266 | gfs2_buffer_copy_tail(blocks[n], sizeof(struct gfs2_meta_header), | ||
267 | dibh, sizeof(struct gfs2_dinode)); | ||
268 | brelse(blocks[n]); | ||
269 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
270 | di = (struct gfs2_dinode *)dibh->b_data; | ||
271 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); | ||
272 | *(__be64 *)(di + 1) = cpu_to_be64(bn); | ||
273 | ip->i_di.di_height += new_height; | ||
274 | ip->i_di.di_blocks += new_height; | ||
275 | gfs2_set_inode_blocks(&ip->i_inode); | ||
276 | di->di_height = cpu_to_be16(ip->i_di.di_height); | ||
277 | di->di_blocks = cpu_to_be64(ip->i_di.di_blocks); | ||
278 | brelse(dibh); | ||
279 | return error; | ||
280 | } | ||
281 | 178 | ||
282 | /** | 179 | /** |
283 | * find_metapath - Find path through the metadata tree | 180 | * find_metapath - Find path through the metadata tree |
284 | * @ip: The inode pointer | 181 | * @sdp: The superblock |
285 | * @mp: The metapath to return the result in | 182 | * @mp: The metapath to return the result in |
286 | * @block: The disk block to look up | 183 | * @block: The disk block to look up |
184 | * @height: The pre-calculated height of the metadata tree | ||
287 | * | 185 | * |
288 | * This routine returns a struct metapath structure that defines a path | 186 | * This routine returns a struct metapath structure that defines a path |
289 | * through the metadata of inode "ip" to get to block "block". | 187 | * through the metadata of inode "ip" to get to block "block". |
@@ -338,21 +236,29 @@ static int build_height(struct inode *inode, unsigned height) | |||
338 | * | 236 | * |
339 | */ | 237 | */ |
340 | 238 | ||
341 | static void find_metapath(struct gfs2_inode *ip, u64 block, | 239 | static void find_metapath(const struct gfs2_sbd *sdp, u64 block, |
342 | struct metapath *mp) | 240 | struct metapath *mp, unsigned int height) |
343 | { | 241 | { |
344 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
345 | u64 b = block; | ||
346 | unsigned int i; | 242 | unsigned int i; |
347 | 243 | ||
348 | for (i = ip->i_di.di_height; i--;) | 244 | for (i = height; i--;) |
349 | mp->mp_list[i] = do_div(b, sdp->sd_inptrs); | 245 | mp->mp_list[i] = do_div(block, sdp->sd_inptrs); |
246 | |||
247 | } | ||
350 | 248 | ||
249 | static inline unsigned int zero_metapath_length(const struct metapath *mp, | ||
250 | unsigned height) | ||
251 | { | ||
252 | unsigned int i; | ||
253 | for (i = 0; i < height - 1; i++) { | ||
254 | if (mp->mp_list[i] != 0) | ||
255 | return i; | ||
256 | } | ||
257 | return height; | ||
351 | } | 258 | } |
352 | 259 | ||
353 | /** | 260 | /** |
354 | * metapointer - Return pointer to start of metadata in a buffer | 261 | * metapointer - Return pointer to start of metadata in a buffer |
355 | * @bh: The buffer | ||
356 | * @height: The metadata height (0 = dinode) | 262 | * @height: The metadata height (0 = dinode) |
357 | * @mp: The metapath | 263 | * @mp: The metapath |
358 | * | 264 | * |
@@ -361,93 +267,302 @@ static void find_metapath(struct gfs2_inode *ip, u64 block, | |||
361 | * metadata tree. | 267 | * metadata tree. |
362 | */ | 268 | */ |
363 | 269 | ||
364 | static inline __be64 *metapointer(struct buffer_head *bh, int *boundary, | 270 | static inline __be64 *metapointer(unsigned int height, const struct metapath *mp) |
365 | unsigned int height, const struct metapath *mp) | ||
366 | { | 271 | { |
272 | struct buffer_head *bh = mp->mp_bh[height]; | ||
367 | unsigned int head_size = (height > 0) ? | 273 | unsigned int head_size = (height > 0) ? |
368 | sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode); | 274 | sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode); |
369 | __be64 *ptr; | 275 | return ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height]; |
370 | *boundary = 0; | ||
371 | ptr = ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height]; | ||
372 | if (ptr + 1 == (__be64 *)(bh->b_data + bh->b_size)) | ||
373 | *boundary = 1; | ||
374 | return ptr; | ||
375 | } | 276 | } |
376 | 277 | ||
377 | /** | 278 | /** |
378 | * lookup_block - Get the next metadata block in metadata tree | 279 | * lookup_metapath - Walk the metadata tree to a specific point |
379 | * @ip: The GFS2 inode | 280 | * @ip: The inode |
380 | * @bh: Buffer containing the pointers to metadata blocks | ||
381 | * @height: The height of the tree (0 = dinode) | ||
382 | * @mp: The metapath | 281 | * @mp: The metapath |
383 | * @create: Non-zero if we may create a new meatdata block | ||
384 | * @new: Used to indicate if we did create a new metadata block | ||
385 | * @block: the returned disk block number | ||
386 | * | 282 | * |
387 | * Given a metatree, complete to a particular height, checks to see if the next | 283 | * Assumes that the inode's buffer has already been looked up and |
388 | * height of the tree exists. If not the next height of the tree is created. | 284 | * hooked onto mp->mp_bh[0] and that the metapath has been initialised |
389 | * The block number of the next height of the metadata tree is returned. | 285 | * by find_metapath(). |
286 | * | ||
287 | * If this function encounters part of the tree which has not been | ||
288 | * allocated, it returns the current height of the tree at the point | ||
289 | * at which it found the unallocated block. Blocks which are found are | ||
290 | * added to the mp->mp_bh[] list. | ||
390 | * | 291 | * |
292 | * Returns: error or height of metadata tree | ||
391 | */ | 293 | */ |
392 | 294 | ||
393 | static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh, | 295 | static int lookup_metapath(struct gfs2_inode *ip, struct metapath *mp) |
394 | unsigned int height, struct metapath *mp, int create, | ||
395 | int *new, u64 *block) | ||
396 | { | 296 | { |
397 | int boundary; | 297 | unsigned int end_of_metadata = ip->i_height - 1; |
398 | __be64 *ptr = metapointer(bh, &boundary, height, mp); | 298 | unsigned int x; |
299 | __be64 *ptr; | ||
300 | u64 dblock; | ||
301 | int ret; | ||
399 | 302 | ||
400 | if (*ptr) { | 303 | for (x = 0; x < end_of_metadata; x++) { |
401 | *block = be64_to_cpu(*ptr); | 304 | ptr = metapointer(x, mp); |
402 | return boundary; | 305 | dblock = be64_to_cpu(*ptr); |
403 | } | 306 | if (!dblock) |
307 | return x + 1; | ||
404 | 308 | ||
405 | *block = 0; | 309 | ret = gfs2_meta_indirect_buffer(ip, x+1, dblock, 0, &mp->mp_bh[x+1]); |
310 | if (ret) | ||
311 | return ret; | ||
312 | } | ||
406 | 313 | ||
407 | if (!create) | 314 | return ip->i_height; |
408 | return 0; | 315 | } |
409 | 316 | ||
410 | if (height == ip->i_di.di_height - 1 && !gfs2_is_dir(ip)) | 317 | static inline void release_metapath(struct metapath *mp) |
411 | *block = gfs2_alloc_data(ip); | 318 | { |
412 | else | 319 | int i; |
413 | *block = gfs2_alloc_meta(ip); | ||
414 | 320 | ||
415 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | 321 | for (i = 0; i < GFS2_MAX_META_HEIGHT; i++) { |
322 | if (mp->mp_bh[i] == NULL) | ||
323 | break; | ||
324 | brelse(mp->mp_bh[i]); | ||
325 | } | ||
326 | } | ||
416 | 327 | ||
417 | *ptr = cpu_to_be64(*block); | 328 | /** |
418 | ip->i_di.di_blocks++; | 329 | * gfs2_extent_length - Returns length of an extent of blocks |
419 | gfs2_set_inode_blocks(&ip->i_inode); | 330 | * @start: Start of the buffer |
331 | * @len: Length of the buffer in bytes | ||
332 | * @ptr: Current position in the buffer | ||
333 | * @limit: Max extent length to return (0 = unlimited) | ||
334 | * @eob: Set to 1 if we hit "end of block" | ||
335 | * | ||
336 | * If the first block is zero (unallocated) it will return the number of | ||
337 | * unallocated blocks in the extent, otherwise it will return the number | ||
338 | * of contiguous blocks in the extent. | ||
339 | * | ||
340 | * Returns: The length of the extent (minimum of one block) | ||
341 | */ | ||
420 | 342 | ||
421 | *new = 1; | 343 | static inline unsigned int gfs2_extent_length(void *start, unsigned int len, __be64 *ptr, unsigned limit, int *eob) |
422 | return 0; | 344 | { |
345 | const __be64 *end = (start + len); | ||
346 | const __be64 *first = ptr; | ||
347 | u64 d = be64_to_cpu(*ptr); | ||
348 | |||
349 | *eob = 0; | ||
350 | do { | ||
351 | ptr++; | ||
352 | if (ptr >= end) | ||
353 | break; | ||
354 | if (limit && --limit == 0) | ||
355 | break; | ||
356 | if (d) | ||
357 | d++; | ||
358 | } while(be64_to_cpu(*ptr) == d); | ||
359 | if (ptr >= end) | ||
360 | *eob = 1; | ||
361 | return (ptr - first); | ||
423 | } | 362 | } |
424 | 363 | ||
425 | static inline void bmap_lock(struct inode *inode, int create) | 364 | static inline void bmap_lock(struct gfs2_inode *ip, int create) |
426 | { | 365 | { |
427 | struct gfs2_inode *ip = GFS2_I(inode); | ||
428 | if (create) | 366 | if (create) |
429 | down_write(&ip->i_rw_mutex); | 367 | down_write(&ip->i_rw_mutex); |
430 | else | 368 | else |
431 | down_read(&ip->i_rw_mutex); | 369 | down_read(&ip->i_rw_mutex); |
432 | } | 370 | } |
433 | 371 | ||
434 | static inline void bmap_unlock(struct inode *inode, int create) | 372 | static inline void bmap_unlock(struct gfs2_inode *ip, int create) |
435 | { | 373 | { |
436 | struct gfs2_inode *ip = GFS2_I(inode); | ||
437 | if (create) | 374 | if (create) |
438 | up_write(&ip->i_rw_mutex); | 375 | up_write(&ip->i_rw_mutex); |
439 | else | 376 | else |
440 | up_read(&ip->i_rw_mutex); | 377 | up_read(&ip->i_rw_mutex); |
441 | } | 378 | } |
442 | 379 | ||
380 | static inline __be64 *gfs2_indirect_init(struct metapath *mp, | ||
381 | struct gfs2_glock *gl, unsigned int i, | ||
382 | unsigned offset, u64 bn) | ||
383 | { | ||
384 | __be64 *ptr = (__be64 *)(mp->mp_bh[i - 1]->b_data + | ||
385 | ((i > 1) ? sizeof(struct gfs2_meta_header) : | ||
386 | sizeof(struct gfs2_dinode))); | ||
387 | BUG_ON(i < 1); | ||
388 | BUG_ON(mp->mp_bh[i] != NULL); | ||
389 | mp->mp_bh[i] = gfs2_meta_new(gl, bn); | ||
390 | gfs2_trans_add_bh(gl, mp->mp_bh[i], 1); | ||
391 | gfs2_metatype_set(mp->mp_bh[i], GFS2_METATYPE_IN, GFS2_FORMAT_IN); | ||
392 | gfs2_buffer_clear_tail(mp->mp_bh[i], sizeof(struct gfs2_meta_header)); | ||
393 | ptr += offset; | ||
394 | *ptr = cpu_to_be64(bn); | ||
395 | return ptr; | ||
396 | } | ||
397 | |||
398 | enum alloc_state { | ||
399 | ALLOC_DATA = 0, | ||
400 | ALLOC_GROW_DEPTH = 1, | ||
401 | ALLOC_GROW_HEIGHT = 2, | ||
402 | /* ALLOC_UNSTUFF = 3, TBD and rather complicated */ | ||
403 | }; | ||
404 | |||
405 | /** | ||
406 | * gfs2_bmap_alloc - Build a metadata tree of the requested height | ||
407 | * @inode: The GFS2 inode | ||
408 | * @lblock: The logical starting block of the extent | ||
409 | * @bh_map: This is used to return the mapping details | ||
410 | * @mp: The metapath | ||
411 | * @sheight: The starting height (i.e. whats already mapped) | ||
412 | * @height: The height to build to | ||
413 | * @maxlen: The max number of data blocks to alloc | ||
414 | * | ||
415 | * In this routine we may have to alloc: | ||
416 | * i) Indirect blocks to grow the metadata tree height | ||
417 | * ii) Indirect blocks to fill in lower part of the metadata tree | ||
418 | * iii) Data blocks | ||
419 | * | ||
420 | * The function is in two parts. The first part works out the total | ||
421 | * number of blocks which we need. The second part does the actual | ||
422 | * allocation asking for an extent at a time (if enough contiguous free | ||
423 | * blocks are available, there will only be one request per bmap call) | ||
424 | * and uses the state machine to initialise the blocks in order. | ||
425 | * | ||
426 | * Returns: errno on error | ||
427 | */ | ||
428 | |||
429 | static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock, | ||
430 | struct buffer_head *bh_map, struct metapath *mp, | ||
431 | const unsigned int sheight, | ||
432 | const unsigned int height, | ||
433 | const unsigned int maxlen) | ||
434 | { | ||
435 | struct gfs2_inode *ip = GFS2_I(inode); | ||
436 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
437 | struct buffer_head *dibh = mp->mp_bh[0]; | ||
438 | u64 bn, dblock = 0; | ||
439 | unsigned n, i, blks, alloced = 0, iblks = 0, zmpl = 0; | ||
440 | unsigned dblks = 0; | ||
441 | unsigned ptrs_per_blk; | ||
442 | const unsigned end_of_metadata = height - 1; | ||
443 | int eob = 0; | ||
444 | enum alloc_state state; | ||
445 | __be64 *ptr; | ||
446 | __be64 zero_bn = 0; | ||
447 | |||
448 | BUG_ON(sheight < 1); | ||
449 | BUG_ON(dibh == NULL); | ||
450 | |||
451 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
452 | |||
453 | if (height == sheight) { | ||
454 | struct buffer_head *bh; | ||
455 | /* Bottom indirect block exists, find unalloced extent size */ | ||
456 | ptr = metapointer(end_of_metadata, mp); | ||
457 | bh = mp->mp_bh[end_of_metadata]; | ||
458 | dblks = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen, | ||
459 | &eob); | ||
460 | BUG_ON(dblks < 1); | ||
461 | state = ALLOC_DATA; | ||
462 | } else { | ||
463 | /* Need to allocate indirect blocks */ | ||
464 | ptrs_per_blk = height > 1 ? sdp->sd_inptrs : sdp->sd_diptrs; | ||
465 | dblks = min(maxlen, ptrs_per_blk - mp->mp_list[end_of_metadata]); | ||
466 | if (height == ip->i_height) { | ||
467 | /* Writing into existing tree, extend tree down */ | ||
468 | iblks = height - sheight; | ||
469 | state = ALLOC_GROW_DEPTH; | ||
470 | } else { | ||
471 | /* Building up tree height */ | ||
472 | state = ALLOC_GROW_HEIGHT; | ||
473 | iblks = height - ip->i_height; | ||
474 | zmpl = zero_metapath_length(mp, height); | ||
475 | iblks -= zmpl; | ||
476 | iblks += height; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /* start of the second part of the function (state machine) */ | ||
481 | |||
482 | blks = dblks + iblks; | ||
483 | i = sheight; | ||
484 | do { | ||
485 | n = blks - alloced; | ||
486 | bn = gfs2_alloc_block(ip, &n); | ||
487 | alloced += n; | ||
488 | if (state != ALLOC_DATA || gfs2_is_jdata(ip)) | ||
489 | gfs2_trans_add_unrevoke(sdp, bn, n); | ||
490 | switch (state) { | ||
491 | /* Growing height of tree */ | ||
492 | case ALLOC_GROW_HEIGHT: | ||
493 | if (i == 1) { | ||
494 | ptr = (__be64 *)(dibh->b_data + | ||
495 | sizeof(struct gfs2_dinode)); | ||
496 | zero_bn = *ptr; | ||
497 | } | ||
498 | for (; i - 1 < height - ip->i_height && n > 0; i++, n--) | ||
499 | gfs2_indirect_init(mp, ip->i_gl, i, 0, bn++); | ||
500 | if (i - 1 == height - ip->i_height) { | ||
501 | i--; | ||
502 | gfs2_buffer_copy_tail(mp->mp_bh[i], | ||
503 | sizeof(struct gfs2_meta_header), | ||
504 | dibh, sizeof(struct gfs2_dinode)); | ||
505 | gfs2_buffer_clear_tail(dibh, | ||
506 | sizeof(struct gfs2_dinode) + | ||
507 | sizeof(__be64)); | ||
508 | ptr = (__be64 *)(mp->mp_bh[i]->b_data + | ||
509 | sizeof(struct gfs2_meta_header)); | ||
510 | *ptr = zero_bn; | ||
511 | state = ALLOC_GROW_DEPTH; | ||
512 | for(i = zmpl; i < height; i++) { | ||
513 | if (mp->mp_bh[i] == NULL) | ||
514 | break; | ||
515 | brelse(mp->mp_bh[i]); | ||
516 | mp->mp_bh[i] = NULL; | ||
517 | } | ||
518 | i = zmpl; | ||
519 | } | ||
520 | if (n == 0) | ||
521 | break; | ||
522 | /* Branching from existing tree */ | ||
523 | case ALLOC_GROW_DEPTH: | ||
524 | if (i > 1 && i < height) | ||
525 | gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[i-1], 1); | ||
526 | for (; i < height && n > 0; i++, n--) | ||
527 | gfs2_indirect_init(mp, ip->i_gl, i, | ||
528 | mp->mp_list[i-1], bn++); | ||
529 | if (i == height) | ||
530 | state = ALLOC_DATA; | ||
531 | if (n == 0) | ||
532 | break; | ||
533 | /* Tree complete, adding data blocks */ | ||
534 | case ALLOC_DATA: | ||
535 | BUG_ON(n > dblks); | ||
536 | BUG_ON(mp->mp_bh[end_of_metadata] == NULL); | ||
537 | gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[end_of_metadata], 1); | ||
538 | dblks = n; | ||
539 | ptr = metapointer(end_of_metadata, mp); | ||
540 | dblock = bn; | ||
541 | while (n-- > 0) | ||
542 | *ptr++ = cpu_to_be64(bn++); | ||
543 | break; | ||
544 | } | ||
545 | } while (state != ALLOC_DATA); | ||
546 | |||
547 | ip->i_height = height; | ||
548 | gfs2_add_inode_blocks(&ip->i_inode, alloced); | ||
549 | gfs2_dinode_out(ip, mp->mp_bh[0]->b_data); | ||
550 | map_bh(bh_map, inode->i_sb, dblock); | ||
551 | bh_map->b_size = dblks << inode->i_blkbits; | ||
552 | set_buffer_new(bh_map); | ||
553 | return 0; | ||
554 | } | ||
555 | |||
443 | /** | 556 | /** |
444 | * gfs2_block_map - Map a block from an inode to a disk block | 557 | * gfs2_block_map - Map a block from an inode to a disk block |
445 | * @inode: The inode | 558 | * @inode: The inode |
446 | * @lblock: The logical block number | 559 | * @lblock: The logical block number |
447 | * @bh_map: The bh to be mapped | 560 | * @bh_map: The bh to be mapped |
561 | * @create: True if its ok to alloc blocks to satify the request | ||
448 | * | 562 | * |
449 | * Find the block number on the current device which corresponds to an | 563 | * Sets buffer_mapped() if successful, sets buffer_boundary() if a |
450 | * inode's block. If the block had to be created, "new" will be set. | 564 | * read of metadata will be required before the next block can be |
565 | * mapped. Sets buffer_new() if new blocks were allocated. | ||
451 | * | 566 | * |
452 | * Returns: errno | 567 | * Returns: errno |
453 | */ | 568 | */ |
@@ -457,97 +572,78 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, | |||
457 | { | 572 | { |
458 | struct gfs2_inode *ip = GFS2_I(inode); | 573 | struct gfs2_inode *ip = GFS2_I(inode); |
459 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 574 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
460 | struct buffer_head *bh; | 575 | unsigned int bsize = sdp->sd_sb.sb_bsize; |
461 | unsigned int bsize; | 576 | const unsigned int maxlen = bh_map->b_size >> inode->i_blkbits; |
462 | unsigned int height; | 577 | const u64 *arr = sdp->sd_heightsize; |
463 | unsigned int end_of_metadata; | 578 | __be64 *ptr; |
464 | unsigned int x; | ||
465 | int error = 0; | ||
466 | int new = 0; | ||
467 | u64 dblock = 0; | ||
468 | int boundary; | ||
469 | unsigned int maxlen = bh_map->b_size >> inode->i_blkbits; | ||
470 | struct metapath mp; | ||
471 | u64 size; | 579 | u64 size; |
472 | struct buffer_head *dibh = NULL; | 580 | struct metapath mp; |
581 | int ret; | ||
582 | int eob; | ||
583 | unsigned int len; | ||
584 | struct buffer_head *bh; | ||
585 | u8 height; | ||
473 | 586 | ||
474 | BUG_ON(maxlen == 0); | 587 | BUG_ON(maxlen == 0); |
475 | 588 | ||
476 | if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip))) | 589 | memset(mp.mp_bh, 0, sizeof(mp.mp_bh)); |
477 | return 0; | 590 | bmap_lock(ip, create); |
478 | |||
479 | bmap_lock(inode, create); | ||
480 | clear_buffer_mapped(bh_map); | 591 | clear_buffer_mapped(bh_map); |
481 | clear_buffer_new(bh_map); | 592 | clear_buffer_new(bh_map); |
482 | clear_buffer_boundary(bh_map); | 593 | clear_buffer_boundary(bh_map); |
483 | bsize = gfs2_is_dir(ip) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize; | 594 | if (gfs2_is_dir(ip)) { |
484 | size = (lblock + 1) * bsize; | 595 | bsize = sdp->sd_jbsize; |
485 | 596 | arr = sdp->sd_jheightsize; | |
486 | if (size > ip->i_di.di_size) { | ||
487 | height = calc_tree_height(ip, size); | ||
488 | if (ip->i_di.di_height < height) { | ||
489 | if (!create) | ||
490 | goto out_ok; | ||
491 | |||
492 | error = build_height(inode, height); | ||
493 | if (error) | ||
494 | goto out_fail; | ||
495 | } | ||
496 | } | 597 | } |
497 | 598 | ||
498 | find_metapath(ip, lblock, &mp); | 599 | ret = gfs2_meta_inode_buffer(ip, &mp.mp_bh[0]); |
499 | end_of_metadata = ip->i_di.di_height - 1; | 600 | if (ret) |
500 | error = gfs2_meta_inode_buffer(ip, &bh); | 601 | goto out; |
501 | if (error) | ||
502 | goto out_fail; | ||
503 | dibh = bh; | ||
504 | get_bh(dibh); | ||
505 | 602 | ||
506 | for (x = 0; x < end_of_metadata; x++) { | 603 | height = ip->i_height; |
507 | lookup_block(ip, bh, x, &mp, create, &new, &dblock); | 604 | size = (lblock + 1) * bsize; |
508 | brelse(bh); | 605 | while (size > arr[height]) |
509 | if (!dblock) | 606 | height++; |
510 | goto out_ok; | 607 | find_metapath(sdp, lblock, &mp, height); |
608 | ret = 1; | ||
609 | if (height > ip->i_height || gfs2_is_stuffed(ip)) | ||
610 | goto do_alloc; | ||
611 | ret = lookup_metapath(ip, &mp); | ||
612 | if (ret < 0) | ||
613 | goto out; | ||
614 | if (ret != ip->i_height) | ||
615 | goto do_alloc; | ||
616 | ptr = metapointer(ip->i_height - 1, &mp); | ||
617 | if (*ptr == 0) | ||
618 | goto do_alloc; | ||
619 | map_bh(bh_map, inode->i_sb, be64_to_cpu(*ptr)); | ||
620 | bh = mp.mp_bh[ip->i_height - 1]; | ||
621 | len = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen, &eob); | ||
622 | bh_map->b_size = (len << inode->i_blkbits); | ||
623 | if (eob) | ||
624 | set_buffer_boundary(bh_map); | ||
625 | ret = 0; | ||
626 | out: | ||
627 | release_metapath(&mp); | ||
628 | bmap_unlock(ip, create); | ||
629 | return ret; | ||
511 | 630 | ||
512 | error = gfs2_meta_indirect_buffer(ip, x+1, dblock, new, &bh); | 631 | do_alloc: |
513 | if (error) | 632 | /* All allocations are done here, firstly check create flag */ |
514 | goto out_fail; | 633 | if (!create) { |
634 | BUG_ON(gfs2_is_stuffed(ip)); | ||
635 | ret = 0; | ||
636 | goto out; | ||
515 | } | 637 | } |
516 | 638 | ||
517 | boundary = lookup_block(ip, bh, end_of_metadata, &mp, create, &new, &dblock); | 639 | /* At this point ret is the tree depth of already allocated blocks */ |
518 | if (dblock) { | 640 | ret = gfs2_bmap_alloc(inode, lblock, bh_map, &mp, ret, height, maxlen); |
519 | map_bh(bh_map, inode->i_sb, dblock); | 641 | goto out; |
520 | if (boundary) | ||
521 | set_buffer_boundary(bh_map); | ||
522 | if (new) { | ||
523 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
524 | gfs2_dinode_out(ip, dibh->b_data); | ||
525 | set_buffer_new(bh_map); | ||
526 | goto out_brelse; | ||
527 | } | ||
528 | while(--maxlen && !buffer_boundary(bh_map)) { | ||
529 | u64 eblock; | ||
530 | |||
531 | mp.mp_list[end_of_metadata]++; | ||
532 | boundary = lookup_block(ip, bh, end_of_metadata, &mp, 0, &new, &eblock); | ||
533 | if (eblock != ++dblock) | ||
534 | break; | ||
535 | bh_map->b_size += (1 << inode->i_blkbits); | ||
536 | if (boundary) | ||
537 | set_buffer_boundary(bh_map); | ||
538 | } | ||
539 | } | ||
540 | out_brelse: | ||
541 | brelse(bh); | ||
542 | out_ok: | ||
543 | error = 0; | ||
544 | out_fail: | ||
545 | if (dibh) | ||
546 | brelse(dibh); | ||
547 | bmap_unlock(inode, create); | ||
548 | return error; | ||
549 | } | 642 | } |
550 | 643 | ||
644 | /* | ||
645 | * Deprecated: do not use in new code | ||
646 | */ | ||
551 | int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen) | 647 | int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen) |
552 | { | 648 | { |
553 | struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 }; | 649 | struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 }; |
@@ -558,7 +654,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi | |||
558 | BUG_ON(!dblock); | 654 | BUG_ON(!dblock); |
559 | BUG_ON(!new); | 655 | BUG_ON(!new); |
560 | 656 | ||
561 | bh.b_size = 1 << (inode->i_blkbits + 5); | 657 | bh.b_size = 1 << (inode->i_blkbits + (create ? 0 : 5)); |
562 | ret = gfs2_block_map(inode, lblock, &bh, create); | 658 | ret = gfs2_block_map(inode, lblock, &bh, create); |
563 | *extlen = bh.b_size >> inode->i_blkbits; | 659 | *extlen = bh.b_size >> inode->i_blkbits; |
564 | *dblock = bh.b_blocknr; | 660 | *dblock = bh.b_blocknr; |
@@ -621,7 +717,7 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
621 | if (error) | 717 | if (error) |
622 | goto out; | 718 | goto out; |
623 | 719 | ||
624 | if (height < ip->i_di.di_height - 1) | 720 | if (height < ip->i_height - 1) |
625 | for (; top < bottom; top++, first = 0) { | 721 | for (; top < bottom; top++, first = 0) { |
626 | if (!*top) | 722 | if (!*top) |
627 | continue; | 723 | continue; |
@@ -679,7 +775,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
679 | sm->sm_first = 0; | 775 | sm->sm_first = 0; |
680 | } | 776 | } |
681 | 777 | ||
682 | metadata = (height != ip->i_di.di_height - 1); | 778 | metadata = (height != ip->i_height - 1); |
683 | if (metadata) | 779 | if (metadata) |
684 | revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs; | 780 | revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs; |
685 | 781 | ||
@@ -713,7 +809,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
713 | else | 809 | else |
714 | goto out; /* Nothing to do */ | 810 | goto out; /* Nothing to do */ |
715 | 811 | ||
716 | gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0); | 812 | gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE); |
717 | 813 | ||
718 | for (x = 0; x < rlist.rl_rgrps; x++) { | 814 | for (x = 0; x < rlist.rl_rgrps; x++) { |
719 | struct gfs2_rgrpd *rgd; | 815 | struct gfs2_rgrpd *rgd; |
@@ -760,10 +856,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
760 | } | 856 | } |
761 | 857 | ||
762 | *p = 0; | 858 | *p = 0; |
763 | if (!ip->i_di.di_blocks) | 859 | gfs2_add_inode_blocks(&ip->i_inode, -1); |
764 | gfs2_consist_inode(ip); | ||
765 | ip->i_di.di_blocks--; | ||
766 | gfs2_set_inode_blocks(&ip->i_inode); | ||
767 | } | 860 | } |
768 | if (bstart) { | 861 | if (bstart) { |
769 | if (metadata) | 862 | if (metadata) |
@@ -804,19 +897,16 @@ static int do_grow(struct gfs2_inode *ip, u64 size) | |||
804 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 897 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
805 | struct gfs2_alloc *al; | 898 | struct gfs2_alloc *al; |
806 | struct buffer_head *dibh; | 899 | struct buffer_head *dibh; |
807 | unsigned int h; | ||
808 | int error; | 900 | int error; |
809 | 901 | ||
810 | al = gfs2_alloc_get(ip); | 902 | al = gfs2_alloc_get(ip); |
903 | if (!al) | ||
904 | return -ENOMEM; | ||
811 | 905 | ||
812 | error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 906 | error = gfs2_quota_lock_check(ip); |
813 | if (error) | 907 | if (error) |
814 | goto out; | 908 | goto out; |
815 | 909 | ||
816 | error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid); | ||
817 | if (error) | ||
818 | goto out_gunlock_q; | ||
819 | |||
820 | al->al_requested = sdp->sd_max_height + RES_DATA; | 910 | al->al_requested = sdp->sd_max_height + RES_DATA; |
821 | 911 | ||
822 | error = gfs2_inplace_reserve(ip); | 912 | error = gfs2_inplace_reserve(ip); |
@@ -829,34 +919,25 @@ static int do_grow(struct gfs2_inode *ip, u64 size) | |||
829 | if (error) | 919 | if (error) |
830 | goto out_ipres; | 920 | goto out_ipres; |
831 | 921 | ||
922 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
923 | if (error) | ||
924 | goto out_end_trans; | ||
925 | |||
832 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { | 926 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { |
833 | if (gfs2_is_stuffed(ip)) { | 927 | if (gfs2_is_stuffed(ip)) { |
834 | error = gfs2_unstuff_dinode(ip, NULL); | 928 | error = gfs2_unstuff_dinode(ip, NULL); |
835 | if (error) | 929 | if (error) |
836 | goto out_end_trans; | 930 | goto out_brelse; |
837 | } | ||
838 | |||
839 | h = calc_tree_height(ip, size); | ||
840 | if (ip->i_di.di_height < h) { | ||
841 | down_write(&ip->i_rw_mutex); | ||
842 | error = build_height(&ip->i_inode, h); | ||
843 | up_write(&ip->i_rw_mutex); | ||
844 | if (error) | ||
845 | goto out_end_trans; | ||
846 | } | 931 | } |
847 | } | 932 | } |
848 | 933 | ||
849 | ip->i_di.di_size = size; | 934 | ip->i_di.di_size = size; |
850 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | 935 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
851 | |||
852 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
853 | if (error) | ||
854 | goto out_end_trans; | ||
855 | |||
856 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 936 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
857 | gfs2_dinode_out(ip, dibh->b_data); | 937 | gfs2_dinode_out(ip, dibh->b_data); |
858 | brelse(dibh); | ||
859 | 938 | ||
939 | out_brelse: | ||
940 | brelse(dibh); | ||
860 | out_end_trans: | 941 | out_end_trans: |
861 | gfs2_trans_end(sdp); | 942 | gfs2_trans_end(sdp); |
862 | out_ipres: | 943 | out_ipres: |
@@ -986,7 +1067,8 @@ out: | |||
986 | 1067 | ||
987 | static int trunc_dealloc(struct gfs2_inode *ip, u64 size) | 1068 | static int trunc_dealloc(struct gfs2_inode *ip, u64 size) |
988 | { | 1069 | { |
989 | unsigned int height = ip->i_di.di_height; | 1070 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1071 | unsigned int height = ip->i_height; | ||
990 | u64 lblock; | 1072 | u64 lblock; |
991 | struct metapath mp; | 1073 | struct metapath mp; |
992 | int error; | 1074 | int error; |
@@ -994,10 +1076,11 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size) | |||
994 | if (!size) | 1076 | if (!size) |
995 | lblock = 0; | 1077 | lblock = 0; |
996 | else | 1078 | else |
997 | lblock = (size - 1) >> GFS2_SB(&ip->i_inode)->sd_sb.sb_bsize_shift; | 1079 | lblock = (size - 1) >> sdp->sd_sb.sb_bsize_shift; |
998 | 1080 | ||
999 | find_metapath(ip, lblock, &mp); | 1081 | find_metapath(sdp, lblock, &mp, ip->i_height); |
1000 | gfs2_alloc_get(ip); | 1082 | if (!gfs2_alloc_get(ip)) |
1083 | return -ENOMEM; | ||
1001 | 1084 | ||
1002 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 1085 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); |
1003 | if (error) | 1086 | if (error) |
@@ -1037,10 +1120,8 @@ static int trunc_end(struct gfs2_inode *ip) | |||
1037 | goto out; | 1120 | goto out; |
1038 | 1121 | ||
1039 | if (!ip->i_di.di_size) { | 1122 | if (!ip->i_di.di_size) { |
1040 | ip->i_di.di_height = 0; | 1123 | ip->i_height = 0; |
1041 | ip->i_di.di_goal_meta = | 1124 | ip->i_goal = ip->i_no_addr; |
1042 | ip->i_di.di_goal_data = | ||
1043 | ip->i_no_addr; | ||
1044 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); | 1125 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); |
1045 | } | 1126 | } |
1046 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | 1127 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
@@ -1197,10 +1278,9 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
1197 | unsigned int len, int *alloc_required) | 1278 | unsigned int len, int *alloc_required) |
1198 | { | 1279 | { |
1199 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1280 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1200 | u64 lblock, lblock_stop, dblock; | 1281 | struct buffer_head bh; |
1201 | u32 extlen; | 1282 | unsigned int shift; |
1202 | int new = 0; | 1283 | u64 lblock, lblock_stop, size; |
1203 | int error = 0; | ||
1204 | 1284 | ||
1205 | *alloc_required = 0; | 1285 | *alloc_required = 0; |
1206 | 1286 | ||
@@ -1214,6 +1294,8 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
1214 | return 0; | 1294 | return 0; |
1215 | } | 1295 | } |
1216 | 1296 | ||
1297 | *alloc_required = 1; | ||
1298 | shift = sdp->sd_sb.sb_bsize_shift; | ||
1217 | if (gfs2_is_dir(ip)) { | 1299 | if (gfs2_is_dir(ip)) { |
1218 | unsigned int bsize = sdp->sd_jbsize; | 1300 | unsigned int bsize = sdp->sd_jbsize; |
1219 | lblock = offset; | 1301 | lblock = offset; |
@@ -1221,27 +1303,25 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
1221 | lblock_stop = offset + len + bsize - 1; | 1303 | lblock_stop = offset + len + bsize - 1; |
1222 | do_div(lblock_stop, bsize); | 1304 | do_div(lblock_stop, bsize); |
1223 | } else { | 1305 | } else { |
1224 | unsigned int shift = sdp->sd_sb.sb_bsize_shift; | ||
1225 | u64 end_of_file = (ip->i_di.di_size + sdp->sd_sb.sb_bsize - 1) >> shift; | 1306 | u64 end_of_file = (ip->i_di.di_size + sdp->sd_sb.sb_bsize - 1) >> shift; |
1226 | lblock = offset >> shift; | 1307 | lblock = offset >> shift; |
1227 | lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; | 1308 | lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; |
1228 | if (lblock_stop > end_of_file) { | 1309 | if (lblock_stop > end_of_file) |
1229 | *alloc_required = 1; | ||
1230 | return 0; | 1310 | return 0; |
1231 | } | ||
1232 | } | 1311 | } |
1233 | 1312 | ||
1234 | for (; lblock < lblock_stop; lblock += extlen) { | 1313 | size = (lblock_stop - lblock) << shift; |
1235 | error = gfs2_extent_map(&ip->i_inode, lblock, &new, &dblock, &extlen); | 1314 | do { |
1236 | if (error) | 1315 | bh.b_state = 0; |
1237 | return error; | 1316 | bh.b_size = size; |
1238 | 1317 | gfs2_block_map(&ip->i_inode, lblock, &bh, 0); | |
1239 | if (!dblock) { | 1318 | if (!buffer_mapped(&bh)) |
1240 | *alloc_required = 1; | ||
1241 | return 0; | 1319 | return 0; |
1242 | } | 1320 | size -= bh.b_size; |
1243 | } | 1321 | lblock += (bh.b_size >> ip->i_inode.i_blkbits); |
1322 | } while(size > 0); | ||
1244 | 1323 | ||
1324 | *alloc_required = 0; | ||
1245 | return 0; | 1325 | return 0; |
1246 | } | 1326 | } |
1247 | 1327 | ||