source: rtems/cpukit/libfs/src/rfs/rtems-rfs-buffer.c @ 1d539c0

4.104.115
Last change on this file since 1d539c0 was 1d539c0, checked in by Chris Johns <chrisj@…>, on 04/12/10 at 05:29:25

2010-04-12 Chris Johns <chrisj@…>

libfs/src/rfs/rtems-rfs-buffer-bdbuf.c,
libfs/src/rfs/rtems-rfs-buffer.c, libfs/src/rfs/rtems-rfs-data.h,
libfs/src/rfs/rtems-rfs-dir.c,
libfs/src/rfs/rtems-rfs-file-system.c,
libfs/src/rfs/rtems-rfs-format.c, libfs/src/rfs/rtems-rfs-inode.h,
libfs/src/rfs/rtems-rfs-rtems.c, libfs/src/rfs/rtems-rfs-rtems.h,
libfs/src/rfs/rtems-rfs-shell.c: Fix for PR1502. Clean up problems
on 16bit targets.

  • Property mode set to 100644
File size: 13.8 KB
Line 
1/*
2 *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.com/license/LICENSE.
7 *
8 *  $Id$
9 */
10/**
11 * @file
12 *
13 * @ingroup rtems-rfs
14 *
15 * RTEMS File Systems Buffer Routines.
16 *
17 */
18
19#if HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include <errno.h>
24
25#include <rtems/rfs/rtems-rfs-buffer.h>
26#include <rtems/rfs/rtems-rfs-file-system.h>
27
28/**
29 * Scan the chain for a buffer that matches the block number.
30 *
31 * @param chain The chain to scan.
32 * @param count The number of items on the chain.
33 * @param block The block number to find.
34 * @return  rtems_rfs_buffer* The buffer if found else NULL.
35 */
36static rtems_rfs_buffer*
37rtems_rfs_scan_chain (rtems_chain_control*   chain,
38                      uint32_t*              count,
39                      rtems_rfs_buffer_block block)
40{
41  rtems_rfs_buffer* buffer;
42  rtems_chain_node* node;
43 
44  node = rtems_chain_last (chain);
45
46  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
47    printf ("rtems-rfs: buffer-scan: count=%lu, block=%lu: ", *count, block);
48
49  while (!rtems_chain_is_head (chain, node))
50  {
51    buffer = (rtems_rfs_buffer*) node;
52
53    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
54      printf ("%lu ", (rtems_rfs_buffer_block) ((intptr_t)(buffer->user)));
55
56    if (((rtems_rfs_buffer_block) ((intptr_t)(buffer->user))) == block)
57    {
58      if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
59        printf (": found block=%lu\n",
60                (rtems_rfs_buffer_block) ((intptr_t)(buffer->user)));
61
62      (*count)--;
63      rtems_chain_extract (node);
64      rtems_chain_set_off_chain (node);
65      return buffer;
66    }
67    node = rtems_chain_previous (node);
68  }
69
70  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
71    printf (": not found\n");
72
73  return NULL;
74}
75
76int
77rtems_rfs_buffer_handle_request (rtems_rfs_file_system*   fs,
78                                 rtems_rfs_buffer_handle* handle,
79                                 rtems_rfs_buffer_block   block,
80                                 bool                     read)
81{
82  int rc;
83 
84  /*
85   * If the handle has a buffer release it. This allows a handle to be reused
86   * without needing to close then open it again.
87   */
88  if (rtems_rfs_buffer_handle_has_block (handle))
89  {
90    /*
91     * Treat block 0 as special to handle the loading of the super block.
92     */
93    if (block && (rtems_rfs_buffer_bnum (handle) == block))
94      return 0;
95
96    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
97      printf ("rtems-rfs: buffer-request: handle has buffer: %lu\n",
98              rtems_rfs_buffer_bnum (handle));
99
100    rc = rtems_rfs_buffer_handle_release (fs, handle);
101    if (rc > 0)
102      return rc;
103    handle->dirty = false;
104    handle->bnum = 0;
105  }
106
107  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
108    printf ("rtems-rfs: buffer-request: block=%lu\n", block);
109
110  /*
111   * First check to see if the buffer has already been requested and is
112   * currently attached to a handle. If it is share the access. A buffer could
113   * be shared where different parts of the block have separate functions. An
114   * example is an inode block and the file system needs to handle 2 inodes in
115   * the same block at the same time.
116   */
117  if (fs->buffers_count)
118  {
119    /*
120     * Check the active buffer list for shared buffers.
121     */
122    handle->buffer = rtems_rfs_scan_chain (&fs->buffers,
123                                           &fs->buffers_count,
124                                           block);
125    if (rtems_rfs_buffer_handle_has_block (handle) &&
126        rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
127      printf ("rtems-rfs: buffer-request: buffer shared: refs: %d\n",
128              rtems_rfs_buffer_refs (handle) + 1);
129  }
130
131  /*
132   * If the buffer has not been found check the local cache of released
133   * buffers. There are release and released modified lists to preserve the
134   * state.
135   */
136  if (!rtems_rfs_fs_no_local_cache (fs) &&
137      !rtems_rfs_buffer_handle_has_block (handle))
138  {
139    /*
140     * Check the local cache of released buffers.
141     */
142    if (fs->release_count)
143      handle->buffer = rtems_rfs_scan_chain (&fs->release,
144                                             &fs->release_count,
145                                             block);
146
147    if (!rtems_rfs_buffer_handle_has_block (handle) &&
148        fs->release_modified_count)
149    {
150      handle->buffer = rtems_rfs_scan_chain (&fs->release_modified,
151                                             &fs->release_modified_count,
152                                             block);
153      /*
154       * If we found a buffer retain the dirty buffer state.
155       */
156      if (rtems_rfs_buffer_handle_has_block (handle))
157        rtems_rfs_buffer_mark_dirty (handle);
158    }
159  }
160   
161  /*
162   * If not located we request the buffer from the I/O layer.
163   */
164  if (!rtems_rfs_buffer_handle_has_block (handle))
165  {
166    rc = rtems_rfs_buffer_io_request (fs, block, read, &handle->buffer);
167
168    rtems_chain_set_off_chain (rtems_rfs_buffer_link(handle));
169
170    if (rc > 0)
171    {
172      if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
173        printf ("rtems-rfs: buffer-request: block=%lu: bdbuf-%s: %d: %s\n",
174                block, read ? "read" : "get", rc, strerror (rc));
175      return rc;
176    }
177  }
178
179  /*
180   * Increase the reference count of the buffer.
181   */
182  rtems_rfs_buffer_refs_up (handle);
183  rtems_chain_append (&fs->buffers, rtems_rfs_buffer_link (handle));
184  fs->buffers_count++;
185 
186  handle->buffer->user = (void*) ((intptr_t) block);
187  handle->bnum = block;
188 
189  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
190    printf ("rtems-rfs: buffer-request: block=%lu bdbuf-%s=%lu refs=%d\n",
191            block, read ? "read" : "get", handle->buffer->block,
192            handle->buffer->references);
193 
194  return 0;
195}
196
197int
198rtems_rfs_buffer_handle_release (rtems_rfs_file_system*   fs,
199                                 rtems_rfs_buffer_handle* handle)
200{
201  int rc = 0;
202 
203  if (rtems_rfs_buffer_handle_has_block (handle))
204  {
205    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_RELEASE))
206      printf ("rtems-rfs: buffer-release: block=%lu %s refs=%d %s\n",
207              rtems_rfs_buffer_bnum (handle),
208              rtems_rfs_buffer_dirty (handle) ? "(dirty)" : "",
209              rtems_rfs_buffer_refs (handle),
210              rtems_rfs_buffer_refs (handle) == 0 ? "BAD REF COUNT" : "");
211
212    if (rtems_rfs_buffer_refs (handle) > 0)
213      rtems_rfs_buffer_refs_down (handle);
214   
215    if (rtems_rfs_buffer_refs (handle) == 0)
216    {
217      rtems_chain_extract (rtems_rfs_buffer_link (handle));
218      fs->buffers_count--;
219     
220      if (rtems_rfs_fs_no_local_cache (fs))
221      {
222        handle->buffer->user = (void*) 0;
223        rc = rtems_rfs_buffer_io_release (handle->buffer,
224                                          rtems_rfs_buffer_dirty (handle));
225      }
226      else
227      {
228        /*
229         * If the total number of held buffers is higher than the configured
230         * value remove a buffer from the queue with the most buffers and
231         * release. The buffers are held on the queues with the newest at the
232         * head.
233         *
234         * This code stops a large series of transactions causing all the
235         * buffers in the cache being held in queues of this file system.
236         */
237        if ((fs->release_count +
238             fs->release_modified_count) >= fs->max_held_buffers)
239        {
240          rtems_rfs_buffer* buffer;
241          bool              modified;
242       
243          if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_RELEASE))
244            printf ("rtems-rfs: buffer-release: local cache overflow:" \
245                    " %lu\n", fs->release_count + fs->release_modified_count);
246       
247          if (fs->release_count > fs->release_modified_count)
248          {
249            buffer = (rtems_rfs_buffer*) rtems_chain_get (&fs->release);
250            fs->release_count--;
251            modified = false;
252          }
253          else
254          {
255            buffer =
256              (rtems_rfs_buffer*) rtems_chain_get (&fs->release_modified);
257            fs->release_modified_count--;
258            modified = true;
259          }
260          buffer->user = (void*) 0;
261          rc = rtems_rfs_buffer_io_release (buffer, modified);
262        }
263     
264        if (rtems_rfs_buffer_dirty (handle))
265        {
266          rtems_chain_append (&fs->release_modified,
267                              rtems_rfs_buffer_link (handle));
268          fs->release_modified_count++;
269        }
270        else
271        {
272          rtems_chain_append (&fs->release, rtems_rfs_buffer_link (handle));
273          fs->release_count++;
274        }
275      }
276    }
277    handle->buffer = NULL;
278  }
279 
280  return rc;
281}
282
283int
284rtems_rfs_buffer_open (const char* name, rtems_rfs_file_system* fs)
285{
286  struct stat st;
287
288  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
289    printf ("rtems-rfs: buffer-open: opening: %s\n", name);
290 
291  if (stat (name, &st) < 0)
292  {
293    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
294      printf ("rtems-rfs: buffer-open: stat '%s' failed: %s\n",
295              name, strerror (errno));
296    return ENOENT;
297  }
298
299#if RTEMS_RFS_USE_LIBBLOCK
300  /*
301   * Is the device a block device ?
302   */
303  if (!S_ISBLK (st.st_mode))
304  {
305    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
306      printf ("rtems-rfs: buffer-open: '%s' is not a block device\n", name);
307    return EIO;
308  }
309
310  /*
311   * Check that device is registred as a block device and lock it.
312   */
313  fs->disk = rtems_disk_obtain (st.st_rdev);
314  if (!fs->disk)
315  {
316    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
317      printf ("rtems-rfs: buffer-open: cannot obtain the disk\n");
318    return EIO;
319  }
320#else
321  fs->device = open (name, O_RDWR);
322  if (fs->device < 0)
323  {
324    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
325      printf ("rtems-rfs: buffer-open: cannot open file\n");
326  }
327  fs->media_size = st.st_size;
328  strcat (fs->name, name);
329#endif
330
331  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
332    printf ("rtems-rfs: buffer-open: blks=%ld, blk-size=%ld\n",
333            rtems_rfs_fs_media_blocks (fs),
334            rtems_rfs_fs_media_block_size (fs));
335 
336  return 0;
337}
338
339int
340rtems_rfs_buffer_close (rtems_rfs_file_system* fs)
341{
342  int rc = 0;
343
344  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
345    printf ("rtems-rfs: buffer-close: closing\n");
346
347  /*
348   * Change the block size to the media device size. It will release and sync
349   * all buffers.
350   */
351  rc = rtems_rfs_buffer_setblksize (fs, rtems_rfs_fs_media_block_size (fs));
352
353  if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
354    printf ("rtems-rfs: buffer-close: set media block size failed: %d: %s\n",
355            rc, strerror (rc));
356 
357#if RTEMS_RFS_USE_LIBBLOCK
358  rtems_disk_release (fs->disk);
359#else
360  if (close (fs->device) < 0)
361  {
362    rc = errno;
363    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
364      printf ("rtems-rfs: buffer-close: file close failed: %d: %s\n",
365              rc, strerror (rc));
366  }
367#endif
368 
369  return rc;
370}
371
372int
373rtems_rfs_buffer_sync (rtems_rfs_file_system* fs)
374{
375  int result = 0;
376#if RTEMS_RFS_USE_LIBBLOCK
377  rtems_status_code sc;
378#endif
379
380  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
381    printf ("rtems-rfs: buffer-sync: syncing\n");
382
383  /*
384   * @todo Split in the separate files for each type.
385   */
386#if RTEMS_RFS_USE_LIBBLOCK
387  sc = rtems_bdbuf_syncdev (rtems_rfs_fs_device (fs));
388  if (sc != RTEMS_SUCCESSFUL)
389  {
390    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
391      printf ("rtems-rfs: buffer-sync: device sync failed: %s\n",
392              rtems_status_text (sc));
393    result = EIO;
394  }
395  rtems_disk_release (fs->disk);
396#else
397  if (fsync (fs->device) < 0)
398  {
399    result = errno;
400    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
401      printf ("rtems-rfs: buffer-sync: file sync failed: %d: %s\n",
402              result, strerror (result));
403  }
404#endif
405  return result;
406}
407
408int
409rtems_rfs_buffer_setblksize (rtems_rfs_file_system* fs, size_t size)
410{
411  int rc;
412
413  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE))
414    printf ("rtems-rfs: buffer-setblksize: block size: %zu\n", size);
415
416  rc = rtems_rfs_buffers_release (fs);
417  if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE))
418    printf ("rtems-rfs: buffer-setblksize: buffer release failed: %d: %s\n",
419            rc, strerror (rc));
420 
421  rc = rtems_rfs_buffer_sync (fs);
422  if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE))
423    printf ("rtems-rfs: buffer-setblksize: device sync failed: %d: %s\n",
424            rc, strerror (rc));
425 
426#if RTEMS_RFS_USE_LIBBLOCK
427  rc = fs->disk->ioctl (fs->disk, RTEMS_BLKIO_SETBLKSIZE, &size);
428  if (rc < 0)
429    rc = errno;
430#endif
431  return rc;
432}
433
434static int
435rtems_rfs_release_chain (rtems_chain_control* chain,
436                         uint32_t*            count,
437                         bool                 modified)
438{
439  rtems_rfs_buffer* buffer;
440  int               rrc = 0;
441  int               rc;
442
443  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
444    printf ("rtems-rfs: release-chain: count=%lu\n", *count);
445
446  while (!rtems_chain_is_empty (chain))
447  {
448    buffer = (rtems_rfs_buffer*) rtems_chain_get (chain);
449    (*count)--;
450
451    buffer->user = (void*) 0;
452   
453    rc = rtems_rfs_buffer_io_release (buffer, modified);
454    if ((rc > 0) && (rrc == 0))
455      rrc = rc;
456  }
457  return rrc;
458}
459
460int
461rtems_rfs_buffers_release (rtems_rfs_file_system* fs)
462{
463  int rrc = 0;
464  int rc;
465
466  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_RELEASE))
467    printf ("rtems-rfs: buffers-release: active:%lu " \
468            "release:%lu release-modified:%lu\n",
469            fs->buffers_count, fs->release_count, fs->release_modified_count);
470
471  rc = rtems_rfs_release_chain (&fs->release,
472                                &fs->release_count,
473                                false);
474  if ((rc > 0) && (rrc == 0))
475    rrc = rc;
476  rc = rtems_rfs_release_chain (&fs->release_modified,
477                                &fs->release_modified_count,
478                                true);
479  if ((rc > 0) && (rrc == 0))
480    rrc = rc;
481
482  return rrc;
483}
Note: See TracBrowser for help on using the repository browser.