part.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #include "stdinc.h"
  2. #include "dat.h"
  3. #include "fns.h"
  4. u32int maxBlockSize;
  5. int readonly;
  6. Part*
  7. initPart(char *name, int writable)
  8. {
  9. Part *part;
  10. Dir *dir;
  11. int how;
  12. part = MK(Part);
  13. part->name = estrdup(name);
  14. if(!writable && readonly)
  15. how = OREAD;
  16. else
  17. how = ORDWR;
  18. part->fd = open(name, how);
  19. if(part->fd < 0){
  20. if(how == ORDWR)
  21. part->fd = open(name, OREAD);
  22. if(part->fd < 0){
  23. freePart(part);
  24. setErr(EOk, "can't open partition='%s': %r", name);
  25. return nil;
  26. }
  27. fprint(2, "warning: %s opened for reading only\n", name);
  28. }
  29. dir = dirfstat(part->fd);
  30. if(dir == nil){
  31. freePart(part);
  32. setErr(EOk, "can't stat partition='%s': %r", name);
  33. return nil;
  34. }
  35. part->size = dir->length;
  36. part->blockSize = 0;
  37. free(dir);
  38. return part;
  39. }
  40. void
  41. freePart(Part *part)
  42. {
  43. if(part == nil)
  44. return;
  45. close(part->fd);
  46. free(part->name);
  47. free(part);
  48. }
  49. void
  50. partBlockSize(Part *part, u32int blockSize)
  51. {
  52. if(part->blockSize)
  53. fatal("resetting partition=%s's block size", part->name);
  54. part->blockSize = blockSize;
  55. if(blockSize > maxBlockSize)
  56. maxBlockSize = blockSize;
  57. }
  58. int
  59. writePart(Part *part, u64int addr, u8int *buf, u32int n)
  60. {
  61. long m, mm, nn;
  62. vtLock(stats.lock);
  63. stats.diskWrites++;
  64. stats.diskBWrites += n;
  65. vtUnlock(stats.lock);
  66. if(addr > part->size || addr + n > part->size){
  67. setErr(ECorrupt, "out of bounds write to partition='%s'", part->name);
  68. return 0;
  69. }
  70. for(nn = 0; nn < n; nn += m){
  71. mm = n - nn;
  72. if(mm > MaxIo)
  73. mm = MaxIo;
  74. m = pwrite(part->fd, &buf[nn], mm, addr + nn);
  75. if(m != mm){
  76. if(m < 0){
  77. setErr(EOk, "can't write partition='%s': %r", part->name);
  78. return 0;
  79. }
  80. logErr(EOk, "truncated write to partition='%s' n=%ld wrote=%ld", part->name, mm, m);
  81. }
  82. }
  83. return 1;
  84. }
  85. int
  86. readPart(Part *part, u64int addr, u8int *buf, u32int n)
  87. {
  88. long m, mm, nn;
  89. int i;
  90. vtLock(stats.lock);
  91. stats.diskReads++;
  92. stats.diskBReads += n;
  93. vtUnlock(stats.lock);
  94. if(addr > part->size || addr + n > part->size){
  95. setErr(ECorrupt, "out of bounds read from partition='%s': addr=%lld n=%d size=%lld", part->name, addr, n, part->size);
  96. return 0;
  97. }
  98. for(nn = 0; nn < n; nn += m){
  99. mm = n - nn;
  100. if(mm > MaxIo)
  101. mm = MaxIo;
  102. m = -1;
  103. for(i=0; i<4; i++) {
  104. m = pread(part->fd, &buf[nn], mm, addr + nn);
  105. if(m == mm)
  106. break;
  107. }
  108. if(m != mm){
  109. if(m < 0){
  110. setErr(EOk, "can't read partition='%s': %r", part->name);
  111. return 0;
  112. }
  113. logErr(EOk, "warning: truncated read from partition='%s' n=%ld read=%ld", part->name, mm, m);
  114. }
  115. }
  116. return 1;
  117. }