diff options
author | Mark Fasheh <mark.fasheh@oracle.com> | 2007-03-09 19:21:46 -0500 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2007-04-26 18:02:41 -0400 |
commit | 49cb8d2d496ce06869ccca2ab368ed6b0b5b979d (patch) | |
tree | 7aded7178e87dc26eb2ceafb169d7e68a8ee5ded /fs/ocfs2 | |
parent | e48edee2d8eab812f31f0ff62c6ba635ca2e1e21 (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.c | 11 | ||||
-rw-r--r-- | fs/ocfs2/aops.c | 21 | ||||
-rw-r--r-- | fs/ocfs2/dir.c | 2 | ||||
-rw-r--r-- | fs/ocfs2/extent_map.c | 14 | ||||
-rw-r--r-- | fs/ocfs2/extent_map.h | 4 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 6 | ||||
-rw-r--r-- | fs/ocfs2/inode.c | 3 | ||||
-rw-r--r-- | fs/ocfs2/journal.c | 2 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 3 | ||||
-rw-r--r-- | fs/ocfs2/slot_map.c | 2 |
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 | ||
72 | int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, | 72 | int 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 | |||
147 | out: | 154 | out: |
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 | */ |
157 | int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, | 164 | int 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 | ||
28 | int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, u32 *p_cluster, | 28 | int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, u32 *p_cluster, |
29 | u32 *num_clusters); | 29 | u32 *num_clusters, unsigned int *extent_flags); |
30 | int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, | 30 | int 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; |