alloc.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * alloc.c --- allocate new inodes, blocks for ext2fs
  4. *
  5. * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
  6. *
  7. * %Begin-Header%
  8. * This file may be redistributed under the terms of the GNU Public
  9. * License.
  10. * %End-Header%
  11. *
  12. */
  13. #include <stdio.h>
  14. #if HAVE_UNISTD_H
  15. #include <unistd.h>
  16. #endif
  17. #include <time.h>
  18. #include <string.h>
  19. #if HAVE_SYS_STAT_H
  20. #include <sys/stat.h>
  21. #endif
  22. #if HAVE_SYS_TYPES_H
  23. #include <sys/types.h>
  24. #endif
  25. #include "ext2_fs.h"
  26. #include "ext2fs.h"
  27. /*
  28. * Right now, just search forward from the parent directory's block
  29. * group to find the next free inode.
  30. *
  31. * Should have a special policy for directories.
  32. */
  33. errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
  34. int mode EXT2FS_ATTR((unused)),
  35. ext2fs_inode_bitmap map, ext2_ino_t *ret)
  36. {
  37. ext2_ino_t dir_group = 0;
  38. ext2_ino_t i;
  39. ext2_ino_t start_inode;
  40. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  41. if (!map)
  42. map = fs->inode_map;
  43. if (!map)
  44. return EXT2_ET_NO_INODE_BITMAP;
  45. if (dir > 0)
  46. dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
  47. start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
  48. if (start_inode < EXT2_FIRST_INODE(fs->super))
  49. start_inode = EXT2_FIRST_INODE(fs->super);
  50. i = start_inode;
  51. do {
  52. if (!ext2fs_fast_test_inode_bitmap(map, i))
  53. break;
  54. i++;
  55. if (i > fs->super->s_inodes_count)
  56. i = EXT2_FIRST_INODE(fs->super);
  57. } while (i != start_inode);
  58. if (ext2fs_test_inode_bitmap(map, i))
  59. return EXT2_ET_INODE_ALLOC_FAIL;
  60. *ret = i;
  61. return 0;
  62. }
  63. /*
  64. * Stupid algorithm --- we now just search forward starting from the
  65. * goal. Should put in a smarter one someday....
  66. */
  67. errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
  68. ext2fs_block_bitmap map, blk_t *ret)
  69. {
  70. blk_t i;
  71. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  72. if (!map)
  73. map = fs->block_map;
  74. if (!map)
  75. return EXT2_ET_NO_BLOCK_BITMAP;
  76. if (!goal || (goal >= fs->super->s_blocks_count))
  77. goal = fs->super->s_first_data_block;
  78. i = goal;
  79. do {
  80. if (!ext2fs_fast_test_block_bitmap(map, i)) {
  81. *ret = i;
  82. return 0;
  83. }
  84. i++;
  85. if (i >= fs->super->s_blocks_count)
  86. i = fs->super->s_first_data_block;
  87. } while (i != goal);
  88. return EXT2_ET_BLOCK_ALLOC_FAIL;
  89. }
  90. /*
  91. * This function zeros out the allocated block, and updates all of the
  92. * appropriate filesystem records.
  93. */
  94. errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
  95. char *block_buf, blk_t *ret)
  96. {
  97. errcode_t retval;
  98. blk_t block;
  99. char *buf = NULL;
  100. if (!block_buf) {
  101. retval = ext2fs_get_mem(fs->blocksize, &buf);
  102. if (retval)
  103. return retval;
  104. block_buf = buf;
  105. }
  106. memset(block_buf, 0, fs->blocksize);
  107. if (!fs->block_map) {
  108. retval = ext2fs_read_block_bitmap(fs);
  109. if (retval)
  110. goto fail;
  111. }
  112. retval = ext2fs_new_block(fs, goal, 0, &block);
  113. if (retval)
  114. goto fail;
  115. retval = io_channel_write_blk(fs->io, block, 1, block_buf);
  116. if (retval)
  117. goto fail;
  118. ext2fs_block_alloc_stats(fs, block, +1);
  119. *ret = block;
  120. return 0;
  121. fail:
  122. if (buf)
  123. ext2fs_free_mem(&buf);
  124. return retval;
  125. }
  126. errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
  127. int num, ext2fs_block_bitmap map, blk_t *ret)
  128. {
  129. blk_t b = start;
  130. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  131. if (!map)
  132. map = fs->block_map;
  133. if (!map)
  134. return EXT2_ET_NO_BLOCK_BITMAP;
  135. if (!b)
  136. b = fs->super->s_first_data_block;
  137. if (!finish)
  138. finish = start;
  139. if (!num)
  140. num = 1;
  141. do {
  142. if (b+num-1 > fs->super->s_blocks_count)
  143. b = fs->super->s_first_data_block;
  144. if (ext2fs_fast_test_block_bitmap_range(map, b, num)) {
  145. *ret = b;
  146. return 0;
  147. }
  148. b++;
  149. } while (b != finish);
  150. return EXT2_ET_BLOCK_ALLOC_FAIL;
  151. }