fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / fs / reiserfs / file.c
index db38c09..2cd522a 100644 (file)
@@ -37,8 +37,7 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
        int err;
        int jbegin_failure = 0;
 
-       if (!S_ISREG(inode->i_mode))
-               BUG();
+       BUG_ON(!S_ISREG(inode->i_mode));
 
        /* fast out for when nothing needs to be done */
        if ((atomic_read(&inode->i_count) > 1 ||
@@ -48,8 +47,13 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
                return 0;
        }
 
-       reiserfs_write_lock(inode->i_sb);
        mutex_lock(&inode->i_mutex);
+
+       mutex_lock(&(REISERFS_I(inode)->i_mmap));
+       if (REISERFS_I(inode)->i_flags & i_ever_mapped)
+               REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
+
+       reiserfs_write_lock(inode->i_sb);
        /* freeing preallocation only involves relogging blocks that
         * are already in the current transaction.  preallocation gets
         * freed at the end of each transaction, so it is impossible for
@@ -75,7 +79,8 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
                        igrab(inode);
                        reiserfs_warning(inode->i_sb,
                                         "pinning inode %lu because the "
-                                        "preallocation can't be freed");
+                                        "preallocation can't be freed",
+                                        inode->i_ino);
                        goto out;
                }
        }
@@ -100,11 +105,24 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
                err = reiserfs_truncate_file(inode, 0);
        }
       out:
+       mutex_unlock(&(REISERFS_I(inode)->i_mmap));
        mutex_unlock(&inode->i_mutex);
        reiserfs_write_unlock(inode->i_sb);
        return err;
 }
 
+static int reiserfs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct inode *inode;
+
+       inode = file->f_path.dentry->d_inode;
+       mutex_lock(&(REISERFS_I(inode)->i_mmap));
+       REISERFS_I(inode)->i_flags |= i_ever_mapped;
+       mutex_unlock(&(REISERFS_I(inode)->i_mmap));
+
+       return generic_file_mmap(file, vma);
+}
+
 static void reiserfs_vfs_truncate_file(struct inode *inode)
 {
        reiserfs_truncate_file(inode, 1);
@@ -124,13 +142,12 @@ static int reiserfs_sync_file(struct file *p_s_filp,
        int n_err;
        int barrier_done;
 
-       if (!S_ISREG(p_s_inode->i_mode))
-               BUG();
+       BUG_ON(!S_ISREG(p_s_inode->i_mode));
        n_err = sync_mapping_buffers(p_s_inode->i_mapping);
        reiserfs_write_lock(p_s_inode->i_sb);
        barrier_done = reiserfs_commit_for_inode(p_s_inode);
        reiserfs_write_unlock(p_s_inode->i_sb);
-       if (barrier_done != 1)
+       if (barrier_done != 1 && reiserfs_barrier_flush(p_s_inode->i_sb))
                blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL);
        if (barrier_done < 0)
                return barrier_done;
@@ -318,12 +335,11 @@ static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handl
                        /* area filled with zeroes, to supply as list of zero blocknumbers
                           We allocate it outside of loop just in case loop would spin for
                           several iterations. */
-                       char *zeros = kmalloc(to_paste * UNFM_P_SIZE, GFP_ATOMIC);      // We cannot insert more than MAX_ITEM_LEN bytes anyway.
+                       char *zeros = kzalloc(to_paste * UNFM_P_SIZE, GFP_ATOMIC);      // We cannot insert more than MAX_ITEM_LEN bytes anyway.
                        if (!zeros) {
                                res = -ENOMEM;
                                goto error_exit_free_blocks;
                        }
-                       memset(zeros, 0, to_paste * UNFM_P_SIZE);
                        do {
                                to_paste =
                                    min_t(__u64, hole_size,
@@ -408,6 +424,8 @@ static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handl
                                   we restart it. This will also free the path. */
                                if (journal_transaction_should_end
                                    (th, th->t_blocks_allocated)) {
+                                       inode->i_size = cpu_key_k_offset(&key) +
+                                               (to_paste << inode->i_blkbits);
                                        res =
                                            restart_transaction(th, inode,
                                                                &path);
@@ -860,8 +878,12 @@ static int reiserfs_submit_file_region_for_write(struct reiserfs_transaction_han
                        // this sets the proper flags for O_SYNC to trigger a commit
                        mark_inode_dirty(inode);
                        reiserfs_write_unlock(inode->i_sb);
-               } else
+               } else {
+                       reiserfs_write_lock(inode->i_sb);
+                       reiserfs_update_inode_transaction(inode);
                        mark_inode_dirty(inode);
+                       reiserfs_write_unlock(inode->i_sb);
+               }
 
                sd_update = 1;
        }
@@ -1042,6 +1064,7 @@ static int reiserfs_prepare_file_region_for_write(struct inode *inode
                        char *kaddr = kmap_atomic(prepared_pages[0], KM_USER0);
                        memset(kaddr, 0, from);
                        kunmap_atomic(kaddr, KM_USER0);
+                       flush_dcache_page(prepared_pages[0]);
                }
                if (to != PAGE_CACHE_SIZE) {    /* Last page needs to be partially zeroed */
                        char *kaddr =
@@ -1049,6 +1072,7 @@ static int reiserfs_prepare_file_region_for_write(struct inode *inode
                                        KM_USER0);
                        memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
                        kunmap_atomic(kaddr, KM_USER0);
+                       flush_dcache_page(prepared_pages[num_pages - 1]);
                }
 
                /* Since all blocks are new - use already calculated value */
@@ -1182,6 +1206,7 @@ static int reiserfs_prepare_file_region_for_write(struct inode *inode
                                        memset(kaddr + block_start, 0,
                                               from - block_start);
                                        kunmap_atomic(kaddr, KM_USER0);
+                                       flush_dcache_page(prepared_pages[0]);
                                        set_buffer_uptodate(bh);
                                }
                        }
@@ -1219,6 +1244,7 @@ static int reiserfs_prepare_file_region_for_write(struct inode *inode
                                                        KM_USER0);
                                        memset(kaddr + to, 0, block_end - to);
                                        kunmap_atomic(kaddr, KM_USER0);
+                                       flush_dcache_page(prepared_pages[num_pages - 1]);
                                        set_buffer_uptodate(bh);
                                }
                        }
