1*4d3c95f5SJorgen Lundman /* 2*4d3c95f5SJorgen Lundman * 3*4d3c95f5SJorgen Lundman * based on code of fs/reiserfs/dev.c by 4*4d3c95f5SJorgen Lundman * 5*4d3c95f5SJorgen Lundman * (C) Copyright 2003 - 2004 6*4d3c95f5SJorgen Lundman * Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com> 7*4d3c95f5SJorgen Lundman * 8*4d3c95f5SJorgen Lundman * This program is free software; you can redistribute it and/or modify 9*4d3c95f5SJorgen Lundman * it under the terms of the GNU General Public License as published by 10*4d3c95f5SJorgen Lundman * the Free Software Foundation; either version 2 of the License, or 11*4d3c95f5SJorgen Lundman * (at your option) any later version. 12*4d3c95f5SJorgen Lundman * 13*4d3c95f5SJorgen Lundman * This program is distributed in the hope that it will be useful, 14*4d3c95f5SJorgen Lundman * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*4d3c95f5SJorgen Lundman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*4d3c95f5SJorgen Lundman * GNU General Public License for more details. 17*4d3c95f5SJorgen Lundman * 18*4d3c95f5SJorgen Lundman * You should have received a copy of the GNU General Public License 19*4d3c95f5SJorgen Lundman * along with this program; if not, write to the Free Software 20*4d3c95f5SJorgen Lundman * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21*4d3c95f5SJorgen Lundman */ 22*4d3c95f5SJorgen Lundman 23*4d3c95f5SJorgen Lundman 24*4d3c95f5SJorgen Lundman #include <common.h> 25*4d3c95f5SJorgen Lundman #include <config.h> 26*4d3c95f5SJorgen Lundman #include <zfs_common.h> 27*4d3c95f5SJorgen Lundman 28*4d3c95f5SJorgen Lundman static block_dev_desc_t *zfs_block_dev_desc; 29*4d3c95f5SJorgen Lundman static disk_partition_t part_info; 30*4d3c95f5SJorgen Lundman 31*4d3c95f5SJorgen Lundman int zfs_set_blk_dev(block_dev_desc_t *rbdd, int part) 32*4d3c95f5SJorgen Lundman { 33*4d3c95f5SJorgen Lundman zfs_block_dev_desc = rbdd; 34*4d3c95f5SJorgen Lundman 35*4d3c95f5SJorgen Lundman if (part == 0) { 36*4d3c95f5SJorgen Lundman /* disk doesn't use partition table */ 37*4d3c95f5SJorgen Lundman part_info.start = 0; 38*4d3c95f5SJorgen Lundman part_info.size = rbdd->lba; 39*4d3c95f5SJorgen Lundman part_info.blksz = rbdd->blksz; 40*4d3c95f5SJorgen Lundman } else { 41*4d3c95f5SJorgen Lundman if (get_partition_info(zfs_block_dev_desc, part, &part_info)) 42*4d3c95f5SJorgen Lundman return 0; 43*4d3c95f5SJorgen Lundman } 44*4d3c95f5SJorgen Lundman 45*4d3c95f5SJorgen Lundman return part_info.size; 46*4d3c95f5SJorgen Lundman } 47*4d3c95f5SJorgen Lundman 48*4d3c95f5SJorgen Lundman /* err */ 49*4d3c95f5SJorgen Lundman int zfs_devread(int sector, int byte_offset, int byte_len, char *buf) 50*4d3c95f5SJorgen Lundman { 51*4d3c95f5SJorgen Lundman short sec_buffer[SECTOR_SIZE/sizeof(short)]; 52*4d3c95f5SJorgen Lundman char *sec_buf = (char *)sec_buffer; 53*4d3c95f5SJorgen Lundman unsigned block_len; 54*4d3c95f5SJorgen Lundman 55*4d3c95f5SJorgen Lundman /* 56*4d3c95f5SJorgen Lundman * Check partition boundaries 57*4d3c95f5SJorgen Lundman */ 58*4d3c95f5SJorgen Lundman if ((sector < 0) || 59*4d3c95f5SJorgen Lundman ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS)) >= 60*4d3c95f5SJorgen Lundman part_info.size)) { 61*4d3c95f5SJorgen Lundman /* errnum = ERR_OUTSIDE_PART; */ 62*4d3c95f5SJorgen Lundman printf(" ** zfs_devread() read outside partition sector %d\n", sector); 63*4d3c95f5SJorgen Lundman return 1; 64*4d3c95f5SJorgen Lundman } 65*4d3c95f5SJorgen Lundman 66*4d3c95f5SJorgen Lundman /* 67*4d3c95f5SJorgen Lundman * Get the read to the beginning of a partition. 68*4d3c95f5SJorgen Lundman */ 69*4d3c95f5SJorgen Lundman sector += byte_offset >> SECTOR_BITS; 70*4d3c95f5SJorgen Lundman byte_offset &= SECTOR_SIZE - 1; 71*4d3c95f5SJorgen Lundman 72*4d3c95f5SJorgen Lundman debug(" <%d, %d, %d>\n", sector, byte_offset, byte_len); 73*4d3c95f5SJorgen Lundman 74*4d3c95f5SJorgen Lundman if (zfs_block_dev_desc == NULL) { 75*4d3c95f5SJorgen Lundman printf("** Invalid Block Device Descriptor (NULL)\n"); 76*4d3c95f5SJorgen Lundman return 1; 77*4d3c95f5SJorgen Lundman } 78*4d3c95f5SJorgen Lundman 79*4d3c95f5SJorgen Lundman if (byte_offset != 0) { 80*4d3c95f5SJorgen Lundman /* read first part which isn't aligned with start of sector */ 81*4d3c95f5SJorgen Lundman if (zfs_block_dev_desc->block_read(zfs_block_dev_desc->dev, 82*4d3c95f5SJorgen Lundman part_info.start + sector, 1, 83*4d3c95f5SJorgen Lundman (unsigned long *) sec_buf) != 1) { 84*4d3c95f5SJorgen Lundman printf(" ** zfs_devread() read error **\n"); 85*4d3c95f5SJorgen Lundman return 1; 86*4d3c95f5SJorgen Lundman } 87*4d3c95f5SJorgen Lundman memcpy(buf, sec_buf + byte_offset, 88*4d3c95f5SJorgen Lundman min(SECTOR_SIZE - byte_offset, byte_len)); 89*4d3c95f5SJorgen Lundman buf += min(SECTOR_SIZE - byte_offset, byte_len); 90*4d3c95f5SJorgen Lundman byte_len -= min(SECTOR_SIZE - byte_offset, byte_len); 91*4d3c95f5SJorgen Lundman sector++; 92*4d3c95f5SJorgen Lundman } 93*4d3c95f5SJorgen Lundman 94*4d3c95f5SJorgen Lundman if (byte_len == 0) 95*4d3c95f5SJorgen Lundman return 0; 96*4d3c95f5SJorgen Lundman 97*4d3c95f5SJorgen Lundman /* read sector aligned part */ 98*4d3c95f5SJorgen Lundman block_len = byte_len & ~(SECTOR_SIZE - 1); 99*4d3c95f5SJorgen Lundman 100*4d3c95f5SJorgen Lundman if (block_len == 0) { 101*4d3c95f5SJorgen Lundman u8 p[SECTOR_SIZE]; 102*4d3c95f5SJorgen Lundman 103*4d3c95f5SJorgen Lundman block_len = SECTOR_SIZE; 104*4d3c95f5SJorgen Lundman zfs_block_dev_desc->block_read(zfs_block_dev_desc->dev, 105*4d3c95f5SJorgen Lundman part_info.start + sector, 106*4d3c95f5SJorgen Lundman 1, (unsigned long *)p); 107*4d3c95f5SJorgen Lundman memcpy(buf, p, byte_len); 108*4d3c95f5SJorgen Lundman return 0; 109*4d3c95f5SJorgen Lundman } 110*4d3c95f5SJorgen Lundman 111*4d3c95f5SJorgen Lundman if (zfs_block_dev_desc->block_read(zfs_block_dev_desc->dev, 112*4d3c95f5SJorgen Lundman part_info.start + sector, 113*4d3c95f5SJorgen Lundman block_len / SECTOR_SIZE, 114*4d3c95f5SJorgen Lundman (unsigned long *) buf) != 115*4d3c95f5SJorgen Lundman block_len / SECTOR_SIZE) { 116*4d3c95f5SJorgen Lundman printf(" ** zfs_devread() read error - block\n"); 117*4d3c95f5SJorgen Lundman return 1; 118*4d3c95f5SJorgen Lundman } 119*4d3c95f5SJorgen Lundman 120*4d3c95f5SJorgen Lundman block_len = byte_len & ~(SECTOR_SIZE - 1); 121*4d3c95f5SJorgen Lundman buf += block_len; 122*4d3c95f5SJorgen Lundman byte_len -= block_len; 123*4d3c95f5SJorgen Lundman sector += block_len / SECTOR_SIZE; 124*4d3c95f5SJorgen Lundman 125*4d3c95f5SJorgen Lundman if (byte_len != 0) { 126*4d3c95f5SJorgen Lundman /* read rest of data which are not in whole sector */ 127*4d3c95f5SJorgen Lundman if (zfs_block_dev_desc-> 128*4d3c95f5SJorgen Lundman block_read(zfs_block_dev_desc->dev, 129*4d3c95f5SJorgen Lundman part_info.start + sector, 1, 130*4d3c95f5SJorgen Lundman (unsigned long *) sec_buf) != 1) { 131*4d3c95f5SJorgen Lundman printf(" ** zfs_devread() read error - last part\n"); 132*4d3c95f5SJorgen Lundman return 1; 133*4d3c95f5SJorgen Lundman } 134*4d3c95f5SJorgen Lundman memcpy(buf, sec_buf, byte_len); 135*4d3c95f5SJorgen Lundman } 136*4d3c95f5SJorgen Lundman return 0; 137*4d3c95f5SJorgen Lundman } 138