source: mainline/uspace/srv/volsrv/part.c@ 9eb1ff5

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

Fdisk should be able to set volume label for newly created partitions.

  • Property mode set to 100644
File size: 8.2 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
[9c2c7d2]145static int vol_part_probe(vol_part_t *part)
[372df8f]146{
[4b6635a7]147 bool empty;
[d2c8533]148 vfs_fs_probe_info_t info;
[395df52]149 struct fsname_type *fst;
[9c2c7d2]150 char *label;
[372df8f]151 int rc;
152
[d2c8533]153 log_msg(LOG_DEFAULT, LVL_NOTE, "Probe partition %s", part->svc_name);
[395df52]154
[9c2c7d2]155 assert(fibril_mutex_is_locked(&vol_parts_lock));
156
[395df52]157 fst = &fstab[0];
158 while (fst->name != NULL) {
[9c2c7d2]159 rc = vfs_fsprobe(fst->name, part->svc_id, &info);
[395df52]160 if (rc == EOK)
161 break;
162 ++fst;
163 }
164
165 if (fst->name != NULL) {
[9c96634]166 log_msg(LOG_DEFAULT, LVL_NOTE, "Found %s, label '%s'",
167 fst->name, info.label);
[9c2c7d2]168 label = str_dup(info.label);
169 if (label == NULL) {
170 rc = ENOMEM;
171 goto error;
172 }
173
[d2c8533]174 part->pcnt = vpc_fs;
[395df52]175 part->fstype = fst->fstype;
[9c2c7d2]176 part->label = label;
[d2c8533]177 } else {
178 log_msg(LOG_DEFAULT, LVL_NOTE, "Partition does not contain "
179 "a recognized file system.");
180
[9c2c7d2]181 rc = volsrv_part_is_empty(part->svc_id, &empty);
[d2c8533]182 if (rc != EOK) {
183 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed determining if "
184 "partition is empty.");
[9c2c7d2]185 rc = EIO;
[d2c8533]186 goto error;
187 }
188
[9c2c7d2]189 label = str_dup("");
190 if (label == NULL) {
191 rc = ENOMEM;
[d858a660]192 goto error;
[9c2c7d2]193 }
194
195 part->pcnt = empty ? vpc_empty : vpc_unknown;
196 part->label = label;
197 }
198
199 return EOK;
200
201error:
202 return rc;
203}
204
205static int vol_part_add_locked(service_id_t sid)
206{
207 vol_part_t *part;
208 int rc;
209
210 assert(fibril_mutex_is_locked(&vol_parts_lock));
211
212 /* Check for duplicates */
213 rc = vol_part_find_by_id(sid, &part);
214 if (rc == EOK)
215 return EEXIST;
216
217 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_add_locked()");
218 part = vol_part_new();
219 if (part == NULL)
220 return ENOMEM;
221
222 part->svc_id = sid;
223
224 rc = loc_service_get_name(sid, &part->svc_name);
225 if (rc != EOK) {
226 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting service name.");
227 goto error;
[4b6635a7]228 }
[372df8f]229
[9c2c7d2]230 rc = vol_part_probe(part);
231 if (rc != EOK)
232 goto error;
233
[372df8f]234 list_append(&part->lparts, &vol_parts);
235
[edebb4a1]236 log_msg(LOG_DEFAULT, LVL_NOTE, "Added partition %zu", part->svc_id);
237
[372df8f]238 return EOK;
239
240error:
241 vol_part_delete(part);
242 return rc;
243}
244
[edebb4a1]245int vol_part_add(service_id_t sid)
246{
247 int rc;
248
249 fibril_mutex_lock(&vol_parts_lock);
250 rc = vol_part_add_locked(sid);
251 fibril_mutex_unlock(&vol_parts_lock);
252
253 return rc;
254}
255
[372df8f]256static void vol_part_cat_change_cb(void)
257{
258 (void) vol_part_check_new();
259}
260
261int vol_part_init(void)
262{
263 return EOK;
264}
265
266int vol_part_discovery_start(void)
267{
268 int rc;
269
270 rc = loc_register_cat_change_cb(vol_part_cat_change_cb);
271 if (rc != EOK) {
272 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback "
273 "for partition discovery (%d).", rc);
274 return rc;
275 }
276
277 return vol_part_check_new();
278}
279
280/** Get list of partitions as array of service IDs. */
281int vol_part_get_ids(service_id_t *id_buf, size_t buf_size, size_t *act_size)
282{
283 size_t act_cnt;
284 size_t buf_cnt;
285
286 fibril_mutex_lock(&vol_parts_lock);
287
288 buf_cnt = buf_size / sizeof(service_id_t);
289
290 act_cnt = list_count(&vol_parts);
291 *act_size = act_cnt * sizeof(service_id_t);
292
293 if (buf_size % sizeof(service_id_t) != 0) {
294 fibril_mutex_unlock(&vol_parts_lock);
295 return EINVAL;
296 }
297
298 size_t pos = 0;
299 list_foreach(vol_parts, lparts, vol_part_t, part) {
300 if (pos < buf_cnt)
301 id_buf[pos] = part->svc_id;
302 pos++;
303 }
304
305 fibril_mutex_unlock(&vol_parts_lock);
306 return EOK;
307}
308
309int vol_part_find_by_id(service_id_t sid, vol_part_t **rpart)
310{
311 list_foreach(vol_parts, lparts, vol_part_t, part) {
312 if (part->svc_id == sid) {
313 *rpart = part;
314 /* XXX Add reference */
315 return EOK;
316 }
317 }
318
319 return ENOENT;
320}
321
322int vol_part_empty_part(vol_part_t *part)
323{
[ea0ff6b]324 int rc;
325
[55f8c6e7]326 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_part()");
[ea0ff6b]327
[44fe800]328 rc = volsrv_part_empty(part->svc_id);
[ea0ff6b]329 if (rc != EOK) {
[55f8c6e7]330 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_part() - failed %d",
[ea0ff6b]331 rc);
332 return rc;
333 }
[372df8f]334
[ea0ff6b]335 part->pcnt = vpc_empty;
[372df8f]336 return EOK;
337}
338
[9c2c7d2]339int vol_part_mkfs_part(vol_part_t *part, vol_fstype_t fstype,
340 const char *label)
[44fe800]341{
342 int rc;
343
[55f8c6e7]344 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_part()");
[44fe800]345
[9c2c7d2]346 fibril_mutex_lock(&vol_parts_lock);
347
348 rc = volsrv_part_mkfs(part->svc_id, fstype, label);
[44fe800]349 if (rc != EOK) {
[55f8c6e7]350 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_part() - failed %d",
[44fe800]351 rc);
[9c2c7d2]352 fibril_mutex_unlock(&vol_parts_lock);
[44fe800]353 return rc;
354 }
355
[9c2c7d2]356 /*
357 * Re-probe the partition to update information. This is needed since
358 * the FS can make conversions of the volume label (e.g. make it
359 * uppercase).
360 */
361 rc = vol_part_probe(part);
362 if (rc != EOK) {
363 fibril_mutex_unlock(&vol_parts_lock);
364 return rc;
365 }
366
367 fibril_mutex_unlock(&vol_parts_lock);
[44fe800]368 return EOK;
369}
370
[0ecfc62]371int vol_part_get_info(vol_part_t *part, vol_part_info_t *pinfo)
[372df8f]372{
[0ecfc62]373 pinfo->pcnt = part->pcnt;
374 pinfo->fstype = part->fstype;
[d858a660]375 str_cpy(pinfo->label, sizeof(pinfo->label), part->label);
[372df8f]376 return EOK;
377}
378
379/** @}
380 */
Note: See TracBrowser for help on using the repository browser.