source: mainline/uspace/srv/volsrv/volume.c@ 64ffd83

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

Configuring mount point for (newly created) paritions.

  • Property mode set to 100644
File size: 7.0 KB
Line 
1/*
2 * Copyright (c) 2018 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 Volume handling
34 * @brief
35 *
36 * Volumes are the file systems (or similar) contained in partitions.
37 * Each vol_volume_t can be considered the configuration entry
38 * for a volume. Each partition has an associated vol_volume_t.
39 *
40 * If there is any non-default configuration to be remembered for a
41 * volume, the vol_volume_t structure is kept around even after the partition
42 * is disassociated from it. Otherwise it is deleted once no longer
43 * referenced.
44 */
45
46#include <adt/list.h>
47#include <errno.h>
48#include <fibril_synch.h>
49#include <io/log.h>
50#include <stdbool.h>
51#include <stdlib.h>
52#include <str.h>
53
54#include "volume.h"
55#include "types/volume.h"
56
57static void vol_volume_delete(vol_volume_t *);
58static void vol_volume_add_locked(vol_volumes_t *, vol_volume_t *);
59static errno_t vol_volume_lookup_ref_locked(vol_volumes_t *, const char *,
60 vol_volume_t **);
61
62/** Allocate new volume structure.
63 *
64 * @return Pointer to new volume structure
65 */
66static vol_volume_t *vol_volume_new(void)
67{
68 vol_volume_t *volume = calloc(1, sizeof(vol_volume_t));
69
70 if (volume == NULL) {
71 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating volume "
72 "structure. Out of memory.");
73 return NULL;
74 }
75
76 volume->label = str_dup("");
77 volume->mountp = str_dup("");
78
79 if (volume->label == NULL || volume->mountp == NULL) {
80 vol_volume_delete(volume);
81 return NULL;
82 }
83
84 atomic_set(&volume->refcnt, 1);
85 link_initialize(&volume->lvolumes);
86 volume->volumes = NULL;
87
88 return volume;
89}
90
91/** Delete volume structure.
92 *
93 * @param volume Volume structure
94 */
95static void vol_volume_delete(vol_volume_t *volume)
96{
97 log_msg(LOG_DEFAULT, LVL_NOTE, "Freeing volume %p", volume);
98
99 free(volume->label);
100 free(volume->mountp);
101 free(volume);
102}
103
104/** Create list of volumes.
105 *
106 * @param rvolumes Place to store pointer to list of volumes.
107 * @return EOK on success, ENOMEM if out of memory
108 */
109errno_t vol_volumes_create(vol_volumes_t **rvolumes)
110{
111 vol_volumes_t *volumes;
112
113 volumes = calloc(1, sizeof(vol_volumes_t));
114 if (volumes == NULL)
115 return ENOMEM;
116
117 fibril_mutex_initialize(&volumes->lock);
118 list_initialize(&volumes->volumes);
119
120 *rvolumes = volumes;
121 return EOK;
122}
123
124/** Destroy list of volumes.
125 *
126 * @param volumes List of volumes or @c NULL
127 */
128void vol_volumes_destroy(vol_volumes_t *volumes)
129{
130 link_t *link;
131 vol_volume_t *volume;
132
133 if (volumes == NULL)
134 return;
135
136 link = list_first(&volumes->volumes);
137 while (link != NULL) {
138 volume = list_get_instance(link, vol_volume_t, lvolumes);
139
140 list_remove(&volume->lvolumes);
141 vol_volume_delete(volume);
142
143 link = list_first(&volumes->volumes);
144 }
145
146 free(volumes);
147}
148
149/** Add new volume structure to list of volumes.
150 *
151 * @param volumes List of volumes
152 * @param volume Volume structure
153 */
154static void vol_volume_add_locked(vol_volumes_t *volumes,
155 vol_volume_t *volume)
156{
157 assert(fibril_mutex_is_locked(&volumes->lock));
158 log_msg(LOG_DEFAULT, LVL_NOTE, "vol_volume_add_locked(%p)", volume);
159
160 volume->volumes = volumes;
161 list_append(&volume->lvolumes, &volumes->volumes);
162}
163
164/** Look up volume structure with locked volumes lock.
165 *
166 * If a matching existing volume is found, it is returned. Otherwise
167 * a new volume structure is created.
168 *
169 * @param volumes List of volumes
170 * @param label Volume label
171 * @param rvolume Place to store pointer to volume structure (existing or new)
172 *
173 * @return EOK on success, ENOMEM if out of memory
174 */
175static errno_t vol_volume_lookup_ref_locked(vol_volumes_t *volumes,
176 const char *label, vol_volume_t **rvolume)
177{
178 vol_volume_t *volume;
179
180 assert(fibril_mutex_is_locked(&volumes->lock));
181
182 list_foreach(volumes->volumes, lvolumes, vol_volume_t, volume) {
183 if (str_cmp(volume->label, label) == 0 &&
184 str_size(label) > 0) {
185 /* Add reference */
186 atomic_inc(&volume->refcnt);
187 *rvolume = volume;
188 return EOK;
189 }
190 }
191
192 /* No existing volume found. Create a new one. */
193 volume = vol_volume_new();
194 if (volume == NULL)
195 return ENOMEM;
196
197 volume->label = str_dup(label);
198 vol_volume_add_locked(volumes, volume);
199
200 *rvolume = volume;
201 return EOK;
202}
203
204/** Look up volume structure.
205 *
206 * If a matching existing volume is found, it is returned. Otherwise
207 * a new volume structure is created.
208 *
209 * @param volumes List of volumes
210 * @param label Volume label
211 * @param rvolume Place to store pointer to volume structure (existing or new)
212 *
213 * @return EOK on success, ENOMEM if out of memory
214 */
215errno_t vol_volume_lookup_ref(vol_volumes_t *volumes, const char *label,
216 vol_volume_t **rvolume)
217{
218 errno_t rc;
219
220 fibril_mutex_lock(&volumes->lock);
221 rc = vol_volume_lookup_ref_locked(volumes, label, rvolume);
222 fibril_mutex_unlock(&volumes->lock);
223
224 return rc;
225}
226
227/** Determine if volume has non-default settings that need to persist.
228 *
229 * @param volume Volume
230 * @return @c true iff volume has settings that need to persist
231 */
232static bool vol_volume_is_persist(vol_volume_t *volume)
233{
234 return str_size(volume->mountp) > 0;
235}
236
237/** Delete reference to volume.
238 *
239 * @param volume Volume
240 */
241void vol_volume_del_ref(vol_volume_t *volume)
242{
243 if (atomic_predec(&volume->refcnt) == 0) {
244 /* No more references. Check if volume is persistent. */
245 if (!vol_volume_is_persist(volume)) {
246 list_remove(&volume->lvolumes);
247 vol_volume_delete(volume);
248 }
249 }
250}
251
252/** Set volume mount point.
253 *
254 * @param volume Volume
255 * @param mountp Mount point
256 *
257 * @return EOK on success or error code
258 */
259errno_t vol_volume_set_mountp(vol_volume_t *volume, const char *mountp)
260{
261 char *mp;
262
263 mp = str_dup(mountp);
264 if (mp == NULL)
265 return ENOMEM;
266
267 free(volume->mountp);
268 volume->mountp = mp;
269
270 return EOK;
271}
272
273/** @}
274 */
Note: See TracBrowser for help on using the repository browser.