source: mainline/uspace/srv/volsrv/part.c@ 54593f3

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 54593f3 was 9e45a41, checked in by Jiri Svoboda <jiri@…>, 6 years ago

Make volume server less chatty

  • Property mode set to 100644
File size: 18.4 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
[e89a06a]37#include <adt/list.h>
[372df8f]38#include <errno.h>
39#include <fibril_synch.h>
40#include <io/log.h>
41#include <loc.h>
[e89a06a]42#include <stdbool.h>
[372df8f]43#include <stdlib.h>
44#include <str.h>
[e89a06a]45#include <str_error.h>
[d2c8533]46#include <vfs/vfs.h>
[64ffd83]47#include <vol.h>
[372df8f]48
[4b6635a7]49#include "empty.h"
[44fe800]50#include "mkfs.h"
[372df8f]51#include "part.h"
52#include "types/part.h"
[64ffd83]53#include "volume.h"
[372df8f]54
[e89a06a]55static errno_t vol_part_add_locked(vol_parts_t *, service_id_t);
[1a9174e]56static void vol_part_remove_locked(vol_part_t *);
[e89a06a]57static errno_t vol_part_find_by_id_ref_locked(vol_parts_t *, service_id_t,
58 vol_part_t **);
[372df8f]59
[395df52]60struct fsname_type {
61 const char *name;
62 vol_fstype_t fstype;
63};
64
65static struct fsname_type fstab[] = {
66 { "ext4fs", fs_ext4 },
67 { "cdfs", fs_cdfs },
68 { "exfat", fs_exfat },
69 { "fat", fs_fat },
70 { "mfs", fs_minix },
71 { NULL, 0 }
72};
73
[5f36841]74static const char *fstype_str(vol_fstype_t fstype)
75{
76 struct fsname_type *fst;
77
78 fst = &fstab[0];
79 while (fst->name != NULL) {
80 if (fst->fstype == fstype)
81 return fst->name;
82 ++fst;
83 }
84
85 assert(false);
86 return NULL;
87}
88
[1a9174e]89/** Check for new and removed partitions */
[e89a06a]90static errno_t vol_part_check_new(vol_parts_t *parts)
[372df8f]91{
92 bool already_known;
[1a9174e]93 bool still_exists;
[372df8f]94 category_id_t part_cat;
95 service_id_t *svcs;
96 size_t count, i;
[1a9174e]97 link_t *cur, *next;
98 vol_part_t *part;
[b7fd2a0]99 errno_t rc;
[372df8f]100
[e89a06a]101 fibril_mutex_lock(&parts->lock);
[372df8f]102
103 rc = loc_category_get_id("partition", &part_cat, IPC_FLAG_BLOCKING);
104 if (rc != EOK) {
105 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'partition'.");
[e89a06a]106 fibril_mutex_unlock(&parts->lock);
[372df8f]107 return ENOENT;
108 }
109
110 rc = loc_category_get_svcs(part_cat, &svcs, &count);
111 if (rc != EOK) {
112 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting list of partition "
113 "devices.");
[e89a06a]114 fibril_mutex_unlock(&parts->lock);
[372df8f]115 return EIO;
116 }
117
[1a9174e]118 /* Check for new partitions */
[372df8f]119 for (i = 0; i < count; i++) {
120 already_known = false;
121
[1a9174e]122 // XXX Make this faster
[e89a06a]123 list_foreach(parts->parts, lparts, vol_part_t, part) {
[372df8f]124 if (part->svc_id == svcs[i]) {
125 already_known = true;
126 break;
127 }
128 }
129
130 if (!already_known) {
[9e45a41]131 log_msg(LOG_DEFAULT, LVL_DEBUG, "Found partition '%lu'",
[372df8f]132 (unsigned long) svcs[i]);
[e89a06a]133 rc = vol_part_add_locked(parts, svcs[i]);
[372df8f]134 if (rc != EOK) {
135 log_msg(LOG_DEFAULT, LVL_ERROR, "Could not add "
136 "partition.");
137 }
138 }
139 }
140
[1a9174e]141 /* Check for removed partitions */
[e89a06a]142 cur = list_first(&parts->parts);
[1a9174e]143 while (cur != NULL) {
[e89a06a]144 next = list_next(cur, &parts->parts);
[1a9174e]145 part = list_get_instance(cur, vol_part_t, lparts);
146
147 still_exists = false;
148 // XXX Make this faster
149 for (i = 0; i < count; i++) {
150 if (part->svc_id == svcs[i]) {
151 still_exists = true;
152 break;
153 }
154 }
155
156 if (!still_exists) {
[9e45a41]157 log_msg(LOG_DEFAULT, LVL_DEBUG, "Partition '%zu' is gone",
[1a9174e]158 part->svc_id);
159 vol_part_remove_locked(part);
160 }
161
162 cur = next;
163 }
164
165 free(svcs);
166
[e89a06a]167 fibril_mutex_unlock(&parts->lock);
[372df8f]168 return EOK;
169}
170
171static vol_part_t *vol_part_new(void)
172{
173 vol_part_t *part = calloc(1, sizeof(vol_part_t));
174
175 if (part == NULL) {
176 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating partition "
177 "structure. Out of memory.");
178 return NULL;
179 }
180
[498ced1]181 refcount_init(&part->refcnt);
[372df8f]182 link_initialize(&part->lparts);
[e89a06a]183 part->parts = NULL;
[0ecfc62]184 part->pcnt = vpc_empty;
[372df8f]185
186 return part;
187}
188
189static void vol_part_delete(vol_part_t *part)
190{
[1a9174e]191 log_msg(LOG_DEFAULT, LVL_ERROR, "Freeing partition %p", part);
[372df8f]192 if (part == NULL)
193 return;
194
[64ffd83]195 if (part->volume != NULL)
196 vol_volume_del_ref(part->volume);
197
[db9c889]198 free(part->cur_mp);
[372df8f]199 free(part->svc_name);
200 free(part);
201}
202
[b7fd2a0]203static errno_t vol_part_probe(vol_part_t *part)
[372df8f]204{
[4b6635a7]205 bool empty;
[d2c8533]206 vfs_fs_probe_info_t info;
[395df52]207 struct fsname_type *fst;
[9c2c7d2]208 char *label;
[64ffd83]209 vol_volume_t *volume;
[b7fd2a0]210 errno_t rc;
[372df8f]211
[9e45a41]212 log_msg(LOG_DEFAULT, LVL_DEBUG, "Probe partition %s", part->svc_name);
[395df52]213
[e89a06a]214 assert(fibril_mutex_is_locked(&part->parts->lock));
[9c2c7d2]215
[395df52]216 fst = &fstab[0];
217 while (fst->name != NULL) {
[9c2c7d2]218 rc = vfs_fsprobe(fst->name, part->svc_id, &info);
[395df52]219 if (rc == EOK)
220 break;
221 ++fst;
222 }
223
224 if (fst->name != NULL) {
[9e45a41]225 log_msg(LOG_DEFAULT, LVL_DEBUG, "Found %s, label '%s'",
[9c96634]226 fst->name, info.label);
[9c2c7d2]227 label = str_dup(info.label);
228 if (label == NULL) {
229 rc = ENOMEM;
230 goto error;
231 }
232
[d2c8533]233 part->pcnt = vpc_fs;
[395df52]234 part->fstype = fst->fstype;
[9c2c7d2]235 part->label = label;
[d2c8533]236 } else {
237 log_msg(LOG_DEFAULT, LVL_NOTE, "Partition does not contain "
238 "a recognized file system.");
239
[9c2c7d2]240 rc = volsrv_part_is_empty(part->svc_id, &empty);
[d2c8533]241 if (rc != EOK) {
242 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed determining if "
243 "partition is empty.");
[9c2c7d2]244 rc = EIO;
[d2c8533]245 goto error;
246 }
247
[9c2c7d2]248 label = str_dup("");
249 if (label == NULL) {
250 rc = ENOMEM;
[d858a660]251 goto error;
[9c2c7d2]252 }
253
254 part->pcnt = empty ? vpc_empty : vpc_unknown;
255 part->label = label;
256 }
257
[64ffd83]258 /* Look up new or existing volume. */
259 rc = vol_volume_lookup_ref(part->parts->volumes, part->label, &volume);
260 if (rc != EOK)
261 goto error;
262
263 part->volume = volume;
[9c2c7d2]264 return EOK;
265
266error:
267 return rc;
268}
269
[da680b4b]270/** Determine if partition is allowed to be mounted by default.
271 *
272 * @param part Partition
273 * @return @c true iff partition is allowed to be mounted by default
274 */
275static bool vol_part_allow_mount_by_def(vol_part_t *part)
276{
277 /* CDFS is safe to mount (after all, it is read-only) */
278 if (part->pcnt == vpc_fs && part->fstype == fs_cdfs)
279 return true;
280
281 /* For other file systems disallow mounting from ATA hard drive */
282 if (str_str(part->svc_name, "\\ata-c") != NULL)
283 return false;
284
285 /* Allow otherwise (e.g. USB mass storage) */
286 return true;
287}
288
[64ffd83]289/** Determine the default mount point for a partition.
290 *
291 * @param part Partition
292 * @return Pointer to the constant string "Auto" or "None"
293 */
294static const char *vol_part_def_mountp(vol_part_t *part)
295{
296 return vol_part_allow_mount_by_def(part) ? "Auto" : "None";
297}
298
[b82985e]299/** Determine actual mount path to be used for a partition.
[64ffd83]300 *
301 * @param part Partition
[b82985e]302 * @param rpath Place to store pointer to newly allocated string or @c NULL
303 * if volume should not be mounted
304 * @param rauto Place to store boolean flag whether mount point is automatic
305 *
306 * @return EOK on success, ENOMEM if out of memory
[64ffd83]307 */
[b82985e]308static errno_t vol_part_determine_mount_path(vol_part_t *part, char **rpath,
309 bool *rauto)
[5f36841]310{
[64ffd83]311 const char *cfg_mp;
[5f36841]312 char *mp;
[64ffd83]313 bool mp_auto;
[b82985e]314 int err;
[5f36841]315
[64ffd83]316 /* Get configured mount point */
317 if (str_size(part->volume->mountp) > 0) {
318 cfg_mp = part->volume->mountp;
[9e45a41]319 log_msg(LOG_DEFAULT, LVL_DEBUG, "Configured mount point '%s'",
[64ffd83]320 cfg_mp);
321 } else {
322 cfg_mp = vol_part_def_mountp(part);
[9e45a41]323 log_msg(LOG_DEFAULT, LVL_DEBUG, "Default mount point '%s'",
[64ffd83]324 cfg_mp);
[5f36841]325 }
326
[64ffd83]327 if (str_cmp(cfg_mp, "Auto") == 0 || str_cmp(cfg_mp, "auto") == 0) {
[da680b4b]328
[64ffd83]329 if (str_size(part->label) < 1) {
330 /* Don't mount nameless volumes */
[b82985e]331 *rpath = NULL;
332 *rauto = false;
[64ffd83]333 return EOK;
334 }
[5f36841]335
[9e45a41]336 log_msg(LOG_DEFAULT, LVL_DEBUG, "Determine MP label='%s'", part->label);
[64ffd83]337 err = asprintf(&mp, "/vol/%s", part->label);
338 if (err < 0) {
339 log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory");
340 return ENOMEM;
341 }
342
[b82985e]343 mp_auto = true;
344 } else if (str_cmp(cfg_mp, "None") == 0 || str_cmp(cfg_mp, "none") == 0) {
345 mp = NULL;
346 mp_auto = false;
347 } else {
348 mp = str_dup(cfg_mp);
349 mp_auto = false;
350 }
351
352 *rpath = mp;
353 *rauto = mp_auto;
354 return EOK;
355}
356
357/** Mount partition.
358 *
359 * @param part Partition
360 */
361static errno_t vol_part_mount(vol_part_t *part)
362{
363 char *mp;
364 bool mp_auto;
365 errno_t rc;
366
367 rc = vol_part_determine_mount_path(part, &mp, &mp_auto);
368 if (rc != EOK) {
369 log_msg(LOG_DEFAULT, LVL_ERROR, "Error determining mount point.\n");
370 return rc;
371 }
372
373 if (mp == NULL) {
374 log_msg(LOG_DEFAULT, LVL_NOTE, "Not mounting volume.");
375 return EOK;
376 }
377
378 if (mp_auto) {
379 /* Create directory for automatic mount point */
[9e45a41]380 log_msg(LOG_DEFAULT, LVL_DEBUG, "Create mount point '%s'", mp);
[64ffd83]381 rc = vfs_link_path(mp, KIND_DIRECTORY, NULL);
382 if (rc != EOK) {
383 log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating mount point '%s'",
384 mp);
385 free(mp);
386 return EIO;
387 }
[5f36841]388 }
389
[9e45a41]390 log_msg(LOG_DEFAULT, LVL_DEBUG, "Call vfs_mount_path mp='%s' fstype='%s' svc_name='%s'",
[5f36841]391 mp, fstype_str(part->fstype), part->svc_name);
392 rc = vfs_mount_path(mp, fstype_str(part->fstype),
393 part->svc_name, "", 0, 0);
394 if (rc != EOK) {
[9e45a41]395 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed mounting %s at %s to %s",
396 fstype_str(part->fstype), part->svc_name, mp);
397 } else {
398 log_msg(LOG_DEFAULT, LVL_NOTE, "Mounted %s at %s to %s\n",
399 fstype_str(part->fstype), part->svc_name, mp);
[5f36841]400 }
401
[db9c889]402 part->cur_mp = mp;
[64ffd83]403 part->cur_mp_auto = mp_auto;
[db9c889]404
[5f36841]405 return rc;
406}
407
[e89a06a]408static errno_t vol_part_add_locked(vol_parts_t *parts, service_id_t sid)
[9c2c7d2]409{
410 vol_part_t *part;
[b7fd2a0]411 errno_t rc;
[9c2c7d2]412
[e89a06a]413 assert(fibril_mutex_is_locked(&parts->lock));
[9e45a41]414 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_add_locked(%zu)", sid);
[9c2c7d2]415
416 /* Check for duplicates */
[e89a06a]417 rc = vol_part_find_by_id_ref_locked(parts, sid, &part);
[1a9174e]418 if (rc == EOK) {
419 vol_part_del_ref(part);
[9c2c7d2]420 return EEXIST;
[1a9174e]421 }
[9c2c7d2]422
[9e45a41]423 log_msg(LOG_DEFAULT, LVL_DEBUG, "partition %zu is new", sid);
[5f36841]424
[9c2c7d2]425 part = vol_part_new();
426 if (part == NULL)
427 return ENOMEM;
428
429 part->svc_id = sid;
[e89a06a]430 part->parts = parts;
[9c2c7d2]431
432 rc = loc_service_get_name(sid, &part->svc_name);
433 if (rc != EOK) {
434 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting service name.");
435 goto error;
[4b6635a7]436 }
[372df8f]437
[9c2c7d2]438 rc = vol_part_probe(part);
439 if (rc != EOK)
440 goto error;
441
[5f36841]442 rc = vol_part_mount(part);
443 if (rc != EOK)
444 goto error;
445
[e89a06a]446 list_append(&part->lparts, &parts->parts);
[372df8f]447
[9e45a41]448 log_msg(LOG_DEFAULT, LVL_DEBUG, "Added partition %zu", part->svc_id);
[edebb4a1]449
[372df8f]450 return EOK;
451
452error:
453 vol_part_delete(part);
454 return rc;
455}
456
[1a9174e]457static void vol_part_remove_locked(vol_part_t *part)
458{
[e89a06a]459 assert(fibril_mutex_is_locked(&part->parts->lock));
[9e45a41]460 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_remove_locked(%zu)",
[e89a06a]461 part->svc_id);
[1a9174e]462
463 list_remove(&part->lparts);
464
[9e45a41]465 log_msg(LOG_DEFAULT, LVL_DEBUG, "Removed partition.");
[1a9174e]466 vol_part_del_ref(part);
467}
468
[64ffd83]469errno_t vol_part_add_part(vol_parts_t *parts, service_id_t sid)
[edebb4a1]470{
[b7fd2a0]471 errno_t rc;
[edebb4a1]472
[e89a06a]473 fibril_mutex_lock(&parts->lock);
474 rc = vol_part_add_locked(parts, sid);
475 fibril_mutex_unlock(&parts->lock);
[edebb4a1]476
477 return rc;
478}
479
[e89a06a]480static void vol_part_cat_change_cb(void *arg)
[372df8f]481{
[e89a06a]482 vol_parts_t *parts = (vol_parts_t *) arg;
483
484 (void) vol_part_check_new(parts);
[372df8f]485}
486
[64ffd83]487errno_t vol_parts_create(vol_volumes_t *volumes, vol_parts_t **rparts)
[372df8f]488{
[e89a06a]489 vol_parts_t *parts;
490
491 parts = calloc(1, sizeof(vol_parts_t));
492 if (parts == NULL)
493 return ENOMEM;
494
495 fibril_mutex_initialize(&parts->lock);
496 list_initialize(&parts->parts);
[64ffd83]497 parts->volumes = volumes;
[e89a06a]498
499 *rparts = parts;
[372df8f]500 return EOK;
501}
502
[e89a06a]503void vol_parts_destroy(vol_parts_t *parts)
504{
505 if (parts == NULL)
506 return;
507
508 assert(list_empty(&parts->parts));
509 free(parts);
510}
511
512errno_t vol_part_discovery_start(vol_parts_t *parts)
[372df8f]513{
[b7fd2a0]514 errno_t rc;
[372df8f]515
[e89a06a]516 rc = loc_register_cat_change_cb(vol_part_cat_change_cb, parts);
[372df8f]517 if (rc != EOK) {
518 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback "
[c1694b6b]519 "for partition discovery: %s.", str_error(rc));
[372df8f]520 return rc;
521 }
522
[e89a06a]523 return vol_part_check_new(parts);
[372df8f]524}
525
526/** Get list of partitions as array of service IDs. */
[e89a06a]527errno_t vol_part_get_ids(vol_parts_t *parts, service_id_t *id_buf,
528 size_t buf_size, size_t *act_size)
[372df8f]529{
530 size_t act_cnt;
531 size_t buf_cnt;
532
[e89a06a]533 fibril_mutex_lock(&parts->lock);
[372df8f]534
535 buf_cnt = buf_size / sizeof(service_id_t);
536
[e89a06a]537 act_cnt = list_count(&parts->parts);
[372df8f]538 *act_size = act_cnt * sizeof(service_id_t);
539
540 if (buf_size % sizeof(service_id_t) != 0) {
[e89a06a]541 fibril_mutex_unlock(&parts->lock);
[372df8f]542 return EINVAL;
543 }
544
545 size_t pos = 0;
[e89a06a]546 list_foreach(parts->parts, lparts, vol_part_t, part) {
[372df8f]547 if (pos < buf_cnt)
548 id_buf[pos] = part->svc_id;
549 pos++;
550 }
551
[e89a06a]552 fibril_mutex_unlock(&parts->lock);
[372df8f]553 return EOK;
554}
555
[e89a06a]556static errno_t vol_part_find_by_id_ref_locked(vol_parts_t *parts,
557 service_id_t sid, vol_part_t **rpart)
[372df8f]558{
[e89a06a]559 assert(fibril_mutex_is_locked(&parts->lock));
[1a9174e]560
[e89a06a]561 list_foreach(parts->parts, lparts, vol_part_t, part) {
[372df8f]562 if (part->svc_id == sid) {
[1a9174e]563 /* Add reference */
[498ced1]564 refcount_up(&part->refcnt);
[372df8f]565 *rpart = part;
566 return EOK;
567 }
568 }
569
570 return ENOENT;
571}
572
[e89a06a]573errno_t vol_part_find_by_id_ref(vol_parts_t *parts, service_id_t sid,
574 vol_part_t **rpart)
[1a9174e]575{
576 errno_t rc;
577
[e89a06a]578 fibril_mutex_lock(&parts->lock);
579 rc = vol_part_find_by_id_ref_locked(parts, sid, rpart);
580 fibril_mutex_unlock(&parts->lock);
[1a9174e]581
582 return rc;
583}
584
[b82985e]585/** Find partition by filesystem path.
586 *
587 * @param parts Partitions
588 * @param path Filesystem path
589 * @param rpart Place to store pointer to partition
590 * @return EOK on success, ENOENT if not found, ENOMEM if out of memory
591 */
592errno_t vol_part_find_by_path_ref(vol_parts_t *parts, const char *path,
593 vol_part_t **rpart)
594{
595 errno_t rc;
596 char *mpath;
597 bool mauto;
598
599 fibril_mutex_lock(&parts->lock);
600
601 list_foreach(parts->parts, lparts, vol_part_t, part) {
602 rc = vol_part_determine_mount_path(part, &mpath, &mauto);
603 if (rc != EOK) {
604 fibril_mutex_unlock(&parts->lock);
605 return ENOMEM;
606 }
607
608 if (mpath != NULL && str_cmp(mpath, path) == 0) {
609 /* Add reference */
610 refcount_up(&part->refcnt);
611 fibril_mutex_unlock(&parts->lock);
612 free(mpath);
613 *rpart = part;
614 return EOK;
615 }
616
617 if (mpath != NULL)
618 free(mpath);
619 }
620
621 fibril_mutex_unlock(&parts->lock);
622 return ENOENT;
623}
624
[1a9174e]625void vol_part_del_ref(vol_part_t *part)
626{
[498ced1]627 if (refcount_down(&part->refcnt))
[1a9174e]628 vol_part_delete(part);
629}
630
[db9c889]631errno_t vol_part_eject_part(vol_part_t *part)
632{
633 int rc;
634
635 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_eject_part()");
636
637 if (part->cur_mp == NULL) {
638 log_msg(LOG_DEFAULT, LVL_DEBUG, "Attempt to mount unmounted "
639 "partition.");
640 return EINVAL;
641 }
642
643 rc = vfs_unmount_path(part->cur_mp);
644 if (rc != EOK) {
645 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed unmounting partition "
646 "from %s", part->cur_mp);
647 return rc;
648 }
649
650 if (part->cur_mp_auto) {
651 rc = vfs_unlink_path(part->cur_mp);
652 if (rc != EOK) {
653 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed deleting "
654 "mount directory %s.", part->cur_mp);
655 }
656 }
657
658 free(part->cur_mp);
659 part->cur_mp = NULL;
660 part->cur_mp_auto = false;
661
662 return EOK;
663}
664
[b7fd2a0]665errno_t vol_part_empty_part(vol_part_t *part)
[372df8f]666{
[b7fd2a0]667 errno_t rc;
[ea0ff6b]668
[55f8c6e7]669 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_part()");
[ea0ff6b]670
[44fe800]671 rc = volsrv_part_empty(part->svc_id);
[ea0ff6b]672 if (rc != EOK) {
[dd8ab1c]673 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_part() - failed %s",
674 str_error(rc));
[ea0ff6b]675 return rc;
676 }
[372df8f]677
[ea0ff6b]678 part->pcnt = vpc_empty;
[372df8f]679 return EOK;
680}
681
[f0f8787]682/** Insert volume.
683 *
684 * Re-mount the volume in the partition, if applicable.
685 *
686 * @param part Partition
687 */
688errno_t vol_part_insert_part(vol_part_t *part)
689{
690 int rc;
691
692 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_insert_part()");
693
694 fibril_mutex_lock(&part->parts->lock);
695
696 if (part->cur_mp != NULL) {
697 fibril_mutex_unlock(&part->parts->lock);
698 return EOK;
699 }
700
701 rc = vol_part_probe(part);
702 if (rc != EOK)
703 goto error;
704
705 rc = vol_part_mount(part);
706 if (rc != EOK)
707 goto error;
708
709 fibril_mutex_unlock(&part->parts->lock);
710
711 return EOK;
712error:
713 return rc;
714}
715
[64ffd83]716/** Set mount point.
717 *
718 * Verify and set a mount point. If the value of the mount point is
719 * the same as the default value, we will actually unset the mount point
720 * value (therefore effectively changing it to use the default).
721 *
722 * @return EOK on success, error code otherwise
723 */
724static errno_t vol_part_mountp_set(vol_part_t *part, const char *mountp)
725{
726 errno_t rc;
727 const char *def_mp;
728 const char *mp;
729
730 rc = vol_mountp_validate(mountp);
731 if (rc != EOK)
732 return rc;
733
734 def_mp = vol_part_def_mountp(part);
735
736 /* If the value is the same as default, set to empty string. */
737 if (str_cmp(def_mp, mountp) == 0)
738 mp = "";
739 else
740 mp = mountp;
741
742 rc = vol_volume_set_mountp(part->volume, mp);
743 if (rc != EOK)
744 return rc;
745
746 return EOK;
747}
748
[b7fd2a0]749errno_t vol_part_mkfs_part(vol_part_t *part, vol_fstype_t fstype,
[64ffd83]750 const char *label, const char *mountp)
[44fe800]751{
[b7fd2a0]752 errno_t rc;
[44fe800]753
[55f8c6e7]754 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_part()");
[44fe800]755
[e89a06a]756 fibril_mutex_lock(&part->parts->lock);
[9c2c7d2]757
758 rc = volsrv_part_mkfs(part->svc_id, fstype, label);
[44fe800]759 if (rc != EOK) {
[dd8ab1c]760 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_part() - failed %s",
761 str_error(rc));
[e89a06a]762 fibril_mutex_unlock(&part->parts->lock);
[44fe800]763 return rc;
764 }
765
[9c2c7d2]766 /*
767 * Re-probe the partition to update information. This is needed since
768 * the FS can make conversions of the volume label (e.g. make it
769 * uppercase).
770 */
771 rc = vol_part_probe(part);
772 if (rc != EOK) {
[e89a06a]773 fibril_mutex_unlock(&part->parts->lock);
[9c2c7d2]774 return rc;
775 }
776
[64ffd83]777 rc = vol_part_mountp_set(part, mountp);
778 if (rc != EOK) {
779 fibril_mutex_unlock(&part->parts->lock);
780 return rc;
781 }
782
[5f36841]783 rc = vol_part_mount(part);
784 if (rc != EOK) {
[e89a06a]785 fibril_mutex_unlock(&part->parts->lock);
[5f36841]786 return rc;
787 }
788
[e89a06a]789 fibril_mutex_unlock(&part->parts->lock);
[44fe800]790 return EOK;
791}
792
[2d78d88]793/** Set partition mount point.
794 *
795 * Set the partition mount point, (un-, re-)mounting the partition as necessary.
796 *
797 * @param part Partition
798 * @param mountp
799 *
800 * @return EOK on success or error code
801 */
802errno_t vol_part_set_mountp_part(vol_part_t *part, const char *mountp)
803{
804 errno_t rc;
805
806 if (part->cur_mp != NULL) {
807 rc = vol_part_eject_part(part);
808 if (rc != EOK)
809 return rc;
810 }
811
812 rc = vol_part_mountp_set(part, mountp);
813 if (rc != EOK)
814 return rc;
815
816 rc = vol_part_mount(part);
817 if (rc != EOK)
818 return rc;
819
820 return EOK;
821}
822
[b7fd2a0]823errno_t vol_part_get_info(vol_part_t *part, vol_part_info_t *pinfo)
[372df8f]824{
[72c72d4]825 memset(pinfo, 0, sizeof(*pinfo));
826
[0ecfc62]827 pinfo->pcnt = part->pcnt;
828 pinfo->fstype = part->fstype;
[d858a660]829 str_cpy(pinfo->label, sizeof(pinfo->label), part->label);
[72c72d4]830 if (part->cur_mp != NULL)
831 str_cpy(pinfo->cur_mp, sizeof(pinfo->cur_mp), part->cur_mp);
[db9c889]832 pinfo->cur_mp_auto = part->cur_mp_auto;
[372df8f]833 return EOK;
834}
835
836/** @}
837 */
Note: See TracBrowser for help on using the repository browser.