Blame view
fs/ext4/fsync.c
4.59 KB
ac27a0ec1 [PATCH] ext4: ini... |
1 |
/* |
617ba13b3 [PATCH] ext4: ren... |
2 |
* linux/fs/ext4/fsync.c |
ac27a0ec1 [PATCH] ext4: ini... |
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 [PATCH] ext4: ren... |
12 |
* ext4fs fsync primitive |
ac27a0ec1 [PATCH] ext4: ini... |
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> |
d755fb384 ext4: call blkdev... |
29 |
#include <linux/blkdev.h> |
9bffad1ed ext4: convert ins... |
30 |
|
3dcf54515 ext4: move header... |
31 32 |
#include "ext4.h" #include "ext4_jbd2.h" |
ac27a0ec1 [PATCH] ext4: ini... |
33 |
|
9bffad1ed ext4: convert ins... |
34 |
#include <trace/events/ext4.h> |
ac27a0ec1 [PATCH] ext4: ini... |
35 |
/* |
14ece1028 ext4: Make fsync ... |
36 37 38 39 40 41 42 |
* 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 ext4: sync the di... |
43 |
static int ext4_sync_parent(struct inode *inode) |
14ece1028 ext4: Make fsync ... |
44 45 |
{ struct dentry *dentry = NULL; |
d59729f4e ext4: fix races i... |
46 |
struct inode *next; |
0893ed458 ext4: sync the di... |
47 |
int ret = 0; |
14ece1028 ext4: Make fsync ... |
48 |
|
d59729f4e ext4: fix races i... |
49 50 51 52 |
if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) return 0; inode = igrab(inode); while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) { |
14ece1028 ext4: Make fsync ... |
53 |
ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY); |
9f713878f ext4: get rid of ... |
54 |
dentry = d_find_any_alias(inode); |
d59729f4e ext4: fix races i... |
55 |
if (!dentry) |
14ece1028 ext4: Make fsync ... |
56 |
break; |
2b0143b5c VFS: normal files... |
57 |
next = igrab(d_inode(dentry->d_parent)); |
d59729f4e ext4: fix races i... |
58 59 60 61 62 |
dput(dentry); if (!next) break; iput(inode); inode = next; |
6ae4c5a69 ext4: cleanup ext... |
63 64 65 66 67 68 69 |
/* * The directory inode may have gone through rmdir by now. But * the inode itself and its blocks are still allocated (we hold * a reference to the inode so it didn't go through * ext4_evict_inode()) and so we are safe to flush metadata * blocks and the inode. */ |
0893ed458 ext4: sync the di... |
70 71 72 |
ret = sync_mapping_buffers(inode->i_mapping); if (ret) break; |
64744e03c ext4: use sync_in... |
73 |
ret = sync_inode_metadata(inode, 1); |
0893ed458 ext4: sync the di... |
74 75 |
if (ret) break; |
14ece1028 ext4: Make fsync ... |
76 |
} |
d59729f4e ext4: fix races i... |
77 |
iput(inode); |
0893ed458 ext4: sync the di... |
78 |
return ret; |
14ece1028 ext4: Make fsync ... |
79 80 81 |
} /* |
617ba13b3 [PATCH] ext4: ren... |
82 |
* akpm: A new design for ext4_sync_file(). |
ac27a0ec1 [PATCH] ext4: ini... |
83 84 85 86 87 88 89 90 91 |
* * 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. */ |
02c24a821 fs: push i_mutex ... |
92 |
int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) |
ac27a0ec1 [PATCH] ext4: ini... |
93 |
{ |
7ea808591 drop unused dentr... |
94 |
struct inode *inode = file->f_mapping->host; |
b436b9bef ext4: Wait for pr... |
95 |
struct ext4_inode_info *ei = EXT4_I(inode); |
d755fb384 ext4: call blkdev... |
96 |
journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; |
37b10dd06 ext4: use generic... |
97 |
int ret = 0, err; |
b436b9bef ext4: Wait for pr... |
98 |
tid_t commit_tid; |
93628ffb9 ext4: fix waiting... |
99 |
bool needs_barrier = false; |
ac27a0ec1 [PATCH] ext4: ini... |
100 |
|
ac39849dd ext4: sparse fixes |
101 |
J_ASSERT(ext4_journal_current_handle() == NULL); |
ac27a0ec1 [PATCH] ext4: ini... |
102 |
|
0562e0bad ext4: add more tr... |
103 |
trace_ext4_sync_file_enter(file, datasync); |
ede86cc47 ext4: Add debuggi... |
104 |
|
4418e1411 ext4: Fix fsync e... |
105 106 107 108 109 |
if (inode->i_sb->s_flags & MS_RDONLY) { /* Make sure that we read updated s_mount_flags value */ smp_rmb(); if (EXT4_SB(inode->i_sb)->s_mount_flags & EXT4_MF_FS_ABORTED) ret = -EROFS; |
92e6222df ext4: remove i_mu... |
110 |
goto out; |
4418e1411 ext4: Fix fsync e... |
111 |
} |
b436b9bef ext4: Wait for pr... |
112 |
|
14ece1028 ext4: Make fsync ... |
113 |
if (!journal) { |
78d962510 ext4: respect the... |
114 |
ret = __generic_file_fsync(file, start, end, datasync); |
6ae4c5a69 ext4: cleanup ext... |
115 |
if (!ret) |
0893ed458 ext4: sync the di... |
116 |
ret = ext4_sync_parent(inode); |
78d962510 ext4: respect the... |
117 118 |
if (test_opt(inode->i_sb, BARRIER)) goto issue_flush; |
92e6222df ext4: remove i_mu... |
119 |
goto out; |
14ece1028 ext4: Make fsync ... |
120 |
} |
b436b9bef ext4: Wait for pr... |
121 |
|
37b10dd06 ext4: use generic... |
122 123 124 |
ret = filemap_write_and_wait_range(inode->i_mapping, start, end); if (ret) return ret; |
ac27a0ec1 [PATCH] ext4: ini... |
125 |
/* |
b436b9bef ext4: Wait for pr... |
126 |
* data=writeback,ordered: |
ac27a0ec1 [PATCH] ext4: ini... |
127 |
* The caller's filemap_fdatawrite()/wait will sync the data. |
b436b9bef ext4: Wait for pr... |
128 129 |
* Metadata is in the journal, we wait for proper transaction to * commit here. |
ac27a0ec1 [PATCH] ext4: ini... |
130 131 132 |
* * data=journal: * filemap_fdatawrite won't do anything (the buffers are clean). |
617ba13b3 [PATCH] ext4: ren... |
133 |
* ext4_force_commit will write the file data into the journal and |
ac27a0ec1 [PATCH] ext4: ini... |
134 135 136 137 138 |
* 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 ext4: add more tr... |
139 140 141 142 |
if (ext4_should_journal_data(inode)) { ret = ext4_force_commit(inode->i_sb); goto out; } |
ac27a0ec1 [PATCH] ext4: ini... |
143 |
|
b436b9bef ext4: Wait for pr... |
144 |
commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid; |
93628ffb9 ext4: fix waiting... |
145 146 147 |
if (journal->j_flags & JBD2_BARRIER && !jbd2_trans_will_send_data_barrier(journal, commit_tid)) needs_barrier = true; |
d76a3a771 ext4/jbd2: don't ... |
148 |
ret = jbd2_complete_transaction(journal, commit_tid); |
a4a39040e ext4: check retur... |
149 |
if (needs_barrier) { |
78d962510 ext4: respect the... |
150 |
issue_flush: |
a4a39040e ext4: check retur... |
151 152 153 154 |
err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); if (!ret) ret = err; } |
37b10dd06 ext4: use generic... |
155 |
out: |
0562e0bad ext4: add more tr... |
156 |
trace_ext4_sync_file_exit(inode, ret); |
ac27a0ec1 [PATCH] ext4: ini... |
157 158 |
return ret; } |