~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/ext4/fsync.c

Version: ~ [ linux-5.4-rc3 ] ~ [ linux-5.3.6 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.79 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.149 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.196 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.196 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.75 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/fs/ext4/fsync.c
  3  *
  4  *  Copyright (C) 1993  Stephen Tweedie (sct@redhat.com)
  5  *  from
  6  *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  7  *                      Laboratoire MASI - Institut Blaise Pascal
  8  *                      Universite Pierre et Marie Curie (Paris VI)
  9  *  from
 10  *  linux/fs/minix/truncate.c   Copyright (C) 1991, 1992  Linus Torvalds
 11  *
 12  *  ext4fs fsync primitive
 13  *
 14  *  Big-endian to little-endian byte-swapping/bitmaps by
 15  *        David S. Miller (davem@caip.rutgers.edu), 1995
 16  *
 17  *  Removed unnecessary code duplication for little endian machines
 18  *  and excessive __inline__s.
 19  *        Andi Kleen, 1997
 20  *
 21  * Major simplications and cleanup - we only need to do the metadata, because
 22  * we can depend on generic_block_fdatasync() to sync the data blocks.
 23  */
 24 
 25 #include <linux/time.h>
 26 #include <linux/fs.h>
 27 #include <linux/sched.h>
 28 #include <linux/writeback.h>
 29 #include <linux/jbd2.h>
 30 #include <linux/blkdev.h>
 31 
 32 #include "ext4.h"
 33 #include "ext4_jbd2.h"
 34 
 35 #include <trace/events/ext4.h>
 36 
 37 /*
 38  * If we're not journaling and this is a just-created file, we have to
 39  * sync our parent directory (if it was freshly created) since
 40  * otherwise it will only be written by writeback, leaving a huge
 41  * window during which a crash may lose the file.  This may apply for
 42  * the parent directory's parent as well, and so on recursively, if
 43  * they are also freshly created.
 44  */
 45 static int ext4_sync_parent(struct inode *inode)
 46 {
 47         struct dentry *dentry = NULL;
 48         struct inode *next;
 49         int ret = 0;
 50 
 51         if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY))
 52                 return 0;
 53         inode = igrab(inode);
 54         while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
 55                 ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
 56                 dentry = d_find_any_alias(inode);
 57                 if (!dentry)
 58                         break;
 59                 next = igrab(dentry->d_parent->d_inode);
 60                 dput(dentry);
 61                 if (!next)
 62                         break;
 63                 iput(inode);
 64                 inode = next;
 65                 ret = sync_mapping_buffers(inode->i_mapping);
 66                 if (ret)
 67                         break;
 68                 ret = sync_inode_metadata(inode, 1);
 69                 if (ret)
 70                         break;
 71         }
 72         iput(inode);
 73         return ret;
 74 }
 75 
 76 /*
 77  * akpm: A new design for ext4_sync_file().
 78  *
 79  * This is only called from sys_fsync(), sys_fdatasync() and sys_msync().
 80  * There cannot be a transaction open by this task.
 81  * Another task could have dirtied this inode.  Its data can be in any
 82  * state in the journalling system.
 83  *
 84  * What we do is just kick off a commit and wait on it.  This will snapshot the
 85  * inode to disk.
 86  */
 87 
 88 int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 89 {
 90         struct inode *inode = file->f_mapping->host;
 91         struct ext4_inode_info *ei = EXT4_I(inode);
 92         journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
 93         int ret = 0, err;
 94         tid_t commit_tid;
 95         bool needs_barrier = false;
 96 
 97         J_ASSERT(ext4_journal_current_handle() == NULL);
 98 
 99         trace_ext4_sync_file_enter(file, datasync);
100 
101         if (inode->i_sb->s_flags & MS_RDONLY) {
102                 /* Make sure that we read updated s_mount_flags value */
103                 smp_rmb();
104                 if (EXT4_SB(inode->i_sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
105                         ret = -EROFS;
106                 goto out;
107         }
108 
109         if (!journal) {
110                 ret = generic_file_fsync(file, start, end, datasync);
111                 if (!ret && !hlist_empty(&inode->i_dentry))
112                         ret = ext4_sync_parent(inode);
113                 goto out;
114         }
115 
116         ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
117         if (ret)
118                 return ret;
119         /*
120          * data=writeback,ordered:
121          *  The caller's filemap_fdatawrite()/wait will sync the data.
122          *  Metadata is in the journal, we wait for proper transaction to
123          *  commit here.
124          *
125          * data=journal:
126          *  filemap_fdatawrite won't do anything (the buffers are clean).
127          *  ext4_force_commit will write the file data into the journal and
128          *  will wait on that.
129          *  filemap_fdatawait() will encounter a ton of newly-dirtied pages
130          *  (they were dirtied by commit).  But that's OK - the blocks are
131          *  safe in-journal, which is all fsync() needs to ensure.
132          */
133         if (ext4_should_journal_data(inode)) {
134                 ret = ext4_force_commit(inode->i_sb);
135                 goto out;
136         }
137 
138         commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid;
139         if (journal->j_flags & JBD2_BARRIER &&
140             !jbd2_trans_will_send_data_barrier(journal, commit_tid))
141                 needs_barrier = true;
142         ret = jbd2_complete_transaction(journal, commit_tid);
143         if (needs_barrier) {
144                 err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
145                 if (!ret)
146                         ret = err;
147         }
148 out:
149         trace_ext4_sync_file_exit(inode, ret);
150         return ret;
151 }
152 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp