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.33-rc2 535 lines 13 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/* 33 * Adoptation to use page cache and UFS2 write support by 34 * Evgeniy Dushistov <dushistov@mail.ru>, 2006-2007 35 */ 36 37#include <linux/errno.h> 38#include <linux/fs.h> 39#include <linux/fcntl.h> 40#include <linux/time.h> 41#include <linux/stat.h> 42#include <linux/string.h> 43#include <linux/smp_lock.h> 44#include <linux/buffer_head.h> 45#include <linux/blkdev.h> 46#include <linux/sched.h> 47 48#include "ufs_fs.h" 49#include "ufs.h" 50#include "swab.h" 51#include "util.h" 52 53/* 54 * Secure deletion currently doesn't work. It interacts very badly 55 * with buffers shared with memory mappings, and for that reason 56 * can't be done in the truncate() routines. It should instead be 57 * done separately in "release()" before calling the truncate routines 58 * that will release the actual file blocks. 59 * 60 * Linus 61 */ 62 63#define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift) 64#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) 65 66 67static int ufs_trunc_direct(struct inode *inode) 68{ 69 struct ufs_inode_info *ufsi = UFS_I(inode); 70 struct super_block * sb; 71 struct ufs_sb_private_info * uspi; 72 void *p; 73 u64 frag1, frag2, frag3, frag4, block1, block2; 74 unsigned frag_to_free, free_count; 75 unsigned i, tmp; 76 int retry; 77 78 UFSD("ENTER: ino %lu\n", inode->i_ino); 79 80 sb = inode->i_sb; 81 uspi = UFS_SB(sb)->s_uspi; 82 83 frag_to_free = 0; 84 free_count = 0; 85 retry = 0; 86 87 frag1 = DIRECT_FRAGMENT; 88 frag4 = min_t(u32, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag); 89 frag2 = ((frag1 & uspi->s_fpbmask) ? ((frag1 | uspi->s_fpbmask) + 1) : frag1); 90 frag3 = frag4 & ~uspi->s_fpbmask; 91 block1 = block2 = 0; 92 if (frag2 > frag3) { 93 frag2 = frag4; 94 frag3 = frag4 = 0; 95 } else if (frag2 < frag3) { 96 block1 = ufs_fragstoblks (frag2); 97 block2 = ufs_fragstoblks (frag3); 98 } 99 100 UFSD("ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu," 101 " frag3 %llu, frag4 %llu\n", inode->i_ino, 102 (unsigned long long)frag1, (unsigned long long)frag2, 103 (unsigned long long)block1, (unsigned long long)block2, 104 (unsigned long long)frag3, (unsigned long long)frag4); 105 106 if (frag1 >= frag2) 107 goto next1; 108 109 /* 110 * Free first free fragments 111 */ 112 p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1)); 113 tmp = ufs_data_ptr_to_cpu(sb, p); 114 if (!tmp ) 115 ufs_panic (sb, "ufs_trunc_direct", "internal error"); 116 frag2 -= frag1; 117 frag1 = ufs_fragnum (frag1); 118 119 ufs_free_fragments(inode, tmp + frag1, frag2); 120 mark_inode_dirty(inode); 121 frag_to_free = tmp + frag1; 122 123next1: 124 /* 125 * Free whole blocks 126 */ 127 for (i = block1 ; i < block2; i++) { 128 p = ufs_get_direct_data_ptr(uspi, ufsi, i); 129 tmp = ufs_data_ptr_to_cpu(sb, p); 130 if (!tmp) 131 continue; 132 ufs_data_ptr_clear(uspi, p); 133 134 if (free_count == 0) { 135 frag_to_free = tmp; 136 free_count = uspi->s_fpb; 137 } else if (free_count > 0 && frag_to_free == tmp - free_count) 138 free_count += uspi->s_fpb; 139 else { 140 ufs_free_blocks (inode, frag_to_free, free_count); 141 frag_to_free = tmp; 142 free_count = uspi->s_fpb; 143 } 144 mark_inode_dirty(inode); 145 } 146 147 if (free_count > 0) 148 ufs_free_blocks (inode, frag_to_free, free_count); 149 150 if (frag3 >= frag4) 151 goto next3; 152 153 /* 154 * Free last free fragments 155 */ 156 p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3)); 157 tmp = ufs_data_ptr_to_cpu(sb, p); 158 if (!tmp ) 159 ufs_panic(sb, "ufs_truncate_direct", "internal error"); 160 frag4 = ufs_fragnum (frag4); 161 ufs_data_ptr_clear(uspi, p); 162 163 ufs_free_fragments (inode, tmp, frag4); 164 mark_inode_dirty(inode); 165 next3: 166 167 UFSD("EXIT: ino %lu\n", inode->i_ino); 168 return retry; 169} 170 171 172static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p) 173{ 174 struct super_block * sb; 175 struct ufs_sb_private_info * uspi; 176 struct ufs_buffer_head * ind_ubh; 177 void *ind; 178 u64 tmp, indirect_block, i, frag_to_free; 179 unsigned free_count; 180 int retry; 181 182 UFSD("ENTER: ino %lu, offset %llu, p: %p\n", 183 inode->i_ino, (unsigned long long)offset, p); 184 185 BUG_ON(!p); 186 187 sb = inode->i_sb; 188 uspi = UFS_SB(sb)->s_uspi; 189 190 frag_to_free = 0; 191 free_count = 0; 192 retry = 0; 193 194 tmp = ufs_data_ptr_to_cpu(sb, p); 195 if (!tmp) 196 return 0; 197 ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize); 198 if (tmp != ufs_data_ptr_to_cpu(sb, p)) { 199 ubh_brelse (ind_ubh); 200 return 1; 201 } 202 if (!ind_ubh) { 203 ufs_data_ptr_clear(uspi, p); 204 return 0; 205 } 206 207 indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0; 208 for (i = indirect_block; i < uspi->s_apb; i++) { 209 ind = ubh_get_data_ptr(uspi, ind_ubh, i); 210 tmp = ufs_data_ptr_to_cpu(sb, ind); 211 if (!tmp) 212 continue; 213 214 ufs_data_ptr_clear(uspi, ind); 215 ubh_mark_buffer_dirty(ind_ubh); 216 if (free_count == 0) { 217 frag_to_free = tmp; 218 free_count = uspi->s_fpb; 219 } else if (free_count > 0 && frag_to_free == tmp - free_count) 220 free_count += uspi->s_fpb; 221 else { 222 ufs_free_blocks (inode, frag_to_free, free_count); 223 frag_to_free = tmp; 224 free_count = uspi->s_fpb; 225 } 226 227 mark_inode_dirty(inode); 228 } 229 230 if (free_count > 0) { 231 ufs_free_blocks (inode, frag_to_free, free_count); 232 } 233 for (i = 0; i < uspi->s_apb; i++) 234 if (!ufs_is_data_ptr_zero(uspi, 235 ubh_get_data_ptr(uspi, ind_ubh, i))) 236 break; 237 if (i >= uspi->s_apb) { 238 tmp = ufs_data_ptr_to_cpu(sb, p); 239 ufs_data_ptr_clear(uspi, p); 240 241 ufs_free_blocks (inode, tmp, uspi->s_fpb); 242 mark_inode_dirty(inode); 243 ubh_bforget(ind_ubh); 244 ind_ubh = NULL; 245 } 246 if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) { 247 ubh_ll_rw_block(SWRITE, ind_ubh); 248 ubh_wait_on_buffer (ind_ubh); 249 } 250 ubh_brelse (ind_ubh); 251 252 UFSD("EXIT: ino %lu\n", inode->i_ino); 253 254 return retry; 255} 256 257static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p) 258{ 259 struct super_block * sb; 260 struct ufs_sb_private_info * uspi; 261 struct ufs_buffer_head *dind_bh; 262 u64 i, tmp, dindirect_block; 263 void *dind; 264 int retry = 0; 265 266 UFSD("ENTER: ino %lu\n", inode->i_ino); 267 268 sb = inode->i_sb; 269 uspi = UFS_SB(sb)->s_uspi; 270 271 dindirect_block = (DIRECT_BLOCK > offset) 272 ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0; 273 retry = 0; 274 275 tmp = ufs_data_ptr_to_cpu(sb, p); 276 if (!tmp) 277 return 0; 278 dind_bh = ubh_bread(sb, tmp, uspi->s_bsize); 279 if (tmp != ufs_data_ptr_to_cpu(sb, p)) { 280 ubh_brelse (dind_bh); 281 return 1; 282 } 283 if (!dind_bh) { 284 ufs_data_ptr_clear(uspi, p); 285 return 0; 286 } 287 288 for (i = dindirect_block ; i < uspi->s_apb ; i++) { 289 dind = ubh_get_data_ptr(uspi, dind_bh, i); 290 tmp = ufs_data_ptr_to_cpu(sb, dind); 291 if (!tmp) 292 continue; 293 retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind); 294 ubh_mark_buffer_dirty(dind_bh); 295 } 296 297 for (i = 0; i < uspi->s_apb; i++) 298 if (!ufs_is_data_ptr_zero(uspi, 299 ubh_get_data_ptr(uspi, dind_bh, i))) 300 break; 301 if (i >= uspi->s_apb) { 302 tmp = ufs_data_ptr_to_cpu(sb, p); 303 ufs_data_ptr_clear(uspi, p); 304 305 ufs_free_blocks(inode, tmp, uspi->s_fpb); 306 mark_inode_dirty(inode); 307 ubh_bforget(dind_bh); 308 dind_bh = NULL; 309 } 310 if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) { 311 ubh_ll_rw_block(SWRITE, dind_bh); 312 ubh_wait_on_buffer (dind_bh); 313 } 314 ubh_brelse (dind_bh); 315 316 UFSD("EXIT: ino %lu\n", inode->i_ino); 317 318 return retry; 319} 320 321static int ufs_trunc_tindirect(struct inode *inode) 322{ 323 struct super_block *sb = inode->i_sb; 324 struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; 325 struct ufs_inode_info *ufsi = UFS_I(inode); 326 struct ufs_buffer_head * tind_bh; 327 u64 tindirect_block, tmp, i; 328 void *tind, *p; 329 int retry; 330 331 UFSD("ENTER: ino %lu\n", inode->i_ino); 332 333 retry = 0; 334 335 tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb)) 336 ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0; 337 338 p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK); 339 if (!(tmp = ufs_data_ptr_to_cpu(sb, p))) 340 return 0; 341 tind_bh = ubh_bread (sb, tmp, uspi->s_bsize); 342 if (tmp != ufs_data_ptr_to_cpu(sb, p)) { 343 ubh_brelse (tind_bh); 344 return 1; 345 } 346 if (!tind_bh) { 347 ufs_data_ptr_clear(uspi, p); 348 return 0; 349 } 350 351 for (i = tindirect_block ; i < uspi->s_apb ; i++) { 352 tind = ubh_get_data_ptr(uspi, tind_bh, i); 353 retry |= ufs_trunc_dindirect(inode, UFS_NDADDR + 354 uspi->s_apb + ((i + 1) << uspi->s_2apbshift), tind); 355 ubh_mark_buffer_dirty(tind_bh); 356 } 357 for (i = 0; i < uspi->s_apb; i++) 358 if (!ufs_is_data_ptr_zero(uspi, 359 ubh_get_data_ptr(uspi, tind_bh, i))) 360 break; 361 if (i >= uspi->s_apb) { 362 tmp = ufs_data_ptr_to_cpu(sb, p); 363 ufs_data_ptr_clear(uspi, p); 364 365 ufs_free_blocks(inode, tmp, uspi->s_fpb); 366 mark_inode_dirty(inode); 367 ubh_bforget(tind_bh); 368 tind_bh = NULL; 369 } 370 if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) { 371 ubh_ll_rw_block(SWRITE, tind_bh); 372 ubh_wait_on_buffer (tind_bh); 373 } 374 ubh_brelse (tind_bh); 375 376 UFSD("EXIT: ino %lu\n", inode->i_ino); 377 return retry; 378} 379 380static int ufs_alloc_lastblock(struct inode *inode) 381{ 382 int err = 0; 383 struct super_block *sb = inode->i_sb; 384 struct address_space *mapping = inode->i_mapping; 385 struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; 386 unsigned i, end; 387 sector_t lastfrag; 388 struct page *lastpage; 389 struct buffer_head *bh; 390 u64 phys64; 391 392 lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift; 393 394 if (!lastfrag) 395 goto out; 396 397 lastfrag--; 398 399 lastpage = ufs_get_locked_page(mapping, lastfrag >> 400 (PAGE_CACHE_SHIFT - inode->i_blkbits)); 401 if (IS_ERR(lastpage)) { 402 err = -EIO; 403 goto out; 404 } 405 406 end = lastfrag & ((1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1); 407 bh = page_buffers(lastpage); 408 for (i = 0; i < end; ++i) 409 bh = bh->b_this_page; 410 411 412 err = ufs_getfrag_block(inode, lastfrag, bh, 1); 413 414 if (unlikely(err)) 415 goto out_unlock; 416 417 if (buffer_new(bh)) { 418 clear_buffer_new(bh); 419 unmap_underlying_metadata(bh->b_bdev, 420 bh->b_blocknr); 421 /* 422 * we do not zeroize fragment, because of 423 * if it maped to hole, it already contains zeroes 424 */ 425 set_buffer_uptodate(bh); 426 mark_buffer_dirty(bh); 427 set_page_dirty(lastpage); 428 } 429 430 if (lastfrag >= UFS_IND_FRAGMENT) { 431 end = uspi->s_fpb - ufs_fragnum(lastfrag) - 1; 432 phys64 = bh->b_blocknr + 1; 433 for (i = 0; i < end; ++i) { 434 bh = sb_getblk(sb, i + phys64); 435 lock_buffer(bh); 436 memset(bh->b_data, 0, sb->s_blocksize); 437 set_buffer_uptodate(bh); 438 mark_buffer_dirty(bh); 439 unlock_buffer(bh); 440 sync_dirty_buffer(bh); 441 brelse(bh); 442 } 443 } 444out_unlock: 445 ufs_put_locked_page(lastpage); 446out: 447 return err; 448} 449 450int ufs_truncate(struct inode *inode, loff_t old_i_size) 451{ 452 struct ufs_inode_info *ufsi = UFS_I(inode); 453 struct super_block *sb = inode->i_sb; 454 struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; 455 int retry, err = 0; 456 457 UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n", 458 inode->i_ino, (unsigned long long)i_size_read(inode), 459 (unsigned long long)old_i_size); 460 461 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || 462 S_ISLNK(inode->i_mode))) 463 return -EINVAL; 464 if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) 465 return -EPERM; 466 467 err = ufs_alloc_lastblock(inode); 468 469 if (err) { 470 i_size_write(inode, old_i_size); 471 goto out; 472 } 473 474 block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block); 475 476 lock_kernel(); 477 while (1) { 478 retry = ufs_trunc_direct(inode); 479 retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK, 480 ufs_get_direct_data_ptr(uspi, ufsi, 481 UFS_IND_BLOCK)); 482 retry |= ufs_trunc_dindirect(inode, UFS_IND_BLOCK + uspi->s_apb, 483 ufs_get_direct_data_ptr(uspi, ufsi, 484 UFS_DIND_BLOCK)); 485 retry |= ufs_trunc_tindirect (inode); 486 if (!retry) 487 break; 488 if (IS_SYNC(inode) && (inode->i_state & I_DIRTY)) 489 ufs_sync_inode (inode); 490 blk_run_address_space(inode->i_mapping); 491 yield(); 492 } 493 494 inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; 495 ufsi->i_lastfrag = DIRECT_FRAGMENT; 496 unlock_kernel(); 497 mark_inode_dirty(inode); 498out: 499 UFSD("EXIT: err %d\n", err); 500 return err; 501} 502 503 504/* 505 * We don't define our `inode->i_op->truncate', and call it here, 506 * because of: 507 * - there is no way to know old size 508 * - there is no way inform user about error, if it happens in `truncate' 509 */ 510static int ufs_setattr(struct dentry *dentry, struct iattr *attr) 511{ 512 struct inode *inode = dentry->d_inode; 513 unsigned int ia_valid = attr->ia_valid; 514 int error; 515 516 error = inode_change_ok(inode, attr); 517 if (error) 518 return error; 519 520 if (ia_valid & ATTR_SIZE && 521 attr->ia_size != i_size_read(inode)) { 522 loff_t old_i_size = inode->i_size; 523 error = vmtruncate(inode, attr->ia_size); 524 if (error) 525 return error; 526 error = ufs_truncate(inode, old_i_size); 527 if (error) 528 return error; 529 } 530 return inode_setattr(inode, attr); 531} 532 533const struct inode_operations ufs_file_inode_operations = { 534 .setattr = ufs_setattr, 535};