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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/sysv/balloc.c
  3.  *
  4.  *  minix/bitmap.c
  5.  *  Copyright (C) 1991, 1992  Linus Torvalds
  6.  *
  7.  *  ext/freelists.c
  8.  *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  9.  *
  10.  *  xenix/alloc.c
  11.  *  Copyright (C) 1992  Doug Evans
  12.  *
  13.  *  coh/alloc.c
  14.  *  Copyright (C) 1993  Pascal Haible, Bruno Haible
  15.  *
  16.  *  sysv/balloc.c
  17.  *  Copyright (C) 1993  Bruno Haible
  18.  *
  19.  *  This file contains code for allocating/freeing blocks.
  20.  */
  21. #include <linux/fs.h>
  22. #include <linux/sysv_fs.h>
  23. #include <linux/locks.h>
  24. /* We don't trust the value of
  25.    sb->sv_sbd2->s_tfree = *sb->sv_free_blocks
  26.    but we nevertheless keep it up to date. */
  27. static inline u32 *get_chunk(struct super_block *sb, struct buffer_head *bh)
  28. {
  29. char *bh_data = bh->b_data;
  30. if (sb->sv_type == FSTYPE_SYSV4)
  31. return (u32*)(bh_data+4);
  32. else
  33. return (u32*)(bh_data+2);
  34. }
  35. /* NOTE NOTE NOTE: nr is a block number _as_ _stored_ _on_ _disk_ */
  36. void sysv_free_block(struct super_block * sb, u32 nr)
  37. {
  38. struct buffer_head * bh;
  39. u32 *blocks = sb->sv_bcache;
  40. unsigned count;
  41. unsigned block = fs32_to_cpu(sb, nr);
  42. /*
  43.  * This code does not work at all for AFS (it has a bitmap
  44.  * free list).  As AFS is supposed to be read-only no one
  45.  * should call this for an AFS filesystem anyway...
  46.  */
  47. if (sb->sv_type == FSTYPE_AFS)
  48. return;
  49. if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
  50. printk("sysv_free_block: trying to free block not in datazonen");
  51. return;
  52. }
  53. lock_super(sb);
  54. count = fs16_to_cpu(sb, *sb->sv_bcache_count);
  55. if (count > sb->sv_flc_size) {
  56. printk("sysv_free_block: flc_count > flc_sizen");
  57. unlock_super(sb);
  58. return;
  59. }
  60. /* If the free list head in super-block is full, it is copied
  61.  * into this block being freed, ditto if it's completely empty
  62.  * (applies only on Coherent).
  63.  */
  64. if (count == sb->sv_flc_size || count == 0) {
  65. block += sb->sv_block_base;
  66. bh = sb_getblk(sb, block);
  67. if (!bh) {
  68. printk("sysv_free_block: getblk() failedn");
  69. unlock_super(sb);
  70. return;
  71. }
  72. memset(bh->b_data, 0, sb->s_blocksize);
  73. *(u16*)bh->b_data = cpu_to_fs16(sb, count);
  74. memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t));
  75. mark_buffer_dirty(bh);
  76. mark_buffer_uptodate(bh, 1);
  77. brelse(bh);
  78. count = 0;
  79. }
  80. sb->sv_bcache[count++] = nr;
  81. *sb->sv_bcache_count = cpu_to_fs16(sb, count);
  82. fs32_add(sb, sb->sv_free_blocks, 1);
  83. dirty_sb(sb);
  84. unlock_super(sb);
  85. }
  86. u32 sysv_new_block(struct super_block * sb)
  87. {
  88. unsigned int block;
  89. u32 nr;
  90. struct buffer_head * bh;
  91. unsigned count;
  92. lock_super(sb);
  93. count = fs16_to_cpu(sb, *sb->sv_bcache_count);
  94. if (count == 0) /* Applies only to Coherent FS */
  95. goto Enospc;
  96. nr = sb->sv_bcache[--count];
  97. if (nr == 0)  /* Applies only to Xenix FS, SystemV FS */
  98. goto Enospc;
  99. block = fs32_to_cpu(sb, nr);
  100. *sb->sv_bcache_count = cpu_to_fs16(sb, count);
  101. if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
  102. printk("sysv_new_block: new block %d is not in data zonen",
  103. block);
  104. goto Enospc;
  105. }
  106. if (count == 0) { /* the last block continues the free list */
  107. unsigned count;
  108. block += sb->sv_block_base;
  109. if (!(bh = sb_bread(sb, block))) {
  110. printk("sysv_new_block: cannot read free-list blockn");
  111. /* retry this same block next time */
  112. *sb->sv_bcache_count = cpu_to_fs16(sb, 1);
  113. goto Enospc;
  114. }
  115. count = fs16_to_cpu(sb, *(u16*)bh->b_data);
  116. if (count > sb->sv_flc_size) {
  117. printk("sysv_new_block: free-list block with >flc_size entriesn");
  118. brelse(bh);
  119. goto Enospc;
  120. }
  121. *sb->sv_bcache_count = cpu_to_fs16(sb, count);
  122. memcpy(sb->sv_bcache, get_chunk(sb, bh),
  123. count * sizeof(sysv_zone_t));
  124. brelse(bh);
  125. }
  126. /* Now the free list head in the superblock is valid again. */
  127. fs32_add(sb, sb->sv_free_blocks, -1);
  128. dirty_sb(sb);
  129. unlock_super(sb);
  130. return nr;
  131. Enospc:
  132. unlock_super(sb);
  133. return 0;
  134. }
  135. unsigned long sysv_count_free_blocks(struct super_block * sb)
  136. {
  137. int sb_count;
  138. int count;
  139. struct buffer_head * bh = NULL;
  140. u32 *blocks;
  141. unsigned block;
  142. int n;
  143. /*
  144.  * This code does not work at all for AFS (it has a bitmap
  145.  * free list).  As AFS is supposed to be read-only we just
  146.  * lie and say it has no free block at all.
  147.  */
  148. if (sb->sv_type == FSTYPE_AFS)
  149. return 0;
  150. lock_super(sb);
  151. sb_count = fs32_to_cpu(sb, *sb->sv_free_blocks);
  152. if (0)
  153. goto trust_sb;
  154. /* this causes a lot of disk traffic ... */
  155. count = 0;
  156. n = fs16_to_cpu(sb, *sb->sv_bcache_count);
  157. blocks = sb->sv_bcache;
  158. while (1) {
  159. if (n > sb->sv_flc_size)
  160. goto E2big;
  161. block = 0;
  162. while (n && (block = blocks[--n]) != 0)
  163. count++;
  164. if (block == 0)
  165. break;
  166. block = fs32_to_cpu(sb, block);
  167. if (bh)
  168. brelse(bh);
  169. if (block < sb->sv_firstdatazone || block >= sb->sv_nzones)
  170. goto Einval;
  171. block += sb->sv_block_base;
  172. bh = sb_bread(sb, block);
  173. if (!bh)
  174. goto Eio;
  175. n = fs16_to_cpu(sb, *(u16*)bh->b_data);
  176. blocks = get_chunk(sb, bh);
  177. }
  178. if (bh)
  179. brelse(bh);
  180. if (count != sb_count)
  181. goto Ecount;
  182. done:
  183. unlock_super(sb);
  184. return count;
  185. Einval:
  186. printk("sysv_count_free_blocks: new block %d is not in data zonen",
  187. block);
  188. goto trust_sb;
  189. Eio:
  190. printk("sysv_count_free_blocks: cannot read free-list blockn");
  191. goto trust_sb;
  192. E2big:
  193. printk("sysv_count_free_blocks: >flc_size entries in free-list blockn");
  194. if (bh)
  195. brelse(bh);
  196. trust_sb:
  197. count = sb_count;
  198. goto done;
  199. Ecount:
  200. printk("sysv_count_free_blocks: free block count was %d, "
  201. "correcting to %dn", sb_count, count);
  202. if (!(sb->s_flags & MS_RDONLY)) {
  203. *sb->sv_free_blocks = cpu_to_fs32(sb, count);
  204. dirty_sb(sb);
  205. }
  206. goto done;
  207. }