Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.15-rc2 474 lines 11 kB view raw
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/time.h> 37#include <linux/stat.h> 38#include <linux/string.h> 39#include <linux/smp_lock.h> 40#include <linux/buffer_head.h> 41#include <linux/blkdev.h> 42#include <linux/sched.h> 43 44#include "swab.h" 45#include "util.h" 46 47#undef UFS_TRUNCATE_DEBUG 48 49#ifdef UFS_TRUNCATE_DEBUG 50#define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x; 51#else 52#define UFSD(x) 53#endif 54 55/* 56 * Secure deletion currently doesn't work. It interacts very badly 57 * with buffers shared with memory mappings, and for that reason 58 * can't be done in the truncate() routines. It should instead be 59 * done separately in "release()" before calling the truncate routines 60 * that will release the actual file blocks. 61 * 62 * Linus 63 */ 64 65#define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift) 66#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) 67 68#define DATA_BUFFER_USED(bh) \ 69 (atomic_read(&bh->b_count)>1 || buffer_locked(bh)) 70 71static int ufs_trunc_direct (struct inode * inode) 72{ 73 struct ufs_inode_info *ufsi = UFS_I(inode); 74 struct super_block * sb; 75 struct ufs_sb_private_info * uspi; 76 struct buffer_head * bh; 77 __fs32 * p; 78 unsigned frag1, frag2, frag3, frag4, block1, block2; 79 unsigned frag_to_free, free_count; 80 unsigned i, j, tmp; 81 int retry; 82 83 UFSD(("ENTER\n")) 84 85 sb = inode->i_sb; 86 uspi = UFS_SB(sb)->s_uspi; 87 88 frag_to_free = 0; 89 free_count = 0; 90 retry = 0; 91 92 frag1 = DIRECT_FRAGMENT; 93 frag4 = min_t(u32, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag); 94 frag2 = ((frag1 & uspi->s_fpbmask) ? ((frag1 | uspi->s_fpbmask) + 1) : frag1); 95 frag3 = frag4 & ~uspi->s_fpbmask; 96 block1 = block2 = 0; 97 if (frag2 > frag3) { 98 frag2 = frag4; 99 frag3 = frag4 = 0; 100 } 101 else if (frag2 < frag3) { 102 block1 = ufs_fragstoblks (frag2); 103 block2 = ufs_fragstoblks (frag3); 104 } 105 106 UFSD(("frag1 %u, frag2 %u, block1 %u, block2 %u, frag3 %u, frag4 %u\n", frag1, frag2, block1, block2, frag3, frag4)) 107 108 if (frag1 >= frag2) 109 goto next1; 110 111 /* 112 * Free first free fragments 113 */ 114 p = ufsi->i_u1.i_data + ufs_fragstoblks (frag1); 115 tmp = fs32_to_cpu(sb, *p); 116 if (!tmp ) 117 ufs_panic (sb, "ufs_trunc_direct", "internal error"); 118 frag1 = ufs_fragnum (frag1); 119 frag2 = ufs_fragnum (frag2); 120 for (j = frag1; j < frag2; j++) { 121 bh = sb_find_get_block (sb, tmp + j); 122 if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) { 123 retry = 1; 124 brelse (bh); 125 goto next1; 126 } 127 bforget (bh); 128 } 129 inode->i_blocks -= (frag2-frag1) << uspi->s_nspfshift; 130 mark_inode_dirty(inode); 131 ufs_free_fragments (inode, tmp + frag1, frag2 - frag1); 132 frag_to_free = tmp + frag1; 133 134next1: 135 /* 136 * Free whole blocks 137 */ 138 for (i = block1 ; i < block2; i++) { 139 p = ufsi->i_u1.i_data + i; 140 tmp = fs32_to_cpu(sb, *p); 141 if (!tmp) 142 continue; 143 for (j = 0; j < uspi->s_fpb; j++) { 144 bh = sb_find_get_block(sb, tmp + j); 145 if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) { 146 retry = 1; 147 brelse (bh); 148 goto next2; 149 } 150 bforget (bh); 151 } 152 *p = 0; 153 inode->i_blocks -= uspi->s_nspb; 154 mark_inode_dirty(inode); 155 if (free_count == 0) { 156 frag_to_free = tmp; 157 free_count = uspi->s_fpb; 158 } else if (free_count > 0 && frag_to_free == tmp - free_count) 159 free_count += uspi->s_fpb; 160 else { 161 ufs_free_blocks (inode, frag_to_free, free_count); 162 frag_to_free = tmp; 163 free_count = uspi->s_fpb; 164 } 165next2:; 166 } 167 168 if (free_count > 0) 169 ufs_free_blocks (inode, frag_to_free, free_count); 170 171 if (frag3 >= frag4) 172 goto next3; 173 174 /* 175 * Free last free fragments 176 */ 177 p = ufsi->i_u1.i_data + ufs_fragstoblks (frag3); 178 tmp = fs32_to_cpu(sb, *p); 179 if (!tmp ) 180 ufs_panic(sb, "ufs_truncate_direct", "internal error"); 181 frag4 = ufs_fragnum (frag4); 182 for (j = 0; j < frag4; j++) { 183 bh = sb_find_get_block (sb, tmp + j); 184 if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) { 185 retry = 1; 186 brelse (bh); 187 goto next1; 188 } 189 bforget (bh); 190 } 191 *p = 0; 192 inode->i_blocks -= frag4 << uspi->s_nspfshift; 193 mark_inode_dirty(inode); 194 ufs_free_fragments (inode, tmp, frag4); 195 next3: 196 197 UFSD(("EXIT\n")) 198 return retry; 199} 200 201 202static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) 203{ 204 struct super_block * sb; 205 struct ufs_sb_private_info * uspi; 206 struct ufs_buffer_head * ind_ubh; 207 struct buffer_head * bh; 208 __fs32 * ind; 209 unsigned indirect_block, i, j, tmp; 210 unsigned frag_to_free, free_count; 211 int retry; 212 213 UFSD(("ENTER\n")) 214 215 sb = inode->i_sb; 216 uspi = UFS_SB(sb)->s_uspi; 217 218 frag_to_free = 0; 219 free_count = 0; 220 retry = 0; 221 222 tmp = fs32_to_cpu(sb, *p); 223 if (!tmp) 224 return 0; 225 ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize); 226 if (tmp != fs32_to_cpu(sb, *p)) { 227 ubh_brelse (ind_ubh); 228 return 1; 229 } 230 if (!ind_ubh) { 231 *p = 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 = fs32_to_cpu(sb, *ind); 239 if (!tmp) 240 continue; 241 for (j = 0; j < uspi->s_fpb; j++) { 242 bh = sb_find_get_block(sb, tmp + j); 243 if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *ind)) { 244 retry = 1; 245 brelse (bh); 246 goto next; 247 } 248 bforget (bh); 249 } 250 *ind = 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); 264next:; 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 (*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 = fs32_to_cpu(sb, *p); 279 *p = 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 (SWRITE, 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 298static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *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 __fs32 * dind; 305 int retry = 0; 306 307 UFSD(("ENTER\n")) 308 309 sb = inode->i_sb; 310 uspi = UFS_SB(sb)->s_uspi; 311 312 dindirect_block = (DIRECT_BLOCK > offset) 313 ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0; 314 retry = 0; 315 316 tmp = fs32_to_cpu(sb, *p); 317 if (!tmp) 318 return 0; 319 dind_bh = ubh_bread(sb, tmp, uspi->s_bsize); 320 if (tmp != fs32_to_cpu(sb, *p)) { 321 ubh_brelse (dind_bh); 322 return 1; 323 } 324 if (!dind_bh) { 325 *p = 0; 326 return 0; 327 } 328 329 for (i = dindirect_block ; i < uspi->s_apb ; i++) { 330 dind = ubh_get_addr32 (dind_bh, i); 331 tmp = fs32_to_cpu(sb, *dind); 332 if (!tmp) 333 continue; 334 retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind); 335 ubh_mark_buffer_dirty(dind_bh); 336 } 337 338 for (i = 0; i < uspi->s_apb; i++) 339 if (*ubh_get_addr32 (dind_bh, i)) 340 break; 341 if (i >= uspi->s_apb) { 342 if (ubh_max_bcount(dind_bh) != 1) 343 retry = 1; 344 else { 345 tmp = fs32_to_cpu(sb, *p); 346 *p = 0; 347 inode->i_blocks -= uspi->s_nspb; 348 mark_inode_dirty(inode); 349 ufs_free_blocks (inode, tmp, uspi->s_fpb); 350 ubh_bforget(dind_bh); 351 dind_bh = NULL; 352 } 353 } 354 if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) { 355 ubh_ll_rw_block (SWRITE, 1, &dind_bh); 356 ubh_wait_on_buffer (dind_bh); 357 } 358 ubh_brelse (dind_bh); 359 360 UFSD(("EXIT\n")) 361 362 return retry; 363} 364 365static int ufs_trunc_tindirect (struct inode * inode) 366{ 367 struct ufs_inode_info *ufsi = UFS_I(inode); 368 struct super_block * sb; 369 struct ufs_sb_private_info * uspi; 370 struct ufs_buffer_head * tind_bh; 371 unsigned tindirect_block, tmp, i; 372 __fs32 * tind, * p; 373 int retry; 374 375 UFSD(("ENTER\n")) 376 377 sb = inode->i_sb; 378 uspi = UFS_SB(sb)->s_uspi; 379 retry = 0; 380 381 tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb)) 382 ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0; 383 p = ufsi->i_u1.i_data + UFS_TIND_BLOCK; 384 if (!(tmp = fs32_to_cpu(sb, *p))) 385 return 0; 386 tind_bh = ubh_bread (sb, tmp, uspi->s_bsize); 387 if (tmp != fs32_to_cpu(sb, *p)) { 388 ubh_brelse (tind_bh); 389 return 1; 390 } 391 if (!tind_bh) { 392 *p = 0; 393 return 0; 394 } 395 396 for (i = tindirect_block ; i < uspi->s_apb ; i++) { 397 tind = ubh_get_addr32 (tind_bh, i); 398 retry |= ufs_trunc_dindirect(inode, UFS_NDADDR + 399 uspi->s_apb + ((i + 1) << uspi->s_2apbshift), tind); 400 ubh_mark_buffer_dirty(tind_bh); 401 } 402 for (i = 0; i < uspi->s_apb; i++) 403 if (*ubh_get_addr32 (tind_bh, i)) 404 break; 405 if (i >= uspi->s_apb) { 406 if (ubh_max_bcount(tind_bh) != 1) 407 retry = 1; 408 else { 409 tmp = fs32_to_cpu(sb, *p); 410 *p = 0; 411 inode->i_blocks -= uspi->s_nspb; 412 mark_inode_dirty(inode); 413 ufs_free_blocks (inode, tmp, uspi->s_fpb); 414 ubh_bforget(tind_bh); 415 tind_bh = NULL; 416 } 417 } 418 if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) { 419 ubh_ll_rw_block (SWRITE, 1, &tind_bh); 420 ubh_wait_on_buffer (tind_bh); 421 } 422 ubh_brelse (tind_bh); 423 424 UFSD(("EXIT\n")) 425 return retry; 426} 427 428void ufs_truncate (struct inode * inode) 429{ 430 struct ufs_inode_info *ufsi = UFS_I(inode); 431 struct super_block * sb; 432 struct ufs_sb_private_info * uspi; 433 struct buffer_head * bh; 434 unsigned offset; 435 int err, retry; 436 437 UFSD(("ENTER\n")) 438 sb = inode->i_sb; 439 uspi = UFS_SB(sb)->s_uspi; 440 441 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) 442 return; 443 if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) 444 return; 445 lock_kernel(); 446 while (1) { 447 retry = ufs_trunc_direct(inode); 448 retry |= ufs_trunc_indirect (inode, UFS_IND_BLOCK, 449 (__fs32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]); 450 retry |= ufs_trunc_dindirect (inode, UFS_IND_BLOCK + uspi->s_apb, 451 (__fs32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]); 452 retry |= ufs_trunc_tindirect (inode); 453 if (!retry) 454 break; 455 if (IS_SYNC(inode) && (inode->i_state & I_DIRTY)) 456 ufs_sync_inode (inode); 457 blk_run_address_space(inode->i_mapping); 458 yield(); 459 } 460 offset = inode->i_size & uspi->s_fshift; 461 if (offset) { 462 bh = ufs_bread (inode, inode->i_size >> uspi->s_fshift, 0, &err); 463 if (bh) { 464 memset (bh->b_data + offset, 0, uspi->s_fsize - offset); 465 mark_buffer_dirty (bh); 466 brelse (bh); 467 } 468 } 469 inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; 470 ufsi->i_lastfrag = DIRECT_FRAGMENT; 471 unlock_kernel(); 472 mark_inode_dirty(inode); 473 UFSD(("EXIT\n")) 474}