block.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * Copyright (c) 2002 Juli Mallett. All rights reserved.
  3. *
  4. * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
  5. * FreeBSD project. Redistribution and use in source and binary forms, with
  6. * or without modification, are permitted provided that the following
  7. * conditions are met:
  8. *
  9. * 1. Redistribution of source code must retain the above copyright notice,
  10. * this list of conditions and the following disclaimer.
  11. * 2. Redistribution in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  19. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  23. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  24. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <u.h>
  28. #include <libc.h>
  29. #include <ufs/libufsdat.h>
  30. #include <ufs/dinode.h>
  31. #include <ufs/fs.h>
  32. #include <ufs/libufs.h>
  33. int32_t
  34. bread(Uufsd *disk, ufs2_daddr_t blockno, void *data, size_t size)
  35. {
  36. void *p2;
  37. int32_t cnt;
  38. libufserror(disk, nil);
  39. p2 = data;
  40. /*
  41. * XXX: various disk controllers require alignment of our buffer
  42. * XXX: which is stricter than struct alignment.
  43. * XXX: Bounce the buffer if not 64 byte aligned.
  44. * XXX: this can be removed if/when the kernel is fixed
  45. */
  46. if (((intptr_t)data) & 0x3f) {
  47. p2 = malloc(size);
  48. if (p2 == nil) {
  49. libufserror(disk, "allocate bounce buffer");
  50. goto fail;
  51. }
  52. }
  53. cnt = pread(disk->d_fd, p2, size, (off_t)(blockno * disk->d_bsize));
  54. if (cnt == -1) {
  55. libufserror(disk, "read error from block device");
  56. goto fail;
  57. }
  58. if (cnt == 0) {
  59. libufserror(disk, "end of file from block device");
  60. goto fail;
  61. }
  62. if ((size_t)cnt != size) {
  63. libufserror(disk, "short read or read error from block device");
  64. goto fail;
  65. }
  66. if (p2 != data) {
  67. memcpy(data, p2, size);
  68. free(p2);
  69. }
  70. return (cnt);
  71. fail: memset(data, 0, size);
  72. if (p2 != data) {
  73. free(p2);
  74. }
  75. return (-1);
  76. }
  77. int32_t
  78. bwrite(Uufsd *disk, ufs2_daddr_t blockno, const void *data, size_t size)
  79. {
  80. int32_t cnt;
  81. int rv;
  82. void *p2 = nil;
  83. libufserror(disk, nil);
  84. rv = ufs_disk_write(disk);
  85. if (rv == -1) {
  86. libufserror(disk, "failed to open disk for writing");
  87. return (-1);
  88. }
  89. /*
  90. * XXX: various disk controllers require alignment of our buffer
  91. * XXX: which is stricter than struct alignment.
  92. * XXX: Bounce the buffer if not 64 byte aligned.
  93. * XXX: this can be removed if/when the kernel is fixed
  94. */
  95. if (((intptr_t)data) & 0x3f) {
  96. p2 = malloc(size);
  97. if (p2 == nil) {
  98. libufserror(disk, "allocate bounce buffer");
  99. return (-1);
  100. }
  101. memcpy(p2, data, size);
  102. data = p2;
  103. }
  104. cnt = pwrite(disk->d_fd, data, size, (off_t)(blockno * disk->d_bsize));
  105. if (p2 != nil)
  106. free(p2);
  107. if (cnt == -1) {
  108. libufserror(disk, "write error to block device");
  109. return (-1);
  110. }
  111. if ((size_t)cnt != size) {
  112. libufserror(disk, "short write to block device");
  113. return (-1);
  114. }
  115. return (cnt);
  116. }
  117. static int
  118. berase_helper(Uufsd *disk, ufs2_daddr_t blockno, ufs2_daddr_t size)
  119. {
  120. char *zero_chunk;
  121. off_t offset, zero_chunk_size, pwrite_size;
  122. int rv;
  123. offset = blockno * disk->d_bsize;
  124. zero_chunk_size = 65536 * disk->d_bsize;
  125. zero_chunk = calloc(1, zero_chunk_size);
  126. if (zero_chunk == nil) {
  127. libufserror(disk, "failed to allocate memory");
  128. return (-1);
  129. }
  130. while (size > 0) {
  131. pwrite_size = size;
  132. if (pwrite_size > zero_chunk_size)
  133. pwrite_size = zero_chunk_size;
  134. rv = pwrite(disk->d_fd, zero_chunk, pwrite_size, offset);
  135. if (rv == -1) {
  136. libufserror(disk, "failed writing to disk");
  137. break;
  138. }
  139. size -= rv;
  140. offset += rv;
  141. rv = 0;
  142. }
  143. free(zero_chunk);
  144. return (rv);
  145. }
  146. int
  147. berase(Uufsd *disk, ufs2_daddr_t blockno, ufs2_daddr_t size)
  148. {
  149. int rv;
  150. libufserror(disk, nil);
  151. rv = ufs_disk_write(disk);
  152. if (rv == -1) {
  153. libufserror(disk, "failed to open disk for writing");
  154. return(rv);
  155. }
  156. return (berase_helper(disk, blockno, size));
  157. }
  158. /*
  159. * Trace steps through libufs, to be used at entry and erroneous return.
  160. */
  161. void
  162. libufserror(Uufsd *u, const char *str)
  163. {
  164. if (str != nil)
  165. perror(str);
  166. if (u != nil)
  167. u->d_error = str;
  168. }