Blame view
fs/ext4/fsync.c
5.02 KB
ac27a0ec1
|
1 |
/* |
617ba13b3
|
2 |
* linux/fs/ext4/fsync.c |
ac27a0ec1
|
3 4 5 6 7 8 9 10 11 |
* * Copyright (C) 1993 Stephen Tweedie (sct@redhat.com) * from * Copyright (C) 1992 Remy Card (card@masi.ibp.fr) * Laboratoire MASI - Institut Blaise Pascal * Universite Pierre et Marie Curie (Paris VI) * from * linux/fs/minix/truncate.c Copyright (C) 1991, 1992 Linus Torvalds * |
617ba13b3
|
12 |
* ext4fs fsync primitive |
ac27a0ec1
|
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
* * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 * * Removed unnecessary code duplication for little endian machines * and excessive __inline__s. * Andi Kleen, 1997 * * Major simplications and cleanup - we only need to do the metadata, because * we can depend on generic_block_fdatasync() to sync the data blocks. */ #include <linux/time.h> #include <linux/fs.h> #include <linux/sched.h> #include <linux/writeback.h> |
dab291af8
|
29 |
#include <linux/jbd2.h> |
d755fb384
|
30 |
#include <linux/blkdev.h> |
9bffad1ed
|
31 |
|
3dcf54515
|
32 33 |
#include "ext4.h" #include "ext4_jbd2.h" |
ac27a0ec1
|
34 |
|
9bffad1ed
|
35 |
#include <trace/events/ext4.h> |
ac27a0ec1
|
36 |
/* |
14ece1028
|
37 38 39 40 41 42 43 |
* If we're not journaling and this is a just-created file, we have to * sync our parent directory (if it was freshly created) since * otherwise it will only be written by writeback, leaving a huge * window during which a crash may lose the file. This may apply for * the parent directory's parent as well, and so on recursively, if * they are also freshly created. */ |
0893ed458
|
44 |
static int ext4_sync_parent(struct inode *inode) |
14ece1028
|
45 46 |
{ struct dentry *dentry = NULL; |
d59729f4e
|
47 |
struct inode *next; |
0893ed458
|
48 |
int ret = 0; |
14ece1028
|
49 |
|
d59729f4e
|
50 51 52 53 |
if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) return 0; inode = igrab(inode); while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) { |
14ece1028
|
54 |
ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY); |
9f713878f
|
55 |
dentry = d_find_any_alias(inode); |
d59729f4e
|
56 |
if (!dentry) |
14ece1028
|
57 |
break; |
d59729f4e
|
58 59 60 61 62 63 |
next = igrab(dentry->d_parent->d_inode); dput(dentry); if (!next) break; iput(inode); inode = next; |
0893ed458
|
64 65 66 |
ret = sync_mapping_buffers(inode->i_mapping); if (ret) break; |
64744e03c
|
67 |
ret = sync_inode_metadata(inode, 1); |
0893ed458
|
68 69 |
if (ret) break; |
14ece1028
|
70 |
} |
d59729f4e
|
71 |
iput(inode); |
0893ed458
|
72 |
return ret; |
14ece1028
|
73 |
} |
02c24a821
|
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
/** * __sync_file - generic_file_fsync without the locking and filemap_write * @inode: inode to sync * @datasync: only sync essential metadata if true * * This is just generic_file_fsync without the locking. This is needed for * nojournal mode to make sure this inodes data/metadata makes it to disk * properly. The i_mutex should be held already. */ static int __sync_inode(struct inode *inode, int datasync) { int err; int ret; ret = sync_mapping_buffers(inode->i_mapping); if (!(inode->i_state & I_DIRTY)) return ret; if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) return ret; err = sync_inode_metadata(inode, 1); if (ret == 0) ret = err; return ret; } |
14ece1028
|
99 |
/* |
617ba13b3
|
100 |
* akpm: A new design for ext4_sync_file(). |
ac27a0ec1
|
101 102 103 104 105 106 107 108 |
* * This is only called from sys_fsync(), sys_fdatasync() and sys_msync(). * There cannot be a transaction open by this task. * Another task could have dirtied this inode. Its data can be in any * state in the journalling system. * * What we do is just kick off a commit and wait on it. This will snapshot the * inode to disk. |
8d5d02e6b
|
109 110 |
* * i_mutex lock is held when entering and exiting this function |
ac27a0ec1
|
111 |
*/ |
02c24a821
|
112 |
int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) |
ac27a0ec1
|
113 |
{ |
7ea808591
|
114 |
struct inode *inode = file->f_mapping->host; |
b436b9bef
|
115 |
struct ext4_inode_info *ei = EXT4_I(inode); |
d755fb384
|
116 |
journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; |
a4a39040e
|
117 |
int ret, err; |
b436b9bef
|
118 |
tid_t commit_tid; |
93628ffb9
|
119 |
bool needs_barrier = false; |
ac27a0ec1
|
120 |
|
ac39849dd
|
121 |
J_ASSERT(ext4_journal_current_handle() == NULL); |
ac27a0ec1
|
122 |
|
0562e0bad
|
123 |
trace_ext4_sync_file_enter(file, datasync); |
ede86cc47
|
124 |
|
02c24a821
|
125 126 127 128 |
ret = filemap_write_and_wait_range(inode->i_mapping, start, end); if (ret) return ret; mutex_lock(&inode->i_mutex); |
b436b9bef
|
129 |
if (inode->i_sb->s_flags & MS_RDONLY) |
02c24a821
|
130 |
goto out; |
b436b9bef
|
131 |
|
c278531d3
|
132 |
ret = ext4_flush_unwritten_io(inode); |
8d5d02e6b
|
133 |
if (ret < 0) |
0562e0bad
|
134 |
goto out; |
60e6679e2
|
135 |
|
14ece1028
|
136 |
if (!journal) { |
02c24a821
|
137 |
ret = __sync_inode(inode, datasync); |
b3d9b7a3c
|
138 |
if (!ret && !hlist_empty(&inode->i_dentry)) |
0893ed458
|
139 |
ret = ext4_sync_parent(inode); |
0562e0bad
|
140 |
goto out; |
14ece1028
|
141 |
} |
b436b9bef
|
142 |
|
ac27a0ec1
|
143 |
/* |
b436b9bef
|
144 |
* data=writeback,ordered: |
ac27a0ec1
|
145 |
* The caller's filemap_fdatawrite()/wait will sync the data. |
b436b9bef
|
146 147 |
* Metadata is in the journal, we wait for proper transaction to * commit here. |
ac27a0ec1
|
148 149 150 |
* * data=journal: * filemap_fdatawrite won't do anything (the buffers are clean). |
617ba13b3
|
151 |
* ext4_force_commit will write the file data into the journal and |
ac27a0ec1
|
152 153 154 155 156 |
* 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. */ |
0562e0bad
|
157 158 159 160 |
if (ext4_should_journal_data(inode)) { ret = ext4_force_commit(inode->i_sb); goto out; } |
ac27a0ec1
|
161 |
|
b436b9bef
|
162 |
commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid; |
93628ffb9
|
163 164 165 166 167 |
if (journal->j_flags & JBD2_BARRIER && !jbd2_trans_will_send_data_barrier(journal, commit_tid)) needs_barrier = true; jbd2_log_start_commit(journal, commit_tid); ret = jbd2_log_wait_commit(journal, commit_tid); |
a4a39040e
|
168 169 170 171 172 |
if (needs_barrier) { err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); if (!ret) ret = err; } |
0562e0bad
|
173 |
out: |
02c24a821
|
174 |
mutex_unlock(&inode->i_mutex); |
0562e0bad
|
175 |
trace_ext4_sync_file_exit(inode, ret); |
ac27a0ec1
|
176 177 |
return ret; } |