aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2008-02-08 08:18:11 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2008-03-31 05:40:53 -0400
commit30cbf189cd2a1ba13ff3c8c8ee2103dbdb18578a (patch)
tree5d3a3e54850f021abf3ccf43879b692025610cb1 /fs
parentc85a665f064863cc8a2fe88e5f1eb4def5446e90 (diff)
[GFS2] Add a function to interate over an extent
This adds a function (currently the only use is during mapping of already allocated blocks, but watch this space) which iterates over a number of pointers in a block and returns the extent length. If the initial pointer is 0 (i.e. unallocated) it will return the number of unallocated blocks in the extent. If the initial pointer is allocated, then it returns the number of contiguously allocated blocks in the extent. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/gfs2/bmap.c68
1 files changed, 52 insertions, 16 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 7f72564e0597..6780aa5841b2 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -422,6 +422,42 @@ static void release_metapath(struct metapath *mp)
422 brelse(mp->mp_bh[i]); 422 brelse(mp->mp_bh[i]);
423} 423}
424 424
425/**
426 * gfs2_extent_length - Returns length of an extent of blocks
427 * @start: Start of the buffer
428 * @len: Length of the buffer in bytes
429 * @ptr: Current position in the buffer
430 * @limit: Max extent length to return (0 = unlimited)
431 * @eob: Set to 1 if we hit "end of block"
432 *
433 * If the first block is zero (unallocated) it will return the number of
434 * unallocated blocks in the extent, otherwise it will return the number
435 * of contiguous blocks in the extent.
436 *
437 * Returns: The length of the extent (minimum of one block)
438 */
439
440static inline unsigned int gfs2_extent_length(void *start, unsigned int len, __be64 *ptr, unsigned limit, int *eob)
441{
442 const __be64 *end = (start + len);
443 const __be64 *first = ptr;
444 u64 d = be64_to_cpu(*ptr);
445
446 *eob = 0;
447 do {
448 ptr++;
449 if (ptr >= end)
450 break;
451 if (limit && --limit == 0)
452 break;
453 if (d)
454 d++;
455 } while(be64_to_cpu(*ptr) == d);
456 if (ptr >= end)
457 *eob = 1;
458 return (ptr - first);
459}
460
425static inline void bmap_lock(struct inode *inode, int create) 461static inline void bmap_lock(struct inode *inode, int create)
426{ 462{
427 struct gfs2_inode *ip = GFS2_I(inode); 463 struct gfs2_inode *ip = GFS2_I(inode);
@@ -499,26 +535,26 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
499 goto out_fail; 535 goto out_fail;
500 boundary = error; 536 boundary = error;
501 537
538 if (new) {
539 map_bh(bh_map, inode->i_sb, dblock);
540 if (boundary)
541 set_buffer_boundary(bh_map);
542 gfs2_trans_add_bh(ip->i_gl, mp.mp_bh[0], 1);
543 gfs2_dinode_out(ip, mp.mp_bh[0]->b_data);
544 set_buffer_new(bh_map);
545 goto out_ok;
546 }
547
502 if (dblock) { 548 if (dblock) {
549 unsigned int len;
550 struct buffer_head *bh = mp.mp_bh[ip->i_height - 1];
551 __be64 *ptr = metapointer(&boundary, ip->i_height - 1, &mp);
503 map_bh(bh_map, inode->i_sb, dblock); 552 map_bh(bh_map, inode->i_sb, dblock);
553 len = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen,
554 &boundary);
555 bh_map->b_size = (len << inode->i_blkbits);
504 if (boundary) 556 if (boundary)
505 set_buffer_boundary(bh_map); 557 set_buffer_boundary(bh_map);
506 if (new) {
507 gfs2_trans_add_bh(ip->i_gl, mp.mp_bh[0], 1);
508 gfs2_dinode_out(ip, mp.mp_bh[0]->b_data);
509 set_buffer_new(bh_map);
510 goto out_ok;
511 }
512 while(--maxlen && !buffer_boundary(bh_map)) {
513 u64 eblock;
514 mp.mp_list[ip->i_height - 1]++;
515 boundary = lookup_block(ip, ip->i_height - 1, &mp, 0, &new, &eblock);
516 if (eblock != ++dblock)
517 break;
518 bh_map->b_size += (1 << inode->i_blkbits);
519 if (boundary)
520 set_buffer_boundary(bh_map);
521 }
522 } 558 }
523out_ok: 559out_ok:
524 error = 0; 560 error = 0;