cache.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /* The file system maintains a buffer cache to reduce the number of disk
  2. * accesses needed. Whenever a read or write to the disk is done, a check is
  3. * first made to see if the block is in the cache. This file contains some
  4. * related routines, but the cache is now in libminixfs.
  5. */
  6. #include "fs.h"
  7. #include <minix/u64.h>
  8. #include <minix/bdev.h>
  9. #include <sys/param.h>
  10. #include <stdlib.h>
  11. #include <assert.h>
  12. #include <minix/libminixfs.h>
  13. #include <math.h>
  14. #include "buf.h"
  15. #include "super.h"
  16. #include "inode.h"
  17. /*===========================================================================*
  18. * get_block *
  19. *===========================================================================*/
  20. struct buf *get_block(dev_t dev, block_t block, int how)
  21. {
  22. /* Wrapper routine for lmfs_get_block(). This MFS implementation does not deal
  23. * well with block read errors pretty much anywhere. To prevent corruption due
  24. * to unchecked error conditions, we panic upon an I/O failure here.
  25. */
  26. struct buf *bp;
  27. int r;
  28. if ((r = lmfs_get_block(&bp, dev, block, how)) != OK && r != ENOENT)
  29. panic("MFS: error getting block (%llu,%u): %d", dev, block, r);
  30. assert(r == OK || how == PEEK);
  31. return (r == OK) ? bp : NULL;
  32. }
  33. /*===========================================================================*
  34. * alloc_zone *
  35. *===========================================================================*/
  36. zone_t alloc_zone(
  37. dev_t dev, /* device where zone wanted */
  38. zone_t z /* try to allocate new zone near this one */
  39. )
  40. {
  41. /* Allocate a new zone on the indicated device and return its number. */
  42. bit_t b, bit;
  43. struct super_block *sp;
  44. static int print_oos_msg = 1;
  45. /* Note that the routine alloc_bit() returns 1 for the lowest possible
  46. * zone, which corresponds to sp->s_firstdatazone. To convert a value
  47. * between the bit number, 'b', used by alloc_bit() and the zone number, 'z',
  48. * stored in the inode, use the formula:
  49. * z = b + sp->s_firstdatazone - 1
  50. * Alloc_bit() never returns 0, since this is used for NO_BIT (failure).
  51. */
  52. sp = &superblock;
  53. /* If z is 0, skip initial part of the map known to be fully in use. */
  54. if (z == sp->s_firstdatazone) {
  55. bit = sp->s_zsearch;
  56. } else {
  57. bit = (bit_t) (z - (sp->s_firstdatazone - 1));
  58. }
  59. b = alloc_bit(sp, ZMAP, bit);
  60. if (b == NO_BIT) {
  61. err_code = ENOSPC;
  62. if (print_oos_msg)
  63. printf("No space on device %d/%d\n", major(sp->s_dev),
  64. minor(sp->s_dev));
  65. print_oos_msg = 0; /* Don't repeat message */
  66. return(NO_ZONE);
  67. }
  68. print_oos_msg = 1;
  69. if (z == sp->s_firstdatazone) sp->s_zsearch = b; /* for next time */
  70. return( (zone_t) (sp->s_firstdatazone - 1) + (zone_t) b);
  71. }
  72. /*===========================================================================*
  73. * free_zone *
  74. *===========================================================================*/
  75. void free_zone(
  76. dev_t dev, /* device where zone located */
  77. zone_t numb /* zone to be returned */
  78. )
  79. {
  80. /* Return a zone. */
  81. register struct super_block *sp;
  82. bit_t bit;
  83. /* Locate the appropriate super_block and return bit. */
  84. sp = &superblock;
  85. if (numb < sp->s_firstdatazone || numb >= sp->s_zones) return;
  86. bit = (bit_t) (numb - (zone_t) (sp->s_firstdatazone - 1));
  87. free_bit(sp, ZMAP, bit);
  88. if (bit < sp->s_zsearch) sp->s_zsearch = bit;
  89. /* Also tell libminixfs, so that 1) if it has a block for this bit, it can
  90. * mark it as clean, thus reducing useless writes, and 2) it can tell VM that
  91. * any previous inode association is to be broken for this block, so that the
  92. * block will not be mapped in erroneously later on.
  93. */
  94. assert(sp->s_log_zone_size == 0); /* otherwise we need a loop here.. */
  95. lmfs_free_block(dev, (block_t)numb);
  96. }