File indexing completed on 2025-05-11 08:24:18
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
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039
0040 #include <sys/stat.h>
0041 #include <inttypes.h>
0042 #include <errno.h>
0043 #include <fcntl.h>
0044 #include <string.h>
0045
0046 #include <rtems/rfs/rtems-rfs-buffer.h>
0047 #include <rtems/rfs/rtems-rfs-file-system.h>
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 static rtems_rfs_buffer*
0058 rtems_rfs_scan_chain (rtems_chain_control* chain,
0059 uint32_t* count,
0060 rtems_rfs_buffer_block block)
0061 {
0062 rtems_rfs_buffer* buffer;
0063 rtems_chain_node* node;
0064
0065 node = rtems_chain_last (chain);
0066
0067 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
0068 printf ("rtems-rfs: buffer-scan: count=%" PRIu32 ", block=%" PRIu32 ": ", *count, block);
0069
0070 while (!rtems_chain_is_head (chain, node))
0071 {
0072 buffer = (rtems_rfs_buffer*) node;
0073
0074 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
0075 printf ("%" PRIiPTR " ", ((intptr_t) buffer->user));
0076
0077 if (((rtems_rfs_buffer_block) ((intptr_t)(buffer->user))) == block)
0078 {
0079 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
0080 printf (": found block=%" PRIiPTR "\n",
0081 ((intptr_t)(buffer->user)));
0082
0083 (*count)--;
0084 rtems_chain_extract_unprotected (node);
0085 rtems_chain_set_off_chain (node);
0086 return buffer;
0087 }
0088 node = rtems_chain_previous (node);
0089 }
0090
0091 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
0092 printf (": not found\n");
0093
0094 return NULL;
0095 }
0096
0097 int
0098 rtems_rfs_buffer_handle_request (rtems_rfs_file_system* fs,
0099 rtems_rfs_buffer_handle* handle,
0100 rtems_rfs_buffer_block block,
0101 bool read)
0102 {
0103 int rc;
0104
0105
0106
0107
0108
0109 if (rtems_rfs_buffer_handle_has_block (handle))
0110 {
0111
0112
0113
0114 if (block && (rtems_rfs_buffer_bnum (handle) == block))
0115 return 0;
0116
0117 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
0118 printf ("rtems-rfs: buffer-request: handle has buffer: %" PRIu32 "\n",
0119 rtems_rfs_buffer_bnum (handle));
0120
0121 rc = rtems_rfs_buffer_handle_release (fs, handle);
0122 if (rc > 0)
0123 return rc;
0124 handle->dirty = false;
0125 handle->bnum = 0;
0126 }
0127
0128 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
0129 printf ("rtems-rfs: buffer-request: block=%" PRIu32 "\n", block);
0130
0131
0132
0133
0134
0135
0136
0137
0138 if (fs->buffers_count)
0139 {
0140
0141
0142
0143 handle->buffer = rtems_rfs_scan_chain (&fs->buffers,
0144 &fs->buffers_count,
0145 block);
0146 if (rtems_rfs_buffer_handle_has_block (handle) &&
0147 rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
0148 printf ("rtems-rfs: buffer-request: buffer shared: refs: %d\n",
0149 rtems_rfs_buffer_refs (handle) + 1);
0150 }
0151
0152
0153
0154
0155
0156
0157 if (!rtems_rfs_fs_no_local_cache (fs) &&
0158 !rtems_rfs_buffer_handle_has_block (handle))
0159 {
0160
0161
0162
0163 if (fs->release_count)
0164 handle->buffer = rtems_rfs_scan_chain (&fs->release,
0165 &fs->release_count,
0166 block);
0167
0168 if (!rtems_rfs_buffer_handle_has_block (handle) &&
0169 fs->release_modified_count)
0170 {
0171 handle->buffer = rtems_rfs_scan_chain (&fs->release_modified,
0172 &fs->release_modified_count,
0173 block);
0174
0175
0176
0177 if (rtems_rfs_buffer_handle_has_block (handle))
0178 rtems_rfs_buffer_mark_dirty (handle);
0179 }
0180 }
0181
0182
0183
0184
0185 if (!rtems_rfs_buffer_handle_has_block (handle))
0186 {
0187 rc = rtems_rfs_buffer_io_request (fs, block, read, &handle->buffer);
0188
0189 if (rc > 0)
0190 {
0191 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
0192 printf ("rtems-rfs: buffer-request: block=%" PRIu32 ": bdbuf-%s: %d: %s\n",
0193 block, read ? "read" : "get", rc, strerror (rc));
0194 return rc;
0195 }
0196
0197 rtems_chain_set_off_chain (rtems_rfs_buffer_link(handle));
0198 }
0199
0200
0201
0202
0203 rtems_rfs_buffer_refs_up (handle);
0204 rtems_chain_append_unprotected (&fs->buffers,
0205 rtems_rfs_buffer_link (handle));
0206 fs->buffers_count++;
0207
0208 handle->buffer->user = (void*) ((intptr_t) block);
0209 handle->bnum = block;
0210
0211 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
0212 printf ("rtems-rfs: buffer-request: block=%" PRIu32 " bdbuf-%s=%" PRIu32 " refs=%d\n",
0213 block, read ? "read" : "get", handle->buffer->block,
0214 handle->buffer->references);
0215
0216 return 0;
0217 }
0218
0219 int
0220 rtems_rfs_buffer_handle_release (rtems_rfs_file_system* fs,
0221 rtems_rfs_buffer_handle* handle)
0222 {
0223 int rc = 0;
0224
0225 if (rtems_rfs_buffer_handle_has_block (handle))
0226 {
0227 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_RELEASE))
0228 printf ("rtems-rfs: buffer-release: block=%" PRIu32 " %s refs=%d %s\n",
0229 rtems_rfs_buffer_bnum (handle),
0230 rtems_rfs_buffer_dirty (handle) ? "(dirty)" : "",
0231 rtems_rfs_buffer_refs (handle),
0232 rtems_rfs_buffer_refs (handle) == 0 ? "BAD REF COUNT" : "");
0233
0234 if (rtems_rfs_buffer_refs (handle) > 0)
0235 rtems_rfs_buffer_refs_down (handle);
0236
0237 if (rtems_rfs_buffer_refs (handle) == 0)
0238 {
0239 rtems_chain_extract_unprotected (rtems_rfs_buffer_link (handle));
0240 fs->buffers_count--;
0241
0242 if (rtems_rfs_fs_no_local_cache (fs))
0243 {
0244 handle->buffer->user = (void*) 0;
0245 rc = rtems_rfs_buffer_io_release (handle->buffer,
0246 rtems_rfs_buffer_dirty (handle));
0247 }
0248 else
0249 {
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 if ((fs->release_count +
0260 fs->release_modified_count) >= fs->max_held_buffers)
0261 {
0262 rtems_rfs_buffer* buffer;
0263 bool modified;
0264
0265 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_RELEASE))
0266 printf ("rtems-rfs: buffer-release: local cache overflow:"
0267 " %" PRIu32 "\n", fs->release_count + fs->release_modified_count);
0268
0269 if (fs->release_count > fs->release_modified_count)
0270 {
0271 buffer = (rtems_rfs_buffer*)
0272 rtems_chain_get_unprotected (&fs->release);
0273 fs->release_count--;
0274 modified = false;
0275 }
0276 else
0277 {
0278 buffer = (rtems_rfs_buffer*)
0279 rtems_chain_get_unprotected (&fs->release_modified);
0280 fs->release_modified_count--;
0281 modified = true;
0282 }
0283 buffer->user = (void*) 0;
0284 rc = rtems_rfs_buffer_io_release (buffer, modified);
0285 }
0286
0287 if (rtems_rfs_buffer_dirty (handle))
0288 {
0289 rtems_chain_append_unprotected (&fs->release_modified,
0290 rtems_rfs_buffer_link (handle));
0291 fs->release_modified_count++;
0292 }
0293 else
0294 {
0295 rtems_chain_append_unprotected (&fs->release,
0296 rtems_rfs_buffer_link (handle));
0297 fs->release_count++;
0298 }
0299 }
0300 }
0301 handle->buffer = NULL;
0302 }
0303
0304 return rc;
0305 }
0306
0307 int
0308 rtems_rfs_buffer_open (const char* name, rtems_rfs_file_system* fs)
0309 {
0310 struct stat st;
0311 #if RTEMS_RFS_USE_LIBBLOCK
0312 int rv;
0313 #endif
0314
0315 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
0316 printf ("rtems-rfs: buffer-open: opening: %s\n", name);
0317
0318 fs->device = open (name, O_RDWR);
0319 if (fs->device < 0)
0320 {
0321 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
0322 printf ("rtems-rfs: buffer-open: cannot open file\n");
0323 return ENXIO;
0324 }
0325
0326 if (fstat (fs->device, &st) < 0)
0327 {
0328 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
0329 printf ("rtems-rfs: buffer-open: stat '%s' failed: %s\n",
0330 name, strerror (errno));
0331 return ENXIO;
0332 }
0333
0334 #if RTEMS_RFS_USE_LIBBLOCK
0335
0336
0337
0338 if (!S_ISBLK (st.st_mode))
0339 {
0340 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
0341 printf ("rtems-rfs: buffer-open: '%s' is not a block device\n", name);
0342 return ENXIO;
0343 }
0344
0345
0346
0347
0348 rv = rtems_disk_fd_get_disk_device (fs->device, &fs->disk);
0349 if (rv != 0)
0350 {
0351 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
0352 printf ("rtems-rfs: buffer-open: cannot obtain the disk\n");
0353 return ENXIO;
0354 }
0355 #else
0356 fs->media_size = st.st_size;
0357 strcat (fs->name, name);
0358 #endif
0359
0360 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
0361 printf ("rtems-rfs: buffer-open: blks=%" PRId32 ", blk-size=%" PRId32 "\n",
0362 rtems_rfs_fs_media_blocks (fs),
0363 rtems_rfs_fs_media_block_size (fs));
0364
0365 return 0;
0366 }
0367
0368 int
0369 rtems_rfs_buffer_close (rtems_rfs_file_system* fs)
0370 {
0371 int rc = 0;
0372
0373 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
0374 printf ("rtems-rfs: buffer-close: closing\n");
0375
0376
0377
0378
0379
0380 rc = rtems_rfs_buffer_setblksize (fs, rtems_rfs_fs_media_block_size (fs));
0381
0382 if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
0383 printf ("rtems-rfs: buffer-close: set media block size failed: %d: %s\n",
0384 rc, strerror (rc));
0385
0386 if (close (fs->device) < 0)
0387 {
0388 rc = errno;
0389 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
0390 printf ("rtems-rfs: buffer-close: file close failed: %d: %s\n",
0391 rc, strerror (rc));
0392 }
0393
0394 return rc;
0395 }
0396
0397 int
0398 rtems_rfs_buffer_sync (rtems_rfs_file_system* fs)
0399 {
0400 int result = 0;
0401 #if RTEMS_RFS_USE_LIBBLOCK
0402 rtems_status_code sc;
0403 #endif
0404
0405 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
0406 printf ("rtems-rfs: buffer-sync: syncing\n");
0407
0408
0409
0410
0411 #if RTEMS_RFS_USE_LIBBLOCK
0412 sc = rtems_bdbuf_syncdev (rtems_rfs_fs_device (fs));
0413 if (sc != RTEMS_SUCCESSFUL)
0414 {
0415 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
0416 printf ("rtems-rfs: buffer-sync: device sync failed: %s\n",
0417 rtems_status_text (sc));
0418 result = EIO;
0419 }
0420 #else
0421 if (fsync (fs->device) < 0)
0422 {
0423 result = errno;
0424 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
0425 printf ("rtems-rfs: buffer-sync: file sync failed: %d: %s\n",
0426 result, strerror (result));
0427 }
0428 #endif
0429 return result;
0430 }
0431
0432 int
0433 rtems_rfs_buffer_setblksize (rtems_rfs_file_system* fs, uint32_t size)
0434 {
0435 int rc;
0436
0437 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE))
0438 printf ("rtems-rfs: buffer-setblksize: block size: %" PRIu32 "\n", size);
0439
0440 rc = rtems_rfs_buffers_release (fs);
0441 if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE))
0442 printf ("rtems-rfs: buffer-setblksize: buffer release failed: %d: %s\n",
0443 rc, strerror (rc));
0444
0445 rc = rtems_rfs_buffer_sync (fs);
0446 if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE))
0447 printf ("rtems-rfs: buffer-setblksize: device sync failed: %d: %s\n",
0448 rc, strerror (rc));
0449
0450 #if RTEMS_RFS_USE_LIBBLOCK
0451 rc = fs->disk->ioctl (fs->disk, RTEMS_BLKIO_SETBLKSIZE, &size);
0452 if (rc < 0)
0453 rc = errno;
0454 #endif
0455 return rc;
0456 }
0457
0458 static int
0459 rtems_rfs_release_chain (rtems_chain_control* chain,
0460 uint32_t* count,
0461 bool modified)
0462 {
0463 rtems_rfs_buffer* buffer;
0464 int rrc = 0;
0465 int rc;
0466
0467 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
0468 printf ("rtems-rfs: release-chain: count=%" PRIu32 "\n", *count);
0469
0470 while (!rtems_chain_is_empty (chain))
0471 {
0472 buffer = (rtems_rfs_buffer*) rtems_chain_get_unprotected (chain);
0473 (*count)--;
0474
0475 buffer->user = (void*) 0;
0476
0477 rc = rtems_rfs_buffer_io_release (buffer, modified);
0478 if ((rc > 0) && (rrc == 0))
0479 rrc = rc;
0480 }
0481 return rrc;
0482 }
0483
0484 int
0485 rtems_rfs_buffers_release (rtems_rfs_file_system* fs)
0486 {
0487 int rrc = 0;
0488 int rc;
0489
0490 if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_RELEASE))
0491 printf ("rtems-rfs: buffers-release: active:%" PRIu32 " "
0492 "release:%" PRIu32 " release-modified:%" PRIu32 "\n",
0493 fs->buffers_count, fs->release_count, fs->release_modified_count);
0494
0495 rc = rtems_rfs_release_chain (&fs->release,
0496 &fs->release_count,
0497 false);
0498 if ((rc > 0) && (rrc == 0))
0499 rrc = rc;
0500 rc = rtems_rfs_release_chain (&fs->release_modified,
0501 &fs->release_modified_count,
0502 true);
0503 if ((rc > 0) && (rrc == 0))
0504 rrc = rc;
0505
0506 return rrc;
0507 }