balloc.c 5.7 KB

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