source: mainline/uspace/srv/volsrv/disk.c@ c02d098

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

Most of extended (but not logical) partition support.

  • Property mode set to 100644
File size: 6.6 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 Disk device handling
34 * @brief
35 */
36
37#include <stdbool.h>
38#include <errno.h>
39#include <fibril_synch.h>
40#include <io/log.h>
41#include <loc.h>
42#include <stdlib.h>
43#include <str.h>
44#include <vbd.h>
45
46#include "disk.h"
47#include "types/disk.h"
48
49static int vol_disk_add(service_id_t);
50
51static LIST_INITIALIZE(vol_disks); /* of vol_disk_t */
52static FIBRIL_MUTEX_INITIALIZE(vol_disks_lock);
53static vbd_t *vbd;
54
55/** Check for new disk devices */
56static int vol_disk_check_new(void)
57{
58 bool already_known;
59 category_id_t disk_cat;
60 service_id_t *svcs;
61 size_t count, i;
62 int rc;
63
64 fibril_mutex_lock(&vol_disks_lock);
65
66 rc = loc_category_get_id("disk", &disk_cat, IPC_FLAG_BLOCKING);
67 if (rc != EOK) {
68 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'disk'.");
69 fibril_mutex_unlock(&vol_disks_lock);
70 return ENOENT;
71 }
72
73 rc = loc_category_get_svcs(disk_cat, &svcs, &count);
74 if (rc != EOK) {
75 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting list of disk "
76 "devices.");
77 fibril_mutex_unlock(&vol_disks_lock);
78 return EIO;
79 }
80
81 for (i = 0; i < count; i++) {
82 already_known = false;
83
84 list_foreach(vol_disks, ldisks, vol_disk_t, disk) {
85 if (disk->svc_id == svcs[i]) {
86 already_known = true;
87 break;
88 }
89 }
90
91 if (!already_known) {
92 log_msg(LOG_DEFAULT, LVL_NOTE, "Found disk '%lu'",
93 (unsigned long) svcs[i]);
94 rc = vol_disk_add(svcs[i]);
95 if (rc != EOK) {
96 log_msg(LOG_DEFAULT, LVL_ERROR, "Could not add "
97 "disk.");
98 }
99 }
100 }
101
102 fibril_mutex_unlock(&vol_disks_lock);
103 return EOK;
104}
105
106static vol_disk_t *vol_disk_new(void)
107{
108 vol_disk_t *disk = calloc(1, sizeof(vol_disk_t));
109
110 if (disk == NULL) {
111 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating disk "
112 "structure. Out of memory.");
113 return NULL;
114 }
115
116 link_initialize(&disk->ldisks);
117 disk->dcnt = dc_empty;
118
119 return disk;
120}
121
122static void vol_disk_delete(vol_disk_t *disk)
123{
124 if (disk == NULL)
125 return;
126
127 free(disk->svc_name);
128 free(disk);
129}
130
131static int vol_disk_add(service_id_t sid)
132{
133 vol_disk_t *disk;
134 vbd_disk_info_t dinfo;
135 int rc;
136
137 assert(fibril_mutex_is_locked(&vol_disks_lock));
138
139 log_msg(LOG_DEFAULT, LVL_NOTE, "vol_disk_add()");
140 disk = vol_disk_new();
141 if (disk == NULL)
142 return ENOMEM;
143
144 disk->svc_id = sid;
145
146 rc = loc_service_get_name(sid, &disk->svc_name);
147 if (rc != EOK) {
148 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting service name.");
149 goto error;
150 }
151
152 log_msg(LOG_DEFAULT, LVL_NOTE, "Probe disk %s", disk->svc_name);
153
154 rc = vbd_disk_add(vbd, sid);
155 if (rc == EOK) {
156 log_msg(LOG_DEFAULT, LVL_NOTE, "Disk %s accepted by VBD.",
157 disk->svc_name);
158
159 rc = vbd_disk_info(vbd, sid, &dinfo);
160 log_msg(LOG_DEFAULT, LVL_NOTE, "Got disk info.");
161 if (rc != EOK) {
162 log_msg(LOG_DEFAULT, LVL_NOTE, "Cannot get disk label "
163 "information.");
164 rc = EIO;
165 goto error;
166 }
167
168 disk->dcnt = dc_label;
169 disk->ltype = dinfo.ltype;
170 } else {
171 log_msg(LOG_DEFAULT, LVL_NOTE, "Disk %s not accepted by VBD.",
172 disk->svc_name);
173 disk->dcnt = dc_unknown;
174 }
175
176 list_append(&disk->ldisks, &vol_disks);
177
178 return EOK;
179
180error:
181 vol_disk_delete(disk);
182 return rc;
183}
184
185static void vol_disk_cat_change_cb(void)
186{
187 (void) vol_disk_check_new();
188}
189
190int vol_disk_init(void)
191{
192 int rc;
193
194 rc = vbd_create(&vbd);
195 if (rc != EOK) {
196 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing VBD.");
197 return EIO;
198 }
199
200 return EOK;
201}
202
203int vol_disk_discovery_start(void)
204{
205 int rc;
206
207 rc = loc_register_cat_change_cb(vol_disk_cat_change_cb);
208 if (rc != EOK) {
209 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback "
210 "for disk discovery (%d).", rc);
211 return rc;
212 }
213
214 return vol_disk_check_new();
215}
216
217/** Get list of disks as array of service IDs. */
218int vol_disk_get_ids(service_id_t *id_buf, size_t buf_size, size_t *act_size)
219{
220 size_t act_cnt;
221 size_t buf_cnt;
222
223 fibril_mutex_lock(&vol_disks_lock);
224
225 buf_cnt = buf_size / sizeof(service_id_t);
226
227 act_cnt = list_count(&vol_disks);
228 *act_size = act_cnt * sizeof(service_id_t);
229
230 if (buf_size % sizeof(service_id_t) != 0) {
231 fibril_mutex_unlock(&vol_disks_lock);
232 return EINVAL;
233 }
234
235 size_t pos = 0;
236 list_foreach(vol_disks, ldisks, vol_disk_t, disk) {
237 if (pos < buf_cnt)
238 id_buf[pos] = disk->svc_id;
239 pos++;
240 }
241
242 fibril_mutex_unlock(&vol_disks_lock);
243 return EOK;
244}
245
246int vol_disk_find_by_id(service_id_t sid, vol_disk_t **rdisk)
247{
248 list_foreach(vol_disks, ldisks, vol_disk_t, disk) {
249 if (disk->svc_id == sid) {
250 *rdisk = disk;
251 /* XXX Add reference */
252 return EOK;
253 }
254 }
255
256 return ENOENT;
257}
258
259int vol_disk_label_create(vol_disk_t *disk, label_type_t ltype)
260{
261 int rc;
262
263 rc = vbd_label_create(vbd, disk->svc_id, ltype);
264 if (rc != EOK)
265 return rc;
266
267 disk->dcnt = dc_label;
268 disk->ltype = ltype;
269
270 return EOK;
271}
272
273int vol_disk_empty_disk(vol_disk_t *disk)
274{
275 int rc;
276
277 if (disk->dcnt == dc_label) {
278 rc = vbd_label_delete(vbd, disk->svc_id);
279 if (rc != EOK)
280 return rc;
281 }
282
283 disk->dcnt = dc_empty;
284
285 return EOK;
286}
287
288int vol_disk_get_info(vol_disk_t *disk, vol_disk_info_t *dinfo)
289{
290 vbd_disk_info_t vdinfo;
291 int rc;
292
293 dinfo->dcnt = disk->dcnt;
294
295 if (disk->dcnt == dc_label) {
296 rc = vbd_disk_info(vbd, disk->svc_id, &vdinfo);
297 if (rc != EOK)
298 return rc;
299
300 dinfo->ltype = vdinfo.ltype;
301 dinfo->flags = vdinfo.flags;
302 }
303
304 return EOK;
305}
306
307
308/** @}
309 */
Note: See TracBrowser for help on using the repository browser.