]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/exofs/inode.c
exofs: simple fsync race fix
[karo-tx-linux.git] / fs / exofs / inode.c
index 42685424817b5d846cbf411bcff815f62f023fa4..fb9d380561037040b40052d24be3364210ebf934 100644 (file)
@@ -350,8 +350,10 @@ static int readpage_strip(void *data, struct page *page)
 
                if (!pcol->read_4_write)
                        unlock_page(page);
-               EXOFS_DBGMSG("readpage_strip(0x%lx, 0x%lx) empty page,"
-                            " splitting\n", inode->i_ino, page->index);
+               EXOFS_DBGMSG("readpage_strip(0x%lx) empty page len=%zx "
+                            "read_4_write=%d index=0x%lx end_index=0x%lx "
+                            "splitting\n", inode->i_ino, len,
+                            pcol->read_4_write, page->index, end_index);
 
                return read_exec(pcol);
        }
@@ -722,11 +724,28 @@ int exofs_write_begin(struct file *file, struct address_space *mapping,
 
         /* read modify write */
        if (!PageUptodate(page) && (len != PAGE_CACHE_SIZE)) {
+               loff_t i_size = i_size_read(mapping->host);
+               pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
+               size_t rlen;
+
+               if (page->index < end_index)
+                       rlen = PAGE_CACHE_SIZE;
+               else if (page->index == end_index)
+                       rlen = i_size & ~PAGE_CACHE_MASK;
+               else
+                       rlen = 0;
+
+               if (!rlen) {
+                       clear_highpage(page);
+                       SetPageUptodate(page);
+                       goto out;
+               }
+
                ret = _readpage(page, true);
                if (ret) {
                        /*SetPageError was done by _readpage. Is it ok?*/
                        unlock_page(page);
-                       EXOFS_DBGMSG("__readpage_filler failed\n");
+                       EXOFS_DBGMSG("__readpage failed\n");
                }
        }
 out:
@@ -1030,7 +1049,6 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino)
                memcpy(oi->i_data, fcb.i_data, sizeof(fcb.i_data));
        }
 
-       inode->i_mapping->backing_dev_info = sb->s_bdi;
        if (S_ISREG(inode->i_mode)) {
                inode->i_op = &exofs_file_inode_operations;
                inode->i_fop = &exofs_file_operations;
@@ -1131,7 +1149,6 @@ struct inode *exofs_new_inode(struct inode *dir, int mode)
 
        sbi = sb->s_fs_info;
 
-       inode->i_mapping->backing_dev_info = sb->s_bdi;
        sb->s_dirt = 1;
        inode_init_owner(inode, dir, mode);
        inode->i_ino = sbi->s_nextid++;
@@ -1273,7 +1290,8 @@ out:
 
 int exofs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
-       return exofs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
+       /* FIXME: fix fsync and use wbc->sync_mode == WB_SYNC_ALL */
+       return exofs_update_inode(inode, 1);
 }
 
 /*