~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/ufs/truncate.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/fs/ufs/truncate.c
  3  *
  4  * Copyright (C) 1998
  5  * Daniel Pirkl <daniel.pirkl@email.cz>
  6  * Charles University, Faculty of Mathematics and Physics
  7  *
  8  *  from
  9  *
 10  *  linux/fs/ext2/truncate.c
 11  *
 12  * Copyright (C) 1992, 1993, 1994, 1995
 13  * Remy Card (card@masi.ibp.fr)
 14  * Laboratoire MASI - Institut Blaise Pascal
 15  * Universite Pierre et Marie Curie (Paris VI)
 16  *
 17  *  from
 18  *
 19  *  linux/fs/minix/truncate.c
 20  *
 21  *  Copyright (C) 1991, 1992  Linus Torvalds
 22  *
 23  *  Big-endian to little-endian byte-swapping/bitmaps by
 24  *        David S. Miller (davem@caip.rutgers.edu), 1995
 25  */
 26 
 27 /*
 28  * Real random numbers for secure rm added 94/02/18
 29  * Idea from Pierre del Perugia <delperug@gla.ecoledoc.ibp.fr>
 30  */
 31 
 32 #include <linux/errno.h>
 33 #include <linux/fs.h>
 34 #include <linux/ufs_fs.h>
 35 #include <linux/fcntl.h>
 36 #include <linux/sched.h>
 37 #include <linux/stat.h>
 38 #include <linux/locks.h>
 39 #include <linux/string.h>
 40 
 41 #include "swab.h"
 42 #include "util.h"
 43 
 44 #undef UFS_TRUNCATE_DEBUG
 45 
 46 #ifdef UFS_TRUNCATE_DEBUG
 47 #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
 48 #else
 49 #define UFSD(x)
 50 #endif
 51  
 52 /*
 53  * Secure deletion currently doesn't work. It interacts very badly
 54  * with buffers shared with memory mappings, and for that reason
 55  * can't be done in the truncate() routines. It should instead be
 56  * done separately in "release()" before calling the truncate routines
 57  * that will release the actual file blocks.
 58  *
 59  *              Linus
 60  */
 61 
 62 #define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift)
 63 #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
 64 
 65 #define DATA_BUFFER_USED(bh) \
 66         (atomic_read(&bh->b_count)>1 || buffer_locked(bh))
 67 
 68 static int ufs_trunc_direct (struct inode * inode)
 69 {
 70         struct super_block * sb;
 71         struct ufs_sb_private_info * uspi;
 72         struct buffer_head * bh;
 73         u32 * p;
 74         unsigned frag1, frag2, frag3, frag4, block1, block2;
 75         unsigned frag_to_free, free_count;
 76         unsigned i, j, tmp;
 77         int retry;
 78         unsigned swab;
 79         
 80         UFSD(("ENTER\n"))
 81 
 82         sb = inode->i_sb;
 83         swab = sb->u.ufs_sb.s_swab;
 84         uspi = sb->u.ufs_sb.s_uspi;
 85         
 86         frag_to_free = 0;
 87         free_count = 0;
 88         retry = 0;
 89         
 90         frag1 = DIRECT_FRAGMENT;
 91         frag4 = min (UFS_NDIR_FRAGMENT, inode->u.ufs_i.i_lastfrag);
 92         frag2 = ((frag1 & uspi->s_fpbmask) ? ((frag1 | uspi->s_fpbmask) + 1) : frag1);
 93         frag3 = frag4 & ~uspi->s_fpbmask;
 94         block1 = block2 = 0;
 95         if (frag2 > frag3) {
 96                 frag2 = frag4;
 97                 frag3 = frag4 = 0;
 98         }
 99         else if (frag2 < frag3) {
100                 block1 = ufs_fragstoblks (frag2);
101                 block2 = ufs_fragstoblks (frag3);
102         }
103 
104         UFSD(("frag1 %u, frag2 %u, block1 %u, block2 %u, frag3 %u, frag4 %u\n", frag1, frag2, block1, block2, frag3, frag4))
105 
106         if (frag1 >= frag2)
107                 goto next1;             
108 
109         /*
110          * Free first free fragments
111          */
112         p = inode->u.ufs_i.i_u1.i_data + ufs_fragstoblks (frag1);
113         tmp = SWAB32(*p);
114         if (!tmp )
115                 ufs_panic (sb, "ufs_trunc_direct", "internal error");
116         frag1 = ufs_fragnum (frag1);
117         frag2 = ufs_fragnum (frag2);
118         for (j = frag1; j < frag2; j++) {
119                 bh = get_hash_table (sb->s_dev, tmp + j, uspi->s_fsize);
120                 if ((bh && DATA_BUFFER_USED(bh)) || tmp != SWAB32(*p)) {
121                         retry = 1;
122                         brelse (bh);
123                         goto next1;
124                 }
125                 bforget (bh);
126         }
127         inode->i_blocks -= (frag2-frag1) << uspi->s_nspfshift;
128         mark_inode_dirty(inode);
129         ufs_free_fragments (inode, tmp + frag1, frag2 - frag1);
130         frag_to_free = tmp + frag1;
131 
132 next1:
133         /*
134          * Free whole blocks
135          */
136         for (i = block1 ; i < block2; i++) {
137                 p = inode->u.ufs_i.i_u1.i_data + i;
138                 tmp = SWAB32(*p);
139                 if (!tmp)
140                         continue;
141                 for (j = 0; j < uspi->s_fpb; j++) {
142                         bh = get_hash_table (sb->s_dev, tmp + j, uspi->s_fsize);
143                         if ((bh && DATA_BUFFER_USED(bh)) || tmp != SWAB32(*p)) {
144                                 retry = 1;
145                                 brelse (bh);
146                                 goto next2;
147                         }
148                         bforget (bh);
149                 }
150                 *p = SWAB32(0);
151                 inode->i_blocks -= uspi->s_nspb;
152                 mark_inode_dirty(inode);
153                 if (free_count == 0) {
154                         frag_to_free = tmp;
155                         free_count = uspi->s_fpb;
156                 } else if (free_count > 0 && frag_to_free == tmp - free_count)
157                         free_count += uspi->s_fpb;
158                 else {
159                         ufs_free_blocks (inode, frag_to_free, free_count);
160                         frag_to_free = tmp;
161                         free_count = uspi->s_fpb;
162                 }
163 next2:
164         }
165         
166         if (free_count > 0)
167                 ufs_free_blocks (inode, frag_to_free, free_count);
168 
169         if (frag3 >= frag4)
170                 goto next3;
171 
172         /*
173          * Free last free fragments
174          */
175         p = inode->u.ufs_i.i_u1.i_data + ufs_fragstoblks (frag3);
176         tmp = SWAB32(*p);
177         if (!tmp )
178                 ufs_panic(sb, "ufs_truncate_direct", "internal error");
179         frag4 = ufs_fragnum (frag4);
180         for (j = 0; j < frag4; j++) {
181                 bh = get_hash_table (sb->s_dev, tmp + j, uspi->s_fsize);
182                 if ((bh && DATA_BUFFER_USED(bh)) || tmp != SWAB32(*p)) {
183                         retry = 1;
184                         brelse (bh);
185                         goto next1;
186                 }
187                 bforget (bh);
188         }
189         *p = SWAB32(0);
190         inode->i_blocks -= frag4 << uspi->s_nspfshift;
191         mark_inode_dirty(inode);
192         ufs_free_fragments (inode, tmp, frag4);
193  next3:
194 
195         UFSD(("EXIT\n"))
196         return retry;
197 }
198 
199 
200 static int ufs_trunc_indirect (struct inode * inode, unsigned offset, u32 * p)
201 {
202         struct super_block * sb;
203         struct ufs_sb_private_info * uspi;
204         struct ufs_buffer_head * ind_ubh;
205         struct buffer_head * bh;
206         u32 * ind;
207         unsigned indirect_block, i, j, tmp;
208         unsigned frag_to_free, free_count;
209         int retry;
210         unsigned swab;
211 
212         UFSD(("ENTER\n"))
213                 
214         sb = inode->i_sb;
215         swab = sb->u.ufs_sb.s_swab;
216         uspi = sb->u.ufs_sb.s_uspi;
217 
218         frag_to_free = 0;
219         free_count = 0;
220         retry = 0;
221         
222         tmp = SWAB32(*p);
223         if (!tmp)
224                 return 0;
225         ind_ubh = ubh_bread (sb->s_dev, tmp, uspi->s_bsize);
226         if (tmp != SWAB32(*p)) {
227                 ubh_brelse (ind_ubh);
228                 return 1;
229         }
230         if (!ind_ubh) {
231                 *p = SWAB32(0);
232                 return 0;
233         }
234 
235         indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0;
236         for (i = indirect_block; i < uspi->s_apb; i++) {
237                 ind = ubh_get_addr32 (ind_ubh, i);
238                 tmp = SWAB32(*ind);
239                 if (!tmp)
240                         continue;
241                 for (j = 0; j < uspi->s_fpb; j++) {
242                         bh = get_hash_table (sb->s_dev, tmp + j, uspi->s_fsize);
243                         if ((bh && DATA_BUFFER_USED(bh)) || tmp != SWAB32(*ind)) {
244                                 retry = 1;
245                                 brelse (bh);
246                                 goto next;
247                         }
248                         bforget (bh);
249                 }       
250                 *ind = SWAB32(0);
251                 ubh_mark_buffer_dirty(ind_ubh);
252                 if (free_count == 0) {
253                         frag_to_free = tmp;
254                         free_count = uspi->s_fpb;
255                 } else if (free_count > 0 && frag_to_free == tmp - free_count)
256                         free_count += uspi->s_fpb;
257                 else {
258                         ufs_free_blocks (inode, frag_to_free, free_count);
259                         frag_to_free = tmp;
260                         free_count = uspi->s_fpb;
261                 }
262                 inode->i_blocks -= uspi->s_nspb;
263                 mark_inode_dirty(inode);
264 next:
265         }
266 
267         if (free_count > 0) {
268                 ufs_free_blocks (inode, frag_to_free, free_count);
269         }
270         for (i = 0; i < uspi->s_apb; i++)
271                 if (SWAB32(*ubh_get_addr32(ind_ubh,i)))
272                         break;
273         if (i >= uspi->s_apb) {
274                 if (ubh_max_bcount(ind_ubh) != 1) {
275                         retry = 1;
276                 }
277                 else {
278                         tmp = SWAB32(*p);
279                         *p = SWAB32(0);
280                         inode->i_blocks -= uspi->s_nspb;
281                         mark_inode_dirty(inode);
282                         ufs_free_blocks (inode, tmp, uspi->s_fpb);
283                         ubh_bforget(ind_ubh);
284                         ind_ubh = NULL;
285                 }
286         }
287         if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) {
288                 ubh_ll_rw_block (WRITE, 1, &ind_ubh);
289                 ubh_wait_on_buffer (ind_ubh);
290         }
291         ubh_brelse (ind_ubh);
292         
293         UFSD(("EXIT\n"))
294         
295         return retry;
296 }
297 
298 static int ufs_trunc_dindirect (struct inode * inode, unsigned offset, u32 * p)
299 {
300         struct super_block * sb;
301         struct ufs_sb_private_info * uspi;
302         struct ufs_buffer_head * dind_bh;
303         unsigned i, tmp, dindirect_block;
304         u32 * dind;
305         int retry = 0;
306         unsigned swab;
307         
308         UFSD(("ENTER\n"))
309         
310         sb = inode->i_sb;
311         swab = sb->u.ufs_sb.s_swab;
312         uspi = sb->u.ufs_sb.s_uspi;
313 
314         dindirect_block = (DIRECT_BLOCK > offset) 
315                 ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0;
316         retry = 0;
317         
318         tmp = SWAB32(*p);
319         if (!tmp)
320                 return 0;
321         dind_bh = ubh_bread (inode->i_dev, tmp, uspi->s_bsize);
322         if (tmp != SWAB32(*p)) {
323                 ubh_brelse (dind_bh);
324                 return 1;
325         }
326         if (!dind_bh) {
327                 *p = SWAB32(0);
328                 return 0;
329         }
330 
331         for (i = dindirect_block ; i < uspi->s_apb ; i++) {
332                 dind = ubh_get_addr32 (dind_bh, i);
333                 tmp = SWAB32(*dind);
334                 if (!tmp)
335                         continue;
336                 retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind);
337                 ubh_mark_buffer_dirty(dind_bh);
338         }
339 
340         for (i = 0; i < uspi->s_apb; i++)
341                 if (SWAB32(*ubh_get_addr32 (dind_bh, i)))
342                         break;
343         if (i >= uspi->s_apb) {
344                 if (ubh_max_bcount(dind_bh) != 1)
345                         retry = 1;
346                 else {
347                         tmp = SWAB32(*p);
348                         *p = SWAB32(0);
349                         inode->i_blocks -= uspi->s_nspb;
350                         mark_inode_dirty(inode);
351                         ufs_free_blocks (inode, tmp, uspi->s_fpb);
352                         ubh_bforget(dind_bh);
353                         dind_bh = NULL;
354                 }
355         }
356         if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) {
357                 ubh_ll_rw_block (WRITE, 1, &dind_bh);
358                 ubh_wait_on_buffer (dind_bh);
359         }
360         ubh_brelse (dind_bh);
361         
362         UFSD(("EXIT\n"))
363         
364         return retry;
365 }
366 
367 static int ufs_trunc_tindirect (struct inode * inode)
368 {
369         struct super_block * sb;
370         struct ufs_sb_private_info * uspi;
371         struct ufs_buffer_head * tind_bh;
372         unsigned tindirect_block, tmp, i;
373         u32 * tind, * p;
374         int retry;
375         unsigned swab;
376         
377         UFSD(("ENTER\n"))
378 
379         sb = inode->i_sb;
380         swab = sb->u.ufs_sb.s_swab;
381         uspi = sb->u.ufs_sb.s_uspi;
382         retry = 0;
383         
384         tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb))
385                 ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0;
386         p = inode->u.ufs_i.i_u1.i_data + UFS_TIND_BLOCK;
387         if (!(tmp = SWAB32(*p)))
388                 return 0;
389         tind_bh = ubh_bread (sb->s_dev, tmp, uspi->s_bsize);
390         if (tmp != SWAB32(*p)) {
391                 ubh_brelse (tind_bh);
392                 return 1;
393         }
394         if (!tind_bh) {
395                 *p = SWAB32(0);
396                 return 0;
397         }
398 
399         for (i = tindirect_block ; i < uspi->s_apb ; i++) {
400                 tind = ubh_get_addr32 (tind_bh, i);
401                 retry |= ufs_trunc_dindirect(inode, UFS_NDADDR + 
402                         uspi->s_apb + ((i + 1) << uspi->s_2apbshift), tind);
403                 ubh_mark_buffer_dirty(tind_bh);
404         }
405         for (i = 0; i < uspi->s_apb; i++)
406                 if (SWAB32(*ubh_get_addr32 (tind_bh, i)))
407                         break;
408         if (i >= uspi->s_apb) {
409                 if (ubh_max_bcount(tind_bh) != 1)
410                         retry = 1;
411                 else {
412                         tmp = SWAB32(*p);
413                         *p = SWAB32(0);
414                         inode->i_blocks -= uspi->s_nspb;
415                         mark_inode_dirty(inode);
416                         ufs_free_blocks (inode, tmp, uspi->s_fpb);
417                         ubh_bforget(tind_bh);
418                         tind_bh = NULL;
419                 }
420         }
421         if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) {
422                 ubh_ll_rw_block (WRITE, 1, &tind_bh);
423                 ubh_wait_on_buffer (tind_bh);
424         }
425         ubh_brelse (tind_bh);
426         
427         UFSD(("EXIT\n"))
428         return retry;
429 }
430                 
431 void ufs_truncate (struct inode * inode)
432 {
433         struct super_block * sb;
434         struct ufs_sb_private_info * uspi;
435         struct buffer_head * bh;
436         unsigned offset;
437         int err, retry;
438         
439         UFSD(("ENTER\n"))
440         sb = inode->i_sb;
441         uspi = sb->u.ufs_sb.s_uspi;
442 
443         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
444                 return;
445         if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
446                 return;
447         while (1) {
448                 retry = ufs_trunc_direct(inode);
449                 retry |= ufs_trunc_indirect (inode, UFS_IND_BLOCK,
450                         (u32 *) &inode->u.ufs_i.i_u1.i_data[UFS_IND_BLOCK]);
451                 retry |= ufs_trunc_dindirect (inode, UFS_IND_BLOCK + uspi->s_apb,
452                         (u32 *) &inode->u.ufs_i.i_u1.i_data[UFS_DIND_BLOCK]);
453                 retry |= ufs_trunc_tindirect (inode);
454                 if (!retry)
455                         break;
456                 if (IS_SYNC(inode) && (inode->i_state & I_DIRTY))
457                         ufs_sync_inode (inode);
458                 run_task_queue(&tq_disk);
459                 current->policy |= SCHED_YIELD;
460                 schedule ();
461 
462 
463         }
464         offset = inode->i_size & uspi->s_fshift;
465         if (offset) {
466                 bh = ufs_bread (inode, inode->i_size >> uspi->s_fshift, 0, &err);
467                 if (bh) {
468                         memset (bh->b_data + offset, 0, uspi->s_fsize - offset);
469                         mark_buffer_dirty (bh);
470                         brelse (bh);
471                 }
472         }
473         inode->i_mtime = inode->i_ctime = CURRENT_TIME;
474         inode->u.ufs_i.i_lastfrag = DIRECT_FRAGMENT;
475         mark_inode_dirty(inode);
476         UFSD(("EXIT\n"))
477 }
478 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.