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

Last change on this file since a7d1992c was da154e14, checked in by Sebastian Huber <sebastian.huber@…>, on 05/14/12 at 14:55:41

Filesystem: Move operations to mount table entry

The scope of the file system operations is the file system instance.
The scope of the file system node handlers is the file location. The
benefit of moving the operations to the mount table entry is a size
reduction of the file location (rtems_filesystem_location_info_t). The
code size is slightly increased due to additional load instructions.

Restructure rtems_filesystem_mount_table_entry_t to improve cache
efficiency.

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