]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] O_DIRECT invalidation fix
authorAndrew Morton <akpm@digeo.com>
Sat, 5 Oct 2002 03:34:57 +0000 (20:34 -0700)
committerRussell King <rmk@flint.arm.linux.org.uk>
Sat, 5 Oct 2002 03:34:57 +0000 (20:34 -0700)
If the alignment checks in generic_direct_IO() fail, we end up not
forcing writeback of dirty pagecache pages, but we still run
invalidate_inode_pages2().  The net result is that dirty pagecache gets
incorrectly removed.  I guess this will expose unwritten disk blocks.

So move the sync up into generic_file_direct_IO(), where we perform the
invalidation.  So we know that pagecache and disk are in sync before we
do anything else.

fs/direct-io.c

index b2472e6fff1b582a48282dc9af633e0ea6f278c4..e9a135036991409f5a693187c2bd97c882fe6313 100644 (file)
@@ -620,13 +620,11 @@ generic_direct_IO(int rw, struct inode *inode, const struct iovec *iov,
        int seg;
        size_t size;
        unsigned long addr;
-       struct address_space *mapping = inode->i_mapping;
        unsigned blocksize_mask = (1 << inode->i_blkbits) - 1;
        ssize_t retval = -EINVAL;
 
-       if (offset & blocksize_mask) {
+       if (offset & blocksize_mask)
                goto out;
-       }
 
        /* Check the memory alignment.  Blocks cannot straddle pages */
        for (seg = 0; seg < nr_segs; seg++) {
@@ -636,14 +634,6 @@ generic_direct_IO(int rw, struct inode *inode, const struct iovec *iov,
                        goto out;       
        }
 
-       if (mapping->nrpages) {
-               retval = filemap_fdatawrite(mapping);
-               if (retval == 0)
-                       retval = filemap_fdatawait(mapping);
-               if (retval)
-                       goto out;
-       }
-
        retval = direct_io_worker(rw, inode, iov, offset, nr_segs, get_blocks);
 out:
        return retval;
@@ -656,8 +646,17 @@ generic_file_direct_IO(int rw, struct inode *inode, const struct iovec *iov,
        struct address_space *mapping = inode->i_mapping;
        ssize_t retval;
 
+       if (mapping->nrpages) {
+               retval = filemap_fdatawrite(mapping);
+               if (retval == 0)
+                       retval = filemap_fdatawait(mapping);
+               if (retval)
+                       goto out;
+       }
+
        retval = mapping->a_ops->direct_IO(rw, inode, iov, offset, nr_segs);
        if (inode->i_mapping->nrpages)
                invalidate_inode_pages2(inode->i_mapping);
+out:
        return retval;
 }