@@ -1280,7 +1306,7 @@ static ssize_t reiserfs_file_write(struct file *file,     /* the file we are going t
        loff_t pos;             // Current position in the file.
        ssize_t res;            // return value of various functions that we call.
        int err = 0;
-       struct inode *inode = file->f_dentry->d_inode;  // Inode of the file that we are writing to.
+       struct inode *inode = file->f_path.dentry->d_inode;     // Inode of the file that we are writing to.
        /* To simplify coding at this time, we store
           locked pages in array for now */
        struct page *prepared_pages[REISERFS_WRITE_PAGES_AT_A_TIME];
@@ -1304,56 +1330,8 @@ static ssize_t reiserfs_file_write(struct file *file,    /* the file we are going t
                        count = MAX_NON_LFS - (unsigned long)*ppos;
        }
 
-       if (file->f_flags & O_DIRECT) { // Direct IO needs treatment
-               ssize_t result, after_file_end = 0;
-               if ((*ppos + count >= inode->i_size)
-                   || (file->f_flags & O_APPEND)) {
-                       /* If we are appending a file, we need to put this savelink in here.
-                          If we will crash while doing direct io, finish_unfinished will
-                          cut the garbage from the file end. */
-                       reiserfs_write_lock(inode->i_sb);
-                       err =
-                           journal_begin(&th, inode->i_sb,
-                                         JOURNAL_PER_BALANCE_CNT);
-                       if (err) {
-                               reiserfs_write_unlock(inode->i_sb);
-                               return err;
-                       }
-                       reiserfs_update_inode_transaction(inode);
-                       add_save_link(&th, inode, 1 /* Truncate */ );
-                       after_file_end = 1;
-                       err =
-                           journal_end(&th, inode->i_sb,
-                                       JOURNAL_PER_BALANCE_CNT);
-                       reiserfs_write_unlock(inode->i_sb);
-                       if (err)
-                               return err;
-               }
-               result = generic_file_write(file, buf, count, ppos);
-
-               if (after_file_end) {   /* Now update i_size and remove the savelink */
-                       struct reiserfs_transaction_handle th;
-                       reiserfs_write_lock(inode->i_sb);
-                       err = journal_begin(&th, inode->i_sb, 1);
-                       if (err) {
-                               reiserfs_write_unlock(inode->i_sb);
-                               return err;
-                       }
-                       reiserfs_update_inode_transaction(inode);
-                       mark_inode_dirty(inode);
-                       err = journal_end(&th, inode->i_sb, 1);
-                       if (err) {
-                               reiserfs_write_unlock(inode->i_sb);
-                               return err;
-                       }
-                       err = remove_save_link(inode, 1 /* truncate */ );
-                       reiserfs_write_unlock(inode->i_sb);
-                       if (err)
-                               return err;
-               }
-
-               return result;
-       }
+       if (file->f_flags & O_DIRECT)
+               return do_sync_write(file, buf, count, ppos);
 
        if (unlikely((ssize_t) count < 0))
                return -EINVAL;
