bitmap.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:7k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/minix/bitmap.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6. /*
  7.  * Modified for 680x0 by Hamish Macdonald
  8.  * Fixed for 680x0 by Andreas Schwab
  9.  */
  10. /* bitmap.c contains the code that handles the inode and block bitmaps */
  11. #include <linux/fs.h>
  12. #include <linux/minix_fs.h>
  13. #include <linux/locks.h>
  14. #include <asm/bitops.h>
  15. static int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
  16. static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits)
  17. {
  18. unsigned i, j, sum = 0;
  19. struct buffer_head *bh;
  20.   
  21. for (i=0; i<numblocks-1; i++) {
  22. if (!(bh=map[i])) 
  23. return(0);
  24. for (j=0; j<BLOCK_SIZE; j++)
  25. sum += nibblemap[bh->b_data[j] & 0xf]
  26. + nibblemap[(bh->b_data[j]>>4) & 0xf];
  27. }
  28. if (numblocks==0 || !(bh=map[numblocks-1]))
  29. return(0);
  30. i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2;
  31. for (j=0; j<i; j++) {
  32. sum += nibblemap[bh->b_data[j] & 0xf]
  33. + nibblemap[(bh->b_data[j]>>4) & 0xf];
  34. }
  35. i = numbits%16;
  36. if (i!=0) {
  37. i = *(__u16 *)(&bh->b_data[j]) | ~((1<<i) - 1);
  38. sum += nibblemap[i & 0xf] + nibblemap[(i>>4) & 0xf];
  39. sum += nibblemap[(i>>8) & 0xf] + nibblemap[(i>>12) & 0xf];
  40. }
  41. return(sum);
  42. }
  43. void minix_free_block(struct inode * inode, int block)
  44. {
  45. struct super_block * sb = inode->i_sb;
  46. struct buffer_head * bh;
  47. unsigned int bit,zone;
  48. if (!sb) {
  49. printk("trying to free block on nonexistent devicen");
  50. return;
  51. }
  52. if (block < sb->u.minix_sb.s_firstdatazone ||
  53.     block >= sb->u.minix_sb.s_nzones) {
  54. printk("trying to free block not in datazonen");
  55. return;
  56. }
  57. zone = block - sb->u.minix_sb.s_firstdatazone + 1;
  58. bit = zone & 8191;
  59. zone >>= 13;
  60. if (zone >= sb->u.minix_sb.s_zmap_blocks) {
  61. printk("minix_free_block: nonexistent bitmap buffern");
  62. return;
  63. }
  64. bh = sb->u.minix_sb.s_zmap[zone];
  65. if (!minix_test_and_clear_bit(bit,bh->b_data))
  66. printk("free_block (%s:%d): bit already clearedn",
  67.        kdevname(sb->s_dev), block);
  68. mark_buffer_dirty(bh);
  69. return;
  70. }
  71. int minix_new_block(struct inode * inode)
  72. {
  73. struct super_block * sb = inode->i_sb;
  74. struct buffer_head * bh;
  75. int i,j;
  76. if (!sb) {
  77. printk("trying to get new block from nonexistent devicen");
  78. return 0;
  79. }
  80. repeat:
  81. j = 8192;
  82. bh = NULL;
  83. for (i = 0; i < sb->u.minix_sb.s_zmap_blocks; i++) {
  84. bh = sb->u.minix_sb.s_zmap[i];
  85. if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
  86. break;
  87. }
  88. if (!bh || j >= 8192)
  89. return 0;
  90. if (minix_test_and_set_bit(j,bh->b_data)) {
  91. printk("new_block: bit already set");
  92. goto repeat;
  93. }
  94. mark_buffer_dirty(bh);
  95. j += i*8192 + sb->u.minix_sb.s_firstdatazone-1;
  96. if (j < sb->u.minix_sb.s_firstdatazone ||
  97.     j >= sb->u.minix_sb.s_nzones)
  98. return 0;
  99. return j;
  100. }
  101. unsigned long minix_count_free_blocks(struct super_block *sb)
  102. {
  103. return (count_free(sb->u.minix_sb.s_zmap, sb->u.minix_sb.s_zmap_blocks,
  104. sb->u.minix_sb.s_nzones - sb->u.minix_sb.s_firstdatazone + 1)
  105. << sb->u.minix_sb.s_log_zone_size);
  106. }
  107. struct minix_inode *
  108. minix_V1_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
  109. {
  110. int block;
  111. struct minix_sb_info *sbi = &sb->u.minix_sb;
  112. struct minix_inode *p;
  113. if (!ino || ino > sbi->s_ninodes) {
  114. printk("Bad inode number on dev %s: %ld is out of rangen",
  115.        bdevname(sb->s_dev), ino);
  116. return NULL;
  117. }
  118. ino--;
  119. block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
  120.  ino / MINIX_INODES_PER_BLOCK;
  121. *bh = sb_bread(sb, block);
  122. if (!*bh) {
  123. printk("unable to read i-node blockn");
  124. return NULL;
  125. }
  126. p = (void *)(*bh)->b_data;
  127. return p + ino % MINIX_INODES_PER_BLOCK;
  128. }
  129. struct minix2_inode *
  130. minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
  131. {
  132. int block;
  133. struct minix_sb_info *sbi = &sb->u.minix_sb;
  134. struct minix2_inode *p;
  135. *bh = NULL;
  136. if (!ino || ino > sbi->s_ninodes) {
  137. printk("Bad inode number on dev %s: %ld is out of rangen",
  138.        bdevname(sb->s_dev), ino);
  139. return NULL;
  140. }
  141. ino--;
  142. block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
  143.  ino / MINIX2_INODES_PER_BLOCK;
  144. *bh = sb_bread(sb, block);
  145. if (!*bh) {
  146. printk("unable to read i-node blockn");
  147. return NULL;
  148. }
  149. p = (void *)(*bh)->b_data;
  150. return p + ino % MINIX2_INODES_PER_BLOCK;
  151. }
  152. /* Clear the link count and mode of a deleted inode on disk. */
  153. static void minix_clear_inode(struct inode *inode)
  154. {
  155. struct buffer_head *bh;
  156. if (INODE_VERSION(inode) == MINIX_V1) {
  157. struct minix_inode *raw_inode;
  158. raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
  159. if (raw_inode) {
  160. raw_inode->i_nlinks = 0;
  161. raw_inode->i_mode = 0;
  162. }
  163. } else {
  164. struct minix2_inode *raw_inode;
  165. raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh);
  166. if (raw_inode) {
  167. raw_inode->i_nlinks = 0;
  168. raw_inode->i_mode = 0;
  169. }
  170. }
  171. if (bh) {
  172. mark_buffer_dirty(bh);
  173. brelse (bh);
  174. }
  175. }
  176. void minix_free_inode(struct inode * inode)
  177. {
  178. struct buffer_head * bh;
  179. unsigned long ino;
  180. if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->u.minix_sb.s_ninodes) {
  181. printk("free_inode: inode 0 or nonexistent inoden");
  182. return;
  183. }
  184. ino = inode->i_ino;
  185. if ((ino >> 13) >= inode->i_sb->u.minix_sb.s_imap_blocks) {
  186. printk("free_inode: nonexistent imap in superblockn");
  187. return;
  188. }
  189. bh = inode->i_sb->u.minix_sb.s_imap[ino >> 13];
  190. minix_clear_inode(inode);
  191. clear_inode(inode);
  192. if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
  193. printk("free_inode: bit %lu already cleared.n",ino);
  194. mark_buffer_dirty(bh);
  195. }
  196. struct inode * minix_new_inode(const struct inode * dir, int * error)
  197. {
  198. struct super_block * sb;
  199. struct inode * inode;
  200. struct buffer_head * bh;
  201. int i,j;
  202. sb = dir->i_sb;
  203. inode = new_inode(sb);
  204. if (!inode) {
  205. *error = -ENOMEM;
  206. return NULL;
  207. }
  208. j = 8192;
  209. bh = NULL;
  210. *error = -ENOSPC;
  211. lock_super(sb);
  212. for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++) {
  213. bh = inode->i_sb->u.minix_sb.s_imap[i];
  214. if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
  215. break;
  216. }
  217. if (!bh || j >= 8192) {
  218. iput(inode);
  219. unlock_super(sb);
  220. return NULL;
  221. }
  222. if (minix_test_and_set_bit(j,bh->b_data)) { /* shouldn't happen */
  223. printk("new_inode: bit already set");
  224. iput(inode);
  225. unlock_super(sb);
  226. return NULL;
  227. }
  228. mark_buffer_dirty(bh);
  229. j += i*8192;
  230. if (!j || j > inode->i_sb->u.minix_sb.s_ninodes) {
  231. iput(inode);
  232. unlock_super(sb);
  233. return NULL;
  234. }
  235. inode->i_uid = current->fsuid;
  236. inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
  237. inode->i_ino = j;
  238. inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
  239. inode->i_blocks = inode->i_blksize = 0;
  240. insert_inode_hash(inode);
  241. mark_inode_dirty(inode);
  242. unlock_super(sb);
  243. *error = 0;
  244. return inode;
  245. }
  246. unsigned long minix_count_free_inodes(struct super_block *sb)
  247. {
  248. return count_free(sb->u.minix_sb.s_imap, sb->u.minix_sb.s_imap_blocks,
  249. sb->u.minix_sb.s_ninodes + 1);
  250. }