2018-09-04 15:46:30 -07:00
// SPDX-License-Identifier: GPL-2.0+
2009-04-06 19:01:33 -07:00
/*
2021-11-08 18:35:01 -08:00
* NILFS regular file handling primitives including fsync ( ) .
2009-04-06 19:01:33 -07:00
*
* Copyright ( C ) 2005 - 2008 Nippon Telegraph and Telephone Corporation .
*
2016-05-23 16:23:09 -07:00
* Written by Amagai Yoshiji and Ryusuke Konishi .
2009-04-06 19:01:33 -07:00
*/
# include <linux/fs.h>
# include <linux/mm.h>
# include <linux/writeback.h>
# include "nilfs.h"
# include "segment.h"
2011-07-16 20:44:56 -04:00
int nilfs_sync_file ( struct file * file , loff_t start , loff_t end , int datasync )
2009-04-06 19:01:33 -07:00
{
/*
* Called from fsync ( ) system call
* This is the only entry point that can catch write and synch
* timing for both data blocks and intermediate blocks .
*
* This function should be implemented when the writeback function
* will be implemented .
*/
2012-05-31 16:26:11 -07:00
struct the_nilfs * nilfs ;
2010-05-26 17:53:25 +02:00
struct inode * inode = file - > f_mapping - > host ;
2014-12-10 15:54:29 -08:00
int err = 0 ;
2011-07-16 20:44:56 -04:00
2012-05-31 16:26:11 -07:00
if ( nilfs_inode_dirty ( inode ) ) {
if ( datasync )
err = nilfs_construct_dsync_segment ( inode - > i_sb , inode ,
2014-12-10 15:54:29 -08:00
start , end ) ;
2012-05-31 16:26:11 -07:00
else
err = nilfs_construct_segment ( inode - > i_sb ) ;
2011-07-16 20:44:56 -04:00
}
2012-05-31 16:26:11 -07:00
nilfs = inode - > i_sb - > s_fs_info ;
2014-10-13 15:53:20 -07:00
if ( ! err )
err = nilfs_flush_device ( nilfs ) ;
2009-04-06 19:01:33 -07:00
return err ;
}
2018-08-21 21:59:08 -07:00
static vm_fault_t nilfs_page_mkwrite ( struct vm_fault * vmf )
2009-04-06 19:01:33 -07:00
{
2017-02-24 14:56:41 -08:00
struct vm_area_struct * vma = vmf - > vma ;
2023-11-14 17:44:27 +09:00
struct folio * folio = page_folio ( vmf - > page ) ;
2013-01-23 17:07:38 -05:00
struct inode * inode = file_inode ( vma - > vm_file ) ;
2009-04-06 19:01:37 -07:00
struct nilfs_transaction_info ti ;
2023-11-14 17:44:27 +09:00
struct buffer_head * bh , * head ;
2012-06-12 16:20:44 +02:00
int ret = 0 ;
2009-04-06 19:01:37 -07:00
2011-03-09 11:05:08 +09:00
if ( unlikely ( nilfs_near_disk_full ( inode - > i_sb - > s_fs_info ) ) )
2009-04-06 19:01:37 -07:00
return VM_FAULT_SIGBUS ; /* -ENOSPC */
2012-06-12 16:20:44 +02:00
sb_start_pagefault ( inode - > i_sb ) ;
2023-11-14 17:44:27 +09:00
folio_lock ( folio ) ;
if ( folio - > mapping ! = inode - > i_mapping | |
folio_pos ( folio ) > = i_size_read ( inode ) | |
! folio_test_uptodate ( folio ) ) {
folio_unlock ( folio ) ;
2012-06-12 16:20:44 +02:00
ret = - EFAULT ; /* make the VM retry the fault */
goto out ;
2009-04-06 19:01:37 -07:00
}
/*
2023-11-14 17:44:27 +09:00
* check to see if the folio is mapped already ( no holes )
2009-04-06 19:01:37 -07:00
*/
2023-11-14 17:44:27 +09:00
if ( folio_test_mappedtodisk ( folio ) )
2009-04-06 19:01:37 -07:00
goto mapped ;
2011-03-27 22:50:49 +09:00
2023-11-14 17:44:27 +09:00
head = folio_buffers ( folio ) ;
if ( head ) {
2009-04-06 19:01:37 -07:00
int fully_mapped = 1 ;
2023-11-14 17:44:27 +09:00
bh = head ;
2009-04-06 19:01:37 -07:00
do {
if ( ! buffer_mapped ( bh ) ) {
fully_mapped = 0 ;
break ;
}
} while ( bh = bh - > b_this_page , bh ! = head ) ;
if ( fully_mapped ) {
2023-11-14 17:44:27 +09:00
folio_set_mappedtodisk ( folio ) ;
2009-04-06 19:01:37 -07:00
goto mapped ;
}
}
2023-11-14 17:44:27 +09:00
folio_unlock ( folio ) ;
2009-04-06 19:01:37 -07:00
/*
* fill hole blocks
*/
ret = nilfs_transaction_begin ( inode - > i_sb , & ti , 1 ) ;
/* never returns -ENOMEM, but may return -ENOSPC */
if ( unlikely ( ret ) )
2012-06-12 16:20:44 +02:00
goto out ;
2009-04-06 19:01:37 -07:00
2012-09-30 23:04:56 -04:00
file_update_time ( vma - > vm_file ) ;
2015-10-13 16:51:02 -06:00
ret = block_page_mkwrite ( vma , vmf , nilfs_get_block ) ;
2012-06-12 16:20:44 +02:00
if ( ret ) {
2009-04-06 19:01:37 -07:00
nilfs_transaction_abort ( inode - > i_sb ) ;
2012-06-12 16:20:44 +02:00
goto out ;
2009-04-06 19:01:37 -07:00
}
2011-03-27 22:50:49 +09:00
nilfs_set_file_dirty ( inode , 1 < < ( PAGE_SHIFT - inode - > i_blkbits ) ) ;
2009-04-06 19:01:37 -07:00
nilfs_transaction_commit ( inode - > i_sb ) ;
mapped :
2024-01-31 23:56:57 +09:00
/*
* Since checksumming including data blocks is performed to determine
* the validity of the log to be written and used for recovery , it is
* necessary to wait for writeback to finish here , regardless of the
* stable write requirement of the backing device .
*/
folio_wait_writeback ( folio ) ;
2012-06-12 16:20:44 +02:00
out :
sb_end_pagefault ( inode - > i_sb ) ;
2023-08-01 19:21:57 +02:00
return vmf_fs_error ( ret ) ;
2009-04-06 19:01:33 -07:00
}
2009-09-27 22:29:37 +04:00
static const struct vm_operations_struct nilfs_file_vm_ops = {
2009-04-06 19:01:33 -07:00
. fault = filemap_fault ,
2014-04-07 15:37:19 -07:00
. map_pages = filemap_map_pages ,
2009-04-06 19:01:33 -07:00
. page_mkwrite = nilfs_page_mkwrite ,
} ;
static int nilfs_file_mmap ( struct file * file , struct vm_area_struct * vma )
{
file_accessed ( file ) ;
vma - > vm_ops = & nilfs_file_vm_ops ;
return 0 ;
}
/*
* We have mostly NULL ' s here : the current defaults are ok for
* the nilfs filesystem .
*/
2009-10-01 15:43:56 -07:00
const struct file_operations nilfs_file_operations = {
2009-04-06 19:01:33 -07:00
. llseek = generic_file_llseek ,
2014-04-02 14:33:16 -04:00
. read_iter = generic_file_read_iter ,
2014-04-03 03:17:43 -04:00
. write_iter = generic_file_write_iter ,
2009-04-06 19:01:53 -07:00
. unlocked_ioctl = nilfs_ioctl ,
2009-04-06 19:01:33 -07:00
# ifdef CONFIG_COMPAT
2011-02-03 21:26:17 +09:00
. compat_ioctl = nilfs_compat_ioctl ,
2009-04-06 19:01:33 -07:00
# endif /* CONFIG_COMPAT */
. mmap = nilfs_file_mmap ,
. open = generic_file_open ,
/* .release = nilfs_release_file, */
. fsync = nilfs_sync_file ,
2023-05-22 14:50:15 +01:00
. splice_read = filemap_splice_read ,
2021-02-09 13:42:36 -08:00
. splice_write = iter_file_splice_write ,
2009-04-06 19:01:33 -07:00
} ;
2009-09-21 17:01:11 -07:00
const struct inode_operations nilfs_file_inode_operations = {
2009-04-06 19:01:33 -07:00
. setattr = nilfs_setattr ,
. permission = nilfs_permission ,
2010-12-26 16:38:43 +09:00
. fiemap = nilfs_fiemap ,
2021-04-07 14:36:44 +02:00
. fileattr_get = nilfs_fileattr_get ,
. fileattr_set = nilfs_fileattr_set ,
2009-04-06 19:01:33 -07:00
} ;
/* end of file */