disk.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "sam.h"
  10. static Block *blist;
  11. static int
  12. tempdisk(void)
  13. {
  14. char buf[128];
  15. int i, fd;
  16. snprint(buf, sizeof buf, "/tmp/X%d.%.4ssam", getpid(), getuser());
  17. for(i='A'; i<='Z'; i++){
  18. buf[5] = i;
  19. if(access(buf, AEXIST) == 0)
  20. continue;
  21. fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
  22. if(fd >= 0)
  23. return fd;
  24. }
  25. return -1;
  26. }
  27. Disk*
  28. diskinit()
  29. {
  30. Disk *d;
  31. d = emalloc(sizeof(Disk));
  32. d->fd = tempdisk();
  33. if(d->fd < 0){
  34. fprint(2, "sam: can't create temp file: %r\n");
  35. exits("diskinit");
  36. }
  37. return d;
  38. }
  39. static
  40. uint
  41. ntosize(uint n, uint *ip)
  42. {
  43. uint size;
  44. if(n > Maxblock)
  45. panic("internal error: ntosize");
  46. size = n;
  47. if(size & (Blockincr-1))
  48. size += Blockincr - (size & (Blockincr-1));
  49. /* last bucket holds blocks of exactly Maxblock */
  50. if(ip)
  51. *ip = size/Blockincr;
  52. return size * sizeof(Rune);
  53. }
  54. Block*
  55. disknewblock(Disk *d, uint n)
  56. {
  57. uint i, j, size;
  58. Block *b;
  59. size = ntosize(n, &i);
  60. b = d->free[i];
  61. if(b)
  62. d->free[i] = b->next;
  63. else{
  64. /* allocate in chunks to reduce malloc overhead */
  65. if(blist == nil){
  66. blist = emalloc(100*sizeof(Block));
  67. for(j=0; j<100-1; j++)
  68. blist[j].next = &blist[j+1];
  69. }
  70. b = blist;
  71. blist = b->next;
  72. b->addr = d->addr;
  73. d->addr += size;
  74. }
  75. b->n = n;
  76. return b;
  77. }
  78. void
  79. diskrelease(Disk *d, Block *b)
  80. {
  81. uint i;
  82. ntosize(b->n, &i);
  83. b->next = d->free[i];
  84. d->free[i] = b;
  85. }
  86. void
  87. diskwrite(Disk *d, Block **bp, Rune *r, uint n)
  88. {
  89. int size, nsize;
  90. Block *b;
  91. b = *bp;
  92. size = ntosize(b->n, nil);
  93. nsize = ntosize(n, nil);
  94. if(size != nsize){
  95. diskrelease(d, b);
  96. b = disknewblock(d, n);
  97. *bp = b;
  98. }
  99. if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
  100. panic("write error to temp file");
  101. b->n = n;
  102. }
  103. void
  104. diskread(Disk *d, Block *b, Rune *r, uint n)
  105. {
  106. if(n > b->n)
  107. panic("internal error: diskread");
  108. ntosize(b->n, nil); /* called only for sanity check on Maxblock */
  109. if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
  110. panic("read error from temp file");
  111. }