File indexing completed on 2025-05-11 08:24:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #ifdef HAVE_CONFIG_H
0036 #include "config.h"
0037 #endif
0038
0039 #include <stdlib.h>
0040
0041 #include <rtems/libio_.h>
0042
0043 rtems_interrupt_lock rtems_filesystem_mt_entry_lock_control =
0044 RTEMS_INTERRUPT_LOCK_INITIALIZER("mount table entry");
0045
0046 RTEMS_INTERRUPT_LOCK_DEFINE(
0047 static,
0048 deferred_release_lock,
0049 "Filesystem Deferred Release"
0050 )
0051
0052 static rtems_filesystem_global_location_t *deferred_released_global_locations;
0053
0054 rtems_filesystem_location_info_t *rtems_filesystem_location_copy(
0055 rtems_filesystem_location_info_t *dst,
0056 const rtems_filesystem_location_info_t *src
0057 )
0058 {
0059 dst->node_access = src->node_access;
0060 dst->node_access_2 = src->node_access_2;
0061 dst->handlers = src->handlers;
0062 dst->mt_entry = src->mt_entry;
0063 rtems_chain_initialize_node(&dst->mt_entry_node);
0064 rtems_filesystem_location_add_to_mt_entry(dst);
0065
0066 return dst;
0067 }
0068
0069 void rtems_filesystem_location_detach(
0070 rtems_filesystem_location_info_t *detach
0071 )
0072 {
0073 rtems_filesystem_location_free(detach);
0074 rtems_filesystem_location_initialize_to_null(detach);
0075 }
0076
0077 void rtems_filesystem_location_copy_and_detach(
0078 rtems_filesystem_location_info_t *copy,
0079 rtems_filesystem_location_info_t *detach
0080 )
0081 {
0082 rtems_filesystem_location_copy(copy, detach);
0083 rtems_filesystem_location_remove_from_mt_entry(detach);
0084 rtems_filesystem_location_initialize_to_null(detach);
0085 }
0086
0087 rtems_filesystem_global_location_t *rtems_filesystem_location_transform_to_global(
0088 rtems_filesystem_location_info_t *loc
0089 )
0090 {
0091 rtems_filesystem_global_location_t *global_loc = malloc(sizeof(*global_loc));
0092
0093 if (global_loc != NULL) {
0094 global_loc->reference_count = 1;
0095 global_loc->deferred_released_next = NULL;
0096 global_loc->deferred_released_count = 0;
0097 rtems_filesystem_location_copy(&global_loc->location, loc);
0098 rtems_filesystem_location_remove_from_mt_entry(loc);
0099 } else {
0100 rtems_filesystem_location_free(loc);
0101 global_loc = rtems_filesystem_global_location_obtain_null();
0102 errno = ENOMEM;
0103 }
0104
0105 return global_loc;
0106 }
0107
0108 void rtems_filesystem_global_location_assign(
0109 rtems_filesystem_global_location_t **lhs_global_loc_ptr,
0110 rtems_filesystem_global_location_t *rhs_global_loc
0111 )
0112 {
0113 rtems_filesystem_mt_entry_declare_lock_context(lock_context);
0114 rtems_filesystem_global_location_t *lhs_global_loc;
0115
0116 rtems_filesystem_mt_entry_lock(lock_context);
0117 lhs_global_loc = *lhs_global_loc_ptr;
0118 *lhs_global_loc_ptr = rhs_global_loc;
0119 rtems_filesystem_mt_entry_unlock(lock_context);
0120
0121 rtems_filesystem_global_location_release(lhs_global_loc, true);
0122 }
0123
0124 static void release_with_count(
0125 rtems_filesystem_global_location_t *global_loc,
0126 int count
0127 )
0128 {
0129 rtems_filesystem_mount_table_entry_t *mt_entry =
0130 global_loc->location.mt_entry;
0131 rtems_filesystem_mt_entry_declare_lock_context(lock_context);
0132 bool do_free;
0133 bool do_unmount;
0134
0135 rtems_filesystem_mt_entry_lock(lock_context);
0136 global_loc->reference_count -= count;
0137 do_free = global_loc->reference_count == 0;
0138 do_unmount = rtems_filesystem_is_ready_for_unmount(mt_entry);
0139 rtems_filesystem_mt_entry_unlock(lock_context);
0140
0141 if (do_free) {
0142 rtems_filesystem_location_free(&global_loc->location);
0143 free(global_loc);
0144 }
0145
0146 if (do_unmount) {
0147 rtems_filesystem_do_unmount(mt_entry);
0148 }
0149 }
0150
0151 static void deferred_release(void)
0152 {
0153 rtems_filesystem_global_location_t *current = NULL;
0154
0155 do {
0156 rtems_interrupt_lock_context lock_context;
0157 int count = 0;
0158
0159 rtems_interrupt_lock_acquire(&deferred_release_lock, &lock_context);
0160 current = deferred_released_global_locations;
0161 if (current != NULL) {
0162 deferred_released_global_locations = current->deferred_released_next;
0163 count = current->deferred_released_count;
0164 current->deferred_released_next = NULL;
0165 current->deferred_released_count = 0;
0166 }
0167 rtems_interrupt_lock_release(&deferred_release_lock, &lock_context);
0168
0169 if (current != NULL) {
0170 release_with_count(current, count);
0171 }
0172 } while (current != NULL);
0173 }
0174
0175 rtems_filesystem_global_location_t *rtems_filesystem_global_location_obtain(
0176 rtems_filesystem_global_location_t *const *global_loc_ptr
0177 )
0178 {
0179 rtems_filesystem_mt_entry_declare_lock_context(lock_context);
0180 rtems_filesystem_global_location_t *global_loc;
0181
0182 if (deferred_released_global_locations != NULL) {
0183 deferred_release();
0184 }
0185
0186 rtems_filesystem_mt_entry_lock(lock_context);
0187 global_loc = *global_loc_ptr;
0188 if (global_loc == NULL || !global_loc->location.mt_entry->mounted) {
0189 global_loc = &rtems_filesystem_global_location_null;
0190 errno = ENXIO;
0191 }
0192 ++global_loc->reference_count;
0193 rtems_filesystem_mt_entry_unlock(lock_context);
0194
0195 return global_loc;
0196 }
0197
0198 void rtems_filesystem_global_location_release(
0199 rtems_filesystem_global_location_t *global_loc,
0200 bool deferred
0201 )
0202 {
0203 if (!deferred) {
0204 release_with_count(global_loc, 1);
0205 } else {
0206 rtems_interrupt_lock_context lock_context;
0207
0208 rtems_interrupt_lock_acquire(&deferred_release_lock, &lock_context);
0209
0210 if (global_loc->deferred_released_count == 0) {
0211 rtems_filesystem_global_location_t *head =
0212 deferred_released_global_locations;
0213
0214 global_loc->deferred_released_count = 1;
0215 global_loc->deferred_released_next = head;
0216 deferred_released_global_locations = global_loc;
0217 } else {
0218 ++global_loc->deferred_released_count;
0219 }
0220
0221 rtems_interrupt_lock_release(&deferred_release_lock, &lock_context);
0222 }
0223 }
0224
0225 void rtems_filesystem_location_remove_from_mt_entry(
0226 rtems_filesystem_location_info_t *loc
0227 )
0228 {
0229 rtems_filesystem_mt_entry_declare_lock_context(lock_context);
0230 bool do_unmount;
0231
0232 rtems_filesystem_mt_entry_lock(lock_context);
0233 rtems_chain_extract_unprotected(&loc->mt_entry_node);
0234 do_unmount = rtems_filesystem_is_ready_for_unmount(loc->mt_entry);
0235 rtems_filesystem_mt_entry_unlock(lock_context);
0236
0237 if (do_unmount) {
0238 rtems_filesystem_do_unmount(loc->mt_entry);
0239 }
0240 }
0241
0242 void rtems_filesystem_do_unmount(
0243 rtems_filesystem_mount_table_entry_t *mt_entry
0244 )
0245 {
0246 rtems_filesystem_mt_lock();
0247 rtems_chain_extract_unprotected(&mt_entry->mt_node);
0248 rtems_filesystem_mt_unlock();
0249 rtems_filesystem_global_location_release(mt_entry->mt_point_node, false);
0250 (*mt_entry->ops->fsunmount_me_h)(mt_entry);
0251
0252 if (mt_entry->unmount_task != 0) {
0253 rtems_status_code sc =
0254 rtems_event_transient_send(mt_entry->unmount_task);
0255 if (sc != RTEMS_SUCCESSFUL) {
0256 rtems_fatal_error_occurred(0xdeadbeef);
0257 }
0258 }
0259
0260 free(mt_entry);
0261 }