@@ -1375,7 +1353,7 @@ static ssize_t reiserfs_file_write(struct file *file,     /* the file we are going t
        if (count == 0)
                goto out;
 
-       res = remove_suid(file->f_dentry);
+       res = remove_suid(file->f_path.dentry);
        if (res)
                goto out;
 
@@ -1532,7 +1510,7 @@ static ssize_t reiserfs_file_write(struct file *file,     /* the file we are going t
                buf += write_bytes;
                *ppos = pos += write_bytes;
                count -= write_bytes;
-               balance_dirty_pages_ratelimited(inode->i_mapping);
+               balance_dirty_pages_ratelimited_nr(inode->i_mapping, num_pages);
        }
 
        /* this is only true on error */
@@ -1546,10 +1524,10 @@ static ssize_t reiserfs_file_write(struct file *file,   /* the file we are going t
                }
        }
 
-       if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
-               res =
-                   generic_osync_inode(inode, file->f_mapping,
-                                       OSYNC_METADATA | OSYNC_DATA);
+       if (likely(res >= 0) &&
+           (unlikely((file->f_flags & O_SYNC) || IS_SYNC(inode))))
+               res = generic_osync_inode(inode, file->f_mapping,
+                                         OSYNC_METADATA | OSYNC_DATA);
 
        mutex_unlock(&inode->i_mutex);
        reiserfs_async_progress_wait(inode->i_sb);
@@ -1560,22 +1538,23 @@ static ssize_t reiserfs_file_write(struct file *file,   /* the file we are going t
        return res;
 }
 
-static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user * buf,
-                                 size_t count, loff_t pos)
-{
-       return generic_file_aio_write(iocb, buf, count, pos);
-}
-
-struct file_operations reiserfs_file_operations = {
-       .read = generic_file_read,
+const struct file_operations reiserfs_file_operations = {
+       .read = do_sync_read,
        .write = reiserfs_file_write,
        .ioctl = reiserfs_ioctl,
-       .mmap = generic_file_mmap,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = reiserfs_compat_ioctl,
+#endif
+       .mmap = reiserfs_file_mmap,
+       .open = generic_file_open,
        .release = reiserfs_file_release,
        .fsync = reiserfs_sync_file,
        .sendfile = generic_file_sendfile,
+       .sendpage = generic_file_sendpage,
        .aio_read = generic_file_aio_read,
-       .aio_write = reiserfs_aio_write,
+       .aio_write = generic_file_aio_write,
+       .splice_read = generic_file_splice_read,
+       .splice_write = generic_file_splice_write,
 };
 
 struct inode_operations reiserfs_file_inode_operations = {