source: mainline/uspace/srv/volsrv/part.c@ 81dd2ed

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

File system probing groundwork. Only MFS can do it for now.

  • Property mode set to 100644
File size: 6.9 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 Partition 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 <vfs/vfs.h>
45
46#include "empty.h"
47#include "mkfs.h"
48#include "part.h"
49#include "types/part.h"
50
51static int vol_part_add_locked(service_id_t);
52static LIST_INITIALIZE(vol_parts); /* of vol_part_t */
53static FIBRIL_MUTEX_INITIALIZE(vol_parts_lock);
54
55/** Check for new partitions */
56static int vol_part_check_new(void)
57{
58 bool already_known;
59 category_id_t part_cat;
60 service_id_t *svcs;
61 size_t count, i;
62 int rc;
63
64 fibril_mutex_lock(&vol_parts_lock);
65
66 rc = loc_category_get_id("partition", &part_cat, IPC_FLAG_BLOCKING);
67 if (rc != EOK) {
68 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'partition'.");
69 fibril_mutex_unlock(&vol_parts_lock);
70 return ENOENT;
71 }
72
73 rc = loc_category_get_svcs(part_cat, &svcs, &count);
74 if (rc != EOK) {
75 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting list of partition "
76 "devices.");
77 fibril_mutex_unlock(&vol_parts_lock);
78 return EIO;
79 }
80
81 for (i = 0; i < count; i++) {
82 already_known = false;
83
84 list_foreach(vol_parts, lparts, vol_part_t, part) {
85 if (part->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 partition '%lu'",
93 (unsigned long) svcs[i]);
94 rc = vol_part_add_locked(svcs[i]);
95 if (rc != EOK) {
96 log_msg(LOG_DEFAULT, LVL_ERROR, "Could not add "
97 "partition.");
98 }
99 }
100 }
101
102 fibril_mutex_unlock(&vol_parts_lock);
103 return EOK;
104}
105
106static vol_part_t *vol_part_new(void)
107{
108 vol_part_t *part = calloc(1, sizeof(vol_part_t));
109
110 if (part == NULL) {
111 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating partition "
112 "structure. Out of memory.");
113 return NULL;
114 }
115
116 link_initialize(&part->lparts);
117 part->pcnt = vpc_empty;
118
119 return part;
120}
121
122static void vol_part_delete(vol_part_t *part)
123{
124 if (part == NULL)
125 return;
126
127 free(part->svc_name);
128 free(part);
129}
130
131static int vol_part_add_locked(service_id_t sid)
132{
133 vol_part_t *part;
134 bool empty;
135 vfs_fs_probe_info_t info;
136 int rc;
137
138 assert(fibril_mutex_is_locked(&vol_parts_lock));
139
140 /* Check for duplicates */
141 rc = vol_part_find_by_id(sid, &part);
142 if (rc == EOK)
143 return EEXIST;
144
145 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_add_locked()");
146 part = vol_part_new();
147 if (part == NULL)
148 return ENOMEM;
149
150 part->svc_id = sid;
151
152 rc = loc_service_get_name(sid, &part->svc_name);
153 if (rc != EOK) {
154 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting service name.");
155 goto error;
156 }
157
158 log_msg(LOG_DEFAULT, LVL_NOTE, "Probe partition %s", part->svc_name);
159 rc = vfs_fsprobe("mfs", sid, &info);
160 if (rc == EOK) {
161 part->pcnt = vpc_fs;
162 part->fstype = fs_minix;
163 } else {
164 log_msg(LOG_DEFAULT, LVL_NOTE, "Partition does not contain "
165 "a recognized file system.");
166
167 rc = volsrv_part_is_empty(sid, &empty);
168 if (rc != EOK) {
169 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed determining if "
170 "partition is empty.");
171 goto error;
172 }
173
174 part->pcnt = empty ? vpc_empty : vpc_unknown;
175 }
176
177 list_append(&part->lparts, &vol_parts);
178
179 log_msg(LOG_DEFAULT, LVL_NOTE, "Added partition %zu", part->svc_id);
180
181 return EOK;
182
183error:
184 vol_part_delete(part);
185 return rc;
186}
187
188int vol_part_add(service_id_t sid)
189{
190 int rc;
191
192 fibril_mutex_lock(&vol_parts_lock);
193 rc = vol_part_add_locked(sid);
194 fibril_mutex_unlock(&vol_parts_lock);
195
196 return rc;
197}
198
199static void vol_part_cat_change_cb(void)
200{
201 (void) vol_part_check_new();
202}
203
204int vol_part_init(void)
205{
206 return EOK;
207}
208
209int vol_part_discovery_start(void)
210{
211 int rc;
212
213 rc = loc_register_cat_change_cb(vol_part_cat_change_cb);
214 if (rc != EOK) {
215 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback "
216 "for partition discovery (%d).", rc);
217 return rc;
218 }
219
220 return vol_part_check_new();
221}
222
223/** Get list of partitions as array of service IDs. */
224int vol_part_get_ids(service_id_t *id_buf, size_t buf_size, size_t *act_size)
225{
226 size_t act_cnt;
227 size_t buf_cnt;
228
229 fibril_mutex_lock(&vol_parts_lock);
230
231 buf_cnt = buf_size / sizeof(service_id_t);
232
233 act_cnt = list_count(&vol_parts);
234 *act_size = act_cnt * sizeof(service_id_t);
235
236 if (buf_size % sizeof(service_id_t) != 0) {
237 fibril_mutex_unlock(&vol_parts_lock);
238 return EINVAL;
239 }
240
241 size_t pos = 0;
242 list_foreach(vol_parts, lparts, vol_part_t, part) {
243 if (pos < buf_cnt)
244 id_buf[pos] = part->svc_id;
245 pos++;
246 }
247
248 fibril_mutex_unlock(&vol_parts_lock);
249 return EOK;
250}
251
252int vol_part_find_by_id(service_id_t sid, vol_part_t **rpart)
253{
254 list_foreach(vol_parts, lparts, vol_part_t, part) {
255 if (part->svc_id == sid) {
256 *rpart = part;
257 /* XXX Add reference */
258 return EOK;
259 }
260 }
261
262 return ENOENT;
263}
264
265int vol_part_empty_part(vol_part_t *part)
266{
267 int rc;
268
269 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_part()");
270
271 rc = volsrv_part_empty(part->svc_id);
272 if (rc != EOK) {
273 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_part() - failed %d",
274 rc);
275 return rc;
276 }
277
278 part->pcnt = vpc_empty;
279 return EOK;
280}
281
282int vol_part_mkfs_part(vol_part_t *part, vol_fstype_t fstype)
283{
284 int rc;
285
286 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_part()");
287
288 rc = volsrv_part_mkfs(part->svc_id, fstype);
289 if (rc != EOK) {
290 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_part() - failed %d",
291 rc);
292 return rc;
293 }
294
295 part->pcnt = vpc_fs;
296 part->fstype = fstype;
297 return EOK;
298}
299
300int vol_part_get_info(vol_part_t *part, vol_part_info_t *pinfo)
301{
302 pinfo->pcnt = part->pcnt;
303 pinfo->fstype = part->fstype;
304 return EOK;
305}
306
307/** @}
308 */
Note: See TracBrowser for help on using the repository browser.