18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * High-level sync()-related operations 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/kernel.h> 78c2ecf20Sopenharmony_ci#include <linux/file.h> 88c2ecf20Sopenharmony_ci#include <linux/fs.h> 98c2ecf20Sopenharmony_ci#include <linux/slab.h> 108c2ecf20Sopenharmony_ci#include <linux/export.h> 118c2ecf20Sopenharmony_ci#include <linux/namei.h> 128c2ecf20Sopenharmony_ci#include <linux/sched.h> 138c2ecf20Sopenharmony_ci#include <linux/writeback.h> 148c2ecf20Sopenharmony_ci#include <linux/syscalls.h> 158c2ecf20Sopenharmony_ci#include <linux/linkage.h> 168c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 178c2ecf20Sopenharmony_ci#include <linux/quotaops.h> 188c2ecf20Sopenharmony_ci#include <linux/backing-dev.h> 198c2ecf20Sopenharmony_ci#include "internal.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ 228c2ecf20Sopenharmony_ci SYNC_FILE_RANGE_WAIT_AFTER) 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* 258c2ecf20Sopenharmony_ci * Write out and wait upon all dirty data associated with this 268c2ecf20Sopenharmony_ci * superblock. Filesystem data as well as the underlying block 278c2ecf20Sopenharmony_ci * device. Takes the superblock lock. 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_ciint sync_filesystem(struct super_block *sb) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci int ret = 0; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci /* 348c2ecf20Sopenharmony_ci * We need to be protected against the filesystem going from 358c2ecf20Sopenharmony_ci * r/o to r/w or vice versa. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci WARN_ON(!rwsem_is_locked(&sb->s_umount)); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci /* 408c2ecf20Sopenharmony_ci * No point in syncing out anything if the filesystem is read-only. 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_ci if (sb_rdonly(sb)) 438c2ecf20Sopenharmony_ci return 0; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* 468c2ecf20Sopenharmony_ci * Do the filesystem syncing work. For simple filesystems 478c2ecf20Sopenharmony_ci * writeback_inodes_sb(sb) just dirties buffers with inodes so we have 488c2ecf20Sopenharmony_ci * to submit I/O for these buffers via __sync_blockdev(). This also 498c2ecf20Sopenharmony_ci * speeds up the wait == 1 case since in that case write_inode() 508c2ecf20Sopenharmony_ci * methods call sync_dirty_buffer() and thus effectively write one block 518c2ecf20Sopenharmony_ci * at a time. 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_ci writeback_inodes_sb(sb, WB_REASON_SYNC); 548c2ecf20Sopenharmony_ci if (sb->s_op->sync_fs) { 558c2ecf20Sopenharmony_ci ret = sb->s_op->sync_fs(sb, 0); 568c2ecf20Sopenharmony_ci if (ret) 578c2ecf20Sopenharmony_ci return ret; 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci ret = __sync_blockdev(sb->s_bdev, 0); 608c2ecf20Sopenharmony_ci if (ret) 618c2ecf20Sopenharmony_ci return ret; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci sync_inodes_sb(sb); 648c2ecf20Sopenharmony_ci if (sb->s_op->sync_fs) { 658c2ecf20Sopenharmony_ci ret = sb->s_op->sync_fs(sb, 1); 668c2ecf20Sopenharmony_ci if (ret) 678c2ecf20Sopenharmony_ci return ret; 688c2ecf20Sopenharmony_ci } 698c2ecf20Sopenharmony_ci return __sync_blockdev(sb->s_bdev, 1); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sync_filesystem); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic void sync_inodes_one_sb(struct super_block *sb, void *arg) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) 768c2ecf20Sopenharmony_ci sync_inodes_sb(sb); 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic void sync_fs_one_sb(struct super_block *sb, void *arg) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci if (!sb_rdonly(sb) && !(sb->s_iflags & SB_I_SKIP_SYNC) && 828c2ecf20Sopenharmony_ci sb->s_op->sync_fs) 838c2ecf20Sopenharmony_ci sb->s_op->sync_fs(sb, *(int *)arg); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic void fdatawrite_one_bdev(struct block_device *bdev, void *arg) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci filemap_fdatawrite(bdev->bd_inode->i_mapping); 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic void fdatawait_one_bdev(struct block_device *bdev, void *arg) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci /* 948c2ecf20Sopenharmony_ci * We keep the error status of individual mapping so that 958c2ecf20Sopenharmony_ci * applications can catch the writeback error using fsync(2). 968c2ecf20Sopenharmony_ci * See filemap_fdatawait_keep_errors() for details. 978c2ecf20Sopenharmony_ci */ 988c2ecf20Sopenharmony_ci filemap_fdatawait_keep_errors(bdev->bd_inode->i_mapping); 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* 1028c2ecf20Sopenharmony_ci * Sync everything. We start by waking flusher threads so that most of 1038c2ecf20Sopenharmony_ci * writeback runs on all devices in parallel. Then we sync all inodes reliably 1048c2ecf20Sopenharmony_ci * which effectively also waits for all flusher threads to finish doing 1058c2ecf20Sopenharmony_ci * writeback. At this point all data is on disk so metadata should be stable 1068c2ecf20Sopenharmony_ci * and we tell filesystems to sync their metadata via ->sync_fs() calls. 1078c2ecf20Sopenharmony_ci * Finally, we writeout all block devices because some filesystems (e.g. ext2) 1088c2ecf20Sopenharmony_ci * just write metadata (such as inodes or bitmaps) to block device page cache 1098c2ecf20Sopenharmony_ci * and do not sync it on their own in ->sync_fs(). 1108c2ecf20Sopenharmony_ci */ 1118c2ecf20Sopenharmony_civoid ksys_sync(void) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci int nowait = 0, wait = 1; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci wakeup_flusher_threads(WB_REASON_SYNC); 1168c2ecf20Sopenharmony_ci iterate_supers(sync_inodes_one_sb, NULL); 1178c2ecf20Sopenharmony_ci iterate_supers(sync_fs_one_sb, &nowait); 1188c2ecf20Sopenharmony_ci iterate_supers(sync_fs_one_sb, &wait); 1198c2ecf20Sopenharmony_ci iterate_bdevs(fdatawrite_one_bdev, NULL); 1208c2ecf20Sopenharmony_ci iterate_bdevs(fdatawait_one_bdev, NULL); 1218c2ecf20Sopenharmony_ci if (unlikely(laptop_mode)) 1228c2ecf20Sopenharmony_ci laptop_sync_completion(); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ciSYSCALL_DEFINE0(sync) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci ksys_sync(); 1288c2ecf20Sopenharmony_ci return 0; 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic void do_sync_work(struct work_struct *work) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci int nowait = 0; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci /* 1368c2ecf20Sopenharmony_ci * Sync twice to reduce the possibility we skipped some inodes / pages 1378c2ecf20Sopenharmony_ci * because they were temporarily locked 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci iterate_supers(sync_inodes_one_sb, &nowait); 1408c2ecf20Sopenharmony_ci iterate_supers(sync_fs_one_sb, &nowait); 1418c2ecf20Sopenharmony_ci iterate_bdevs(fdatawrite_one_bdev, NULL); 1428c2ecf20Sopenharmony_ci iterate_supers(sync_inodes_one_sb, &nowait); 1438c2ecf20Sopenharmony_ci iterate_supers(sync_fs_one_sb, &nowait); 1448c2ecf20Sopenharmony_ci iterate_bdevs(fdatawrite_one_bdev, NULL); 1458c2ecf20Sopenharmony_ci printk("Emergency Sync complete\n"); 1468c2ecf20Sopenharmony_ci kfree(work); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_civoid emergency_sync(void) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci struct work_struct *work; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci work = kmalloc(sizeof(*work), GFP_ATOMIC); 1548c2ecf20Sopenharmony_ci if (work) { 1558c2ecf20Sopenharmony_ci INIT_WORK(work, do_sync_work); 1568c2ecf20Sopenharmony_ci schedule_work(work); 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* 1618c2ecf20Sopenharmony_ci * sync a single super 1628c2ecf20Sopenharmony_ci */ 1638c2ecf20Sopenharmony_ciSYSCALL_DEFINE1(syncfs, int, fd) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci struct fd f = fdget(fd); 1668c2ecf20Sopenharmony_ci struct super_block *sb; 1678c2ecf20Sopenharmony_ci int ret, ret2; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci if (!f.file) 1708c2ecf20Sopenharmony_ci return -EBADF; 1718c2ecf20Sopenharmony_ci sb = f.file->f_path.dentry->d_sb; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci down_read(&sb->s_umount); 1748c2ecf20Sopenharmony_ci ret = sync_filesystem(sb); 1758c2ecf20Sopenharmony_ci up_read(&sb->s_umount); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci ret2 = errseq_check_and_advance(&sb->s_wb_err, &f.file->f_sb_err); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci fdput(f); 1808c2ecf20Sopenharmony_ci return ret ? ret : ret2; 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci/** 1848c2ecf20Sopenharmony_ci * vfs_fsync_range - helper to sync a range of data & metadata to disk 1858c2ecf20Sopenharmony_ci * @file: file to sync 1868c2ecf20Sopenharmony_ci * @start: offset in bytes of the beginning of data range to sync 1878c2ecf20Sopenharmony_ci * @end: offset in bytes of the end of data range (inclusive) 1888c2ecf20Sopenharmony_ci * @datasync: perform only datasync 1898c2ecf20Sopenharmony_ci * 1908c2ecf20Sopenharmony_ci * Write back data in range @start..@end and metadata for @file to disk. If 1918c2ecf20Sopenharmony_ci * @datasync is set only metadata needed to access modified file data is 1928c2ecf20Sopenharmony_ci * written. 1938c2ecf20Sopenharmony_ci */ 1948c2ecf20Sopenharmony_ciint vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci struct inode *inode = file->f_mapping->host; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci if (!file->f_op->fsync) 1998c2ecf20Sopenharmony_ci return -EINVAL; 2008c2ecf20Sopenharmony_ci if (!datasync && (inode->i_state & I_DIRTY_TIME)) 2018c2ecf20Sopenharmony_ci mark_inode_dirty_sync(inode); 2028c2ecf20Sopenharmony_ci return file->f_op->fsync(file, start, end, datasync); 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vfs_fsync_range); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci/** 2078c2ecf20Sopenharmony_ci * vfs_fsync - perform a fsync or fdatasync on a file 2088c2ecf20Sopenharmony_ci * @file: file to sync 2098c2ecf20Sopenharmony_ci * @datasync: only perform a fdatasync operation 2108c2ecf20Sopenharmony_ci * 2118c2ecf20Sopenharmony_ci * Write back data and metadata for @file to disk. If @datasync is 2128c2ecf20Sopenharmony_ci * set only metadata needed to access modified file data is written. 2138c2ecf20Sopenharmony_ci */ 2148c2ecf20Sopenharmony_ciint vfs_fsync(struct file *file, int datasync) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci return vfs_fsync_range(file, 0, LLONG_MAX, datasync); 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vfs_fsync); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic int do_fsync(unsigned int fd, int datasync) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci struct fd f = fdget(fd); 2238c2ecf20Sopenharmony_ci int ret = -EBADF; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci if (f.file) { 2268c2ecf20Sopenharmony_ci ret = vfs_fsync(f.file, datasync); 2278c2ecf20Sopenharmony_ci fdput(f); 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci return ret; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ciSYSCALL_DEFINE1(fsync, unsigned int, fd) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci return do_fsync(fd, 0); 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ciSYSCALL_DEFINE1(fdatasync, unsigned int, fd) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci return do_fsync(fd, 1); 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ciint sync_file_range(struct file *file, loff_t offset, loff_t nbytes, 2438c2ecf20Sopenharmony_ci unsigned int flags) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci int ret; 2468c2ecf20Sopenharmony_ci struct address_space *mapping; 2478c2ecf20Sopenharmony_ci loff_t endbyte; /* inclusive */ 2488c2ecf20Sopenharmony_ci umode_t i_mode; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci ret = -EINVAL; 2518c2ecf20Sopenharmony_ci if (flags & ~VALID_FLAGS) 2528c2ecf20Sopenharmony_ci goto out; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci endbyte = offset + nbytes; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci if ((s64)offset < 0) 2578c2ecf20Sopenharmony_ci goto out; 2588c2ecf20Sopenharmony_ci if ((s64)endbyte < 0) 2598c2ecf20Sopenharmony_ci goto out; 2608c2ecf20Sopenharmony_ci if (endbyte < offset) 2618c2ecf20Sopenharmony_ci goto out; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (sizeof(pgoff_t) == 4) { 2648c2ecf20Sopenharmony_ci if (offset >= (0x100000000ULL << PAGE_SHIFT)) { 2658c2ecf20Sopenharmony_ci /* 2668c2ecf20Sopenharmony_ci * The range starts outside a 32 bit machine's 2678c2ecf20Sopenharmony_ci * pagecache addressing capabilities. Let it "succeed" 2688c2ecf20Sopenharmony_ci */ 2698c2ecf20Sopenharmony_ci ret = 0; 2708c2ecf20Sopenharmony_ci goto out; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci if (endbyte >= (0x100000000ULL << PAGE_SHIFT)) { 2738c2ecf20Sopenharmony_ci /* 2748c2ecf20Sopenharmony_ci * Out to EOF 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_ci nbytes = 0; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci } 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci if (nbytes == 0) 2818c2ecf20Sopenharmony_ci endbyte = LLONG_MAX; 2828c2ecf20Sopenharmony_ci else 2838c2ecf20Sopenharmony_ci endbyte--; /* inclusive */ 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci i_mode = file_inode(file)->i_mode; 2868c2ecf20Sopenharmony_ci ret = -ESPIPE; 2878c2ecf20Sopenharmony_ci if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) && 2888c2ecf20Sopenharmony_ci !S_ISLNK(i_mode)) 2898c2ecf20Sopenharmony_ci goto out; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci mapping = file->f_mapping; 2928c2ecf20Sopenharmony_ci ret = 0; 2938c2ecf20Sopenharmony_ci if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) { 2948c2ecf20Sopenharmony_ci ret = file_fdatawait_range(file, offset, endbyte); 2958c2ecf20Sopenharmony_ci if (ret < 0) 2968c2ecf20Sopenharmony_ci goto out; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci if (flags & SYNC_FILE_RANGE_WRITE) { 3008c2ecf20Sopenharmony_ci int sync_mode = WB_SYNC_NONE; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if ((flags & SYNC_FILE_RANGE_WRITE_AND_WAIT) == 3038c2ecf20Sopenharmony_ci SYNC_FILE_RANGE_WRITE_AND_WAIT) 3048c2ecf20Sopenharmony_ci sync_mode = WB_SYNC_ALL; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci ret = __filemap_fdatawrite_range(mapping, offset, endbyte, 3078c2ecf20Sopenharmony_ci sync_mode); 3088c2ecf20Sopenharmony_ci if (ret < 0) 3098c2ecf20Sopenharmony_ci goto out; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci if (flags & SYNC_FILE_RANGE_WAIT_AFTER) 3138c2ecf20Sopenharmony_ci ret = file_fdatawait_range(file, offset, endbyte); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ciout: 3168c2ecf20Sopenharmony_ci return ret; 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci/* 3208c2ecf20Sopenharmony_ci * ksys_sync_file_range() permits finely controlled syncing over a segment of 3218c2ecf20Sopenharmony_ci * a file in the range offset .. (offset+nbytes-1) inclusive. If nbytes is 3228c2ecf20Sopenharmony_ci * zero then ksys_sync_file_range() will operate from offset out to EOF. 3238c2ecf20Sopenharmony_ci * 3248c2ecf20Sopenharmony_ci * The flag bits are: 3258c2ecf20Sopenharmony_ci * 3268c2ecf20Sopenharmony_ci * SYNC_FILE_RANGE_WAIT_BEFORE: wait upon writeout of all pages in the range 3278c2ecf20Sopenharmony_ci * before performing the write. 3288c2ecf20Sopenharmony_ci * 3298c2ecf20Sopenharmony_ci * SYNC_FILE_RANGE_WRITE: initiate writeout of all those dirty pages in the 3308c2ecf20Sopenharmony_ci * range which are not presently under writeback. Note that this may block for 3318c2ecf20Sopenharmony_ci * significant periods due to exhaustion of disk request structures. 3328c2ecf20Sopenharmony_ci * 3338c2ecf20Sopenharmony_ci * SYNC_FILE_RANGE_WAIT_AFTER: wait upon writeout of all pages in the range 3348c2ecf20Sopenharmony_ci * after performing the write. 3358c2ecf20Sopenharmony_ci * 3368c2ecf20Sopenharmony_ci * Useful combinations of the flag bits are: 3378c2ecf20Sopenharmony_ci * 3388c2ecf20Sopenharmony_ci * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE: ensures that all pages 3398c2ecf20Sopenharmony_ci * in the range which were dirty on entry to ksys_sync_file_range() are placed 3408c2ecf20Sopenharmony_ci * under writeout. This is a start-write-for-data-integrity operation. 3418c2ecf20Sopenharmony_ci * 3428c2ecf20Sopenharmony_ci * SYNC_FILE_RANGE_WRITE: start writeout of all dirty pages in the range which 3438c2ecf20Sopenharmony_ci * are not presently under writeout. This is an asynchronous flush-to-disk 3448c2ecf20Sopenharmony_ci * operation. Not suitable for data integrity operations. 3458c2ecf20Sopenharmony_ci * 3468c2ecf20Sopenharmony_ci * SYNC_FILE_RANGE_WAIT_BEFORE (or SYNC_FILE_RANGE_WAIT_AFTER): wait for 3478c2ecf20Sopenharmony_ci * completion of writeout of all pages in the range. This will be used after an 3488c2ecf20Sopenharmony_ci * earlier SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE operation to wait 3498c2ecf20Sopenharmony_ci * for that operation to complete and to return the result. 3508c2ecf20Sopenharmony_ci * 3518c2ecf20Sopenharmony_ci * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER 3528c2ecf20Sopenharmony_ci * (a.k.a. SYNC_FILE_RANGE_WRITE_AND_WAIT): 3538c2ecf20Sopenharmony_ci * a traditional sync() operation. This is a write-for-data-integrity operation 3548c2ecf20Sopenharmony_ci * which will ensure that all pages in the range which were dirty on entry to 3558c2ecf20Sopenharmony_ci * ksys_sync_file_range() are written to disk. It should be noted that disk 3568c2ecf20Sopenharmony_ci * caches are not flushed by this call, so there are no guarantees here that the 3578c2ecf20Sopenharmony_ci * data will be available on disk after a crash. 3588c2ecf20Sopenharmony_ci * 3598c2ecf20Sopenharmony_ci * 3608c2ecf20Sopenharmony_ci * SYNC_FILE_RANGE_WAIT_BEFORE and SYNC_FILE_RANGE_WAIT_AFTER will detect any 3618c2ecf20Sopenharmony_ci * I/O errors or ENOSPC conditions and will return those to the caller, after 3628c2ecf20Sopenharmony_ci * clearing the EIO and ENOSPC flags in the address_space. 3638c2ecf20Sopenharmony_ci * 3648c2ecf20Sopenharmony_ci * It should be noted that none of these operations write out the file's 3658c2ecf20Sopenharmony_ci * metadata. So unless the application is strictly performing overwrites of 3668c2ecf20Sopenharmony_ci * already-instantiated disk blocks, there are no guarantees here that the data 3678c2ecf20Sopenharmony_ci * will be available after a crash. 3688c2ecf20Sopenharmony_ci */ 3698c2ecf20Sopenharmony_ciint ksys_sync_file_range(int fd, loff_t offset, loff_t nbytes, 3708c2ecf20Sopenharmony_ci unsigned int flags) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci int ret; 3738c2ecf20Sopenharmony_ci struct fd f; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci ret = -EBADF; 3768c2ecf20Sopenharmony_ci f = fdget(fd); 3778c2ecf20Sopenharmony_ci if (f.file) 3788c2ecf20Sopenharmony_ci ret = sync_file_range(f.file, offset, nbytes, flags); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci fdput(f); 3818c2ecf20Sopenharmony_ci return ret; 3828c2ecf20Sopenharmony_ci} 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ciSYSCALL_DEFINE4(sync_file_range, int, fd, loff_t, offset, loff_t, nbytes, 3858c2ecf20Sopenharmony_ci unsigned int, flags) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci return ksys_sync_file_range(fd, offset, nbytes, flags); 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci/* It would be nice if people remember that not all the world's an i386 3918c2ecf20Sopenharmony_ci when they introduce new system calls */ 3928c2ecf20Sopenharmony_ciSYSCALL_DEFINE4(sync_file_range2, int, fd, unsigned int, flags, 3938c2ecf20Sopenharmony_ci loff_t, offset, loff_t, nbytes) 3948c2ecf20Sopenharmony_ci{ 3958c2ecf20Sopenharmony_ci return ksys_sync_file_range(fd, offset, nbytes, flags); 3968c2ecf20Sopenharmony_ci} 397