Skip to content

Commit

Permalink
ocfs2: Read from an unwritten extent returns zeros
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Mark Fasheh committed Apr 26, 2007
1 parent e48edee commit 49cb8d2
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 23 deletions.
11 changes: 7 additions & 4 deletions fs/ocfs2/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3487,6 +3487,7 @@ static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page *
{
int i, numpages = 0, ret = 0;
unsigned int csize = OCFS2_SB(inode->i_sb)->s_clustersize;
unsigned int ext_flags;
struct super_block *sb = inode->i_sb;
struct address_space *mapping = inode->i_mapping;
unsigned long index;
Expand All @@ -3499,7 +3500,7 @@ static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page *
goto out;

ret = ocfs2_extent_map_get_blocks(inode, isize >> sb->s_blocksize_bits,
phys, NULL);
phys, NULL, &ext_flags);
if (ret) {
mlog_errno(ret);
goto out;
Expand All @@ -3509,6 +3510,11 @@ static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page *
if (*phys == 0)
goto out;

/* Tail is marked as unwritten, we can count on write to zero
* in that case. */
if (ext_flags & OCFS2_EXT_UNWRITTEN)
goto out;

next_cluster_bytes = ocfs2_align_bytes_to_clusters(inode->i_sb, isize);
index = isize >> PAGE_CACHE_SHIFT;
do {
Expand Down Expand Up @@ -3579,9 +3585,6 @@ int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle,
goto out;
}

/*
* Truncate on an i_size boundary - nothing more to do.
*/
if (numpages == 0)
goto out;

Expand Down
21 changes: 14 additions & 7 deletions fs/ocfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create)
{
int err = 0;
unsigned int ext_flags;
u64 p_blkno, past_eof;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);

Expand All @@ -153,7 +154,8 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
goto bail;
}

err = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, NULL);
err = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, NULL,
&ext_flags);
if (err) {
mlog(ML_ERROR, "Error %d from get_blocks(0x%p, %llu, 1, "
"%llu, NULL)\n", err, inode, (unsigned long long)iblock,
Expand All @@ -171,7 +173,8 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
"ino %lu, iblock %llu\n", inode->i_ino,
(unsigned long long)iblock);

if (p_blkno)
/* Treat the unwritten extent as a hole for zeroing purposes. */
if (p_blkno && !(ext_flags & OCFS2_EXT_UNWRITTEN))
map_bh(bh_result, inode->i_sb, p_blkno);

if (!ocfs2_sparse_alloc(osb)) {
Expand Down Expand Up @@ -396,7 +399,7 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block)
down_read(&OCFS2_I(inode)->ip_alloc_sem);
}

err = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL);
err = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL, NULL);

