source: mainline/uspace/srv/volsrv/part.c@ 23c8acd9

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

CDFS decoding of volume label.

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