]> err.no Git - linux-2.6/commitdiff
ocfs2: Read from an unwritten extent returns zeros
authorMark Fasheh <mark.fasheh@oracle.com>
Sat, 10 Mar 2007 00:21:46 +0000 (16:21 -0800)
committerMark Fasheh <mark.fasheh@oracle.com>
Thu, 26 Apr 2007 22:02:41 +0000 (15:02 -0700)
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>
fs/ocfs2/alloc.c
fs/ocfs2/aops.c
fs/ocfs2/dir.c
fs/ocfs2/extent_map.c
fs/ocfs2/extent_map.h
fs/ocfs2/file.c
fs/ocfs2/inode.c
fs/ocfs2/journal.c
fs/ocfs2/namei.c
fs/ocfs2/slot_map.c

index 0eab0d328289cbfe0a63f6d9489203124e60da69..412a2888a3ed3e80effbb8293fb2c4a3d282dea1 100644 (file)
@@ -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;
@@ -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;
@@ -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 {
@@ -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;
 
index 014f4f52809cddf6fe6b1119ccb72e1a7d20345a..eb67c902b002a2b3212f42cc0d9677fa47d614ad 100644 (file)
@@ -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);
 
@@ -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,
@@ -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)) {
@@ -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);
@@ -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;
 
@@ -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);
@@ -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 {
                /*
@@ -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) {
 
                /*
@@ -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;
index c91490670ffa02ceed45c9676a017743e8b1531e..8d22e1e4a88d36a086f5e63bc710ccf4c32f154e 100644 (file)
@@ -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;
index ea0ce41d4193130408baa98e4c6523dd1a78ba35..eef6c1887708042586a04e8a1e7a6e87bc583f69 100644 (file)
@@ -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;
@@ -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);
@@ -155,7 +162,7 @@ out:
  * 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);
@@ -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;
index 625d0ee5e04a5e16876672092fde54a6c1623006..0031c59c347f3f33440211a983e8a81189b8de4a 100644 (file)
@@ -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 */
index 36176018b4b44a1eb93d3ce6c83a78e9965ae1a9..f516619a374481eb8a507b687a8cd6cbc5901dc9 100644 (file)
@@ -1127,6 +1127,7 @@ 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;
 
@@ -1134,13 +1135,14 @@ static int ocfs2_check_range_for_holes(struct inode *inode, loff_t pos,
        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;
                }
index 78c99b5050df52dee1fb09888da994f071d72796..310049bf7f6bc5a44f42aa7bb1d854670b915418 100644 (file)
@@ -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;
index 2e2e04fe97381b34cdaab87274938b07c2101dae..db77e0996bb74b648b73907acc823de40a6869d9 100644 (file)
@@ -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;
index 5755e07482562492f8eaef8c3b7295e5c59b6ae4..395859edb51f5d1769bd46c83562ff22024f409e 100644 (file)
@@ -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;
index f4416e7330e162540d82b288849dc58ed1ba0c1b..d921a28329dcb81e21525b51e0da41a2aceeec9e 100644 (file)
@@ -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;