nilfs2: use iget for all metadata files
[linux-2.6.git] / fs / nilfs2 / file.c
index 7ddd42e..c9a30d7 100644 (file)
@@ -27,7 +27,7 @@
 #include "nilfs.h"
 #include "segment.h"
 
-int nilfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
+int nilfs_sync_file(struct file *file, int datasync)
 {
        /*
         * Called from fsync() system call
@@ -37,52 +37,87 @@ int nilfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
         * This function should be implemented when the writeback function
         * will be implemented.
         */
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = file->f_mapping->host;
        int err;
 
        if (!nilfs_inode_dirty(inode))
                return 0;
 
        if (datasync)
-               err = nilfs_construct_dsync_segment(inode->i_sb, inode);
+               err = nilfs_construct_dsync_segment(inode->i_sb, inode, 0,
+                                                   LLONG_MAX);
        else
                err = nilfs_construct_segment(inode->i_sb);
 
        return err;
 }
 
-static ssize_t
-nilfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
-                    unsigned long nr_segs, loff_t pos)
+static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
-       struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_dentry->d_inode;
-       ssize_t ret;
+       struct page *page = vmf->page;
+       struct inode *inode = vma->vm_file->f_dentry->d_inode;
+       struct nilfs_transaction_info ti;
+       int ret;
 
-       ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
-       if (ret <= 0)
-               return ret;
+       if (unlikely(nilfs_near_disk_full(NILFS_SB(inode->i_sb)->s_nilfs)))
+               return VM_FAULT_SIGBUS; /* -ENOSPC */
 
-       if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
-               int err;
+       lock_page(page);
+       if (page->mapping != inode->i_mapping ||
+           page_offset(page) >= i_size_read(inode) || !PageUptodate(page)) {
+               unlock_page(page);
+               return VM_FAULT_NOPAGE; /* make the VM retry the fault */
+       }
 
-               err = nilfs_construct_dsync_segment(inode->i_sb, inode);
-               if (unlikely(err))
-                       return err;
+       /*
+        * check to see if the page is mapped already (no holes)
+        */
+       if (PageMappedToDisk(page)) {
+               unlock_page(page);
+               goto mapped;
        }
-       return ret;
-}
+       if (page_has_buffers(page)) {
+               struct buffer_head *bh, *head;
+               int fully_mapped = 1;
 
-static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct page *page)
-{
-       if (!(vma->vm_flags & (VM_WRITE | VM_MAYWRITE)))
-               return -EPERM;
+               bh = head = page_buffers(page);
+               do {
+                       if (!buffer_mapped(bh)) {
+                               fully_mapped = 0;
+                               break;
+                       }
+               } while (bh = bh->b_this_page, bh != head);
+
+               if (fully_mapped) {
+                       SetPageMappedToDisk(page);
+                       unlock_page(page);
+                       goto mapped;
+               }
+       }
+       unlock_page(page);
+
+       /*
+        * fill hole blocks
+        */
+       ret = nilfs_transaction_begin(inode->i_sb, &ti, 1);
+       /* never returns -ENOMEM, but may return -ENOSPC */
+       if (unlikely(ret))
+               return VM_FAULT_SIGBUS;
+
+       ret = block_page_mkwrite(vma, vmf, nilfs_get_block);
+       if (unlikely(ret)) {
+               nilfs_transaction_abort(inode->i_sb);
+               return ret;
+       }
+       nilfs_transaction_commit(inode->i_sb);
+
+ mapped:
        SetPageChecked(page);
        wait_on_page_writeback(page);
        return 0;
 }
 
-struct vm_operations_struct nilfs_file_vm_ops = {
+static const struct vm_operations_struct nilfs_file_vm_ops = {
        .fault          = filemap_fault,
        .page_mkwrite   = nilfs_page_mkwrite,
 };
@@ -99,15 +134,15 @@ static int nilfs_file_mmap(struct file *file, struct vm_area_struct *vma)
  * We have mostly NULL's here: the current defaults are ok for
  * the nilfs filesystem.
  */
-struct file_operations nilfs_file_operations = {
+const struct file_operations nilfs_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
        .aio_read       = generic_file_aio_read,
-       .aio_write      = nilfs_file_aio_write,
-       .ioctl          = nilfs_ioctl,
+       .aio_write      = generic_file_aio_write,
+       .unlocked_ioctl = nilfs_ioctl,
 #ifdef CONFIG_COMPAT
-       .compat_ioctl   = nilfs_compat_ioctl,
+       .compat_ioctl   = nilfs_ioctl,
 #endif /* CONFIG_COMPAT */
        .mmap           = nilfs_file_mmap,
        .open           = generic_file_open,
@@ -116,7 +151,7 @@ struct file_operations nilfs_file_operations = {
        .splice_read    = generic_file_splice_read,
 };
 
-struct inode_operations nilfs_file_inode_operations = {
+const struct inode_operations nilfs_file_inode_operations = {
        .truncate       = nilfs_truncate,
        .setattr        = nilfs_setattr,
        .permission     = nilfs_permission,