source: mainline/uspace/srv/volsrv/part.c@ 33c08929

Last change on this file since 33c08929 was 4285f384, checked in by Jiri Svoboda <jiri@…>, 7 months ago

Allow physically ejecting CD-ROM using vol eject -s

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