199193Sjmallett/* 299193Sjmallett * Copyright (c) 2002 Juli Mallett. All rights reserved. 399193Sjmallett * 499193Sjmallett * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 599193Sjmallett * FreeBSD project. Redistribution and use in source and binary forms, with 699193Sjmallett * or without modification, are permitted provided that the following 799193Sjmallett * conditions are met: 899193Sjmallett * 999193Sjmallett * 1. Redistribution of source code must retain the above copyright notice, 1099193Sjmallett * this list of conditions and the following disclaimer. 1199193Sjmallett * 2. Redistribution in binary form must reproduce the above copyright 1299193Sjmallett * notice, this list of conditions and the following disclaimer in the 1399193Sjmallett * documentation and/or other materials provided with the distribution. 1499193Sjmallett * 1599193Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1699193Sjmallett * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1799193Sjmallett * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1899193Sjmallett * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 1999193Sjmallett * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2099193Sjmallett * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2199193Sjmallett * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2299193Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2399193Sjmallett * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 2499193Sjmallett * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2599193Sjmallett * POSSIBILITY OF SUCH DAMAGE. 2699193Sjmallett */ 2799193Sjmallett 2899193Sjmallett#include <sys/cdefs.h> 2999193Sjmallett__FBSDID("$FreeBSD$"); 3099193Sjmallett 3199193Sjmallett#include <sys/param.h> 3299193Sjmallett#include <sys/mount.h> 33174668Sphk#include <sys/disk.h> 3499193Sjmallett#include <sys/disklabel.h> 3599193Sjmallett#include <sys/stat.h> 3699193Sjmallett 3799193Sjmallett#include <ufs/ufs/ufsmount.h> 3899193Sjmallett#include <ufs/ufs/dinode.h> 3999193Sjmallett#include <ufs/ffs/fs.h> 4099193Sjmallett 4199193Sjmallett#include <errno.h> 42109766Sjmallett#include <fcntl.h> 4399193Sjmallett#include <stdio.h> 44120874Sphk#include <stdlib.h> 4599193Sjmallett#include <string.h> 4699193Sjmallett#include <unistd.h> 4799193Sjmallett 4899193Sjmallett#include <libufs.h> 4999193Sjmallett 5099193Sjmallettssize_t 5199193Sjmallettbread(struct uufsd *disk, ufs2_daddr_t blockno, void *data, size_t size) 5299193Sjmallett{ 53120874Sphk void *p2; 5499193Sjmallett ssize_t cnt; 5599193Sjmallett 56109462Sjmallett ERROR(disk, NULL); 5799193Sjmallett 58120874Sphk p2 = data; 5999193Sjmallett /* 60120874Sphk * XXX: various disk controllers require alignment of our buffer 61120874Sphk * XXX: which is stricter than struct alignment. 62120874Sphk * XXX: Bounce the buffer if not 64 byte aligned. 63120874Sphk * XXX: this can be removed if/when the kernel is fixed 6499193Sjmallett */ 65120874Sphk if (((intptr_t)data) & 0x3f) { 66120874Sphk p2 = malloc(size); 67190646Sdelphij if (p2 == NULL) { 68120874Sphk ERROR(disk, "allocate bounce buffer"); 69190646Sdelphij goto fail; 70190646Sdelphij } 71120874Sphk } 72120874Sphk cnt = pread(disk->d_fd, p2, size, (off_t)(blockno * disk->d_bsize)); 73111111Sjmallett if (cnt == -1) { 74111111Sjmallett ERROR(disk, "read error from block device"); 75111111Sjmallett goto fail; 7699193Sjmallett } 77111111Sjmallett if (cnt == 0) { 78111111Sjmallett ERROR(disk, "end of file from block device"); 79111111Sjmallett goto fail; 80111111Sjmallett } 81111111Sjmallett if ((size_t)cnt != size) { 82111111Sjmallett ERROR(disk, "short read or read error from block device"); 83111111Sjmallett goto fail; 84111111Sjmallett } 85120874Sphk if (p2 != data) { 86120874Sphk memcpy(data, p2, size); 87120874Sphk free(p2); 88120874Sphk } 89116084Sjmallett return (cnt); 90120874Sphkfail: memset(data, 0, size); 91120874Sphk if (p2 != data) { 92120874Sphk free(p2); 93120874Sphk } 94116084Sjmallett return (-1); 9599193Sjmallett} 9699193Sjmallett 9799193Sjmallettssize_t 9899193Sjmallettbwrite(struct uufsd *disk, ufs2_daddr_t blockno, const void *data, size_t size) 9999193Sjmallett{ 10099193Sjmallett ssize_t cnt; 101110066Sjmallett int rv; 102120874Sphk void *p2 = NULL; 10399193Sjmallett 104109462Sjmallett ERROR(disk, NULL); 10599193Sjmallett 106110066Sjmallett rv = ufs_disk_write(disk); 107110066Sjmallett if (rv == -1) { 108109766Sjmallett ERROR(disk, "failed to open disk for writing"); 109116084Sjmallett return (-1); 110109766Sjmallett } 111109766Sjmallett 112120874Sphk /* 113120874Sphk * XXX: various disk controllers require alignment of our buffer 114120874Sphk * XXX: which is stricter than struct alignment. 115120874Sphk * XXX: Bounce the buffer if not 64 byte aligned. 116120874Sphk * XXX: this can be removed if/when the kernel is fixed 117120874Sphk */ 118120874Sphk if (((intptr_t)data) & 0x3f) { 119120874Sphk p2 = malloc(size); 120190646Sdelphij if (p2 == NULL) { 121120874Sphk ERROR(disk, "allocate bounce buffer"); 122190646Sdelphij return (-1); 123190646Sdelphij } 124120874Sphk memcpy(p2, data, size); 125120874Sphk data = p2; 126120874Sphk } 12799193Sjmallett cnt = pwrite(disk->d_fd, data, size, (off_t)(blockno * disk->d_bsize)); 128120874Sphk if (p2 != NULL) 129120874Sphk free(p2); 130111111Sjmallett if (cnt == -1) { 131112850Sjmallett ERROR(disk, "write error to block device"); 132116084Sjmallett return (-1); 133111111Sjmallett } 134111111Sjmallett if ((size_t)cnt != size) { 135109462Sjmallett ERROR(disk, "short write to block device"); 136116084Sjmallett return (-1); 13799193Sjmallett } 138109766Sjmallett 139116084Sjmallett return (cnt); 14099193Sjmallett} 141174668Sphk 142228349Srmh#ifdef __FreeBSD_kernel__ 143228349Srmh 144228349Srmhstatic int 145228349Srmhberase_helper(struct uufsd *disk, ufs2_daddr_t blockno, ufs2_daddr_t size) 146228349Srmh{ 147228349Srmh off_t ioarg[2]; 148228349Srmh 149228349Srmh ioarg[0] = blockno * disk->d_bsize; 150228349Srmh ioarg[1] = size; 151228349Srmh return (ioctl(disk->d_fd, DIOCGDELETE, ioarg)); 152228349Srmh} 153228349Srmh 154228349Srmh#else 155228349Srmh 156228349Srmhstatic int 157228349Srmhberase_helper(struct uufsd *disk, ufs2_daddr_t blockno, ufs2_daddr_t size) 158228349Srmh{ 159228349Srmh char *zero_chunk; 160228349Srmh off_t offset, zero_chunk_size, pwrite_size; 161228349Srmh int rv; 162228349Srmh 163228349Srmh offset = blockno * disk->d_bsize; 164228349Srmh zero_chunk_size = 65536 * disk->d_bsize; 165228349Srmh zero_chunk = calloc(1, zero_chunk_size); 166228349Srmh if (zero_chunk == NULL) { 167228349Srmh ERROR(disk, "failed to allocate memory"); 168228349Srmh return (-1); 169228349Srmh } 170228349Srmh while (size > 0) { 171228349Srmh pwrite_size = size; 172228349Srmh if (pwrite_size > zero_chunk_size) 173228349Srmh pwrite_size = zero_chunk_size; 174228349Srmh rv = pwrite(disk->d_fd, zero_chunk, pwrite_size, offset); 175228349Srmh if (rv == -1) { 176228349Srmh ERROR(disk, "failed writing to disk"); 177228349Srmh break; 178228349Srmh } 179228349Srmh size -= rv; 180228349Srmh offset += rv; 181228349Srmh rv = 0; 182228349Srmh } 183228349Srmh free(zero_chunk); 184228349Srmh return (rv); 185228349Srmh} 186228349Srmh 187228349Srmh#endif 188228349Srmh 189174668Sphkint 190174668Sphkberase(struct uufsd *disk, ufs2_daddr_t blockno, ufs2_daddr_t size) 191174668Sphk{ 192174668Sphk int rv; 193174668Sphk 194174668Sphk ERROR(disk, NULL); 195174668Sphk rv = ufs_disk_write(disk); 196174668Sphk if (rv == -1) { 197174668Sphk ERROR(disk, "failed to open disk for writing"); 198174668Sphk return(rv); 199174668Sphk } 200228349Srmh return (berase_helper(disk, blockno, size)); 201174668Sphk} 202