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