aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-03-09 19:21:46 -0500
committerMark Fasheh <mark.fasheh@oracle.com>2007-04-26 18:02:41 -0400
commit49cb8d2d496ce06869ccca2ab368ed6b0b5b979d (patch)
tree7aded7178e87dc26eb2ceafb169d7e68a8ee5ded /fs/ocfs2
parente48edee2d8eab812f31f0ff62c6ba635ca2e1e21 (diff)
ocfs2: Read from an unwritten extent returns zeros
Return an optional extent flags field from our lookup functions and wire up callers to treat unwritten regions as holes for the purpose of returning zeros to the user. Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/alloc.c11
-rw-r--r--fs/ocfs2/aops.c21
-rw-r--r--fs/ocfs2/dir.c2
-rw-r--r--fs/ocfs2/extent_map.c14
-rw-r--r--fs/ocfs2/extent_map.h4
-rw-r--r--fs/ocfs2/file.c6
-rw-r--r--fs/ocfs2/inode.c3
-rw-r--r--fs/ocfs2/journal.c2
-rw-r--r--fs/ocfs2/namei.c3
-rw-r--r--fs/ocfs2/slot_map.c2
10 files changed, 45 insertions, 23 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 0eab0d328289..412a2888a3ed 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -3487,6 +3487,7 @@ static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page *
3487{ 3487{
3488 int i, numpages = 0, ret = 0; 3488 int i, numpages = 0, ret = 0;
3489 unsigned int csize = OCFS2_SB(inode->i_sb)->s_clustersize; 3489 unsigned int csize = OCFS2_SB(inode->i_sb)->s_clustersize;
3490 unsigned int ext_flags;
3490 struct super_block *sb = inode->i_sb; 3491 struct super_block *sb = inode->i_sb;
3491 struct address_space *mapping = inode->i_mapping; 3492 struct address_space *mapping = inode->i_mapping;
3492 unsigned long index; 3493 unsigned long index;
@@ -3499,7 +3500,7 @@ static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page *
3499 goto out; 3500 goto out;
3500 3501
3501 ret = ocfs2_extent_map_get_blocks(inode, isize >> sb->s_blocksize_bits, 3502 ret = ocfs2_extent_map_get_blocks(inode, isize >> sb->s_blocksize_bits,
3502 phys, NULL); 3503 phys, NULL, &ext_flags);
3503 if (ret) { 3504 if (ret) {
3504 mlog_errno(ret); 3505 mlog_errno(ret);
3505 goto out; 3506 goto out;
@@ -3509,6 +3510,11 @@ static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page *
3509 if (*phys == 0) 3510 if (*phys == 0)
3510 goto out; 3511 goto out;
3511 3512
3513 /* Tail is marked as unwritten, we can count on write to zero
3514 * in that case. */
3515 if (ext_flags & OCFS2_EXT_UNWRITTEN)
3516 goto out;
3517
3512 next_cluster_bytes = ocfs2_align_bytes_to_clusters(inode->i_sb, isize); 3518 next_cluster_bytes = ocfs2_align_bytes_to_clusters(inode->i_sb, isize);
3513 index = isize >> PAGE_CACHE_SHIFT; 3519 index = isize >> PAGE_CACHE_SHIFT;
3514 do { 3520 do {
@@ -3579,9 +3585,6 @@ int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle,
3579 goto out; 3585 goto out;
3580 } 3586 }
3581 3587
3582 /*
3583 * Truncate on an i_size boundary - nothing more to do.
3584 */
3585 if (numpages == 0) 3588 if (numpages == 0)
3586 goto out; 3589 goto out;
3587 3590
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 014f4f52809c..eb67c902b002 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -137,6 +137,7 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
137 struct buffer_head *bh_result, int create) 137 struct buffer_head *bh_result, int create)
138{ 138{
139 int err = 0; 139 int err = 0;
140 unsigned int ext_flags;
140 u64 p_blkno, past_eof; 141 u64 p_blkno, past_eof;
141 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 142 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
142 143
@@ -153,7 +154,8 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
153 goto bail; 154 goto bail;
154 } 155 }
155 156
156 err = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, NULL); 157 err = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, NULL,
158 &ext_flags);
157 if (err) { 159 if (err) {
158 mlog(ML_ERROR, "Error %d from get_blocks(0x%p, %llu, 1, " 160 mlog(ML_ERROR, "Error %d from get_blocks(0x%p, %llu, 1, "
159 "%llu, NULL)\n", err, inode, (unsigned long long)iblock, 161 "%llu, NULL)\n", err, inode, (unsigned long long)iblock,
@@ -171,7 +173,8 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
171 "ino %lu, iblock %llu\n", inode->i_ino, 173 "ino %lu, iblock %llu\n", inode->i_ino,
172 (unsigned long long)iblock); 174 (unsigned long long)iblock);
173 175
174 if (p_blkno) 176 /* Treat the unwritten extent as a hole for zeroing purposes. */
177 if (p_blkno && !(ext_flags & OCFS2_EXT_UNWRITTEN))
175 map_bh(bh_result, inode->i_sb, p_blkno); 178 map_bh(bh_result, inode->i_sb, p_blkno);
176 179
177 if (!ocfs2_sparse_alloc(osb)) { 180 if (!ocfs2_sparse_alloc(osb)) {
@@ -396,7 +399,7 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block)
396 down_read(&OCFS2_I(inode)->ip_alloc_sem); 399 down_read(&OCFS2_I(inode)->ip_alloc_sem);
397 } 400 }
398 401
399 err = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL); 402 err = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL, NULL);
400 403
401 if (!INODE_JOURNAL(inode)) { 404 if (!INODE_JOURNAL(inode)) {
402 up_read(&OCFS2_I(inode)->ip_alloc_sem); 405 up_read(&OCFS2_I(inode)->ip_alloc_sem);
@@ -438,6 +441,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
438 int ret; 441 int ret;
439 u64 p_blkno, inode_blocks; 442 u64 p_blkno, inode_blocks;
440 int contig_blocks; 443 int contig_blocks;
444 unsigned int ext_flags;
441 unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; 445 unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
442 unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; 446 unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
443 447
@@ -458,7 +462,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
458 /* This figures out the size of the next contiguous block, and 462 /* This figures out the size of the next contiguous block, and
459 * our logical offset */ 463 * our logical offset */
460 ret = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, 464 ret = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno,
461 &contig_blocks); 465 &contig_blocks, &ext_flags);
462 if (ret) { 466 if (ret) {
463 mlog(ML_ERROR, "get_blocks() failed iblock=%llu\n", 467 mlog(ML_ERROR, "get_blocks() failed iblock=%llu\n",
464 (unsigned long long)iblock); 468 (unsigned long long)iblock);
@@ -478,8 +482,10 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
478 /* 482 /*
479 * get_more_blocks() expects us to describe a hole by clearing 483 * get_more_blocks() expects us to describe a hole by clearing
480 * the mapped bit on bh_result(). 484 * the mapped bit on bh_result().
485 *
486 * Consider an unwritten extent as a hole.
481 */ 487 */
482 if (p_blkno) 488 if (p_blkno && !(ext_flags & OCFS2_EXT_UNWRITTEN))
483 map_bh(bh_result, inode->i_sb, p_blkno); 489 map_bh(bh_result, inode->i_sb, p_blkno);
484 else { 490 else {
485 /* 491 /*
@@ -1111,7 +1117,8 @@ static ssize_t ocfs2_write(struct file *file, u32 phys, handle_t *handle,
1111 } 1117 }
1112 } 1118 }
1113 1119
1114 ret = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, NULL); 1120 ret = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, NULL,
1121 NULL);
1115 if (ret < 0) { 1122 if (ret < 0) {
1116 1123
1117 /* 1124 /*
@@ -1215,7 +1222,7 @@ ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
1215 */ 1222 */
1216 down_write(&OCFS2_I(inode)->ip_alloc_sem); 1223 down_write(&OCFS2_I(inode)->ip_alloc_sem);
1217 1224
1218 ret = ocfs2_get_clusters(inode, wc.w_cpos, &phys, NULL); 1225 ret = ocfs2_get_clusters(inode, wc.w_cpos, &phys, NULL, NULL);
1219 if (ret) { 1226 if (ret) {
1220 mlog_errno(ret); 1227 mlog_errno(ret);
1221 goto out_meta; 1228 goto out_meta;
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index c91490670ffa..8d22e1e4a88d 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -379,7 +379,7 @@ int ocfs2_do_extend_dir(struct super_block *sb,
379 379
380 status = ocfs2_extent_map_get_blocks(dir, (dir->i_blocks >> 380 status = ocfs2_extent_map_get_blocks(dir, (dir->i_blocks >>
381 (sb->s_blocksize_bits - 9)), 381 (sb->s_blocksize_bits - 9)),
382 &p_blkno, NULL); 382 &p_blkno, NULL, NULL);
383 if (status < 0) { 383 if (status < 0) {
384 mlog_errno(status); 384 mlog_errno(status);
385 goto bail; 385 goto bail;
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index ea0ce41d4193..eef6c1887708 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -70,9 +70,11 @@ static int ocfs2_search_extent_list(struct ocfs2_extent_list *el,
70} 70}
71 71
72int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, 72int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
73 u32 *p_cluster, u32 *num_clusters) 73 u32 *p_cluster, u32 *num_clusters,
74 unsigned int *extent_flags)
74{ 75{
75 int ret, i; 76 int ret, i;
77 unsigned int flags = 0;
76 struct buffer_head *di_bh = NULL; 78 struct buffer_head *di_bh = NULL;
77 struct buffer_head *eb_bh = NULL; 79 struct buffer_head *eb_bh = NULL;
78 struct ocfs2_dinode *di; 80 struct ocfs2_dinode *di;
@@ -142,8 +144,13 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
142 144
143 if (num_clusters) 145 if (num_clusters)
144 *num_clusters = ocfs2_rec_clusters(el, rec) - coff; 146 *num_clusters = ocfs2_rec_clusters(el, rec) - coff;
147
148 flags = rec->e_flags;
145 } 149 }
146 150
151 if (extent_flags)
152 *extent_flags = flags;
153
147out: 154out:
148 brelse(di_bh); 155 brelse(di_bh);
149 brelse(eb_bh); 156 brelse(eb_bh);
@@ -155,7 +162,7 @@ out:
155 * all while the map is in the process of being updated. 162 * all while the map is in the process of being updated.
156 */ 163 */
157int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, 164int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
158 int *ret_count) 165 int *ret_count, unsigned int *extent_flags)
159{ 166{
160 int ret; 167 int ret;
161 int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); 168 int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
@@ -164,7 +171,8 @@ int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
164 171
165 cpos = ocfs2_blocks_to_clusters(inode->i_sb, v_blkno); 172 cpos = ocfs2_blocks_to_clusters(inode->i_sb, v_blkno);
166 173
167 ret = ocfs2_get_clusters(inode, cpos, &p_cluster, &num_clusters); 174 ret = ocfs2_get_clusters(inode, cpos, &p_cluster, &num_clusters,
175 extent_flags);
168 if (ret) { 176 if (ret) {
169 mlog_errno(ret); 177 mlog_errno(ret);
170 goto out; 178 goto out;
diff --git a/fs/ocfs2/extent_map.h b/fs/ocfs2/extent_map.h
index 625d0ee5e04a..0031c59c347f 100644
--- a/fs/ocfs2/extent_map.h
+++ b/fs/ocfs2/extent_map.h
@@ -26,8 +26,8 @@
26#define _EXTENT_MAP_H 26#define _EXTENT_MAP_H
27 27
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); 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); 31 int *ret_count, unsigned int *extent_flags);
32 32
33#endif /* _EXTENT_MAP_H */ 33#endif /* _EXTENT_MAP_H */
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 36176018b4b4..f516619a3744 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1127,6 +1127,7 @@ static int ocfs2_check_range_for_holes(struct inode *inode, loff_t pos,
1127 size_t count) 1127 size_t count)
1128{ 1128{
1129 int ret = 0; 1129 int ret = 0;
1130 unsigned int extent_flags;
1130 u32 cpos, clusters, extent_len, phys_cpos; 1131 u32 cpos, clusters, extent_len, phys_cpos;
1131 struct super_block *sb = inode->i_sb; 1132 struct super_block *sb = inode->i_sb;
1132 1133
@@ -1134,13 +1135,14 @@ static int ocfs2_check_range_for_holes(struct inode *inode, loff_t pos,
1134 clusters = ocfs2_clusters_for_bytes(sb, pos + count) - cpos; 1135 clusters = ocfs2_clusters_for_bytes(sb, pos + count) - cpos;
1135 1136
1136 while (clusters) { 1137 while (clusters) {
1137 ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, &extent_len); 1138 ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, &extent_len,
1139 &extent_flags);
1138 if (ret < 0) { 1140 if (ret < 0) {
1139 mlog_errno(ret); 1141 mlog_errno(ret);
1140 goto out; 1142 goto out;
1141 } 1143 }
1142 1144
1143 if (phys_cpos == 0) { 1145 if (phys_cpos == 0 || (extent_flags & OCFS2_EXT_UNWRITTEN)) {
1144 ret = 1; 1146 ret = 1;
1145 break; 1147 break;
1146 } 1148 }
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 78c99b5050df..310049bf7f6b 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -1105,7 +1105,8 @@ struct buffer_head *ocfs2_bread(struct inode *inode,
1105 return NULL; 1105 return NULL;
1106 } 1106 }
1107 1107
1108 tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL); 1108 tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
1109 NULL);
1109 if (tmperr < 0) { 1110 if (tmperr < 0) {
1110 mlog_errno(tmperr); 1111 mlog_errno(tmperr);
1111 goto fail; 1112 goto fail;
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 2e2e04fe9738..db77e0996bb7 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -670,7 +670,7 @@ static int ocfs2_force_read_journal(struct inode *inode)
670 (inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9))) { 670 (inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9))) {
671 671
672 status = ocfs2_extent_map_get_blocks(inode, v_blkno, 672 status = ocfs2_extent_map_get_blocks(inode, v_blkno,
673 &p_blkno, &p_blocks); 673 &p_blkno, &p_blocks, NULL);
674 if (status < 0) { 674 if (status < 0) {
675 mlog_errno(status); 675 mlog_errno(status);
676 goto bail; 676 goto bail;
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 5755e0748256..395859edb51f 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1511,7 +1511,8 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
1511 goto bail; 1511 goto bail;
1512 } 1512 }
1513 1513
1514 status = ocfs2_extent_map_get_blocks(inode, 0, &p_blkno, &p_blocks); 1514 status = ocfs2_extent_map_get_blocks(inode, 0, &p_blkno, &p_blocks,
1515 NULL);
1515 if (status < 0) { 1516 if (status < 0) {
1516 mlog_errno(status); 1517 mlog_errno(status);
1517 goto bail; 1518 goto bail;
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c
index f4416e7330e1..d921a28329dc 100644
--- a/fs/ocfs2/slot_map.c
+++ b/fs/ocfs2/slot_map.c
@@ -197,7 +197,7 @@ int ocfs2_init_slot_info(struct ocfs2_super *osb)
197 goto bail; 197 goto bail;
198 } 198 }
199 199
200 status = ocfs2_extent_map_get_blocks(inode, 0ULL, &blkno, NULL); 200 status = ocfs2_extent_map_get_blocks(inode, 0ULL, &blkno, NULL, NULL);
201 if (status < 0) { 201 if (status < 0) {
202 mlog_errno(status); 202 mlog_errno(status);
203 goto bail; 203 goto bail;