This source file includes following definitions.
- sync_block
- sync_iblock
- sync_direct
- sync_indirect
- sync_dindirect
- sync_tindirect
- ext2_sync_file
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <asm/segment.h>
14 #include <asm/system.h>
15
16 #include <linux/errno.h>
17 #include <linux/fs.h>
18 #include <linux/ext2_fs.h>
19 #include <linux/fcntl.h>
20 #include <linux/sched.h>
21 #include <linux/stat.h>
22 #include <linux/locks.h>
23
24
25 #define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
26 #define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
27
28 static int sync_block (struct inode * inode, unsigned long * block, int wait)
29 {
30 struct buffer_head * bh;
31 int tmp;
32
33 if (!*block)
34 return 0;
35 tmp = *block;
36 bh = get_hash_table (inode->i_dev, *block, blocksize);
37 if (!bh)
38 return 0;
39 if (*block != tmp) {
40 brelse (bh);
41 return 1;
42 }
43 if (wait && bh->b_req && !bh->b_uptodate) {
44 brelse (bh);
45 return -1;
46 }
47 if (wait || !bh->b_uptodate || !bh->b_dirt) {
48 brelse (bh);
49 return 0;
50 }
51 ll_rw_block (WRITE, 1, &bh);
52 bh->b_count--;
53 return 0;
54 }
55
56 static int sync_iblock (struct inode * inode, unsigned long * iblock,
57 struct buffer_head ** bh, int wait)
58 {
59 int rc, tmp;
60
61 *bh = NULL;
62 tmp = *iblock;
63 if (!tmp)
64 return 0;
65 rc = sync_block (inode, iblock, wait);
66 if (rc)
67 return rc;
68 *bh = bread (inode->i_dev, tmp, blocksize);
69 if (tmp != *iblock) {
70 brelse (*bh);
71 *bh = NULL;
72 return 1;
73 }
74 if (!*bh)
75 return -1;
76 return 0;
77 }
78
79
80 static int sync_direct (struct inode * inode, int wait)
81 {
82 int i;
83 int rc, err = 0;
84
85 for (i = 0; i < EXT2_NDIR_BLOCKS; i++) {
86 rc = sync_block (inode, inode->u.ext2_i.i_data + i, wait);
87 if (rc > 0)
88 break;
89 if (rc)
90 err = rc;
91 }
92 return err;
93 }
94
95 static int sync_indirect (struct inode * inode, unsigned long * iblock,
96 int wait)
97 {
98 int i;
99 struct buffer_head * ind_bh;
100 int rc, err = 0;
101
102 rc = sync_iblock (inode, iblock, &ind_bh, wait);
103 if (rc || !ind_bh)
104 return rc;
105
106 for (i = 0; i < addr_per_block; i++) {
107 rc = sync_block (inode,
108 ((unsigned long *) ind_bh->b_data) + i,
109 wait);
110 if (rc > 0)
111 break;
112 if (rc)
113 err = rc;
114 }
115 brelse (ind_bh);
116 return err;
117 }
118
119 static int sync_dindirect (struct inode * inode, unsigned long * diblock,
120 int wait)
121 {
122 int i;
123 struct buffer_head * dind_bh;
124 int rc, err = 0;
125
126 rc = sync_iblock (inode, diblock, &dind_bh, wait);
127 if (rc || !dind_bh)
128 return rc;
129
130 for (i = 0; i < addr_per_block; i++) {
131 rc = sync_indirect (inode,
132 ((unsigned long *) dind_bh->b_data) + i,
133 wait);
134 if (rc > 0)
135 break;
136 if (rc)
137 err = rc;
138 }
139 brelse (dind_bh);
140 return err;
141 }
142
143 static int sync_tindirect (struct inode * inode, unsigned long * tiblock,
144 int wait)
145 {
146 int i;
147 struct buffer_head * tind_bh;
148 int rc, err = 0;
149
150 rc = sync_iblock (inode, tiblock, &tind_bh, wait);
151 if (rc || !tind_bh)
152 return rc;
153
154 for (i = 0; i < addr_per_block; i++) {
155 rc = sync_dindirect (inode,
156 ((unsigned long *) tind_bh->b_data) + i,
157 wait);
158 if (rc > 0)
159 break;
160 if (rc)
161 err = rc;
162 }
163 brelse (tind_bh);
164 return err;
165 }
166
167 int ext2_sync_file (struct inode * inode, struct file * file)
168 {
169 int wait, err = 0;
170
171 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
172 S_ISLNK(inode->i_mode)))
173 return -EINVAL;
174
175 if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
176 goto skip;
177
178 for (wait=0; wait<=1; wait++)
179 {
180 err |= sync_direct (inode, wait);
181 err |= sync_indirect (inode,
182 inode->u.ext2_i.i_data+EXT2_IND_BLOCK,
183 wait);
184 err |= sync_dindirect (inode,
185 inode->u.ext2_i.i_data+EXT2_DIND_BLOCK,
186 wait);
187 err |= sync_tindirect (inode,
188 inode->u.ext2_i.i_data+EXT2_TIND_BLOCK,
189 wait);
190 }
191 skip:
192 err |= ext2_sync_inode (inode);
193 return (err < 0) ? -EIO : 0;
194 }