Blame view

fs/ext4/fsync.c 4.59 KB
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
2
   *  linux/fs/ext4/fsync.c
ac27a0ec1   Dave Kleikamp   [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   Mingming Cao   [PATCH] ext4: ren...
12
   *  ext4fs fsync primitive
ac27a0ec1   Dave Kleikamp   [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   Eric Sandeen   ext4: call blkdev...
29
  #include <linux/blkdev.h>
9bffad1ed   Theodore Ts'o   ext4: convert ins...
30

3dcf54515   Christoph Hellwig   ext4: move header...
31
32
  #include "ext4.h"
  #include "ext4_jbd2.h"
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
33

9bffad1ed   Theodore Ts'o   ext4: convert ins...
34
  #include <trace/events/ext4.h>
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
35
  /*
14ece1028   Frank Mayhar   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   Curt Wohlgemuth   ext4: sync the di...
43
  static int ext4_sync_parent(struct inode *inode)
14ece1028   Frank Mayhar   ext4: Make fsync ...
44
45
  {
  	struct dentry *dentry = NULL;
d59729f4e   Theodore Ts'o   ext4: fix races i...
46
  	struct inode *next;
0893ed458   Curt Wohlgemuth   ext4: sync the di...
47
  	int ret = 0;
14ece1028   Frank Mayhar   ext4: Make fsync ...
48

d59729f4e   Theodore Ts'o   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   Frank Mayhar   ext4: Make fsync ...
53
  		ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
9f713878f   Al Viro   ext4: get rid of ...
54
  		dentry = d_find_any_alias(inode);
d59729f4e   Theodore Ts'o   ext4: fix races i...
55
  		if (!dentry)
14ece1028   Frank Mayhar   ext4: Make fsync ...
56
  			break;
2b0143b5c   David Howells   VFS: normal files...
57
  		next = igrab(d_inode(dentry->d_parent));
d59729f4e   Theodore Ts'o   ext4: fix races i...
58
59
60
61
62
  		dput(dentry);
  		if (!next)
  			break;
  		iput(inode);
  		inode = next;
6ae4c5a69   Jan Kara   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   Curt Wohlgemuth   ext4: sync the di...
70
71
72
  		ret = sync_mapping_buffers(inode->i_mapping);
  		if (ret)
  			break;
64744e03c   Guo Chao   ext4: use sync_in...
73
  		ret = sync_inode_metadata(inode, 1);
0893ed458   Curt Wohlgemuth   ext4: sync the di...
74
75
  		if (ret)
  			break;
14ece1028   Frank Mayhar   ext4: Make fsync ...
76
  	}
d59729f4e   Theodore Ts'o   ext4: fix races i...
77
  	iput(inode);
0893ed458   Curt Wohlgemuth   ext4: sync the di...
78
  	return ret;
14ece1028   Frank Mayhar   ext4: Make fsync ...
79
80
81
  }
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
82
   * akpm: A new design for ext4_sync_file().
ac27a0ec1   Dave Kleikamp   [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   Josef Bacik   fs: push i_mutex ...
92
  int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
93
  {
7ea808591   Christoph Hellwig   drop unused dentr...
94
  	struct inode *inode = file->f_mapping->host;
b436b9bef   Jan Kara   ext4: Wait for pr...
95
  	struct ext4_inode_info *ei = EXT4_I(inode);
d755fb384   Eric Sandeen   ext4: call blkdev...
96
  	journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
37b10dd06   Jan Kara   ext4: use generic...
97
  	int ret = 0, err;
b436b9bef   Jan Kara   ext4: Wait for pr...
98
  	tid_t commit_tid;
93628ffb9   Jan Kara   ext4: fix waiting...
99
  	bool needs_barrier = false;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
100

ac39849dd   Aneesh Kumar K.V   ext4: sparse fixes
101
  	J_ASSERT(ext4_journal_current_handle() == NULL);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
102

0562e0bad   Jiaying Zhang   ext4: add more tr...
103
  	trace_ext4_sync_file_enter(file, datasync);
ede86cc47   Theodore Ts'o   ext4: Add debuggi...
104

4418e1411   Dmitry Monakhov   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   Jan Kara   ext4: remove i_mu...
110
  		goto out;
4418e1411   Dmitry Monakhov   ext4: Fix fsync e...
111
  	}
b436b9bef   Jan Kara   ext4: Wait for pr...
112

14ece1028   Frank Mayhar   ext4: Make fsync ...
113
  	if (!journal) {
78d962510   Theodore Ts'o   ext4: respect the...
114
  		ret = __generic_file_fsync(file, start, end, datasync);
6ae4c5a69   Jan Kara   ext4: cleanup ext...
115
  		if (!ret)
0893ed458   Curt Wohlgemuth   ext4: sync the di...
116
  			ret = ext4_sync_parent(inode);
78d962510   Theodore Ts'o   ext4: respect the...
117
118
  		if (test_opt(inode->i_sb, BARRIER))
  			goto issue_flush;
92e6222df   Jan Kara   ext4: remove i_mu...
119
  		goto out;
14ece1028   Frank Mayhar   ext4: Make fsync ...
120
  	}
b436b9bef   Jan Kara   ext4: Wait for pr...
121

37b10dd06   Jan Kara   ext4: use generic...
122
123
124
  	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
  	if (ret)
  		return ret;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
125
  	/*
b436b9bef   Jan Kara   ext4: Wait for pr...
126
  	 * data=writeback,ordered:
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
127
  	 *  The caller's filemap_fdatawrite()/wait will sync the data.
b436b9bef   Jan Kara   ext4: Wait for pr...
128
129
  	 *  Metadata is in the journal, we wait for proper transaction to
  	 *  commit here.
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
130
131
132
  	 *
  	 * data=journal:
  	 *  filemap_fdatawrite won't do anything (the buffers are clean).
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
133
  	 *  ext4_force_commit will write the file data into the journal and
ac27a0ec1   Dave Kleikamp   [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   Jiaying Zhang   ext4: add more tr...
139
140
141
142
  	if (ext4_should_journal_data(inode)) {
  		ret = ext4_force_commit(inode->i_sb);
  		goto out;
  	}
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
143

b436b9bef   Jan Kara   ext4: Wait for pr...
144
  	commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid;
93628ffb9   Jan Kara   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   Theodore Ts'o   ext4/jbd2: don't ...
148
  	ret = jbd2_complete_transaction(journal, commit_tid);
a4a39040e   Theodore Ts'o   ext4: check retur...
149
  	if (needs_barrier) {
78d962510   Theodore Ts'o   ext4: respect the...
150
  	issue_flush:
a4a39040e   Theodore Ts'o   ext4: check retur...
151
152
153
154
  		err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
  		if (!ret)
  			ret = err;
  	}
37b10dd06   Jan Kara   ext4: use generic...
155
  out:
0562e0bad   Jiaying Zhang   ext4: add more tr...
156
  	trace_ext4_sync_file_exit(inode, ret);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
157
158
  	return ret;
  }