Merge with Linux 2.3.40.
[linux-2.6/linux-mips.git] / fs / ext2 / fsync.c
blobc29fef5ea7379a66e6983eeb40322c8f020d3bab
1 /*
2 * linux/fs/ext2/fsync.c
4 * Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
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
12 * ext2fs fsync primitive
14 * Big-endian to little-endian byte-swapping/bitmaps by
15 * David S. Miller (davem@caip.rutgers.edu), 1995
17 * Removed unnecessary code duplication for little endian machines
18 * and excessive __inline__s.
19 * Andi Kleen, 1997
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.
25 #include <linux/fs.h>
26 #include <linux/locks.h>
31 #define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
32 #define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
34 static int sync_indirect(struct inode * inode, u32 * block, int wait)
36 struct buffer_head * bh;
38 if (!*block)
39 return 0;
40 bh = get_hash_table(inode->i_dev, le32_to_cpu(*block), blocksize);
41 if (!bh)
42 return 0;
43 if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
44 /* There can be a parallell read(2) that started read-I/O
45 on the buffer so we can't assume that there's been
46 an I/O error without first waiting I/O completation. */
47 wait_on_buffer(bh);
48 if (!buffer_uptodate(bh))
50 brelse (bh);
51 return -1;
54 if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
55 if (wait)
56 /* when we return from fsync all the blocks
57 must be _just_ stored on disk */
58 wait_on_buffer(bh);
59 brelse(bh);
60 return 0;
62 ll_rw_block(WRITE, 1, &bh);
63 atomic_dec(&bh->b_count);
64 return 0;
67 static int sync_iblock(struct inode * inode, u32 * iblock,
68 struct buffer_head ** bh, int wait)
70 int rc, tmp;
72 *bh = NULL;
73 tmp = le32_to_cpu(*iblock);
74 if (!tmp)
75 return 0;
76 rc = sync_indirect(inode, iblock, wait);
77 if (rc)
78 return rc;
79 *bh = bread(inode->i_dev, tmp, blocksize);
80 if (!*bh)
81 return -1;
82 return 0;
85 static int sync_dindirect(struct inode * inode, u32 * diblock, int wait)
87 int i;
88 struct buffer_head * dind_bh;
89 int rc, err = 0;
91 rc = sync_iblock(inode, diblock, &dind_bh, wait);
92 if (rc || !dind_bh)
93 return rc;
95 for (i = 0; i < addr_per_block; i++) {
96 rc = sync_indirect(inode, ((u32 *) dind_bh->b_data) + i, wait);
97 if (rc)
98 err = rc;
100 brelse(dind_bh);
101 return err;
104 static int sync_tindirect(struct inode * inode, u32 * tiblock, int wait)
106 int i;
107 struct buffer_head * tind_bh;
108 int rc, err = 0;
110 rc = sync_iblock(inode, tiblock, &tind_bh, wait);
111 if (rc || !tind_bh)
112 return rc;
114 for (i = 0; i < addr_per_block; i++) {
115 rc = sync_dindirect(inode, ((u32 *) tind_bh->b_data) + i, wait);
116 if (rc)
117 err = rc;
119 brelse(tind_bh);
120 return err;
124 * File may be NULL when we are called. Perhaps we shouldn't
125 * even pass file to fsync ?
128 int ext2_sync_file(struct file * file, struct dentry *dentry)
130 int wait, err = 0;
131 struct inode *inode = dentry->d_inode;
133 if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
135 * Don't sync fast links!
137 goto skip;
139 err = generic_buffer_fdatasync(inode, 0, ~0UL);
141 for (wait=0; wait<=1; wait++)
143 err |= sync_indirect(inode,
144 inode->u.ext2_i.i_data+EXT2_IND_BLOCK,
145 wait);
146 err |= sync_dindirect(inode,
147 inode->u.ext2_i.i_data+EXT2_DIND_BLOCK,
148 wait);
149 err |= sync_tindirect(inode,
150 inode->u.ext2_i.i_data+EXT2_TIND_BLOCK,
151 wait);
153 skip:
154 err |= ext2_sync_inode (inode);
155 return err ? -EIO : 0;