aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-03-09 19:26:50 -0500
committerMark Fasheh <mark.fasheh@oracle.com>2007-04-26 18:02:45 -0400
commit4f902c37727bbedbc0508a1477874c58ddcc9af8 (patch)
tree841b35387cfea5d2518c258c4de6ef868948369b
parent49cb8d2d496ce06869ccca2ab368ed6b0b5b979d (diff)
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>
-rw-r--r--fs/ocfs2/aops.c3
-rw-r--r--fs/ocfs2/extent_map.c107
-rw-r--r--fs/ocfs2/extent_map.h2
-rw-r--r--fs/ocfs2/journal.c6
-rw-r--r--fs/ocfs2/namei.c3
5 files changed, 109 insertions, 12 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index eb67c902b002..ff71e0b430cd 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -439,8 +439,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
439 struct buffer_head *bh_result, int create) 439 struct buffer_head *bh_result, int create)
440{ 440{
441 int ret; 441 int ret;
442 u64 p_blkno, inode_blocks; 442 u64 p_blkno, inode_blocks, contig_blocks;
443 int contig_blocks;
444 unsigned int ext_flags; 443 unsigned int ext_flags;
445 unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; 444 unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
446 unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; 445 unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index eef6c1887708..f35e04f27f32 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -39,6 +39,97 @@
39#include "buffer_head_io.h" 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 */
45static 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 */
72static 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
114no_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;
127out:
128 brelse(next_eb_bh);
129 return ret;
130}
131
132/*
42 * Return the index of the extent record which contains cluster #v_cluster. 133 * Return the index of the extent record which contains cluster #v_cluster.
43 * -1 is returned if it was not found. 134 * -1 is returned if it was not found.
44 * 135 *
@@ -117,11 +208,19 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
117 if (i == -1) { 208 if (i == -1) {
118 /* 209 /*
119 * A hole was found. Return some canned values that 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 *p_cluster = 0; 214 *p_cluster = 0;
123 if (num_clusters) 215 if (num_clusters) {
124 *num_clusters = 1; 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 } else { 224 } else {
126 rec = &el->l_recs[i]; 225 rec = &el->l_recs[i];
127 226
@@ -162,7 +261,7 @@ out:
162 * all while the map is in the process of being updated. 261 * all while the map is in the process of being updated.
163 */ 262 */
164int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, 263int 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 int ret; 266 int ret;
168 int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); 267 int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
diff --git a/fs/ocfs2/extent_map.h b/fs/ocfs2/extent_map.h
index 0031c59c347f..1d745e174afc 100644
--- a/fs/ocfs2/extent_map.h
+++ b/fs/ocfs2/extent_map.h
@@ -28,6 +28,6 @@
28int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, u32 *p_cluster, 28int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, u32 *p_cluster,
29 u32 *num_clusters, unsigned int *extent_flags); 29 u32 *num_clusters, unsigned int *extent_flags);
30int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, 30int 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#endif /* _EXTENT_MAP_H */ 33#endif /* _EXTENT_MAP_H */
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index db77e0996bb7..12d2340eee29 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -649,9 +649,9 @@ bail:
649static int ocfs2_force_read_journal(struct inode *inode) 649static int ocfs2_force_read_journal(struct inode *inode)
650{ 650{
651 int status = 0; 651 int status = 0;
652 int i, p_blocks; 652 int i;
653 u64 v_blkno, p_blkno; 653 u64 v_blkno, p_blkno, p_blocks;
654#define CONCURRENT_JOURNAL_FILL 32 654#define CONCURRENT_JOURNAL_FILL 32ULL
655 struct buffer_head *bhs[CONCURRENT_JOURNAL_FILL]; 655 struct buffer_head *bhs[CONCURRENT_JOURNAL_FILL];
656 656
657 mlog_entry_void(); 657 mlog_entry_void();
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 395859edb51f..9bdbe4ae92f8 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1483,8 +1483,7 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
1483 struct buffer_head **bhs = NULL; 1483 struct buffer_head **bhs = NULL;
1484 const char *c; 1484 const char *c;
1485 struct super_block *sb = osb->sb; 1485 struct super_block *sb = osb->sb;
1486 u64 p_blkno; 1486 u64 p_blkno, p_blocks;
1487 int p_blocks;
1488 int virtual, blocks, status, i, bytes_left; 1487 int virtual, blocks, status, i, bytes_left;
1489 1488
1490 bytes_left = i_size_read(inode) + 1; 1489 bytes_left = i_size_read(inode) + 1;