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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * inode.c
  3.  *
  4.  * Copyright (c) 1999 Al Smith
  5.  *
  6.  * Portions derived from work (c) 1995,1996 Christian Vogelgsang,
  7.  *              and from work (c) 1998 Mike Shaver.
  8.  */
  9. #include <linux/efs_fs.h>
  10. #include <linux/efs_fs_sb.h>
  11. #include <linux/module.h>
  12. extern int efs_get_block(struct inode *, long, struct buffer_head *, int);
  13. static int efs_readpage(struct file *file, struct page *page)
  14. {
  15. return block_read_full_page(page,efs_get_block);
  16. }
  17. static int _efs_bmap(struct address_space *mapping, long block)
  18. {
  19. return generic_block_bmap(mapping,block,efs_get_block);
  20. }
  21. struct address_space_operations efs_aops = {
  22. readpage: efs_readpage,
  23. sync_page: block_sync_page,
  24. bmap: _efs_bmap
  25. };
  26. static inline void extent_copy(efs_extent *src, efs_extent *dst) {
  27. /*
  28.  * this is slightly evil. it doesn't just copy
  29.  * efs_extent from src to dst, it also mangles
  30.  * the bits so that dst ends up in cpu byte-order.
  31.  */
  32. dst->cooked.ex_magic  =  (unsigned int) src->raw[0];
  33. dst->cooked.ex_bn     = ((unsigned int) src->raw[1] << 16) |
  34. ((unsigned int) src->raw[2] <<  8) |
  35. ((unsigned int) src->raw[3] <<  0);
  36. dst->cooked.ex_length =  (unsigned int) src->raw[4];
  37. dst->cooked.ex_offset = ((unsigned int) src->raw[5] << 16) |
  38. ((unsigned int) src->raw[6] <<  8) |
  39. ((unsigned int) src->raw[7] <<  0);
  40. return;
  41. }
  42. void efs_read_inode(struct inode *inode) {
  43. int i, inode_index;
  44. dev_t device;
  45. struct buffer_head *bh;
  46. struct efs_sb_info    *sb = SUPER_INFO(inode->i_sb);
  47. struct efs_inode_info *in = INODE_INFO(inode);
  48. efs_block_t block, offset;
  49. struct efs_dinode *efs_inode;
  50.   
  51. /*
  52. ** EFS layout:
  53. **
  54. ** |   cylinder group    |   cylinder group    |   cylinder group ..etc
  55. ** |inodes|data          |inodes|data          |inodes|data       ..etc
  56. **
  57. ** work out the inode block index, (considering initially that the
  58. ** inodes are stored as consecutive blocks). then work out the block
  59. ** number of that inode given the above layout, and finally the
  60. ** offset of the inode within that block.
  61. */
  62. inode_index = inode->i_ino /
  63. (EFS_BLOCKSIZE / sizeof(struct efs_dinode));
  64. block = sb->fs_start + sb->first_block + 
  65. (sb->group_size * (inode_index / sb->inode_blocks)) +
  66. (inode_index % sb->inode_blocks);
  67. offset = (inode->i_ino %
  68. (EFS_BLOCKSIZE / sizeof(struct efs_dinode))) *
  69. sizeof(struct efs_dinode);
  70. bh = sb_bread(inode->i_sb, block);
  71. if (!bh) {
  72. printk(KERN_WARNING "EFS: bread() failed at block %dn", block);
  73. goto read_inode_error;
  74. }
  75. efs_inode = (struct efs_dinode *) (bh->b_data + offset);
  76.     
  77. inode->i_mode  = be16_to_cpu(efs_inode->di_mode);
  78. inode->i_nlink = be16_to_cpu(efs_inode->di_nlink);
  79. inode->i_uid   = (uid_t)be16_to_cpu(efs_inode->di_uid);
  80. inode->i_gid   = (gid_t)be16_to_cpu(efs_inode->di_gid);
  81. inode->i_size  = be32_to_cpu(efs_inode->di_size);
  82. inode->i_atime = be32_to_cpu(efs_inode->di_atime);
  83. inode->i_mtime = be32_to_cpu(efs_inode->di_mtime);
  84. inode->i_ctime = be32_to_cpu(efs_inode->di_ctime);
  85. /* this is the number of blocks in the file */
  86. if (inode->i_size == 0) {
  87. inode->i_blocks = 0;
  88. } else {
  89. inode->i_blocks = ((inode->i_size - 1) >> EFS_BLOCKSIZE_BITS) + 1;
  90. }
  91. /*
  92.  * BUG: irix dev_t is 32-bits. linux dev_t is only 16-bits.
  93.  *
  94.  * apparently linux will change to 32-bit dev_t sometime during
  95.  * linux 2.3.
  96.  *
  97.  * as is, this code maps devices that can't be represented in
  98.  * 16-bits (ie major > 255 or minor > 255) to major = minor = 255.
  99.  *
  100.  * during 2.3 when 32-bit dev_t become available, we should test
  101.  * to see whether odev contains 65535. if this is the case then we
  102.  * should then do device = be32_to_cpu(efs_inode->di_u.di_dev.ndev).
  103.  */
  104.      device = be16_to_cpu(efs_inode->di_u.di_dev.odev);
  105. /* get the number of extents for this object */
  106. in->numextents = be16_to_cpu(efs_inode->di_numextents);
  107. in->lastextent = 0;
  108. /* copy the extents contained within the inode to memory */
  109. for(i = 0; i < EFS_DIRECTEXTENTS; i++) {
  110. extent_copy(&(efs_inode->di_u.di_extents[i]), &(in->extents[i]));
  111. if (i < in->numextents && in->extents[i].cooked.ex_magic != 0) {
  112. printk(KERN_WARNING "EFS: extent %d has bad magic number in inode %lun", i, inode->i_ino);
  113. brelse(bh);
  114. goto read_inode_error;
  115. }
  116. }
  117. brelse(bh);
  118.    
  119. #ifdef DEBUG
  120. printk(KERN_DEBUG "EFS: read_inode(): inode %lu, extents %d, mode %on",
  121. inode->i_ino, in->numextents, inode->i_mode);
  122. #endif
  123. switch (inode->i_mode & S_IFMT) {
  124. case S_IFDIR: 
  125. inode->i_op = &efs_dir_inode_operations; 
  126. inode->i_fop = &efs_dir_operations; 
  127. break;
  128. case S_IFREG:
  129. inode->i_fop = &generic_ro_fops;
  130. inode->i_data.a_ops = &efs_aops;
  131. break;
  132. case S_IFLNK:
  133. inode->i_op = &page_symlink_inode_operations;
  134. inode->i_data.a_ops = &efs_symlink_aops;
  135. break;
  136. case S_IFCHR:
  137. case S_IFBLK:
  138. case S_IFIFO:
  139. init_special_inode(inode, inode->i_mode, device);
  140. break;
  141. default:
  142. printk(KERN_WARNING "EFS: unsupported inode mode %on", inode->i_mode);
  143. goto read_inode_error;
  144. break;
  145. }
  146. return;
  147.         
  148. read_inode_error:
  149. printk(KERN_WARNING "EFS: failed to read inode %lun", inode->i_ino);
  150. make_bad_inode(inode);
  151. return;
  152. }
  153. static inline efs_block_t
  154. efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_sb_info *sb) {
  155. efs_block_t start;
  156. efs_block_t length;
  157. efs_block_t offset;
  158. /*
  159.  * given an extent and a logical block within a file,
  160.  * can this block be found within this extent ?
  161.  */
  162. start  = ptr->cooked.ex_bn;
  163. length = ptr->cooked.ex_length;
  164. offset = ptr->cooked.ex_offset;
  165. if ((block >= offset) && (block < offset+length)) {
  166. return(sb->fs_start + start + block - offset);
  167. } else {
  168. return 0;
  169. }
  170. }
  171. efs_block_t efs_map_block(struct inode *inode, efs_block_t block) {
  172. struct efs_sb_info    *sb = SUPER_INFO(inode->i_sb);
  173. struct efs_inode_info *in = INODE_INFO(inode);
  174. struct buffer_head    *bh = NULL;
  175. int cur, last, first = 1;
  176. int ibase, ioffset, dirext, direxts, indext, indexts;
  177. efs_block_t iblock, result = 0, lastblock = 0;
  178. efs_extent ext, *exts;
  179. last = in->lastextent;
  180. if (in->numextents <= EFS_DIRECTEXTENTS) {
  181. /* first check the last extent we returned */
  182. if ((result = efs_extent_check(&in->extents[last], block, sb)))
  183. return result;
  184.     
  185. /* if we only have one extent then nothing can be found */
  186. if (in->numextents == 1) {
  187. printk(KERN_ERR "EFS: map_block() failed to map (1 extent)n");
  188. return 0;
  189. }
  190. direxts = in->numextents;
  191. /*
  192.  * check the stored extents in the inode
  193.  * start with next extent and check forwards
  194.  */
  195. for(dirext = 1; dirext < direxts; dirext++) {
  196. cur = (last + dirext) % in->numextents;
  197. if ((result = efs_extent_check(&in->extents[cur], block, sb))) {
  198. in->lastextent = cur;
  199. return result;
  200. }
  201. }
  202. printk(KERN_ERR "EFS: map_block() failed to map block %u (dir)n", block);
  203. return 0;
  204. }
  205. #ifdef DEBUG
  206. printk(KERN_DEBUG "EFS: map_block(): indirect search for logical block %un", block);
  207. #endif
  208. direxts = in->extents[0].cooked.ex_offset;
  209. indexts = in->numextents;
  210. for(indext = 0; indext < indexts; indext++) {
  211. cur = (last + indext) % indexts;
  212. /*
  213.  * work out which direct extent contains `cur'.
  214.  *
  215.  * also compute ibase: i.e. the number of the first
  216.  * indirect extent contained within direct extent `cur'.
  217.  *
  218.  */
  219. ibase = 0;
  220. for(dirext = 0; cur < ibase && dirext < direxts; dirext++) {
  221. ibase += in->extents[dirext].cooked.ex_length *
  222. (EFS_BLOCKSIZE / sizeof(efs_extent));
  223. }
  224. if (dirext == direxts) {
  225. /* should never happen */
  226. printk(KERN_ERR "EFS: couldn't find direct extent for indirect extent %d (block %u)n", cur, block);
  227. if (bh) brelse(bh);
  228. return 0;
  229. }
  230. /* work out block number and offset of this indirect extent */
  231. iblock = sb->fs_start + in->extents[dirext].cooked.ex_bn +
  232. (cur - ibase) /
  233. (EFS_BLOCKSIZE / sizeof(efs_extent));
  234. ioffset = (cur - ibase) %
  235. (EFS_BLOCKSIZE / sizeof(efs_extent));
  236. if (first || lastblock != iblock) {
  237. if (bh) brelse(bh);
  238. bh = sb_bread(inode->i_sb, iblock);
  239. if (!bh) {
  240. printk(KERN_ERR "EFS: bread() failed at block %dn", iblock);
  241. return 0;
  242. }
  243. #ifdef DEBUG
  244. printk(KERN_DEBUG "EFS: map_block(): read indirect extent block %dn", iblock);
  245. #endif
  246. first = 0;
  247. lastblock = iblock;
  248. }
  249. exts = (efs_extent *) bh->b_data;
  250. extent_copy(&(exts[ioffset]), &ext);
  251. if (ext.cooked.ex_magic != 0) {
  252. printk(KERN_ERR "EFS: extent %d has bad magic number in block %dn", cur, iblock);
  253. if (bh) brelse(bh);
  254. return 0;
  255. }
  256. if ((result = efs_extent_check(&ext, block, sb))) {
  257. if (bh) brelse(bh);
  258. in->lastextent = cur;
  259. return result;
  260. }
  261. }
  262. if (bh) brelse(bh);
  263. printk(KERN_ERR "EFS: map_block() failed to map block %u (indir)n", block);
  264. return 0;
  265. }  
  266. MODULE_LICENSE("GPL");