balloc.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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/buffer_head.h>
  22. #include <linux/string.h>
  23. #include "sysv.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 sysv_zone_t *get_chunk(struct super_block *sb, struct buffer_head *bh)
  28. {
  29. char *bh_data = bh->b_data;
  30. if (SYSV_SB(sb)->s_type == FSTYPE_SYSV4)
  31. return (sysv_zone_t*)(bh_data+4);
  32. else
  33. return (sysv_zone_t*)(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, sysv_zone_t nr)
  37. {
  38. struct sysv_sb_info * sbi = SYSV_SB(sb);
  39. struct buffer_head * bh;
  40. sysv_zone_t *blocks = sbi->s_bcache;
  41. unsigned count;
  42. unsigned block = fs32_to_cpu(sbi, nr);
  43. /*
  44. * This code does not work at all for AFS (it has a bitmap
  45. * free list). As AFS is supposed to be read-only no one
  46. * should call this for an AFS filesystem anyway...
  47. */
  48. if (sbi->s_type == FSTYPE_AFS)
  49. return;
  50. if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
  51. printk("sysv_free_block: trying to free block not in datazone\n");
  52. return;
  53. }
  54. lock_super(sb);
  55. count = fs16_to_cpu(sbi, *sbi->s_bcache_count);
  56. if (count > sbi->s_flc_size) {
  57. printk("sysv_free_block: flc_count > flc_size\n");
  58. unlock_super(sb);
  59. return;
  60. }
  61. /* If the free list head in super-block is full, it is copied
  62. * into this block being freed, ditto if it's completely empty
  63. * (applies only on Coherent).
  64. */
  65. if (count == sbi->s_flc_size || count == 0) {
  66. block += sbi->s_block_base;
  67. bh = sb_getblk(sb, block);
  68. if (!bh) {
  69. printk("sysv_free_block: getblk() failed\n");
  70. unlock_super(sb);
  71. return;
  72. }
  73. memset(bh->b_data, 0, sb->s_blocksize);
  74. *(__fs16*)bh->b_data = cpu_to_fs16(sbi, count);
  75. memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t));
  76. mark_buffer_dirty(bh);
  77. set_buffer_uptodate(bh);
  78. brelse(bh);
  79. count = 0;
  80. }
  81. sbi->s_bcache[count++] = nr;
  82. *sbi->s_bcache_count = cpu_to_fs16(sbi, count);
  83. fs32_add(sbi, sbi->s_free_blocks, 1);
  84. dirty_sb(sb);
  85. unlock_super(sb);
  86. }
  87. sysv_zone_t sysv_new_block(struct super_block * sb)
  88. {
  89. struct sysv_sb_info *sbi = SYSV_SB(sb);
  90. unsigned int block;
  91. sysv_zone_t nr;
  92. struct buffer_head * bh;
  93. unsigned count;
  94. lock_super(sb);
  95. count = fs16_to_cpu(sbi, *sbi->s_bcache_count);
  96. if (count == 0) /* Applies only to Coherent FS */
  97. goto Enospc;
  98. nr = sbi->s_bcache[--count];
  99. if (nr == 0) /* Applies only to Xenix FS, SystemV FS */
  100. goto Enospc;
  101. block = fs32_to_cpu(sbi, nr);
  102. *sbi->s_bcache_count = cpu_to_fs16(sbi, count);
  103. if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
  104. printk("sysv_new_block: new block %d is not in data zone\n",
  105. block);
  106. goto Enospc;
  107. }
  108. if (count == 0) { /* the last block continues the free list */
  109. unsigned count;
  110. block += sbi->s_block_base;
  111. if (!(bh = sb_bread(sb, block))) {
  112. printk("sysv_new_block: cannot read free-list block\n");
  113. /* retry this same block next time */
  114. *sbi->s_bcache_count = cpu_to_fs16(sbi, 1);
  115. goto Enospc;
  116. }
  117. count = fs16_to_cpu(sbi, *(__fs16*)bh->b_data);
  118. if (count > sbi->s_flc_size) {
  119. printk("sysv_new_block: free-list block with >flc_size entries\n");
  120. brelse(bh);
  121. goto Enospc;
  122. }
  123. *sbi->s_bcache_count = cpu_to_fs16(sbi, count);
  124. memcpy(sbi->s_bcache, get_chunk(sb, bh),
  125. count * sizeof(sysv_zone_t));
  126. brelse(bh);
  127. }
  128. /* Now the free list head in the superblock is valid again. */
  129. fs32_add(sbi, sbi->s_free_blocks, -1);
  130. dirty_sb(sb);
  131. unlock_super(sb);
  132. return nr;
  133. Enospc:
  134. unlock_super(sb);
  135. return 0;
  136. }
  137. unsigned long sysv_count_free_blocks(struct super_block * sb)
  138. {
  139. struct sysv_sb_info * sbi = SYSV_SB(sb);
  140. int sb_count;
  141. int count;
  142. struct buffer_head * bh = NULL;
  143. sysv_zone_t *blocks;
  144. unsigned block;
  145. int n;
  146. /*
  147. * This code does not work at all for AFS (it has a bitmap
  148. * free list). As AFS is supposed to be read-only we just
  149. * lie and say it has no free block at all.
  150. */
  151. if (sbi->s_type == FSTYPE_AFS)
  152. return 0;
  153. lock_super(sb);
  154. sb_count = fs32_to_cpu(sbi, *sbi->s_free_blocks);
  155. if (0)
  156. goto trust_sb;
  157. /* this causes a lot of disk traffic ... */
  158. count = 0;
  159. n = fs16_to_cpu(sbi, *sbi->s_bcache_count);
  160. blocks = sbi->s_bcache;
  161. while (1) {
  162. sysv_zone_t zone;
  163. if (n > sbi->s_flc_size)
  164. goto E2big;
  165. zone = 0;
  166. while (n && (zone = blocks[--n]) != 0)
  167. count++;
  168. if (zone == 0)
  169. break;
  170. block = fs32_to_cpu(sbi, zone);
  171. if (bh)
  172. brelse(bh);
  173. if (block < sbi->s_firstdatazone || block >= sbi->s_nzones)
  174. goto Einval;
  175. block += sbi->s_block_base;
  176. bh = sb_bread(sb, block);
  177. if (!bh)
  178. goto Eio;
  179. n = fs16_to_cpu(sbi, *(__fs16*)bh->b_data);
  180. blocks = get_chunk(sb, bh);
  181. }
  182. if (bh)
  183. brelse(bh);
  184. if (count != sb_count)
  185. goto Ecount;
  186. done:
  187. unlock_super(sb);
  188. return count;
  189. Einval:
  190. printk("sysv_count_free_blocks: new block %d is not in data zone\n",
  191. block);
  192. goto trust_sb;
  193. Eio:
  194. printk("sysv_count_free_blocks: cannot read free-list block\n");
  195. goto trust_sb;
  196. E2big:
  197. printk("sysv_count_free_blocks: >flc_size entries in free-list block\n");
  198. if (bh)
  199. brelse(bh);
  200. trust_sb:
  201. count = sb_count;
  202. goto done;
  203. Ecount:
  204. printk("sysv_count_free_blocks: free block count was %d, "
  205. "correcting to %d\n", sb_count, count);
  206. if (!(sb->s_flags & MS_RDONLY)) {
  207. *sbi->s_free_blocks = cpu_to_fs32(sbi, count);
  208. dirty_sb(sb);
  209. }
  210. goto done;
  211. }