linux/fs/nilfs2/file.c
<<
>>
Prefs
   1/*
   2 * file.c - NILFS regular file handling primitives including fsync().
   3 *
   4 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  19 *
  20 * Written by Amagai Yoshiji <amagai@osrg.net>,
  21 *            Ryusuke Konishi <ryusuke@osrg.net>
  22 */
  23
  24#include <linux/fs.h>
  25#include <linux/mm.h>
  26#include <linux/writeback.h>
  27#include "nilfs.h"
  28#include "segment.h"
  29
  30int nilfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
  31{
  32        /*
  33         * Called from fsync() system call
  34         * This is the only entry point that can catch write and synch
  35         * timing for both data blocks and intermediate blocks.
  36         *
  37         * This function should be implemented when the writeback function
  38         * will be implemented.
  39         */
  40        struct the_nilfs *nilfs;
  41        struct inode *inode = file->f_mapping->host;
  42        int err;
  43
  44        err = filemap_write_and_wait_range(inode->i_mapping, start, end);
  45        if (err)
  46                return err;
  47        mutex_lock(&inode->i_mutex);
  48
  49        if (nilfs_inode_dirty(inode)) {
  50                if (datasync)
  51                        err = nilfs_construct_dsync_segment(inode->i_sb, inode,
  52                                                            0, LLONG_MAX);
  53                else
  54                        err = nilfs_construct_segment(inode->i_sb);
  55        }
  56        mutex_unlock(&inode->i_mutex);
  57
  58        nilfs = inode->i_sb->s_fs_info;
  59        if (!err && nilfs_test_opt(nilfs, BARRIER)) {
  60                err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
  61                if (err != -EIO)
  62                        err = 0;
  63        }
  64        return err;
  65}
  66
  67static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
  68{
  69        struct page *page = vmf->page;
  70        struct inode *inode = vma->vm_file->f_dentry->d_inode;
  71        struct nilfs_transaction_info ti;
  72        int ret = 0;
  73
  74        if (unlikely(nilfs_near_disk_full(inode->i_sb->s_fs_info)))
  75                return VM_FAULT_SIGBUS; /* -ENOSPC */
  76
  77        sb_start_pagefault(inode->i_sb);
  78        lock_page(page);
  79        if (page->mapping != inode->i_mapping ||
  80            page_offset(page) >= i_size_read(inode) || !PageUptodate(page)) {
  81                unlock_page(page);
  82                ret = -EFAULT;  /* make the VM retry the fault */
  83                goto out;
  84        }
  85
  86        /*
  87         * check to see if the page is mapped already (no holes)
  88         */
  89        if (PageMappedToDisk(page))
  90                goto mapped;
  91
  92        if (page_has_buffers(page)) {
  93                struct buffer_head *bh, *head;
  94                int fully_mapped = 1;
  95
  96                bh = head = page_buffers(page);
  97                do {
  98                        if (!buffer_mapped(bh)) {
  99                                fully_mapped = 0;
 100                                break;
 101                        }
 102                } while (bh = bh->b_this_page, bh != head);
 103
 104                if (fully_mapped) {
 105                        SetPageMappedToDisk(page);
 106                        goto mapped;
 107                }
 108        }
 109        unlock_page(page);
 110
 111        /*
 112         * fill hole blocks
 113         */
 114        ret = nilfs_transaction_begin(inode->i_sb, &ti, 1);
 115        /* never returns -ENOMEM, but may return -ENOSPC */
 116        if (unlikely(ret))
 117                goto out;
 118
 119        ret = __block_page_mkwrite(vma, vmf, nilfs_get_block);
 120        if (ret) {
 121                nilfs_transaction_abort(inode->i_sb);
 122                goto out;
 123        }
 124        nilfs_set_file_dirty(inode, 1 << (PAGE_SHIFT - inode->i_blkbits));
 125        nilfs_transaction_commit(inode->i_sb);
 126
 127 mapped:
 128        wait_on_page_writeback(page);
 129 out:
 130        sb_end_pagefault(inode->i_sb);
 131        return block_page_mkwrite_return(ret);
 132}
 133
 134static const struct vm_operations_struct nilfs_file_vm_ops = {
 135        .fault          = filemap_fault,
 136        .page_mkwrite   = nilfs_page_mkwrite,
 137};
 138
 139static int nilfs_file_mmap(struct file *file, struct vm_area_struct *vma)
 140{
 141        file_accessed(file);
 142        vma->vm_ops = &nilfs_file_vm_ops;
 143        vma->vm_flags |= VM_CAN_NONLINEAR;
 144        return 0;
 145}
 146
 147/*
 148 * We have mostly NULL's here: the current defaults are ok for
 149 * the nilfs filesystem.
 150 */
 151const struct file_operations nilfs_file_operations = {
 152        .llseek         = generic_file_llseek,
 153        .read           = do_sync_read,
 154        .write          = do_sync_write,
 155        .aio_read       = generic_file_aio_read,
 156        .aio_write      = generic_file_aio_write,
 157        .unlocked_ioctl = nilfs_ioctl,
 158#ifdef CONFIG_COMPAT
 159        .compat_ioctl   = nilfs_compat_ioctl,
 160#endif  /* CONFIG_COMPAT */
 161        .mmap           = nilfs_file_mmap,
 162        .open           = generic_file_open,
 163        /* .release     = nilfs_release_file, */
 164        .fsync          = nilfs_sync_file,
 165        .splice_read    = generic_file_splice_read,
 166};
 167
 168const struct inode_operations nilfs_file_inode_operations = {
 169        .truncate       = nilfs_truncate,
 170        .setattr        = nilfs_setattr,
 171        .permission     = nilfs_permission,
 172        .fiemap         = nilfs_fiemap,
 173};
 174
 175/* end of file */
 176
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.