source: mainline/uspace/srv/volsrv/part.c@ 8d2dd7f2

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

Probing for ExFAT, Ext4 and CDFS.

  • 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) {
184 log_msg(LOG_DEFAULT, LVL_NOTE, "Found %s", fst->name);
[d2c8533]185 part->pcnt = vpc_fs;
[395df52]186 part->fstype = fst->fstype;
[d2c8533]187 } else {
188 log_msg(LOG_DEFAULT, LVL_NOTE, "Partition does not contain "
189 "a recognized file system.");
190
191 rc = volsrv_part_is_empty(sid, &empty);
192 if (rc != EOK) {
193 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed determining if "
194 "partition is empty.");
195 goto error;
196 }
197
198 part->pcnt = empty ? vpc_empty : vpc_unknown;
[4b6635a7]199 }
[372df8f]200
201 list_append(&part->lparts, &vol_parts);
202
[edebb4a1]203 log_msg(LOG_DEFAULT, LVL_NOTE, "Added partition %zu", part->svc_id);
204
[372df8f]205 return EOK;
206
207error:
208 vol_part_delete(part);
209 return rc;
210}
211
[edebb4a1]212int vol_part_add(service_id_t sid)
213{
214 int rc;
215
216 fibril_mutex_lock(&vol_parts_lock);
217 rc = vol_part_add_locked(sid);
218 fibril_mutex_unlock(&vol_parts_lock);
219
220 return rc;
221}
222
[372df8f]223static void vol_part_cat_change_cb(void)
224{
225 (void) vol_part_check_new();
226}
227
228int vol_part_init(void)
229{
230 return EOK;
231}
232
233int vol_part_discovery_start(void)
234{
235 int rc;
236
237 rc = loc_register_cat_change_cb(vol_part_cat_change_cb);
238 if (rc != EOK) {
239 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback "
240 "for partition discovery (%d).", rc);
241 return rc;
242 }
243
244 return vol_part_check_new();
245}
246
247/** Get list of partitions as array of service IDs. */
248int vol_part_get_ids(service_id_t *id_buf, size_t buf_size, size_t *act_size)
249{
250 size_t act_cnt;
251 size_t buf_cnt;
252
253 fibril_mutex_lock(&vol_parts_lock);
254
255 buf_cnt = buf_size / sizeof(service_id_t);
256
257 act_cnt = list_count(&vol_parts);
258 *act_size = act_cnt * sizeof(service_id_t);
259
260 if (buf_size % sizeof(service_id_t) != 0) {
261 fibril_mutex_unlock(&vol_parts_lock);
262 return EINVAL;
263 }
264
265 size_t pos = 0;
266 list_foreach(vol_parts, lparts, vol_part_t, part) {
267 if (pos < buf_cnt)
268 id_buf[pos] = part->svc_id;
269 pos++;
270 }
271
272 fibril_mutex_unlock(&vol_parts_lock);
273 return EOK;
274}
275
276int vol_part_find_by_id(service_id_t sid, vol_part_t **rpart)
277{
278 list_foreach(vol_parts, lparts, vol_part_t, part) {
279 if (part->svc_id == sid) {
280 *rpart = part;
281 /* XXX Add reference */
282 return EOK;
283 }
284 }
285
286 return ENOENT;
287}
288
289int vol_part_empty_part(vol_part_t *part)
290{
[ea0ff6b]291 int rc;
292
[55f8c6e7]293 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_part()");
[ea0ff6b]294
[44fe800]295 rc = volsrv_part_empty(part->svc_id);
[ea0ff6b]296 if (rc != EOK) {
[55f8c6e7]297 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_part() - failed %d",
[ea0ff6b]298 rc);
299 return rc;
300 }
[372df8f]301
[ea0ff6b]302 part->pcnt = vpc_empty;
[372df8f]303 return EOK;
304}
305
[44fe800]306int vol_part_mkfs_part(vol_part_t *part, vol_fstype_t fstype)
307{
308 int rc;
309
[55f8c6e7]310 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_part()");
[44fe800]311
312 rc = volsrv_part_mkfs(part->svc_id, fstype);
313 if (rc != EOK) {
[55f8c6e7]314 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_part() - failed %d",
[44fe800]315 rc);
316 return rc;
317 }
318
319 part->pcnt = vpc_fs;
320 part->fstype = fstype;
321 return EOK;
322}
323
[0ecfc62]324int vol_part_get_info(vol_part_t *part, vol_part_info_t *pinfo)
[372df8f]325{
[0ecfc62]326 pinfo->pcnt = part->pcnt;
327 pinfo->fstype = part->fstype;
[372df8f]328 return EOK;
329}
330
331/** @}
332 */
Note: See TracBrowser for help on using the repository browser.