This source file includes following definitions.
- trunc_direct
- trunc_indirect
- trunc_dindirect
- trunc_tindirect
- trunc_all
- sysv_truncate
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #include <linux/sched.h>
15 #include <linux/fs.h>
16 #include <linux/sysv_fs.h>
17 #include <linux/stat.h>
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 static int trunc_direct(struct inode * inode)
41 {
42 struct super_block * sb;
43 unsigned int i;
44 unsigned long * p;
45 unsigned long block;
46 struct buffer_head * bh;
47 int retry = 0;
48
49 sb = inode->i_sb;
50 repeat:
51 for (i = ((unsigned long) inode->i_size + sb->sv_block_size_1) >> sb->sv_block_size_bits; i < 10; i++) {
52 p = inode->u.sysv_i.i_data + i;
53 block = *p;
54 if (!block)
55 continue;
56 bh = sv_get_hash_table(sb, inode->i_dev, block);
57 if ((i << sb->sv_block_size_bits) < inode->i_size) {
58 brelse(bh);
59 goto repeat;
60 }
61 if ((bh && bh->b_count != 1) || (block != *p)) {
62 retry = 1;
63 brelse(bh);
64 continue;
65 }
66 *p = 0;
67 inode->i_dirt = 1;
68 brelse(bh);
69 sysv_free_block(sb,block);
70 }
71 return retry;
72 }
73
74 static int trunc_indirect(struct inode * inode, unsigned long offset, unsigned long * p, int convert, unsigned char * dirt)
75 {
76 unsigned long indtmp, indblock;
77 struct super_block * sb;
78 struct buffer_head * indbh;
79 unsigned int i;
80 sysv_zone_t * ind;
81 unsigned long tmp, block;
82 struct buffer_head * bh;
83 int retry = 0;
84
85 indblock = indtmp = *p;
86 if (convert)
87 indblock = from_coh_ulong(indblock);
88 if (!indblock)
89 return 0;
90 sb = inode->i_sb;
91 indbh = sv_bread(sb, inode->i_dev, indblock);
92 if (indtmp != *p) {
93 brelse(indbh);
94 return 1;
95 }
96 if (!indbh) {
97 *p = 0;
98 *dirt = 1;
99 return 0;
100 }
101 repeat:
102 if (inode->i_size < offset)
103 i = 0;
104 else
105 i = (inode->i_size - offset + sb->sv_block_size_1) >> sb->sv_block_size_bits;
106 for (; i < sb->sv_ind_per_block; i++) {
107 ind = ((sysv_zone_t *) indbh->b_data) + i;
108 block = tmp = *ind;
109 if (sb->sv_convert)
110 block = from_coh_ulong(block);
111 if (!block)
112 continue;
113 bh = sv_get_hash_table(sb, inode->i_dev, block);
114 if ((i << sb->sv_block_size_bits) + offset < inode->i_size) {
115 brelse(bh);
116 goto repeat;
117 }
118 if ((bh && bh->b_count != 1) || (tmp != *ind)) {
119 retry = 1;
120 brelse(bh);
121 continue;
122 }
123 *ind = 0;
124 mark_buffer_dirty(indbh, 1);
125 brelse(bh);
126 sysv_free_block(sb,block);
127 }
128 for (i = 0; i < sb->sv_ind_per_block; i++)
129 if (((sysv_zone_t *) indbh->b_data)[i])
130 goto done;
131 if ((indbh->b_count != 1) || (indtmp != *p)) {
132 brelse(indbh);
133 return 1;
134 }
135 *p = 0;
136 *dirt = 1;
137 sysv_free_block(sb,indblock);
138 done:
139 brelse(indbh);
140 return retry;
141 }
142
143 static int trunc_dindirect(struct inode * inode, unsigned long offset, unsigned long * p, int convert, unsigned char * dirt)
144 {
145 unsigned long indtmp, indblock;
146 struct super_block * sb;
147 struct buffer_head * indbh;
148 unsigned int i;
149 sysv_zone_t * ind;
150 unsigned long tmp, block;
151 int retry = 0;
152
153 indblock = indtmp = *p;
154 if (convert)
155 indblock = from_coh_ulong(indblock);
156 if (!indblock)
157 return 0;
158 sb = inode->i_sb;
159 indbh = sv_bread(sb, inode->i_dev, indblock);
160 if (indtmp != *p) {
161 brelse(indbh);
162 return 1;
163 }
164 if (!indbh) {
165 *p = 0;
166 *dirt = 1;
167 return 0;
168 }
169 if (inode->i_size < offset)
170 i = 0;
171 else
172 i = (inode->i_size - offset + sb->sv_ind_per_block_block_size_1) >> sb->sv_ind_per_block_block_size_bits;
173 for (; i < sb->sv_ind_per_block; i++) {
174 unsigned char dirty = 0;
175 ind = ((sysv_zone_t *) indbh->b_data) + i;
176 block = tmp = *ind;
177 if (sb->sv_convert)
178 block = from_coh_ulong(block);
179 if (!block)
180 continue;
181 retry |= trunc_indirect(inode,offset+(i<<sb->sv_ind_per_block_bits),ind,sb->sv_convert,&dirty);
182 if (dirty)
183 mark_buffer_dirty(indbh, 1);
184 }
185 for (i = 0; i < sb->sv_ind_per_block; i++)
186 if (((sysv_zone_t *) indbh->b_data)[i])
187 goto done;
188 if ((indbh->b_count != 1) || (indtmp != *p)) {
189 brelse(indbh);
190 return 1;
191 }
192 *p = 0;
193 *dirt = 1;
194 sysv_free_block(sb,indblock);
195 done:
196 brelse(indbh);
197 return retry;
198 }
199
200 static int trunc_tindirect(struct inode * inode, unsigned long offset, unsigned long * p, int convert, unsigned char * dirt)
201 {
202 unsigned long indtmp, indblock;
203 struct super_block * sb;
204 struct buffer_head * indbh;
205 unsigned int i;
206 sysv_zone_t * ind;
207 unsigned long tmp, block;
208 int retry = 0;
209
210 indblock = indtmp = *p;
211 if (convert)
212 indblock = from_coh_ulong(indblock);
213 if (!indblock)
214 return 0;
215 sb = inode->i_sb;
216 indbh = sv_bread(sb, inode->i_dev, indblock);
217 if (indtmp != *p) {
218 brelse(indbh);
219 return 1;
220 }
221 if (!indbh) {
222 *p = 0;
223 *dirt = 1;
224 return 0;
225 }
226 if (inode->i_size < offset)
227 i = 0;
228 else
229 i = (inode->i_size - offset + sb->sv_ind_per_block_2_block_size_1) >> sb->sv_ind_per_block_2_block_size_bits;
230 for (; i < sb->sv_ind_per_block; i++) {
231 unsigned char dirty = 0;
232 ind = ((sysv_zone_t *) indbh->b_data) + i;
233 block = tmp = *ind;
234 if (sb->sv_convert)
235 block = from_coh_ulong(block);
236 if (!block)
237 continue;
238 retry |= trunc_dindirect(inode,offset+(i<<sb->sv_ind_per_block_2_bits),ind,sb->sv_convert,&dirty);
239 if (dirty)
240 mark_buffer_dirty(indbh, 1);
241 }
242 for (i = 0; i < sb->sv_ind_per_block; i++)
243 if (((sysv_zone_t *) indbh->b_data)[i])
244 goto done;
245 if ((indbh->b_count != 1) || (indtmp != *p)) {
246 brelse(indbh);
247 return 1;
248 }
249 *p = 0;
250 *dirt = 1;
251 sysv_free_block(sb,indblock);
252 done:
253 brelse(indbh);
254 return retry;
255 }
256
257 static int trunc_all(struct inode * inode)
258 {
259 struct super_block * sb;
260
261 sb = inode->i_sb;
262 return trunc_direct(inode)
263 | trunc_indirect(inode,sb->sv_ind0_size,&inode->u.sysv_i.i_data[10],0,&inode->i_dirt)
264 | trunc_dindirect(inode,sb->sv_ind1_size,&inode->u.sysv_i.i_data[11],0,&inode->i_dirt)
265 | trunc_tindirect(inode,sb->sv_ind2_size,&inode->u.sysv_i.i_data[12],0,&inode->i_dirt);
266 }
267
268
269 void sysv_truncate(struct inode * inode)
270 {
271
272
273
274
275
276
277
278
279 if (S_ISLNK(inode->i_mode))
280 printk("sysv_truncate: truncating symbolic link\n");
281 else if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
282 return;
283 while (trunc_all(inode)) {
284 current->counter = 0;
285 schedule();
286 }
287 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
288 inode->i_dirt = 1;
289 }