diff options
-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; |