int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync) { struct inode *inode = file->f_mapping->host; struct ext3_inode_info *ei = EXT3_I(inode); journal_t *journal = EXT3_SB(inode->i_sb)->s_journal; int ret, needs_barrier = 0; tid_t commit_tid; trace_ext3_sync_file_enter(file, datasync); if (inode->i_sb->s_flags & MS_RDONLY) return 0; ret = filemap_write_and_wait_range(inode->i_mapping, start, end); if (ret) goto out; J_ASSERT(ext3_journal_current_handle() == NULL); /* * data=writeback,ordered: * The caller's filemap_fdatawrite()/wait will sync the data. * Metadata is in the journal, we wait for a proper transaction * to commit here. * * data=journal: * filemap_fdatawrite won't do anything (the buffers are clean). * ext3_force_commit will write the file data into the journal and * will wait on that. * filemap_fdatawait() will encounter a ton of newly-dirtied pages * (they were dirtied by commit). But that's OK - the blocks are * safe in-journal, which is all fsync() needs to ensure. */ if (ext3_should_journal_data(inode)) { ret = ext3_force_commit(inode->i_sb); goto out; } if (datasync) commit_tid = atomic_read(&ei->i_datasync_tid); else commit_tid = atomic_read(&ei->i_sync_tid); if (test_opt(inode->i_sb, BARRIER) && !journal_trans_will_send_data_barrier(journal, commit_tid)) needs_barrier = 1; log_start_commit(journal, commit_tid); ret = log_wait_commit(journal, commit_tid); /* * In case we didn't commit a transaction, we have to flush * disk caches manually so that data really is on persistent * storage */ if (needs_barrier) blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); out: trace_ext3_sync_file_exit(inode, ret); return ret; }
int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; int ret; J_ASSERT(ext3_journal_current_handle() == 0); /* * fsync_inode_buffers() just walks i_dirty_buffers and waits * on them. It's a no-op for full data journalling because * i_dirty_buffers will be ampty. * Really, we only need to start I/O on the dirty buffers - * we'll end up waiting on them in commit. */ ret = fsync_inode_buffers(inode); /* In writeback mode, we need to force out data buffers too. In * the other modes, ext3_force_commit takes care of forcing out * just the right data blocks. */ if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA) ret |= fsync_inode_data_buffers(inode); ext3_force_commit(inode->i_sb); return ret; }
static ssize_t ext3_file_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct file *file = iocb->ki_filp; struct inode *inode = file->f_dentry->d_inode; ssize_t ret; int err; ret = generic_file_aio_write(iocb, iov, nr_segs, pos); /* * Skip flushing if there was an error, or if nothing was written. */ if (ret <= 0) return ret; /* * If the inode is IS_SYNC, or is O_SYNC and we are doing data * journalling then we need to make sure that we force the transaction * to disk to keep all metadata uptodate synchronously. */ if (file->f_flags & O_SYNC) { /* * If we are non-data-journaled, then the dirty data has * already been flushed to backing store by generic_osync_inode, * and the inode has been flushed too if there have been any * modifications other than mere timestamp updates. * * Open question --- do we care about flushing timestamps too * if the inode is IS_SYNC? */ if (!ext3_should_journal_data(inode)) return ret; goto force_commit; } /* * So we know that there has been no forced data flush. If the inode * is marked IS_SYNC, we need to force one ourselves. */ if (!IS_SYNC(inode)) return ret; /* * Open question #2 --- should we force data to disk here too? If we * don't, the only impact is that data=writeback filesystems won't * flush data to disk automatically on IS_SYNC, only metadata (but * historically, that is what ext2 has done.) */ force_commit: err = ext3_force_commit(inode->i_sb); if (err) return err; return ret; }
int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; int ret = 0; J_ASSERT(ext3_journal_current_handle() == 0); /* * data=writeback: * The caller's filemap_fdatawrite()/wait will sync the data. * sync_inode() will sync the metadata * * data=ordered: * The caller's filemap_fdatawrite() will write the data and * sync_inode() will write the inode if it is dirty. Then the caller's * filemap_fdatawait() will wait on the pages. * * data=journal: * filemap_fdatawrite won't do anything (the buffers are clean). * ext3_force_commit will write the file data into the journal and * will wait on that. * filemap_fdatawait() will encounter a ton of newly-dirtied pages * (they were dirtied by commit). But that's OK - the blocks are * safe in-journal, which is all fsync() needs to ensure. */ if (ext3_should_journal_data(inode)) { ret = ext3_force_commit(inode->i_sb); goto out; } if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) goto flush; /* * The VFS has written the file data. If the inode is unaltered * then we need not start a commit. */ if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) { struct writeback_control wbc = { .sync_mode = WB_SYNC_ALL, .nr_to_write = 0, /* sys_fsync did this */ }; ret = sync_inode(inode, &wbc); goto out; } flush: /* * In case we didn't commit a transaction, we have to flush * disk caches manually so that data really is on persistent * storage */ if (test_opt(inode->i_sb, BARRIER)) blkdev_issue_flush(inode->i_sb->s_bdev, NULL); out: return ret; }
int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; struct ext3_inode_info *ei = EXT3_I(inode); journal_t *journal = EXT3_SB(inode->i_sb)->s_journal; int ret = 0; tid_t commit_tid; if (inode->i_sb->s_flags & MS_RDONLY) return 0; J_ASSERT(ext3_journal_current_handle() == NULL); /* * data=writeback,ordered: * The caller's filemap_fdatawrite()/wait will sync the data. * Metadata is in the journal, we wait for a proper transaction * to commit here. * * data=journal: * filemap_fdatawrite won't do anything (the buffers are clean). * ext3_force_commit will write the file data into the journal and * will wait on that. * filemap_fdatawait() will encounter a ton of newly-dirtied pages * (they were dirtied by commit). But that's OK - the blocks are * safe in-journal, which is all fsync() needs to ensure. */ if (ext3_should_journal_data(inode)) { ret = ext3_force_commit(inode->i_sb); goto out; } if (datasync) commit_tid = atomic_read(&ei->i_datasync_tid); else commit_tid = atomic_read(&ei->i_sync_tid); if (log_start_commit(journal, commit_tid)) { log_wait_commit(journal, commit_tid); goto out; } /* * In case we didn't commit a transaction, we have to flush * disk caches manually so that data really is on persistent * storage */ if (test_opt(inode->i_sb, BARRIER)) blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL, BLKDEV_IFL_WAIT); out: return ret; }
int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; int ret = 0; J_ASSERT(ext3_journal_current_handle() == NULL); /* * data=writeback: * The caller's filemap_fdatawrite()/wait will sync the data. * sync_inode() will sync the metadata * * data=ordered: * The caller's filemap_fdatawrite() will write the data and * sync_inode() will write the inode if it is dirty. Then the caller's * filemap_fdatawait() will wait on the pages. * * data=journal: * filemap_fdatawrite won't do anything (the buffers are clean). * ext3_force_commit will write the file data into the journal and * will wait on that. * filemap_fdatawait() will encounter a ton of newly-dirtied pages * (they were dirtied by commit). But that's OK - the blocks are * safe in-journal, which is all fsync() needs to ensure. */ if (ext3_should_journal_data(inode)) { ret = ext3_force_commit(inode->i_sb); goto out; } /* * The VFS has written the file data. If the inode is unaltered * then we need not start a commit. */ if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) { struct writeback_control wbc = { .sync_mode = WB_SYNC_ALL, .nr_to_write = 0, /* sys_fsync did this */ }; ret = sync_inode(inode, &wbc); } out: return ret; }