1/* 2 * linux/fs/affs/file.c 3 * 4 * (c) 1996 Hans-Joachim Widmaier - Rewritten 5 * 6 * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem. 7 * 8 * (C) 1992 Eric Youngdale Modified for ISO 9660 filesystem. 9 * 10 * (C) 1991 Linus Torvalds - minix filesystem 11 * 12 * affs regular file handling primitives 13 */ 14 15#include <asm/div64.h> 16#include <asm/uaccess.h> 17#include <asm/system.h> 18#include <linux/sched.h> 19#include <linux/affs_fs.h> 20#include <linux/fcntl.h> 21#include <linux/kernel.h> 22#include <linux/errno.h> 23#include <linux/slab.h> 24#include <linux/stat.h> 25#include <linux/locks.h> 26#include <linux/smp_lock.h> 27#include <linux/dirent.h> 28#include <linux/fs.h> 29#include <linux/amigaffs.h> 30#include <linux/mm.h> 31#include <linux/pagemap.h> 32 33#if PAGE_SIZE < 4096 34#error PAGE_SIZE must be at least 4096 35#endif 36 37static int affs_grow_extcache(struct inode *inode, u32 lc_idx); 38static struct buffer_head *affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext); 39static inline struct buffer_head *affs_get_extblock(struct inode *inode, u32 ext); 40static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext); 41static int affs_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create); 42 43static ssize_t affs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos); 44static int affs_file_open(struct inode *inode, struct file *filp); 45static int affs_file_release(struct inode *inode, struct file *filp); 46 47struct file_operations affs_file_operations = { 48 llseek: generic_file_llseek, 49 read: generic_file_read, 50 write: affs_file_write, 51 mmap: generic_file_mmap, 52 open: affs_file_open, 53 release: affs_file_release, 54 fsync: file_fsync, 55}; 56 57struct inode_operations affs_file_inode_operations = { 58 truncate: affs_truncate, 59 setattr: affs_notify_change, 60}; 61 62static int 63affs_file_open(struct inode *inode, struct file *filp) 64{ 65 if (atomic_read(&filp->f_count) != 1) 66 return 0; 67 pr_debug("AFFS: open(%d)\n", AFFS_INODE->i_opencnt); 68 AFFS_INODE->i_opencnt++; 69 return 0; 70} 71 72static int 73affs_file_release(struct inode *inode, struct file *filp) 74{ 75 if (atomic_read(&filp->f_count) != 0) 76 return 0; 77 pr_debug("AFFS: release(%d)\n", AFFS_INODE->i_opencnt); 78 AFFS_INODE->i_opencnt--; 79 if (!AFFS_INODE->i_opencnt) 80 affs_free_prealloc(inode); 81 82 return 0; 83} 84 85static int 86affs_grow_extcache(struct inode *inode, u32 lc_idx) 87{ 88 struct super_block *sb = inode->i_sb; 89 struct buffer_head *bh; 90 u32 lc_max; 91 int i, j, key; 92 93 if (!AFFS_INODE->i_lc) { 94 char *ptr = (char *)get_zeroed_page(GFP_NOFS); 95 if (!ptr) 96 return -ENOMEM; 97 AFFS_INODE->i_lc = (u32 *)ptr; 98 AFFS_INODE->i_ac = (struct affs_ext_key *)(ptr + AFFS_CACHE_SIZE / 2); 99 } 100 101 lc_max = AFFS_LC_SIZE << AFFS_INODE->i_lc_shift; 102 103 if (AFFS_INODE->i_extcnt > lc_max) { 104 u32 lc_shift, lc_mask, tmp, off; 105 106 /* need to recalculate linear cache, start from old size */ 107 lc_shift = AFFS_INODE->i_lc_shift; 108 tmp = (AFFS_INODE->i_extcnt / AFFS_LC_SIZE) >> lc_shift; 109 for (; tmp; tmp >>= 1) 110 lc_shift++; 111 lc_mask = (1 << lc_shift) - 1; 112 113 /* fix idx and old size to new shift */ 114 lc_idx >>= (lc_shift - AFFS_INODE->i_lc_shift); 115 AFFS_INODE->i_lc_size >>= (lc_shift - AFFS_INODE->i_lc_shift); 116 117 /* first shrink old cache to make more space */ 118 off = 1 << (lc_shift - AFFS_INODE->i_lc_shift); 119 for (i = 1, j = off; j < AFFS_LC_SIZE; i++, j += off) 120 AFFS_INODE->i_ac[i] = AFFS_INODE->i_ac[j]; 121 122 AFFS_INODE->i_lc_shift = lc_shift; 123 AFFS_INODE->i_lc_mask = lc_mask; 124 } 125 126 /* fill cache to the needed index */ 127 i = AFFS_INODE->i_lc_size; 128 AFFS_INODE->i_lc_size = lc_idx + 1; 129 for (; i <= lc_idx; i++) { 130 if (!i) { 131 AFFS_INODE->i_lc[0] = inode->i_ino; 132 continue; 133 } 134 key = AFFS_INODE->i_lc[i - 1]; 135 j = AFFS_INODE->i_lc_mask + 1; 136 // unlock cache 137 for (; j > 0; j--) { 138 bh = affs_bread(sb, key); 139 if (!bh) 140 goto err; 141 key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension); 142 affs_brelse(bh); 143 } 144 // lock cache 145 AFFS_INODE->i_lc[i] = key; 146 } 147 148 return 0; 149 150err: 151 // lock cache 152 return -EIO; 153} 154 155static struct buffer_head * 156affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext) 157{ 158 struct super_block *sb = inode->i_sb; 159 struct buffer_head *new_bh; 160 u32 blocknr, tmp; 161 162 blocknr = affs_alloc_block(inode, bh->b_blocknr); 163 if (!blocknr) 164 return ERR_PTR(-ENOSPC); 165 166 new_bh = affs_getzeroblk(sb, blocknr); 167 if (!new_bh) { 168 affs_free_block(sb, blocknr); 169 return ERR_PTR(-EIO); 170 } 171 172 AFFS_HEAD(new_bh)->ptype = cpu_to_be32(T_LIST); 173 AFFS_HEAD(new_bh)->key = cpu_to_be32(blocknr); 174 AFFS_TAIL(sb, new_bh)->stype = cpu_to_be32(ST_FILE); 175 AFFS_TAIL(sb, new_bh)->parent = cpu_to_be32(inode->i_ino); 176 affs_fix_checksum(sb, new_bh); 177 178 mark_buffer_dirty_inode(new_bh, inode); 179 180 tmp = be32_to_cpu(AFFS_TAIL(sb, bh)->extension); 181 if (tmp) 182 affs_warning(sb, "alloc_ext", "previous extension set (%x)", tmp); 183 AFFS_TAIL(sb, bh)->extension = cpu_to_be32(blocknr); 184 affs_adjust_checksum(bh, blocknr - tmp); 185 mark_buffer_dirty_inode(bh, inode); 186 187 AFFS_INODE->i_extcnt++; 188 mark_inode_dirty(inode); 189 190 return new_bh; 191} 192 193static inline struct buffer_head * 194affs_get_extblock(struct inode *inode, u32 ext) 195{ 196 /* inline the simplest case: same extended block as last time */ 197 struct buffer_head *bh = AFFS_INODE->i_ext_bh; 198 if (ext == AFFS_INODE->i_ext_last) 199 atomic_inc(&bh->b_count); 200 else 201 /* we have to do more (not inlined) */ 202 bh = affs_get_extblock_slow(inode, ext); 203 204 return bh; 205} 206 207static struct buffer_head * 208affs_get_extblock_slow(struct inode *inode, u32 ext) 209{ 210 struct super_block *sb = inode->i_sb; 211 struct buffer_head *bh; 212 u32 ext_key; 213 u32 lc_idx, lc_off, ac_idx; 214 u32 tmp, idx; 215 216 if (ext == AFFS_INODE->i_ext_last + 1) { 217 /* read the next extended block from the current one */ 218 bh = AFFS_INODE->i_ext_bh; 219 ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension); 220 if (ext < AFFS_INODE->i_extcnt) 221 goto read_ext; 222 if (ext > AFFS_INODE->i_extcnt) 223 BUG(); 224 bh = affs_alloc_extblock(inode, bh, ext); 225 if (IS_ERR(bh)) 226 return bh; 227 goto store_ext; 228 } 229 230 if (ext == 0) { 231 /* we seek back to the file header block */ 232 ext_key = inode->i_ino; 233 goto read_ext; 234 } 235 236 if (ext >= AFFS_INODE->i_extcnt) { 237 struct buffer_head *prev_bh; 238 239 /* allocate a new extended block */ 240 if (ext > AFFS_INODE->i_extcnt) 241 BUG(); 242 243 /* get previous extended block */ 244 prev_bh = affs_get_extblock(inode, ext - 1); 245 if (IS_ERR(prev_bh)) 246 return prev_bh; 247 bh = affs_alloc_extblock(inode, prev_bh, ext); 248 affs_brelse(prev_bh); 249 if (IS_ERR(bh)) 250 return bh; 251 goto store_ext; 252 } 253 254again: 255 /* check if there is an extended cache and whether it's large enough */ 256 lc_idx = ext >> AFFS_INODE->i_lc_shift; 257 lc_off = ext & AFFS_INODE->i_lc_mask; 258 259 if (lc_idx >= AFFS_INODE->i_lc_size) { 260 int err; 261 262 err = affs_grow_extcache(inode, lc_idx); 263 if (err) 264 return ERR_PTR(err); 265 goto again; 266 } 267 268 /* every n'th key we find in the linear cache */ 269 if (!lc_off) { 270 ext_key = AFFS_INODE->i_lc[lc_idx]; 271 goto read_ext; 272 } 273 274 /* maybe it's still in the associative cache */ 275 ac_idx = (ext - lc_idx - 1) & AFFS_AC_MASK; 276 if (AFFS_INODE->i_ac[ac_idx].ext == ext) { 277 ext_key = AFFS_INODE->i_ac[ac_idx].key; 278 goto read_ext; 279 } 280 281 /* try to find one of the previous extended blocks */ 282 tmp = ext; 283 idx = ac_idx; 284 while (--tmp, --lc_off > 0) { 285 idx = (idx - 1) & AFFS_AC_MASK; 286 if (AFFS_INODE->i_ac[idx].ext == tmp) { 287 ext_key = AFFS_INODE->i_ac[idx].key; 288 goto find_ext; 289 } 290 } 291 292 /* fall back to the linear cache */ 293 ext_key = AFFS_INODE->i_lc[lc_idx]; 294find_ext: 295 /* read all extended blocks until we find the one we need */ 296 //unlock cache 297 do { 298 bh = affs_bread(sb, ext_key); 299 if (!bh) 300 goto err_bread; 301 ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension); 302 affs_brelse(bh); 303 tmp++; 304 } while (tmp < ext); 305 //lock cache 306 307 /* store it in the associative cache */ 308 // recalculate ac_idx? 309 AFFS_INODE->i_ac[ac_idx].ext = ext; 310 AFFS_INODE->i_ac[ac_idx].key = ext_key; 311 312read_ext: 313 /* finally read the right extended block */ 314 //unlock cache 315 bh = affs_bread(sb, ext_key); 316 if (!bh) 317 goto err_bread; 318 //lock cache 319 320store_ext: 321 /* release old cached extended block and store the new one */ 322 affs_brelse(AFFS_INODE->i_ext_bh); 323 AFFS_INODE->i_ext_last = ext; 324 AFFS_INODE->i_ext_bh = bh; 325 atomic_inc(&bh->b_count); 326 327 return bh; 328 329err_bread: 330 affs_brelse(bh); 331 return ERR_PTR(-EIO); 332} 333 334static int 335affs_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create) 336{ 337 struct super_block *sb = inode->i_sb; 338 struct buffer_head *ext_bh; 339 u32 ext; 340 341 pr_debug("AFFS: get_block(%u, %ld)\n", (u32)inode->i_ino, block); 342 343 if (block < 0) 344 goto err_small; 345 346 if (block >= AFFS_INODE->i_blkcnt) { 347 if (block > AFFS_INODE->i_blkcnt || !create) 348 goto err_big; 349 } else 350 create = 0; 351 352 //lock cache 353 affs_lock_ext(inode); 354 355 ext = block / AFFS_SB->s_hashsize; 356 block -= ext * AFFS_SB->s_hashsize; 357 ext_bh = affs_get_extblock(inode, ext); 358 if (IS_ERR(ext_bh)) 359 goto err_ext; 360 bh_result->b_blocknr = be32_to_cpu(AFFS_BLOCK(sb, ext_bh, block)); 361 bh_result->b_dev = inode->i_dev; 362 bh_result->b_state |= (1UL << BH_Mapped); 363 364 if (create) { 365 u32 blocknr = affs_alloc_block(inode, ext_bh->b_blocknr); 366 if (!blocknr) 367 goto err_alloc; 368 bh_result->b_state |= (1UL << BH_New); 369 AFFS_INODE->mmu_private += AFFS_SB->s_data_blksize; 370 AFFS_INODE->i_blkcnt++; 371 372 /* store new block */ 373 if (bh_result->b_blocknr) 374 affs_warning(sb, "get_block", "block already set (%x)", bh_result->b_blocknr); 375 AFFS_BLOCK(sb, ext_bh, block) = cpu_to_be32(blocknr); 376 AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(block + 1); 377 affs_adjust_checksum(ext_bh, blocknr - bh_result->b_blocknr + 1); 378 bh_result->b_blocknr = blocknr; 379 380 if (!block) { 381 /* insert first block into header block */ 382 u32 tmp = be32_to_cpu(AFFS_HEAD(ext_bh)->first_data); 383 if (tmp) 384 affs_warning(sb, "get_block", "first block already set (%d)", tmp); 385 AFFS_HEAD(ext_bh)->first_data = cpu_to_be32(blocknr); 386 affs_adjust_checksum(ext_bh, blocknr - tmp); 387 } 388 } 389 390 affs_brelse(ext_bh); 391 //unlock cache 392 affs_unlock_ext(inode); 393 return 0; 394 395err_small: 396 affs_error(inode->i_sb,"get_block","Block < 0"); 397 return -EIO; 398err_big: 399 affs_error(inode->i_sb,"get_block","strange block request %d", block); 400 return -EIO; 401err_ext: 402 // unlock cache 403 affs_unlock_ext(inode); 404 return PTR_ERR(ext_bh); 405err_alloc: 406 brelse(ext_bh); 407 bh_result->b_state &= ~(1UL << BH_Mapped); 408 // unlock cache 409 affs_unlock_ext(inode); 410 return -ENOSPC; 411} 412 413static int affs_writepage(struct page *page) 414{ 415 return block_write_full_page(page, affs_get_block); 416} 417static int affs_readpage(struct file *file, struct page *page) 418{ 419 return block_read_full_page(page, affs_get_block); 420} 421static int affs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) 422{ 423 return cont_prepare_write(page, from, to, affs_get_block, 424 &page->mapping->host->u.affs_i.mmu_private); 425} 426static int _affs_bmap(struct address_space *mapping, long block) 427{ 428 return generic_block_bmap(mapping,block,affs_get_block); 429} 430struct address_space_operations affs_aops = { 431 readpage: affs_readpage, 432 writepage: affs_writepage, 433 sync_page: block_sync_page, 434 prepare_write: affs_prepare_write, 435 commit_write: generic_commit_write, 436 bmap: _affs_bmap 437}; 438 439static inline struct buffer_head * 440affs_bread_ino(struct inode *inode, int block, int create) 441{ 442 struct buffer_head *bh, tmp_bh; 443 int err; 444 445 tmp_bh.b_state = 0; 446 err = affs_get_block(inode, block, &tmp_bh, create); 447 if (!err) { 448 bh = affs_bread(inode->i_sb, tmp_bh.b_blocknr); 449 if (bh) { 450 bh->b_state |= tmp_bh.b_state; 451 return bh; 452 } 453 err = -EIO; 454 } 455 return ERR_PTR(err); 456} 457 458static inline struct buffer_head * 459affs_getzeroblk_ino(struct inode *inode, int block) 460{ 461 struct buffer_head *bh, tmp_bh; 462 int err; 463 464 tmp_bh.b_state = 0; 465 err = affs_get_block(inode, block, &tmp_bh, 1); 466 if (!err) { 467 bh = affs_getzeroblk(inode->i_sb, tmp_bh.b_blocknr); 468 if (bh) { 469 bh->b_state |= tmp_bh.b_state; 470 return bh; 471 } 472 err = -EIO; 473 } 474 return ERR_PTR(err); 475} 476 477static inline struct buffer_head * 478affs_getemptyblk_ino(struct inode *inode, int block) 479{ 480 struct buffer_head *bh, tmp_bh; 481 int err; 482 483 tmp_bh.b_state = 0; 484 err = affs_get_block(inode, block, &tmp_bh, 1); 485 if (!err) { 486 bh = affs_getemptyblk(inode->i_sb, tmp_bh.b_blocknr); 487 if (bh) { 488 bh->b_state |= tmp_bh.b_state; 489 return bh; 490 } 491 err = -EIO; 492 } 493 return ERR_PTR(err); 494} 495 496static ssize_t 497affs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) 498{ 499 ssize_t retval; 500 501 retval = generic_file_write (file, buf, count, ppos); 502 if (retval >0) { 503 struct inode *inode = file->f_dentry->d_inode; 504 inode->i_ctime = inode->i_mtime = CURRENT_TIME; 505 mark_inode_dirty(inode); 506 } 507 return retval; 508} 509 510static int 511affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsigned to) 512{ 513 struct inode *inode = page->mapping->host; 514 struct super_block *sb = inode->i_sb; 515 struct buffer_head *bh; 516 char *data; 517 u32 bidx, boff, bsize; 518 u32 tmp; 519 520 pr_debug("AFFS: read_page(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to); 521 if (from > to || to > PAGE_CACHE_SIZE) 522 BUG(); 523 data = page_address(page); 524 bsize = AFFS_SB->s_data_blksize; 525 tmp = (page->index << PAGE_CACHE_SHIFT) + from; 526 bidx = tmp / bsize; 527 boff = tmp % bsize; 528 529 while (from < to) { 530 bh = affs_bread_ino(inode, bidx, 0); 531 if (IS_ERR(bh)) 532 return PTR_ERR(bh); 533 tmp = min(bsize - boff, to - from); 534 if (from + tmp > to || tmp > bsize) 535 BUG(); 536 memcpy(data + from, AFFS_DATA(bh) + boff, tmp); 537 affs_brelse(bh); 538 bidx++; 539 from += tmp; 540 boff = 0; 541 } 542 return 0; 543} 544 545static int 546affs_extent_file_ofs(struct inode *inode, u32 newsize) 547{ 548 struct super_block *sb = inode->i_sb; 549 struct buffer_head *bh, *prev_bh; 550 u32 bidx, boff; 551 u32 size, bsize; 552 u32 tmp; 553 554 pr_debug("AFFS: extent_file(%u, %d)\n", (u32)inode->i_ino, newsize); 555 bsize = AFFS_SB->s_data_blksize; 556 bh = NULL; 557 size = AFFS_INODE->mmu_private; 558 bidx = size / bsize; 559 boff = size % bsize; 560 if (boff) { 561 bh = affs_bread_ino(inode, bidx, 0); 562 if (IS_ERR(bh)) 563 return PTR_ERR(bh); 564 tmp = min(bsize - boff, newsize - size); 565 if (boff + tmp > bsize || tmp > bsize) 566 BUG(); 567 memset(AFFS_DATA(bh) + boff, 0, tmp); 568 AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp); 569 affs_fix_checksum(sb, bh); 570 mark_buffer_dirty_inode(bh, inode); 571 size += tmp; 572 bidx++; 573 } else if (bidx) { 574 bh = affs_bread_ino(inode, bidx - 1, 0); 575 if (IS_ERR(bh)) 576 return PTR_ERR(bh); 577 } 578 579 while (size < newsize) { 580 prev_bh = bh; 581 bh = affs_getzeroblk_ino(inode, bidx); 582 if (IS_ERR(bh)) 583 goto out; 584 tmp = min(bsize, newsize - size); 585 if (tmp > bsize) 586 BUG(); 587 AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA); 588 AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino); 589 AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx); 590 AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp); 591 affs_fix_checksum(sb, bh); 592 bh->b_state &= ~(1UL << BH_New); 593 mark_buffer_dirty_inode(bh, inode); 594 if (prev_bh) { 595 u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next); 596 if (tmp) 597 affs_warning(sb, "extent_file_ofs", "next block already set for %d (%d)", bidx, tmp); 598 AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr); 599 affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp); 600 mark_buffer_dirty_inode(prev_bh, inode); 601 affs_brelse(prev_bh); 602 } 603 size += bsize; 604 bidx++; 605 } 606 affs_brelse(bh); 607 inode->i_size = AFFS_INODE->mmu_private = newsize; 608 return 0; 609 610out: 611 inode->i_size = AFFS_INODE->mmu_private = size; 612 return PTR_ERR(bh); 613} 614 615static int 616affs_readpage_ofs(struct file *file, struct page *page) 617{ 618 struct inode *inode = page->mapping->host; 619 u32 to; 620 int err; 621 622 pr_debug("AFFS: read_page(%u, %ld)\n", (u32)inode->i_ino, page->index); 623 to = PAGE_CACHE_SIZE; 624 if (((page->index + 1) << PAGE_CACHE_SHIFT) > inode->i_size) { 625 to = inode->i_size & ~PAGE_CACHE_MASK; 626 memset(page_address(page) + to, 0, PAGE_CACHE_SIZE - to); 627 } 628 629 err = affs_do_readpage_ofs(file, page, 0, to); 630 if (!err) 631 SetPageUptodate(page); 632 UnlockPage(page); 633 return err; 634} 635 636static int affs_prepare_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to) 637{ 638 struct inode *inode = page->mapping->host; 639 u32 size, offset; 640 u32 tmp; 641 int err = 0; 642 643 pr_debug("AFFS: prepare_write(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to); 644 offset = page->index << PAGE_CACHE_SHIFT; 645 if (offset + from > AFFS_INODE->mmu_private) { 646 err = affs_extent_file_ofs(inode, offset + from); 647 if (err) 648 return err; 649 } 650 size = inode->i_size; 651 652 if (Page_Uptodate(page)) 653 return 0; 654 655 if (from) { 656 err = affs_do_readpage_ofs(file, page, 0, from); 657 if (err) 658 return err; 659 } 660 if (to < PAGE_CACHE_SIZE) { 661 memset(page_address(page) + to, 0, PAGE_CACHE_SIZE - to); 662 if (size > offset + to) { 663 if (size < offset + PAGE_CACHE_SIZE) 664 tmp = size & ~PAGE_CACHE_MASK; 665 else 666 tmp = PAGE_CACHE_SIZE; 667 err = affs_do_readpage_ofs(file, page, to, tmp); 668 } 669 } 670 return err; 671} 672 673static int affs_commit_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to) 674{ 675 struct inode *inode = page->mapping->host; 676 struct super_block *sb = inode->i_sb; 677 struct buffer_head *bh, *prev_bh; 678 char *data; 679 u32 bidx, boff, bsize; 680 u32 tmp; 681 int written; 682 683 pr_debug("AFFS: commit_write(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to); 684 bsize = AFFS_SB->s_data_blksize; 685 data = page_address(page); 686 687 bh = NULL; 688 written = 0; 689 tmp = (page->index << PAGE_CACHE_SHIFT) + from; 690 bidx = tmp / bsize; 691 boff = tmp % bsize; 692 if (boff) { 693 bh = affs_bread_ino(inode, bidx, 0); 694 if (IS_ERR(bh)) 695 return PTR_ERR(bh); 696 tmp = min(bsize - boff, to - from); 697 if (boff + tmp > bsize || tmp > bsize) 698 BUG(); 699 memcpy(AFFS_DATA(bh) + boff, data + from, tmp); 700 AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp); 701 affs_fix_checksum(sb, bh); 702 mark_buffer_dirty_inode(bh, inode); 703 written += tmp; 704 from += tmp; 705 bidx++; 706 } else if (bidx) { 707 bh = affs_bread_ino(inode, bidx - 1, 0); 708 if (IS_ERR(bh)) 709 return PTR_ERR(bh); 710 } 711 while (from + bsize <= to) { 712 prev_bh = bh; 713 bh = affs_getemptyblk_ino(inode, bidx); 714 if (IS_ERR(bh)) 715 goto out; 716 memcpy(AFFS_DATA(bh), data + from, bsize); 717 if (bh->b_state & (1UL << BH_New)) { 718 AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA); 719 AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino); 720 AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx); 721 AFFS_DATA_HEAD(bh)->size = cpu_to_be32(bsize); 722 AFFS_DATA_HEAD(bh)->next = 0; 723 bh->b_state &= ~(1UL << BH_New); 724 if (prev_bh) { 725 u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next); 726 if (tmp) 727 affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp); 728 AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr); 729 affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp); 730 mark_buffer_dirty_inode(prev_bh, inode); 731 } 732 } 733 affs_brelse(prev_bh); 734 affs_fix_checksum(sb, bh); 735 mark_buffer_dirty_inode(bh, inode); 736 written += bsize; 737 from += bsize; 738 bidx++; 739 } 740 if (from < to) { 741 prev_bh = bh; 742 bh = affs_bread_ino(inode, bidx, 1); 743 if (IS_ERR(bh)) 744 goto out; 745 tmp = min(bsize, to - from); 746 if (tmp > bsize) 747 BUG(); 748 memcpy(AFFS_DATA(bh), data + from, tmp); 749 if (bh->b_state & (1UL << BH_New)) { 750 AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA); 751 AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino); 752 AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx); 753 AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp); 754 AFFS_DATA_HEAD(bh)->next = 0; 755 bh->b_state &= ~(1UL << BH_New); 756 if (prev_bh) { 757 u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next); 758 if (tmp) 759 affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp); 760 AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr); 761 affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp); 762 mark_buffer_dirty_inode(prev_bh, inode); 763 } 764 } else if (be32_to_cpu(AFFS_DATA_HEAD(bh)->size) < tmp) 765 AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp); 766 affs_brelse(prev_bh); 767 affs_fix_checksum(sb, bh); 768 mark_buffer_dirty_inode(bh, inode); 769 written += tmp; 770 from += tmp; 771 bidx++; 772 } 773 SetPageUptodate(page); 774 775done: 776 affs_brelse(bh); 777 tmp = (page->index << PAGE_CACHE_SHIFT) + from; 778 if (tmp > inode->i_size) 779 inode->i_size = AFFS_INODE->mmu_private = tmp; 780 781 return written; 782 783out: 784 bh = prev_bh; 785 if (!written) 786 written = PTR_ERR(bh); 787 goto done; 788} 789 790struct address_space_operations affs_aops_ofs = { 791 readpage: affs_readpage_ofs, 792 //writepage: affs_writepage_ofs, 793 //sync_page: affs_sync_page_ofs, 794 prepare_write: affs_prepare_write_ofs, 795 commit_write: affs_commit_write_ofs 796}; 797 798/* Free any preallocated blocks. */ 799 800void 801affs_free_prealloc(struct inode *inode) 802{ 803 struct super_block *sb = inode->i_sb; 804 805 pr_debug("AFFS: free_prealloc(ino=%lu)\n", inode->i_ino); 806 807 while (inode->u.affs_i.i_pa_cnt) { 808 inode->u.affs_i.i_pa_cnt--; 809 affs_free_block(sb, ++inode->u.affs_i.i_lastalloc); 810 } 811} 812 813/* Truncate (or enlarge) a file to the requested size. */ 814 815void 816affs_truncate(struct inode *inode) 817{ 818 struct super_block *sb = inode->i_sb; 819 u32 ext, ext_key; 820 u32 last_blk, blkcnt, blk; 821 u32 size; 822 struct buffer_head *ext_bh; 823 int i; 824 825 pr_debug("AFFS: truncate(inode=%d, oldsize=%u, newsize=%u)\n", 826 (u32)inode->i_ino, (u32)AFFS_INODE->mmu_private, (u32)inode->i_size); 827 828 last_blk = 0; 829 ext = 0; 830 if (inode->i_size) { 831 last_blk = ((u32)inode->i_size - 1) / AFFS_SB->s_data_blksize; 832 ext = last_blk / AFFS_SB->s_hashsize; 833 } 834 835 if (inode->i_size > AFFS_INODE->mmu_private) { 836 struct address_space *mapping = inode->i_mapping; 837 struct page *page; 838 u32 size = inode->i_size - 1; 839 int res; 840 841 page = grab_cache_page(mapping, size >> PAGE_CACHE_SHIFT); 842 if (!page) 843 return; 844 size = (size & (PAGE_CACHE_SIZE - 1)) + 1; 845 res = mapping->a_ops->prepare_write(NULL, page, size, size); 846 if (!res) 847 res = mapping->a_ops->commit_write(NULL, page, size, size); 848 UnlockPage(page); 849 page_cache_release(page); 850 mark_inode_dirty(inode); 851 return; 852 } else if (inode->i_size == AFFS_INODE->mmu_private) 853 return; 854 855 // lock cache 856 ext_bh = affs_get_extblock(inode, ext); 857 if (IS_ERR(ext_bh)) { 858 affs_warning(sb, "truncate", "unexpected read error for ext block %u (%d)", 859 ext, PTR_ERR(ext_bh)); 860 return; 861 } 862 if (AFFS_INODE->i_lc) { 863 /* clear linear cache */ 864 i = (ext + 1) >> AFFS_INODE->i_lc_shift; 865 if (AFFS_INODE->i_lc_size > i) { 866 AFFS_INODE->i_lc_size = i; 867 for (; i < AFFS_LC_SIZE; i++) 868 AFFS_INODE->i_lc[i] = 0; 869 } 870 /* clear associative cache */ 871 for (i = 0; i < AFFS_AC_SIZE; i++) 872 if (AFFS_INODE->i_ac[i].ext >= ext) 873 AFFS_INODE->i_ac[i].ext = 0; 874 } 875 ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension); 876 877 blkcnt = AFFS_INODE->i_blkcnt; 878 i = 0; 879 blk = last_blk; 880 if (inode->i_size) { 881 i = last_blk % AFFS_SB->s_hashsize + 1; 882 blk++; 883 } else 884 AFFS_HEAD(ext_bh)->first_data = 0; 885 size = AFFS_SB->s_hashsize; 886 if (size > blkcnt - blk + i) 887 size = blkcnt - blk + i; 888 for (; i < size; i++, blk++) { 889 affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i))); 890 AFFS_BLOCK(sb, ext_bh, i) = 0; 891 } 892 AFFS_TAIL(sb, ext_bh)->extension = 0; 893 affs_fix_checksum(sb, ext_bh); 894 mark_buffer_dirty_inode(ext_bh, inode); 895 affs_brelse(ext_bh); 896 897 if (inode->i_size) { 898 AFFS_INODE->i_blkcnt = last_blk + 1; 899 AFFS_INODE->i_extcnt = ext + 1; 900 if (AFFS_SB->s_flags & SF_OFS) { 901 struct buffer_head *bh = affs_bread_ino(inode, last_blk, 0); 902 u32 tmp; 903 if (IS_ERR(bh)) { 904 affs_warning(sb, "truncate", "unexpected read error for last block %u (%d)", 905 last_blk, PTR_ERR(bh)); 906 return; 907 } 908 tmp = be32_to_cpu(AFFS_DATA_HEAD(bh)->next); 909 AFFS_DATA_HEAD(bh)->next = 0; 910 affs_adjust_checksum(bh, -tmp); 911 affs_brelse(bh); 912 } 913 } else { 914 AFFS_INODE->i_blkcnt = 0; 915 AFFS_INODE->i_extcnt = 1; 916 } 917 AFFS_INODE->mmu_private = inode->i_size; 918 // unlock cache 919 920 while (ext_key) { 921 ext_bh = affs_bread(sb, ext_key); 922 size = AFFS_SB->s_hashsize; 923 if (size > blkcnt - blk) 924 size = blkcnt - blk; 925 for (i = 0; i < size; i++, blk++) 926 affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i))); 927 affs_free_block(sb, ext_key); 928 ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension); 929 affs_brelse(ext_bh); 930 } 931 affs_free_prealloc(inode); 932} 933