Branch data Line data Source code
1 : : /*
2 : : * linux/fs/ext3/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 : : * ext3fs 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/blkdev.h>
26 : : #include <linux/writeback.h>
27 : : #include "ext3.h"
28 : :
29 : : /*
30 : : * akpm: A new design for ext3_sync_file().
31 : : *
32 : : * This is only called from sys_fsync(), sys_fdatasync() and sys_msync().
33 : : * There cannot be a transaction open by this task.
34 : : * Another task could have dirtied this inode. Its data can be in any
35 : : * state in the journalling system.
36 : : *
37 : : * What we do is just kick off a commit and wait on it. This will snapshot the
38 : : * inode to disk.
39 : : */
40 : :
41 : 0 : int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
42 : : {
43 : 0 : struct inode *inode = file->f_mapping->host;
44 : : struct ext3_inode_info *ei = EXT3_I(inode);
45 : 0 : journal_t *journal = EXT3_SB(inode->i_sb)->s_journal;
46 : : int ret, needs_barrier = 0;
47 : : tid_t commit_tid;
48 : :
49 : : trace_ext3_sync_file_enter(file, datasync);
50 : :
51 [ # # ]: 0 : if (inode->i_sb->s_flags & MS_RDONLY) {
52 : : /* Make sure that we read updated state */
53 : 0 : smp_rmb();
54 [ # # ]: 0 : if (EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ERROR_FS)
55 : : return -EROFS;
56 : 0 : return 0;
57 : : }
58 : 0 : ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
59 [ # # ]: 0 : if (ret)
60 : : goto out;
61 : :
62 [ # # ]: 0 : J_ASSERT(ext3_journal_current_handle() == NULL);
63 : :
64 : : /*
65 : : * data=writeback,ordered:
66 : : * The caller's filemap_fdatawrite()/wait will sync the data.
67 : : * Metadata is in the journal, we wait for a proper transaction
68 : : * to commit here.
69 : : *
70 : : * data=journal:
71 : : * filemap_fdatawrite won't do anything (the buffers are clean).
72 : : * ext3_force_commit will write the file data into the journal and
73 : : * will wait on that.
74 : : * filemap_fdatawait() will encounter a ton of newly-dirtied pages
75 : : * (they were dirtied by commit). But that's OK - the blocks are
76 : : * safe in-journal, which is all fsync() needs to ensure.
77 : : */
78 [ # # ]: 0 : if (ext3_should_journal_data(inode)) {
79 : 0 : ret = ext3_force_commit(inode->i_sb);
80 : 0 : goto out;
81 : : }
82 : :
83 [ # # ]: 0 : if (datasync)
84 : 0 : commit_tid = atomic_read(&ei->i_datasync_tid);
85 : : else
86 : 0 : commit_tid = atomic_read(&ei->i_sync_tid);
87 : :
88 [ # # # # ]: 0 : if (test_opt(inode->i_sb, BARRIER) &&
89 : 0 : !journal_trans_will_send_data_barrier(journal, commit_tid))
90 : : needs_barrier = 1;
91 : 0 : log_start_commit(journal, commit_tid);
92 : 0 : ret = log_wait_commit(journal, commit_tid);
93 : :
94 : : /*
95 : : * In case we didn't commit a transaction, we have to flush
96 : : * disk caches manually so that data really is on persistent
97 : : * storage
98 : : */
99 [ # # ]: 0 : if (needs_barrier) {
100 : : int err;
101 : :
102 : 0 : err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
103 [ # # ]: 0 : if (!ret)
104 : : ret = err;
105 : : }
106 : : out:
107 : : trace_ext3_sync_file_exit(inode, ret);
108 : 0 : return ret;
109 : : }
|