source: mainline/uspace/lib/label/src/empty.c@ 36f0738

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 36f0738 was 5772aa1, checked in by Jiri Svoboda <jiri@…>, 8 years ago

VBD needs to empty a newly created partition before exposing it to the volume server.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*
2 * Copyright (c) 2015 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions 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 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup liblabel
30 * @{
31 */
32/**
33 * @file Empty partition handling
34 * @brief
35 */
36
37#include <errno.h>
38#include <io/log.h>
39#include <label/empty.h>
40#include <loc.h>
41#include <stdlib.h>
42
43/*
44 * The partition will be considered empty if at least a minimum number of
45 * bytes *and* blocks (whichever is larger) at the beginning and end of
46 * the partition is zero.
47 */
48enum {
49 min_empty_bytes = 16384,
50 /*
51 * First block in ISO 9660 that cannot be empty is the first
52 * volume descriptor at LBA 16
53 */
54 min_empty_blocks = 17
55};
56
57static bool mem_is_zero(void *buf, size_t size)
58{
59 uint8_t *bp;
60 size_t i;
61
62 bp = (uint8_t *)buf;
63 for (i = 0; i < size; i++) {
64 if (bp[i] != 0)
65 return false;
66 }
67
68 return true;
69}
70
71/** Calculate number of blocks to check.
72 *
73 * Will store to @a *ncb the number of blocks that should be checked
74 * at the beginning and end of device each.
75 *
76 * @param nblocks Total number of blocks on block device
77 * @param block_size Block size
78 * @param ncb Place to store number of blocks to check.
79 */
80static void calc_num_check_blocks(aoff64_t nblocks, size_t block_size,
81 aoff64_t *ncb)
82{
83 aoff64_t n;
84
85 /* Check first 16 kiB / 16 blocks, whichever is more */
86 n = (min_empty_bytes + block_size - 1) / block_size;
87 if (n < min_empty_blocks)
88 n = min_empty_blocks;
89 /*
90 * Limit to half of the device so we do not process the same blocks
91 * twice
92 */
93 if (n > (nblocks + 1) / 2)
94 n = (nblocks + 1) / 2;
95
96 *ncb = n;
97}
98
99int label_bd_is_empty(label_bd_t *bd, bool *rempty)
100{
101 int rc;
102 void *buf = NULL;
103 aoff64_t nblocks;
104 aoff64_t n;
105 aoff64_t i;
106 size_t block_size;
107 bool empty;
108
109 rc = bd->ops->get_bsize(bd->arg, &block_size);
110 if (rc != EOK) {
111 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
112 "block size.");
113 rc = EIO;
114 goto error;
115 }
116
117 rc = bd->ops->get_nblocks(bd->arg, &nblocks);
118 if (rc != EOK) {
119 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
120 "number of blocks.");
121 rc = EIO;
122 goto error;
123 }
124
125 calc_num_check_blocks(nblocks, block_size, &n);
126
127 buf = calloc(block_size, 1);
128 if (buf == NULL) {
129 log_msg(LOG_DEFAULT, LVL_ERROR, "Error allocating buffer.");
130 rc = ENOMEM;
131 goto error;
132 }
133
134 empty = true;
135
136 for (i = 0; i < n; i++) {
137 rc = bd->ops->read(bd->arg, i, 1, buf);
138 if (rc != EOK) {
139 log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
140 "reading blocks.");
141 rc = EIO;
142 goto error;
143 }
144
145 if (!mem_is_zero(buf, block_size)) {
146 empty = false;
147 goto done;
148 }
149 }
150
151 for (i = 0; i < n; i++) {
152 rc = bd->ops->read(bd->arg, nblocks - n + i, 1, buf);
153 if (rc != EOK) {
154 log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
155 "reading blocks.");
156 rc = EIO;
157 goto error;
158 }
159
160 if (!mem_is_zero(buf, block_size)) {
161 empty = false;
162 goto done;
163 }
164 }
165
166done:
167 free(buf);
168 *rempty = empty;
169 return EOK;
170error:
171 if (buf != NULL)
172 free(buf);
173 return rc;
174}
175
176int label_bd_empty(label_bd_t *bd)
177{
178 int rc;
179 void *buf = NULL;
180 aoff64_t nblocks;
181 aoff64_t n;
182 aoff64_t i;
183 size_t block_size;
184
185 rc = bd->ops->get_bsize(bd->arg, &block_size);
186 if (rc != EOK) {
187 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
188 "block size.");
189 rc = EIO;
190 goto error;
191 }
192
193 rc = bd->ops->get_nblocks(bd->arg, &nblocks);
194 if (rc != EOK) {
195 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
196 "number of blocks.");
197 rc = EIO;
198 goto error;
199 }
200
201 calc_num_check_blocks(nblocks, block_size, &n);
202
203 buf = calloc(block_size, 1);
204 if (buf == NULL) {
205 log_msg(LOG_DEFAULT, LVL_ERROR, "Error allocating buffer.");
206 rc = ENOMEM;
207 goto error;
208 }
209
210 for (i = 0; i < n; i++) {
211 rc = bd->ops->write(bd->arg, i, 1, buf);
212 if (rc != EOK) {
213 log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
214 "reading blocks.");
215 rc = EIO;
216 goto error;
217 }
218 }
219
220 for (i = 0; i < n; i++) {
221 rc = bd->ops->write(bd->arg, nblocks - n + i, 1, buf);
222 if (rc != EOK) {
223 log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
224 "reading blocks.");
225 rc = EIO;
226 goto error;
227 }
228 }
229
230 free(buf);
231 return EOK;
232error:
233 if (buf != NULL)
234 free(buf);
235 return rc;
236}
237
238int label_part_empty(label_part_t *part)
239{
240 int rc;
241 void *buf = NULL;
242 aoff64_t block0;
243 aoff64_t nblocks;
244 aoff64_t n;
245 aoff64_t i;
246 size_t block_size;
247 label_bd_t *bd;
248
249 bd = &part->label->bd;
250
251 block_size = part->label->block_size;
252 block0 = part->block0;
253 nblocks = part->nblocks;
254
255 calc_num_check_blocks(nblocks, block_size, &n);
256
257 buf = calloc(block_size, 1);
258 if (buf == NULL) {
259 log_msg(LOG_DEFAULT, LVL_ERROR, "Error allocating buffer.");
260 rc = ENOMEM;
261 goto error;
262 }
263
264 for (i = 0; i < n; i++) {
265 rc = bd->ops->write(bd->arg, block0 + i, 1, buf);
266 if (rc != EOK) {
267 log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
268 "reading blocks.");
269 rc = EIO;
270 goto error;
271 }
272 }
273
274 for (i = 0; i < n; i++) {
275 rc = bd->ops->write(bd->arg, block0 + nblocks - n + i, 1, buf);
276 if (rc != EOK) {
277 log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
278 "reading blocks.");
279 rc = EIO;
280 goto error;
281 }
282 }
283
284 free(buf);
285 return EOK;
286error:
287 if (buf != NULL)
288 free(buf);
289 return rc;
290}
291
292/** @}
293 */
Note: See TracBrowser for help on using the repository browser.