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