source: rtems/cpukit/libcsupport/src/sup_fs_location.c @ cefc9aea

4.115
Last change on this file since cefc9aea was cefc9aea, checked in by Alex Ivanov <alexivanov97@…>, on 12/15/12 at 12:23:36

libcsupport: Doxygen Enhancement Task #8

http://www.google-melange.com/gci/task/view/google/gci2012/7996208

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