buf.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Buffered I/O on block devices.
  3. * Write buffering ignores offset.
  4. */
  5. #include <u.h>
  6. #include <libc.h>
  7. #include <disk.h>
  8. #include "dat.h"
  9. #include "fns.h"
  10. Buf*
  11. bopen(long (*fn)(Buf*, void*, long, ulong), int omode, int bs, int nblock)
  12. {
  13. Buf *b;
  14. assert(omode == OREAD || OWRITE);
  15. assert(bs > 0 && nblock > 0);
  16. assert(fn != nil);
  17. b = emalloc(sizeof(*b));
  18. b->data = emalloc(bs*nblock);
  19. b->ndata = 0;
  20. b->nblock = nblock;
  21. b->bs = bs;
  22. b->omode = omode;
  23. b->fn = fn; /* function to read or write bs-byte blocks */
  24. return b;
  25. }
  26. long
  27. bread(Buf *b, void *v, long n, vlong off)
  28. {
  29. long m;
  30. vlong noff;
  31. assert(b->omode == OREAD);
  32. /* Refill buffer */
  33. if(b->off > off || off >= b->off+b->ndata) {
  34. noff = off - off % b->bs;
  35. if(vflag)
  36. fprint(2, "try refill at %lld...", noff);
  37. if((m = b->fn(b, b->data, b->nblock, noff/b->bs)) <= 0) {
  38. if (vflag)
  39. fprint(2, "failed\n");
  40. return m;
  41. }
  42. b->ndata = b->bs * m;
  43. b->off = noff;
  44. if(vflag)
  45. fprint(2, "got %ld\n", b->ndata);
  46. }
  47. // fprint(2, "read %ld at %ld\n", n, off);
  48. /* Satisfy request from buffer */
  49. off -= b->off;
  50. if(n > b->ndata - off)
  51. n = b->ndata - off;
  52. memmove(v, b->data+off, n);
  53. return n;
  54. }
  55. long
  56. bwrite(Buf *b, void *v, long n)
  57. {
  58. long on, m, mdata;
  59. uchar *p;
  60. p = v;
  61. on = n;
  62. /* Fill buffer */
  63. mdata = b->bs*b->nblock;
  64. m = mdata - b->ndata;
  65. if(m > n)
  66. m = n;
  67. memmove(b->data+b->ndata, p, m);
  68. p += m;
  69. n -= m;
  70. b->ndata += m;
  71. /* Flush buffer */
  72. if(b->ndata == mdata) {
  73. if(b->fn(b, b->data, b->nblock, 0) < 0) {
  74. if(vflag)
  75. fprint(2, "write fails: %r\n");
  76. return -1;
  77. }
  78. b->ndata = 0;
  79. }
  80. /* For now, don't worry about big writes; 9P only does 8k */
  81. assert(n < mdata);
  82. /* Add remainder to buffer */
  83. if(n) {
  84. memmove(b->data, p, n);
  85. b->ndata = n;
  86. }
  87. return on;
  88. }
  89. void
  90. bterm(Buf *b)
  91. {
  92. /* DVD & BD prefer full ecc blocks (tracks), but can cope with less */
  93. if(b->omode == OWRITE && b->ndata)
  94. b->fn(b, b->data, (b->ndata + b->bs - 1)/b->bs, 0);
  95. free(b->data);
  96. free(b);
  97. }