file.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * fs/bfs/file.c
  3.  * BFS file operations.
  4.  * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
  5.  */
  6. #include <linux/fs.h>
  7. #include <linux/locks.h>
  8. #include <linux/bfs_fs.h>
  9. #include <linux/smp_lock.h>
  10. #include "bfs_defs.h"
  11. #undef DEBUG
  12. #ifdef DEBUG
  13. #define dprintf(x...) printf(x)
  14. #else
  15. #define dprintf(x...)
  16. #endif
  17. struct file_operations bfs_file_operations = {
  18. llseek: generic_file_llseek,
  19. read: generic_file_read,
  20. write: generic_file_write,
  21. mmap: generic_file_mmap,
  22. };
  23. static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev)
  24. {
  25. struct buffer_head *bh, *new;
  26. bh = bread(dev, from, BFS_BSIZE);
  27. if (!bh)
  28. return -EIO;
  29. new = getblk(dev, to, BFS_BSIZE);
  30. memcpy(new->b_data, bh->b_data, bh->b_size);
  31. mark_buffer_dirty(new);
  32. bforget(bh);
  33. brelse(new);
  34. return 0;
  35. }
  36. static int bfs_move_blocks(kdev_t dev, unsigned long start, unsigned long end, 
  37. unsigned long where)
  38. {
  39. unsigned long i;
  40. dprintf("%08lx-%08lx->%08lxn", start, end, where);
  41. for (i = start; i <= end; i++)
  42. if(bfs_move_block(i, where + i, dev)) {
  43. dprintf("failed to move block %08lx -> %08lxn", i, where + i);
  44. return -EIO;
  45. }
  46. return 0;
  47. }
  48. static int bfs_get_block(struct inode * inode, long block, 
  49. struct buffer_head * bh_result, int create)
  50. {
  51. long phys;
  52. int err;
  53. struct super_block *sb = inode->i_sb;
  54. struct buffer_head *sbh = sb->su_sbh;
  55. if (block < 0 || block > sb->su_blocks)
  56. return -EIO;
  57. phys = inode->iu_sblock + block;
  58. if (!create) {
  59. if (phys <= inode->iu_eblock) {
  60. dprintf("c=%d, b=%08lx, phys=%08lx (granted)n", create, block, phys);
  61. bh_result->b_dev = inode->i_dev;
  62. bh_result->b_blocknr = phys;
  63. bh_result->b_state |= (1UL << BH_Mapped);
  64. }
  65. return 0;
  66. }
  67. /* if the file is not empty and the requested block is within the range
  68.    of blocks allocated for this file, we can grant it */
  69. if (inode->i_size && phys <= inode->iu_eblock) {
  70. dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)n", 
  71. create, block, phys);
  72. bh_result->b_dev = inode->i_dev;
  73. bh_result->b_blocknr = phys;
  74. bh_result->b_state |= (1UL << BH_Mapped);
  75. return 0;
  76. }
  77. /* the rest has to be protected against itself */
  78. lock_kernel();
  79. /* if the last data block for this file is the last allocated block, we can
  80.    extend the file trivially, without moving it anywhere */
  81. if (inode->iu_eblock == sb->su_lf_eblk) {
  82. dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)n", 
  83. create, block, phys);
  84. bh_result->b_dev = inode->i_dev;
  85. bh_result->b_blocknr = phys;
  86. bh_result->b_state |= (1UL << BH_Mapped);
  87. sb->su_freeb -= phys - inode->iu_eblock;
  88. sb->su_lf_eblk = inode->iu_eblock = phys;
  89. mark_inode_dirty(inode);
  90. mark_buffer_dirty(sbh);
  91. err = 0;
  92. goto out;
  93. }
  94. /* Ok, we have to move this entire file to the next free block */
  95. phys = sb->su_lf_eblk + 1;
  96. if (inode->iu_sblock) { /* if data starts on block 0 then there is no data */
  97. err = bfs_move_blocks(inode->i_dev, inode->iu_sblock, 
  98. inode->iu_eblock, phys);
  99. if (err) {
  100. dprintf("failed to move ino=%08lx -> fs corruptionn", inode->i_ino);
  101. goto out;
  102. }
  103. } else
  104. err = 0;
  105. dprintf("c=%d, b=%08lx, phys=%08lx (moved)n", create, block, phys);
  106. inode->iu_sblock = phys;
  107. phys += block;
  108. sb->su_lf_eblk = inode->iu_eblock = phys;
  109. /* this assumes nothing can write the inode back while we are here
  110.  * and thus update inode->i_blocks! (XXX)*/
  111. sb->su_freeb -= inode->iu_eblock - inode->iu_sblock + 1 - inode->i_blocks;
  112. mark_inode_dirty(inode);
  113. mark_buffer_dirty(sbh);
  114. bh_result->b_dev = inode->i_dev;
  115. bh_result->b_blocknr = phys;
  116. bh_result->b_state |= (1UL << BH_Mapped);
  117. out:
  118. unlock_kernel();
  119. return err;
  120. }
  121. static int bfs_writepage(struct page *page)
  122. {
  123. return block_write_full_page(page, bfs_get_block);
  124. }
  125. static int bfs_readpage(struct file *file, struct page *page)
  126. {
  127. return block_read_full_page(page, bfs_get_block);
  128. }
  129. static int bfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
  130. {
  131. return block_prepare_write(page, from, to, bfs_get_block);
  132. }
  133. static int bfs_bmap(struct address_space *mapping, long block)
  134. {
  135. return generic_block_bmap(mapping, block, bfs_get_block);
  136. }
  137. struct address_space_operations bfs_aops = {
  138. readpage: bfs_readpage,
  139. writepage: bfs_writepage,
  140. sync_page: block_sync_page,
  141. prepare_write: bfs_prepare_write,
  142. commit_write: generic_commit_write,
  143. bmap: bfs_bmap,
  144. };
  145. struct inode_operations bfs_file_inops;