1f183ff4fSRyusuke Konishi /* 2f183ff4fSRyusuke Konishi * file.c - NILFS regular file handling primitives including fsync(). 3f183ff4fSRyusuke Konishi * 4f183ff4fSRyusuke Konishi * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. 5f183ff4fSRyusuke Konishi * 6f183ff4fSRyusuke Konishi * This program is free software; you can redistribute it and/or modify 7f183ff4fSRyusuke Konishi * it under the terms of the GNU General Public License as published by 8f183ff4fSRyusuke Konishi * the Free Software Foundation; either version 2 of the License, or 9f183ff4fSRyusuke Konishi * (at your option) any later version. 10f183ff4fSRyusuke Konishi * 11f183ff4fSRyusuke Konishi * This program is distributed in the hope that it will be useful, 12f183ff4fSRyusuke Konishi * but WITHOUT ANY WARRANTY; without even the implied warranty of 13f183ff4fSRyusuke Konishi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14f183ff4fSRyusuke Konishi * GNU General Public License for more details. 15f183ff4fSRyusuke Konishi * 16f183ff4fSRyusuke Konishi * You should have received a copy of the GNU General Public License 17f183ff4fSRyusuke Konishi * along with this program; if not, write to the Free Software 18f183ff4fSRyusuke Konishi * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19f183ff4fSRyusuke Konishi * 20f183ff4fSRyusuke Konishi * Written by Amagai Yoshiji <amagai@osrg.net>, 21f183ff4fSRyusuke Konishi * Ryusuke Konishi <ryusuke@osrg.net> 22f183ff4fSRyusuke Konishi */ 23f183ff4fSRyusuke Konishi 24f183ff4fSRyusuke Konishi #include <linux/fs.h> 25f183ff4fSRyusuke Konishi #include <linux/mm.h> 26f183ff4fSRyusuke Konishi #include <linux/writeback.h> 27f183ff4fSRyusuke Konishi #include "nilfs.h" 28f183ff4fSRyusuke Konishi #include "segment.h" 29f183ff4fSRyusuke Konishi 30f183ff4fSRyusuke Konishi int nilfs_sync_file(struct file *file, struct dentry *dentry, int datasync) 31f183ff4fSRyusuke Konishi { 32f183ff4fSRyusuke Konishi /* 33f183ff4fSRyusuke Konishi * Called from fsync() system call 34f183ff4fSRyusuke Konishi * This is the only entry point that can catch write and synch 35f183ff4fSRyusuke Konishi * timing for both data blocks and intermediate blocks. 36f183ff4fSRyusuke Konishi * 37f183ff4fSRyusuke Konishi * This function should be implemented when the writeback function 38f183ff4fSRyusuke Konishi * will be implemented. 39f183ff4fSRyusuke Konishi */ 40f183ff4fSRyusuke Konishi struct inode *inode = dentry->d_inode; 41f183ff4fSRyusuke Konishi int err; 42f183ff4fSRyusuke Konishi 43f183ff4fSRyusuke Konishi if (!nilfs_inode_dirty(inode)) 44f183ff4fSRyusuke Konishi return 0; 45f183ff4fSRyusuke Konishi 46f183ff4fSRyusuke Konishi if (datasync) 47f30bf3e4SRyusuke Konishi err = nilfs_construct_dsync_segment(inode->i_sb, inode, 0, 48f30bf3e4SRyusuke Konishi LLONG_MAX); 49f183ff4fSRyusuke Konishi else 50f183ff4fSRyusuke Konishi err = nilfs_construct_segment(inode->i_sb); 51f183ff4fSRyusuke Konishi 52f183ff4fSRyusuke Konishi return err; 53f183ff4fSRyusuke Konishi } 54f183ff4fSRyusuke Konishi 559ff05123SRyusuke Konishi static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) 56f183ff4fSRyusuke Konishi { 579ff05123SRyusuke Konishi struct page *page = vmf->page; 589ff05123SRyusuke Konishi struct inode *inode = vma->vm_file->f_dentry->d_inode; 599ff05123SRyusuke Konishi struct nilfs_transaction_info ti; 609ff05123SRyusuke Konishi int ret; 619ff05123SRyusuke Konishi 629ff05123SRyusuke Konishi if (unlikely(nilfs_near_disk_full(NILFS_SB(inode->i_sb)->s_nilfs))) 639ff05123SRyusuke Konishi return VM_FAULT_SIGBUS; /* -ENOSPC */ 649ff05123SRyusuke Konishi 659ff05123SRyusuke Konishi lock_page(page); 669ff05123SRyusuke Konishi if (page->mapping != inode->i_mapping || 679ff05123SRyusuke Konishi page_offset(page) >= i_size_read(inode) || !PageUptodate(page)) { 689ff05123SRyusuke Konishi unlock_page(page); 699ff05123SRyusuke Konishi return VM_FAULT_NOPAGE; /* make the VM retry the fault */ 709ff05123SRyusuke Konishi } 719ff05123SRyusuke Konishi 729ff05123SRyusuke Konishi /* 739ff05123SRyusuke Konishi * check to see if the page is mapped already (no holes) 749ff05123SRyusuke Konishi */ 759ff05123SRyusuke Konishi if (PageMappedToDisk(page)) { 769ff05123SRyusuke Konishi unlock_page(page); 779ff05123SRyusuke Konishi goto mapped; 789ff05123SRyusuke Konishi } 799ff05123SRyusuke Konishi if (page_has_buffers(page)) { 809ff05123SRyusuke Konishi struct buffer_head *bh, *head; 819ff05123SRyusuke Konishi int fully_mapped = 1; 829ff05123SRyusuke Konishi 839ff05123SRyusuke Konishi bh = head = page_buffers(page); 849ff05123SRyusuke Konishi do { 859ff05123SRyusuke Konishi if (!buffer_mapped(bh)) { 869ff05123SRyusuke Konishi fully_mapped = 0; 879ff05123SRyusuke Konishi break; 889ff05123SRyusuke Konishi } 899ff05123SRyusuke Konishi } while (bh = bh->b_this_page, bh != head); 909ff05123SRyusuke Konishi 919ff05123SRyusuke Konishi if (fully_mapped) { 929ff05123SRyusuke Konishi SetPageMappedToDisk(page); 939ff05123SRyusuke Konishi unlock_page(page); 949ff05123SRyusuke Konishi goto mapped; 959ff05123SRyusuke Konishi } 969ff05123SRyusuke Konishi } 979ff05123SRyusuke Konishi unlock_page(page); 989ff05123SRyusuke Konishi 999ff05123SRyusuke Konishi /* 1009ff05123SRyusuke Konishi * fill hole blocks 1019ff05123SRyusuke Konishi */ 1029ff05123SRyusuke Konishi ret = nilfs_transaction_begin(inode->i_sb, &ti, 1); 1039ff05123SRyusuke Konishi /* never returns -ENOMEM, but may return -ENOSPC */ 1049ff05123SRyusuke Konishi if (unlikely(ret)) 1059ff05123SRyusuke Konishi return VM_FAULT_SIGBUS; 1069ff05123SRyusuke Konishi 1079ff05123SRyusuke Konishi ret = block_page_mkwrite(vma, vmf, nilfs_get_block); 1089ff05123SRyusuke Konishi if (unlikely(ret)) { 1099ff05123SRyusuke Konishi nilfs_transaction_abort(inode->i_sb); 1109ff05123SRyusuke Konishi return ret; 1119ff05123SRyusuke Konishi } 1129ff05123SRyusuke Konishi nilfs_transaction_commit(inode->i_sb); 1139ff05123SRyusuke Konishi 1149ff05123SRyusuke Konishi mapped: 115f183ff4fSRyusuke Konishi SetPageChecked(page); 116f183ff4fSRyusuke Konishi wait_on_page_writeback(page); 117f183ff4fSRyusuke Konishi return 0; 118f183ff4fSRyusuke Konishi } 119f183ff4fSRyusuke Konishi 120f183ff4fSRyusuke Konishi struct vm_operations_struct nilfs_file_vm_ops = { 121f183ff4fSRyusuke Konishi .fault = filemap_fault, 122f183ff4fSRyusuke Konishi .page_mkwrite = nilfs_page_mkwrite, 123f183ff4fSRyusuke Konishi }; 124f183ff4fSRyusuke Konishi 125f183ff4fSRyusuke Konishi static int nilfs_file_mmap(struct file *file, struct vm_area_struct *vma) 126f183ff4fSRyusuke Konishi { 127f183ff4fSRyusuke Konishi file_accessed(file); 128f183ff4fSRyusuke Konishi vma->vm_ops = &nilfs_file_vm_ops; 129f183ff4fSRyusuke Konishi vma->vm_flags |= VM_CAN_NONLINEAR; 130f183ff4fSRyusuke Konishi return 0; 131f183ff4fSRyusuke Konishi } 132f183ff4fSRyusuke Konishi 133f183ff4fSRyusuke Konishi /* 134f183ff4fSRyusuke Konishi * We have mostly NULL's here: the current defaults are ok for 135f183ff4fSRyusuke Konishi * the nilfs filesystem. 136f183ff4fSRyusuke Konishi */ 137f183ff4fSRyusuke Konishi struct file_operations nilfs_file_operations = { 138f183ff4fSRyusuke Konishi .llseek = generic_file_llseek, 139f183ff4fSRyusuke Konishi .read = do_sync_read, 140f183ff4fSRyusuke Konishi .write = do_sync_write, 141f183ff4fSRyusuke Konishi .aio_read = generic_file_aio_read, 142f30bf3e4SRyusuke Konishi .aio_write = generic_file_aio_write, 143f183ff4fSRyusuke Konishi .ioctl = nilfs_ioctl, 144f183ff4fSRyusuke Konishi #ifdef CONFIG_COMPAT 145f183ff4fSRyusuke Konishi .compat_ioctl = nilfs_compat_ioctl, 146f183ff4fSRyusuke Konishi #endif /* CONFIG_COMPAT */ 147f183ff4fSRyusuke Konishi .mmap = nilfs_file_mmap, 148f183ff4fSRyusuke Konishi .open = generic_file_open, 149f183ff4fSRyusuke Konishi /* .release = nilfs_release_file, */ 150f183ff4fSRyusuke Konishi .fsync = nilfs_sync_file, 151f183ff4fSRyusuke Konishi .splice_read = generic_file_splice_read, 152f183ff4fSRyusuke Konishi }; 153f183ff4fSRyusuke Konishi 154f183ff4fSRyusuke Konishi struct inode_operations nilfs_file_inode_operations = { 155f183ff4fSRyusuke Konishi .truncate = nilfs_truncate, 156f183ff4fSRyusuke Konishi .setattr = nilfs_setattr, 157f183ff4fSRyusuke Konishi .permission = nilfs_permission, 158f183ff4fSRyusuke Konishi }; 159f183ff4fSRyusuke Konishi 160f183ff4fSRyusuke Konishi /* end of file */ 161