Commit 4f902c37727bbedbc0508a1477874c58ddcc9af8

Authored by Mark Fasheh
1 parent 49cb8d2d49

ocfs2: Fix extent lookup to return true size of holes

Initially, we had wired things to return a size '1' of holes. Cook up a
small amount of code to find the next extent and calculate the number of
clusters between the virtual offset and the next allocated extent.

Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>

Showing 5 changed files with 109 additions and 12 deletions Side-by-side Diff

... ... @@ -439,8 +439,7 @@
439 439 struct buffer_head *bh_result, int create)
440 440 {
441 441 int ret;
442   - u64 p_blkno, inode_blocks;
443   - int contig_blocks;
  442 + u64 p_blkno, inode_blocks, contig_blocks;
444 443 unsigned int ext_flags;
445 444 unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
446 445 unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
fs/ocfs2/extent_map.c
... ... @@ -39,6 +39,97 @@
39 39 #include "buffer_head_io.h"
40 40  
41 41 /*
  42 + * Return the 1st index within el which contains an extent start
  43 + * larger than v_cluster.
  44 + */
  45 +static int ocfs2_search_for_hole_index(struct ocfs2_extent_list *el,
  46 + u32 v_cluster)
  47 +{
  48 + int i;
  49 + struct ocfs2_extent_rec *rec;
  50 +
  51 + for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
  52 + rec = &el->l_recs[i];
  53 +
  54 + if (v_cluster < le32_to_cpu(rec->e_cpos))
  55 + break;
  56 + }
  57 +
  58 + return i;
  59 +}
  60 +
  61 +/*
  62 + * Figure out the size of a hole which starts at v_cluster within the given
  63 + * extent list.
  64 + *
  65 + * If there is no more allocation past v_cluster, we return the maximum
  66 + * cluster size minus v_cluster.
  67 + *
  68 + * If we have in-inode extents, then el points to the dinode list and
  69 + * eb_bh is NULL. Otherwise, eb_bh should point to the extent block
  70 + * containing el.
  71 + */
  72 +static int ocfs2_figure_hole_clusters(struct inode *inode,
  73 + struct ocfs2_extent_list *el,
  74 + struct buffer_head *eb_bh,
  75 + u32 v_cluster,
  76 + u32 *num_clusters)
  77 +{
  78 + int ret, i;
  79 + struct buffer_head *next_eb_bh = NULL;
  80 + struct ocfs2_extent_block *eb, *next_eb;
  81 +
  82 + i = ocfs2_search_for_hole_index(el, v_cluster);
  83 +
  84 + if (i == le16_to_cpu(el->l_next_free_rec) && eb_bh) {
  85 + eb = (struct ocfs2_extent_block *)eb_bh->b_data;
  86 +
  87 + /*
  88 + * Check the next leaf for any extents.
  89 + */
  90 +
  91 + if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL)
  92 + goto no_more_extents;
  93 +
  94 + ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
  95 + le64_to_cpu(eb->h_next_leaf_blk),
  96 + &next_eb_bh, OCFS2_BH_CACHED, inode);
  97 + if (ret) {
  98 + mlog_errno(ret);
  99 + goto out;
  100 + }
  101 + next_eb = (struct ocfs2_extent_block *)next_eb_bh->b_data;
  102 +
  103 + if (!OCFS2_IS_VALID_EXTENT_BLOCK(next_eb)) {
  104 + ret = -EROFS;
  105 + OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, next_eb);
  106 + goto out;
  107 + }
  108 +
  109 + el = &next_eb->h_list;
  110 +
  111 + i = ocfs2_search_for_hole_index(el, v_cluster);
  112 + }
  113 +
  114 +no_more_extents:
  115 + if (i == le16_to_cpu(el->l_next_free_rec)) {
  116 + /*
  117 + * We're at the end of our existing allocation. Just
  118 + * return the maximum number of clusters we could
  119 + * possibly allocate.
  120 + */
  121 + *num_clusters = UINT_MAX - v_cluster;
  122 + } else {
  123 + *num_clusters = le32_to_cpu(el->l_recs[i].e_cpos) - v_cluster;
  124 + }
  125 +
  126 + ret = 0;
  127 +out:
  128 + brelse(next_eb_bh);
  129 + return ret;
  130 +}
  131 +
  132 +/*
42 133 * Return the index of the extent record which contains cluster #v_cluster.
43 134 * -1 is returned if it was not found.
44 135 *
45 136  
... ... @@ -117,11 +208,19 @@
117 208 if (i == -1) {
118 209 /*
119 210 * A hole was found. Return some canned values that
120   - * callers can key on.
  211 + * callers can key on. If asked for, num_clusters will
  212 + * be populated with the size of the hole.
121 213 */
122 214 *p_cluster = 0;
123   - if (num_clusters)
124   - *num_clusters = 1;
  215 + if (num_clusters) {
  216 + ret = ocfs2_figure_hole_clusters(inode, el, eb_bh,
  217 + v_cluster,
  218 + num_clusters);
  219 + if (ret) {
  220 + mlog_errno(ret);
  221 + goto out;
  222 + }
  223 + }
125 224 } else {
126 225 rec = &el->l_recs[i];
127 226  
... ... @@ -162,7 +261,7 @@
162 261 * all while the map is in the process of being updated.
163 262 */
164 263 int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
165   - int *ret_count, unsigned int *extent_flags)
  264 + u64 *ret_count, unsigned int *extent_flags)
166 265 {
167 266 int ret;
168 267 int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
fs/ocfs2/extent_map.h
... ... @@ -28,7 +28,7 @@
28 28 int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, u32 *p_cluster,
29 29 u32 *num_clusters, unsigned int *extent_flags);
30 30 int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
31   - int *ret_count, unsigned int *extent_flags);
  31 + u64 *ret_count, unsigned int *extent_flags);
32 32  
33 33 #endif /* _EXTENT_MAP_H */
... ... @@ -649,9 +649,9 @@
649 649 static int ocfs2_force_read_journal(struct inode *inode)
650 650 {
651 651 int status = 0;
652   - int i, p_blocks;
653   - u64 v_blkno, p_blkno;
654   -#define CONCURRENT_JOURNAL_FILL 32
  652 + int i;
  653 + u64 v_blkno, p_blkno, p_blocks;
  654 +#define CONCURRENT_JOURNAL_FILL 32ULL
655 655 struct buffer_head *bhs[CONCURRENT_JOURNAL_FILL];
656 656  
657 657 mlog_entry_void();
... ... @@ -1483,8 +1483,7 @@
1483 1483 struct buffer_head **bhs = NULL;
1484 1484 const char *c;
1485 1485 struct super_block *sb = osb->sb;
1486   - u64 p_blkno;
1487   - int p_blocks;
  1486 + u64 p_blkno, p_blocks;
1488 1487 int virtual, blocks, status, i, bytes_left;
1489 1488  
1490 1489 bytes_left = i_size_read(inode) + 1;