source: rtems/cpukit/libcsupport/src/sup_fs_location.c @ 80cf60e

5
Last change on this file since 80cf60e was 80cf60e, checked in by Sebastian Huber <sebastian.huber@…>, on 04/15/20 at 07:48:32

Canonicalize config.h include

Use the following variant which was already used by most source files:

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

  • Property mode set to 100644
File size: 6.7 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief RTEMS File System Location Support
5 *  @ingroup LibIOInternal
6 */
7
8/*
9 * Copyright (c) 2012-2015 embedded brains GmbH.  All rights reserved.
10 *
11 *  embedded brains GmbH
12 *  Dornierstr. 4
13 *  82178 Puchheim
14 *  Germany
15 *  <rtems@embedded-brains.de>
16 *
17 * The license and distribution terms for this file may be
18 * found in the file LICENSE in this distribution or at
19 * http://www.rtems.org/license/LICENSE.
20 */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#include <stdlib.h>
27
28#include <rtems/libio_.h>
29#include <rtems/score/threaddispatch.h>
30
31rtems_interrupt_lock rtems_filesystem_mt_entry_lock_control =
32  RTEMS_INTERRUPT_LOCK_INITIALIZER("mount table entry");
33
34RTEMS_INTERRUPT_LOCK_DEFINE(
35  static,
36  deferred_release_lock,
37  "Filesystem Deferred Release"
38)
39
40static rtems_filesystem_global_location_t *deferred_released_global_locations;
41
42rtems_filesystem_location_info_t *rtems_filesystem_location_copy(
43  rtems_filesystem_location_info_t *dst,
44  const rtems_filesystem_location_info_t *src
45)
46{
47  dst->node_access = src->node_access;
48  dst->node_access_2 = src->node_access_2;
49  dst->handlers = src->handlers;
50  dst->mt_entry = src->mt_entry;
51  rtems_chain_initialize_node(&dst->mt_entry_node);
52  rtems_filesystem_location_add_to_mt_entry(dst);
53
54  return dst;
55}
56
57void rtems_filesystem_location_detach(
58  rtems_filesystem_location_info_t *detach
59)
60{
61  rtems_filesystem_location_free(detach);
62  rtems_filesystem_location_initialize_to_null(detach);
63}
64
65void rtems_filesystem_location_copy_and_detach(
66  rtems_filesystem_location_info_t *copy,
67  rtems_filesystem_location_info_t *detach
68)
69{
70  rtems_filesystem_location_copy(copy, detach);
71  rtems_filesystem_location_remove_from_mt_entry(detach);
72  rtems_filesystem_location_initialize_to_null(detach);
73}
74
75rtems_filesystem_global_location_t *rtems_filesystem_location_transform_to_global(
76  rtems_filesystem_location_info_t *loc
77)
78{
79  rtems_filesystem_global_location_t *global_loc = malloc(sizeof(*global_loc));
80
81  if (global_loc != NULL) {
82    global_loc->reference_count = 1;
83    global_loc->deferred_released_next = NULL;
84    global_loc->deferred_released_count = 0;
85    rtems_filesystem_location_copy(&global_loc->location, loc);
86    rtems_filesystem_location_remove_from_mt_entry(loc);
87  } else {
88    rtems_filesystem_location_free(loc);
89    global_loc = rtems_filesystem_global_location_obtain_null();
90    errno = ENOMEM;
91  }
92
93  return global_loc;
94}
95
96void rtems_filesystem_global_location_assign(
97  rtems_filesystem_global_location_t **lhs_global_loc_ptr,
98  rtems_filesystem_global_location_t *rhs_global_loc
99)
100{
101  rtems_filesystem_mt_entry_declare_lock_context(lock_context);
102  rtems_filesystem_global_location_t *lhs_global_loc;
103
104  rtems_filesystem_mt_entry_lock(lock_context);
105  lhs_global_loc = *lhs_global_loc_ptr;
106  *lhs_global_loc_ptr = rhs_global_loc;
107  rtems_filesystem_mt_entry_unlock(lock_context);
108
109  rtems_filesystem_global_location_release(lhs_global_loc, true);
110}
111
112static void release_with_count(
113  rtems_filesystem_global_location_t *global_loc,
114  int count
115)
116{
117  rtems_filesystem_mount_table_entry_t *mt_entry =
118    global_loc->location.mt_entry;
119  rtems_filesystem_mt_entry_declare_lock_context(lock_context);
120  bool do_free;
121  bool do_unmount;
122
123  rtems_filesystem_mt_entry_lock(lock_context);
124  global_loc->reference_count -= count;
125  do_free = global_loc->reference_count == 0;
126  do_unmount = rtems_filesystem_is_ready_for_unmount(mt_entry);
127  rtems_filesystem_mt_entry_unlock(lock_context);
128
129  if (do_free) {
130    rtems_filesystem_location_free(&global_loc->location);
131    free(global_loc);
132  }
133
134  if (do_unmount) {
135    rtems_filesystem_do_unmount(mt_entry);
136  }
137}
138
139static void deferred_release(void)
140{
141  rtems_filesystem_global_location_t *current = NULL;
142
143  do {
144    rtems_interrupt_lock_context lock_context;
145    int count = 0;
146
147    rtems_interrupt_lock_acquire(&deferred_release_lock, &lock_context);
148    current = deferred_released_global_locations;
149    if (current != NULL) {
150      deferred_released_global_locations = current->deferred_released_next;
151      count = current->deferred_released_count;
152      current->deferred_released_next = NULL;
153      current->deferred_released_count = 0;
154    }
155    rtems_interrupt_lock_release(&deferred_release_lock, &lock_context);
156
157    if (current != NULL) {
158      release_with_count(current, count);
159    }
160  } while (current != NULL);
161}
162
163rtems_filesystem_global_location_t *rtems_filesystem_global_location_obtain(
164  rtems_filesystem_global_location_t *const *global_loc_ptr
165)
166{
167  rtems_filesystem_mt_entry_declare_lock_context(lock_context);
168  rtems_filesystem_global_location_t *global_loc;
169
170  if (deferred_released_global_locations != NULL) {
171    deferred_release();
172  }
173
174  rtems_filesystem_mt_entry_lock(lock_context);
175  global_loc = *global_loc_ptr;
176  if (global_loc == NULL || !global_loc->location.mt_entry->mounted) {
177    global_loc = &rtems_filesystem_global_location_null;
178    errno = ENXIO;
179  }
180  ++global_loc->reference_count;
181  rtems_filesystem_mt_entry_unlock(lock_context);
182
183  return global_loc;
184}
185
186void rtems_filesystem_global_location_release(
187  rtems_filesystem_global_location_t *global_loc,
188  bool deferred
189)
190{
191  if (!deferred) {
192    release_with_count(global_loc, 1);
193  } else {
194    rtems_interrupt_lock_context lock_context;
195
196    rtems_interrupt_lock_acquire(&deferred_release_lock, &lock_context);
197
198    if (global_loc->deferred_released_count == 0) {
199      rtems_filesystem_global_location_t *head =
200        deferred_released_global_locations;
201
202      global_loc->deferred_released_count = 1;
203      global_loc->deferred_released_next = head;
204      deferred_released_global_locations = global_loc;
205    } else {
206      ++global_loc->deferred_released_count;
207    }
208
209    rtems_interrupt_lock_release(&deferred_release_lock, &lock_context);
210  }
211}
212
213void rtems_filesystem_location_remove_from_mt_entry(
214  rtems_filesystem_location_info_t *loc
215)
216{
217  rtems_filesystem_mt_entry_declare_lock_context(lock_context);
218  bool do_unmount;
219
220  rtems_filesystem_mt_entry_lock(lock_context);
221  rtems_chain_extract_unprotected(&loc->mt_entry_node);
222  do_unmount = rtems_filesystem_is_ready_for_unmount(loc->mt_entry);
223  rtems_filesystem_mt_entry_unlock(lock_context);
224
225  if (do_unmount) {
226    rtems_filesystem_do_unmount(loc->mt_entry);
227  }
228}
229
230void rtems_filesystem_do_unmount(
231  rtems_filesystem_mount_table_entry_t *mt_entry
232)
233{
234  rtems_filesystem_mt_lock();
235  rtems_chain_extract_unprotected(&mt_entry->mt_node);
236  rtems_filesystem_mt_unlock();
237  rtems_filesystem_global_location_release(mt_entry->mt_point_node, false);
238  (*mt_entry->ops->fsunmount_me_h)(mt_entry);
239
240  if (mt_entry->unmount_task != 0) {
241    rtems_status_code sc =
242      rtems_event_transient_send(mt_entry->unmount_task);
243    if (sc != RTEMS_SUCCESSFUL) {
244      rtems_fatal_error_occurred(0xdeadbeef);
245    }
246  }
247
248  free(mt_entry);
249}
Note: See TracBrowser for help on using the repository browser.