if (!INODE_JOURNAL(inode)) {
up_read(&OCFS2_I(inode)->ip_alloc_sem);
Expand Down Expand Up @@ -438,6 +441,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
int ret;
u64 p_blkno, inode_blocks;
int contig_blocks;
unsigned int ext_flags;
unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;

Expand All @@ -458,7 +462,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
/* This figures out the size of the next contiguous block, and
* our logical offset */
ret = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno,
&contig_blocks);
&contig_blocks, &ext_flags);
if (ret) {
mlog(ML_ERROR, "get_blocks() failed iblock=%llu\n",
(unsigned long long)iblock);
Expand All @@ -478,8 +482,10 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
/*
* get_more_blocks() expects us to describe a hole by clearing
* the mapped bit on bh_result().
*
* Consider an unwritten extent as a hole.
*/
if (p_blkno)
if (p_blkno && !(ext_flags & OCFS2_EXT_UNWRITTEN))
map_bh(bh_result, inode->i_sb, p_blkno);
else {
/*
Expand Down Expand Up @@ -1111,7 +1117,8 @@ static ssize_t ocfs2_write(struct file *file, u32 phys, handle_t *handle,
}
}

ret = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, NULL);
ret = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, NULL,
NULL);
if (ret < 0) {

/*
Expand Down Expand Up @@ -1215,7 +1222,7 @@ ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
*/
down_write(&OCFS2_I(inode)->ip_alloc_sem);

ret = ocfs2_get_clusters(inode, wc.w_cpos, &phys, NULL);
ret = ocfs2_get_clusters(inode, wc.w_cpos, &phys, NULL, NULL);
if (ret) {
mlog_errno(ret);
goto out_meta;
Expand Down
2 changes: 1 addition & 1 deletion fs/ocfs2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ int ocfs2_do_extend_dir(struct super_block *sb,

status = ocfs2_extent_map_get_blocks(dir, (dir->i_blocks >>
(sb->s_blocksize_bits - 9)),
&p_blkno, NULL);
&p_blkno, NULL, NULL);
if (status < 0) {
mlog_errno(status);
goto bail;
Expand Down
14 changes: 11 additions & 3 deletions fs/ocfs2/extent_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,11 @@ static int ocfs2_search_extent_list(struct ocfs2_extent_list *el,
}

int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
u32 *p_cluster, u32 *num_clusters)
u32 *p_cluster, u32 *num_clusters,
unsigned int *extent_flags)
{
int ret, i;
unsigned int flags = 0;
struct buffer_head *di_bh = NULL;
struct buffer_head *eb_bh = NULL;
struct ocfs2_dinode *di;
Expand Down Expand Up @@ -142,8 +144,13 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,

if (num_clusters)
*num_clusters = ocfs2_rec_clusters(el, rec) - coff;

flags = rec->e_flags;
}

if (extent_flags)
*extent_flags = flags;

out:
brelse(di_bh);
brelse(eb_bh);
Expand All @@ -155,7 +162,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
* all while the map is in the process of being updated.
*/
int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
int *ret_count)
int *ret_count, unsigned int *extent_flags)
{
int ret;
int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
Expand All @@ -164,7 +171,8 @@ int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,

cpos = ocfs2_blocks_to_clusters(inode->i_sb, v_blkno);

ret = ocfs2_get_clusters(inode, cpos, &p_cluster, &num_clusters);
ret = ocfs2_get_clusters(inode, cpos, &p_cluster, &num_clusters,
extent_flags);
if (ret) {
mlog_errno(ret);
goto out;
Expand Down
4 changes: 2 additions & 2 deletions fs/ocfs2/extent_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
#define _EXTENT_MAP_H

int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, u32 *p_cluster,
u32 *num_clusters);
u32 *num_clusters, unsigned int *extent_flags);
int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
int *ret_count);
int *ret_count, unsigned int *extent_flags);

#endif /* _EXTENT_MAP_H */
6 changes: 4 additions & 2 deletions fs/ocfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1127,20 +1127,22 @@ static int ocfs2_check_range_for_holes(struct inode *inode, loff_t pos,
size_t count)
{
int ret = 0;
unsigned int extent_flags;
u32 cpos, clusters, extent_len, phys_cpos;
struct super_block *sb = inode->i_sb;

cpos = pos >> OCFS2_SB(sb)->s_clustersize_bits;
clusters = ocfs2_clusters_for_bytes(sb, pos + count) - cpos;

while (clusters) {
ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, &extent_len);
ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, &extent_len,
&extent_flags);
if (ret < 0) {
mlog_errno(ret);
goto out;
}

if (phys_cpos == 0) {
if (phys_cpos == 0 || (extent_flags & OCFS2_EXT_UNWRITTEN)) {
ret = 1;
break;
}
Expand Down
3 changes: 2 additions & 1 deletion fs/ocfs2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1105,7 +1105,8 @@ struct buffer_head *ocfs2_bread(struct inode *inode,
return NULL;
}

tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL);
tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
NULL);
if (tmperr < 0) {
mlog_errno(tmperr);
goto fail;
Expand Down
2 changes: 1 addition & 1 deletion fs/ocfs2/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ static int ocfs2_force_read_journal(struct inode *inode)
(inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9))) {

status = ocfs2_extent_map_get_blocks(inode, v_blkno,
&p_blkno, &p_blocks);
&p_blkno, &p_blocks, NULL);
if (status < 0) {
mlog_errno(status);
goto bail;
Expand Down
3 changes: 2 additions & 1 deletion fs/ocfs2/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -1511,7 +1511,8 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
goto bail;
}

status = ocfs2_extent_map_get_blocks(inode, 0, &p_blkno, &p_blocks);
status = ocfs2_extent_map_get_blocks(inode, 0, &p_blkno, &p_blocks,
NULL);
if (status < 0) {
mlog_errno(status);
goto bail;
Expand Down
2 changes: 1 addition & 1 deletion fs/ocfs2/slot_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ int ocfs2_init_slot_info(struct ocfs2_super *osb)
goto bail;
}

status = ocfs2_extent_map_get_blocks(inode, 0ULL, &blkno, NULL);
status = ocfs2_extent_map_get_blocks(inode, 0ULL, &blkno, NULL, NULL);
if (status < 0) {
mlog_errno(status);
goto bail;
Expand Down

0 comments on commit 49cb8d2

Please sign in to comment.