source: mainline/uspace/srv/volsrv/part.c@ ca127f37

Last change on this file since ca127f37 was ca127f37, checked in by Jiri Svoboda <jiri@…>, 10 months ago

Persist volume configuration

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