source: mainline/uspace/srv/volsrv/empty.c@ f63a0073

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

Merge mainline changes.

  • Property mode set to 100644
File size: 5.5 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 volsrv
30 * @{
31 */
32/**
33 * @file Empty partition handling
34 * @brief
35 */
36
37#include <block.h>
38#include <errno.h>
39#include <io/log.h>
40#include <loc.h>
41#include <stdlib.h>
42
43#include "empty.h"
44
45static bool mem_is_zero(void *buf, size_t size)
46{
47 uint8_t *bp;
48 size_t i;
49
50 bp = (uint8_t *)buf;
51 for (i = 0; i < size; i++) {
52 if (bp[i] != 0)
53 return false;
54 }
55
56 return true;
57}
58
59/** Calculate number of blocks to check.
60 *
61 * Will store to @a *ncb the number of blocks that should be checked
62 * at the beginning and end of device each.
63 *
64 * @param nblocks Total number of blocks on block device
65 * @param block_size Block size
66 * @param ncb Place to store number of blocks to check.
67 */
68static void calc_num_check_blocks(aoff64_t nblocks, size_t block_size,
69 aoff64_t *ncb)
70{
71 aoff64_t n;
72
73 /* Check first 16 kiB / 16 blocks, whichever is more */
74 n = (16384 + block_size - 1) / block_size;
75 if (n < 16)
76 n = 16;
77 /*
78 * Limit to half of the device so we do not process the same blocks
79 * twice
80 */
81 if (n > (nblocks + 1) / 2)
82 n = (nblocks + 1) / 2;
83
84 *ncb = n;
85}
86
87int volsrv_part_is_empty(service_id_t sid, bool *rempty)
88{
89 int rc;
90 bool block_inited = false;
91 void *buf = NULL;
92 aoff64_t nblocks;
93 aoff64_t n;
94 aoff64_t i;
95 size_t block_size;
96 bool empty;
97
98 rc = block_init(sid, 2048);
99 if (rc != EOK) {
100 log_msg(LOG_DEFAULT, LVL_ERROR, "Error opening "
101 "block device service %zu", sid);
102 rc = EIO;
103 goto error;
104 }
105
106 block_inited = true;
107
108 rc = block_get_bsize(sid, &block_size);
109 if (rc != EOK) {
110 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
111 "block size.");
112 rc = EIO;
113 goto error;
114 }
115
116 rc = block_get_nblocks(sid, &nblocks);
117 if (rc != EOK) {
118 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
119 "number of blocks.");
120 rc = EIO;
121 goto error;
122 }
123
124 calc_num_check_blocks(nblocks, block_size, &n);
125
126 buf = calloc(block_size, 1);
127 if (buf == NULL) {
128 log_msg(LOG_DEFAULT, LVL_ERROR, "Error allocating buffer.");
129 rc = ENOMEM;
130 goto error;
131 }
132
133 empty = true;
134
135 for (i = 0; i < n; i++) {
136 rc = block_read_direct(sid, i, 1, buf);
137 if (rc != EOK) {
138 log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
139 "reading blocks.");
140 rc = EIO;
141 goto error;
142 }
143
144 if (!mem_is_zero(buf, block_size)) {
145 empty = false;
146 goto done;
147 }
148 }
149
150 for (i = 0; i < n; i++) {
151 rc = block_read_direct(sid, nblocks - n + i, 1, buf);
152 if (rc != EOK) {
153 log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
154 "reading blocks.");
155 rc = EIO;
156 goto error;
157 }
158
159 if (!mem_is_zero(buf, block_size)) {
160 empty = false;
161 goto done;
162 }
163 }
164
165done:
166 block_fini(sid);
167 free(buf);
168 *rempty = empty;
169 return EOK;
170error:
171 if (block_inited)
172 block_fini(sid);
173 if (buf != NULL)
174 free(buf);
175 return rc;
176}
177
178int volsrv_part_empty(service_id_t sid)
179{
180 int rc;
181 bool block_inited = false;
182 void *buf = NULL;
183 aoff64_t nblocks;
184 aoff64_t n;
185 aoff64_t i;
186 size_t block_size;
187
188 rc = block_init(sid, 2048);
189 if (rc != EOK) {
190 log_msg(LOG_DEFAULT, LVL_ERROR, "Error opening "
191 "block device service %zu", sid);
192 rc = EIO;
193 goto error;
194 }
195
196 block_inited = true;
197
198 rc = block_get_bsize(sid, &block_size);
199 if (rc != EOK) {
200 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
201 "block size.");
202 rc = EIO;
203 goto error;
204 }
205
206 rc = block_get_nblocks(sid, &nblocks);
207 if (rc != EOK) {
208 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
209 "number of blocks.");
210 rc = EIO;
211 goto error;
212 }
213
214 calc_num_check_blocks(nblocks, block_size, &n);
215
216 buf = calloc(block_size, 1);
217 if (buf == NULL) {
218 log_msg(LOG_DEFAULT, LVL_ERROR, "Error allocating buffer.");
219 rc = ENOMEM;
220 goto error;
221 }
222
223 for (i = 0; i < n; i++) {
224 rc = block_write_direct(sid, i, 1, buf);
225 if (rc != EOK) {
226 log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
227 "reading blocks.");
228 rc = EIO;
229 goto error;
230 }
231 }
232
233 for (i = 0; i < n; i++) {
234 rc = block_write_direct(sid, nblocks - n + i, 1, buf);
235 if (rc != EOK) {
236 log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
237 "reading blocks.");
238 rc = EIO;
239 goto error;
240 }
241 }
242
243 block_fini(sid);
244 free(buf);
245 return EOK;
246error:
247 if (block_inited)
248 block_fini(sid);
249 if (buf != NULL)
250 free(buf);
251 return rc;
252}
253
254/** @}
255 */
Note: See TracBrowser for help on using the repository browser.