xref: /openbmc/linux/fs/nilfs2/file.c (revision 8174202b)
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 
3002c24a82SJosef Bacik int nilfs_sync_file(struct file *file, loff_t start, loff_t end, 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 	 */
4011475975SRyusuke Konishi 	struct the_nilfs *nilfs;
417ea80859SChristoph Hellwig 	struct inode *inode = file->f_mapping->host;
42f183ff4fSRyusuke Konishi 	int err;
43f183ff4fSRyusuke Konishi 
4402c24a82SJosef Bacik 	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
4502c24a82SJosef Bacik 	if (err)
4602c24a82SJosef Bacik 		return err;
4702c24a82SJosef Bacik 	mutex_lock(&inode->i_mutex);
4802c24a82SJosef Bacik 
4911475975SRyusuke Konishi 	if (nilfs_inode_dirty(inode)) {
50f183ff4fSRyusuke Konishi 		if (datasync)
5111475975SRyusuke Konishi 			err = nilfs_construct_dsync_segment(inode->i_sb, inode,
5211475975SRyusuke Konishi 							    0, LLONG_MAX);
53f183ff4fSRyusuke Konishi 		else
54f183ff4fSRyusuke Konishi 			err = nilfs_construct_segment(inode->i_sb);
5511475975SRyusuke Konishi 	}
5602c24a82SJosef Bacik 	mutex_unlock(&inode->i_mutex);
5711475975SRyusuke Konishi 
5811475975SRyusuke Konishi 	nilfs = inode->i_sb->s_fs_info;
5911475975SRyusuke Konishi 	if (!err && nilfs_test_opt(nilfs, BARRIER)) {
6011475975SRyusuke Konishi 		err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
6111475975SRyusuke Konishi 		if (err != -EIO)
6211475975SRyusuke Konishi 			err = 0;
6311475975SRyusuke Konishi 	}
64f183ff4fSRyusuke Konishi 	return err;
65f183ff4fSRyusuke Konishi }
66f183ff4fSRyusuke Konishi 
679ff05123SRyusuke Konishi static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
68f183ff4fSRyusuke Konishi {
699ff05123SRyusuke Konishi 	struct page *page = vmf->page;
70496ad9aaSAl Viro 	struct inode *inode = file_inode(vma->vm_file);
719ff05123SRyusuke Konishi 	struct nilfs_transaction_info ti;
722c22b337SJan Kara 	int ret = 0;
739ff05123SRyusuke Konishi 
74e3154e97SRyusuke Konishi 	if (unlikely(nilfs_near_disk_full(inode->i_sb->s_fs_info)))
759ff05123SRyusuke Konishi 		return VM_FAULT_SIGBUS; /* -ENOSPC */
769ff05123SRyusuke Konishi 
772c22b337SJan Kara 	sb_start_pagefault(inode->i_sb);
789ff05123SRyusuke Konishi 	lock_page(page);
799ff05123SRyusuke Konishi 	if (page->mapping != inode->i_mapping ||
809ff05123SRyusuke Konishi 	    page_offset(page) >= i_size_read(inode) || !PageUptodate(page)) {
819ff05123SRyusuke Konishi 		unlock_page(page);
822c22b337SJan Kara 		ret = -EFAULT;	/* make the VM retry the fault */
832c22b337SJan Kara 		goto out;
849ff05123SRyusuke Konishi 	}
859ff05123SRyusuke Konishi 
869ff05123SRyusuke Konishi 	/*
879ff05123SRyusuke Konishi 	 * check to see if the page is mapped already (no holes)
889ff05123SRyusuke Konishi 	 */
8934094537SRyusuke Konishi 	if (PageMappedToDisk(page))
909ff05123SRyusuke Konishi 		goto mapped;
9134094537SRyusuke Konishi 
929ff05123SRyusuke Konishi 	if (page_has_buffers(page)) {
939ff05123SRyusuke Konishi 		struct buffer_head *bh, *head;
949ff05123SRyusuke Konishi 		int fully_mapped = 1;
959ff05123SRyusuke Konishi 
969ff05123SRyusuke Konishi 		bh = head = page_buffers(page);
979ff05123SRyusuke Konishi 		do {
989ff05123SRyusuke Konishi 			if (!buffer_mapped(bh)) {
999ff05123SRyusuke Konishi 				fully_mapped = 0;
1009ff05123SRyusuke Konishi 				break;
1019ff05123SRyusuke Konishi 			}
1029ff05123SRyusuke Konishi 		} while (bh = bh->b_this_page, bh != head);
1039ff05123SRyusuke Konishi 
1049ff05123SRyusuke Konishi 		if (fully_mapped) {
1059ff05123SRyusuke Konishi 			SetPageMappedToDisk(page);
1069ff05123SRyusuke Konishi 			goto mapped;
1079ff05123SRyusuke Konishi 		}
1089ff05123SRyusuke Konishi 	}
1099ff05123SRyusuke Konishi 	unlock_page(page);
1109ff05123SRyusuke Konishi 
1119ff05123SRyusuke Konishi 	/*
1129ff05123SRyusuke Konishi 	 * fill hole blocks
1139ff05123SRyusuke Konishi 	 */
1149ff05123SRyusuke Konishi 	ret = nilfs_transaction_begin(inode->i_sb, &ti, 1);
1159ff05123SRyusuke Konishi 	/* never returns -ENOMEM, but may return -ENOSPC */
1169ff05123SRyusuke Konishi 	if (unlikely(ret))
1172c22b337SJan Kara 		goto out;
1189ff05123SRyusuke Konishi 
119041bbb6dSTheodore Ts'o 	file_update_time(vma->vm_file);
1202c22b337SJan Kara 	ret = __block_page_mkwrite(vma, vmf, nilfs_get_block);
1212c22b337SJan Kara 	if (ret) {
1229ff05123SRyusuke Konishi 		nilfs_transaction_abort(inode->i_sb);
1232c22b337SJan Kara 		goto out;
1249ff05123SRyusuke Konishi 	}
12534094537SRyusuke Konishi 	nilfs_set_file_dirty(inode, 1 << (PAGE_SHIFT - inode->i_blkbits));
1269ff05123SRyusuke Konishi 	nilfs_transaction_commit(inode->i_sb);
1279ff05123SRyusuke Konishi 
1289ff05123SRyusuke Konishi  mapped:
1291d1d1a76SDarrick J. Wong 	wait_for_stable_page(page);
1302c22b337SJan Kara  out:
1312c22b337SJan Kara 	sb_end_pagefault(inode->i_sb);
1322c22b337SJan Kara 	return block_page_mkwrite_return(ret);
133f183ff4fSRyusuke Konishi }
134f183ff4fSRyusuke Konishi 
135f0f37e2fSAlexey Dobriyan static const struct vm_operations_struct nilfs_file_vm_ops = {
136f183ff4fSRyusuke Konishi 	.fault		= filemap_fault,
137f1820361SKirill A. Shutemov 	.map_pages	= filemap_map_pages,
138f183ff4fSRyusuke Konishi 	.page_mkwrite	= nilfs_page_mkwrite,
1390b173bc4SKonstantin Khlebnikov 	.remap_pages	= generic_file_remap_pages,
140f183ff4fSRyusuke Konishi };
141f183ff4fSRyusuke Konishi 
142f183ff4fSRyusuke Konishi static int nilfs_file_mmap(struct file *file, struct vm_area_struct *vma)
143f183ff4fSRyusuke Konishi {
144f183ff4fSRyusuke Konishi 	file_accessed(file);
145f183ff4fSRyusuke Konishi 	vma->vm_ops = &nilfs_file_vm_ops;
146f183ff4fSRyusuke Konishi 	return 0;
147f183ff4fSRyusuke Konishi }
148f183ff4fSRyusuke Konishi 
149f183ff4fSRyusuke Konishi /*
150f183ff4fSRyusuke Konishi  * We have mostly NULL's here: the current defaults are ok for
151f183ff4fSRyusuke Konishi  * the nilfs filesystem.
152f183ff4fSRyusuke Konishi  */
153828c0950SAlexey Dobriyan const struct file_operations nilfs_file_operations = {
154f183ff4fSRyusuke Konishi 	.llseek		= generic_file_llseek,
155aad4f8bbSAl Viro 	.read		= new_sync_read,
1568174202bSAl Viro 	.write		= new_sync_write,
157aad4f8bbSAl Viro 	.read_iter	= generic_file_read_iter,
1588174202bSAl Viro 	.write_iter	= generic_file_write_iter,
1597a946193SRyusuke Konishi 	.unlocked_ioctl	= nilfs_ioctl,
160f183ff4fSRyusuke Konishi #ifdef CONFIG_COMPAT
161828b1c50SRyusuke Konishi 	.compat_ioctl	= nilfs_compat_ioctl,
162f183ff4fSRyusuke Konishi #endif	/* CONFIG_COMPAT */
163f183ff4fSRyusuke Konishi 	.mmap		= nilfs_file_mmap,
164f183ff4fSRyusuke Konishi 	.open		= generic_file_open,
165f183ff4fSRyusuke Konishi 	/* .release	= nilfs_release_file, */
166f183ff4fSRyusuke Konishi 	.fsync		= nilfs_sync_file,
167f183ff4fSRyusuke Konishi 	.splice_read	= generic_file_splice_read,
168f183ff4fSRyusuke Konishi };
169f183ff4fSRyusuke Konishi 
1706e1d5dccSAlexey Dobriyan const struct inode_operations nilfs_file_inode_operations = {
171f183ff4fSRyusuke Konishi 	.setattr	= nilfs_setattr,
172f183ff4fSRyusuke Konishi 	.permission     = nilfs_permission,
173622daaffSRyusuke Konishi 	.fiemap		= nilfs_fiemap,
174f183ff4fSRyusuke Konishi };
175f183ff4fSRyusuke Konishi 
176f183ff4fSRyusuke Konishi /* end of file */
177