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 ind = ((sysv_zone_t *) indbh->b_data) + i;
175 block = tmp = *ind;
176 if (sb->sv_convert)
177 block = from_coh_ulong(block);
178 if (!block)
179 continue;
180 retry |= trunc_indirect(inode,offset+(i<<sb->sv_ind_per_block_bits),ind,sb->sv_convert,&indbh->b_dirt);
181 }
182 for (i = 0; i < sb->sv_ind_per_block; i++)
183 if (((sysv_zone_t *) indbh->b_data)[i])
184 goto done;
185 if ((indbh->b_count != 1) || (indtmp != *p)) {
186 brelse(indbh);
187 return 1;
188 }
189 *p = 0;
190 *dirt = 1;
191 sysv_free_block(sb,indblock);
192 done:
193 brelse(indbh);
194 return retry;
195 }
196
197 static int trunc_tindirect(struct inode * inode, unsigned long offset, unsigned long * p, int convert, unsigned char * dirt)
198 {
199 unsigned long indtmp, indblock;
200 struct super_block * sb;
201 struct buffer_head * indbh;
202 unsigned int i;
203 sysv_zone_t * ind;
204 unsigned long tmp, block;
205 int retry = 0;
206
207 indblock = indtmp = *p;
208 if (convert)
209 indblock = from_coh_ulong(indblock);
210 if (!indblock)
211 return 0;
212 sb = inode->i_sb;
213 indbh = sv_bread(sb, inode->i_dev, indblock);
214 if (indtmp != *p) {
215 brelse(indbh);
216 return 1;
217 }
218 if (!indbh) {
219 *p = 0;
220 *dirt = 1;
221 return 0;
222 }
223 if (inode->i_size < offset)
224 i = 0;
225 else
226 i = (inode->i_size - offset + sb->sv_ind_per_block_2_block_size_1) >> sb->sv_ind_per_block_2_block_size_bits;
227 for (; i < sb->sv_ind_per_block; i++) {
228 ind = ((sysv_zone_t *) indbh->b_data) + i;
229 block = tmp = *ind;
230 if (sb->sv_convert)
231 block = from_coh_ulong(block);
232 if (!block)
233 continue;
234 retry |= trunc_dindirect(inode,offset+(i<<sb->sv_ind_per_block_2_bits),ind,sb->sv_convert,&indbh->b_dirt);
235 }
236 for (i = 0; i < sb->sv_ind_per_block; i++)
237 if (((sysv_zone_t *) indbh->b_data)[i])
238 goto done;
239 if ((indbh->b_count != 1) || (indtmp != *p)) {
240 brelse(indbh);
241 return 1;
242 }
243 *p = 0;
244 *dirt = 1;
245 sysv_free_block(sb,indblock);
246 done:
247 brelse(indbh);
248 return retry;
249 }
250
251 static int trunc_all(struct inode * inode)
252 {
253 struct super_block * sb;
254
255 sb = inode->i_sb;
256 return trunc_direct(inode)
257 | trunc_indirect(inode,sb->sv_ind0_size,&inode->u.sysv_i.i_data[10],0,&inode->i_dirt)
258 | trunc_dindirect(inode,sb->sv_ind1_size,&inode->u.sysv_i.i_data[11],0,&inode->i_dirt)
259 | trunc_tindirect(inode,sb->sv_ind2_size,&inode->u.sysv_i.i_data[12],0,&inode->i_dirt);
260 }
261
262
263 void sysv_truncate(struct inode * inode)
264 {
265
266
267
268
269
270
271
272
273 if (S_ISLNK(inode->i_mode))
274 printk("sysv_truncate: truncating symbolic link\n");
275 else if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
276 return;
277 while (trunc_all(inode)) {
278 current->counter = 0;
279 schedule();
280 }
281 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
282 inode->i_dirt = 1;
283 }