]> git.hungrycats.org Git - linux/commitdiff
[XFS] Fix data loss when writing into unwritten extents while memory is being reclaimed.
authorNathan Scott <nathans@sgi.com>
Tue, 10 Feb 2004 02:39:45 +0000 (13:39 +1100)
committerNathan Scott <nathans@sgi.com>
Tue, 10 Feb 2004 02:39:45 +0000 (13:39 +1100)
SGI Modid: xfs-linux:xfs-kern:166324a

fs/xfs/linux/xfs_aops.c

index 5e2c9a3d88095c9d5cc8320c103fd8eee230d0e7..1d13a91e3b37ff33380ce262d992684943bfc327 100644 (file)
@@ -724,7 +724,7 @@ page_state_convert(
                                iomp = match_offset_to_mapping(page, &iomap,
                                                                p_offset);
                        }
-                       if (iomp) {
+                       if (iomp && startio) {
                                if (!bh->b_end_io) {
                                        err = map_unwritten(inode, page,
                                                        head, bh, p_offset,
@@ -734,13 +734,7 @@ page_state_convert(
                                                goto error;
                                        }
                                }
-                               if (startio) {
-                                       bh_arr[cnt++] = bh;
-                               } else {
-                                       set_buffer_dirty(bh);
-                                       unlock_buffer(bh);
-                                       mark_buffer_dirty(bh);
-                               }
+                               bh_arr[cnt++] = bh;
                                page_dirty = 0;
                        }
                /*
@@ -886,9 +880,9 @@ linvfs_get_block_core(
                loff_t                  delta;
 
                /* For unwritten extents do not report a disk address on
-                * the read case.
+                * the read case (treat as if we're reading into a hole).
                 */
-               if (create || ((iomap.iomap_flags & IOMAP_UNWRITTEN) == 0)) {
+               if (create || !(iomap.iomap_flags & IOMAP_UNWRITTEN)) {
                        delta = offset - iomap.iomap_offset;
                        delta >>= inode->i_blkbits;
 
@@ -899,12 +893,9 @@ linvfs_get_block_core(
                        bh_result->b_bdev = iomap.iomap_target->pbr_bdev;
                        set_buffer_mapped(bh_result);
                }
-               if (iomap.iomap_flags & IOMAP_UNWRITTEN) {
-                       if (create) {
-                               if (direct)
-                                       bh_result->b_private = inode;
-                               set_buffer_mapped(bh_result);
-                       }
+               if (create && (iomap.iomap_flags & IOMAP_UNWRITTEN)) {
+                       if (direct)
+                               bh_result->b_private = inode;
                        set_buffer_unwritten(bh_result);
                        set_buffer_delay(bh_result);
                }
@@ -1173,7 +1164,7 @@ linvfs_release_page(
        int                     gfp_mask)
 {
        struct inode            *inode = page->mapping->host;
-       int                     delalloc, unmapped, unwritten;
+       int                     dirty, delalloc, unmapped, unwritten;
 
        count_page_state(page, &delalloc, &unmapped, &unwritten);
        if (!delalloc && !unwritten)
@@ -1194,7 +1185,8 @@ linvfs_release_page(
         * Never need to allocate space here - we will always
         * come back to writepage in that case.
         */
-       if (page_state_convert(inode, page, 0, 0) == 0)
+       dirty = page_state_convert(inode, page, 0, 0);
+       if (dirty == 0 && !unwritten)
                goto free_buffers;
        return 0;