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

4.104.115
Last change on this file since a290e72a was 355b0544, checked in by Chris Johns <chrisj@…>, on 03/27/10 at 04:04:40

2010-03-27 Chris Johns <chrisj@…>

libfs/src/nfsclient/src/cexphelp.c,
libfs/src/nfsclient/src/dirutils.c,
libfs/src/nfsclient/src/nfs.modini.c,
libfs/src/nfsclient/src/nfsTest.c,
libfs/src/nfsclient/src/rpcio.c,
libfs/src/nfsclient/src/rpcio.modini.c,
libfs/src/nfsclient/src/sock_mbuf.c,
libfs/src/nfsclient/src/xdr_mbuf.c,
libfs/src/rfs/rtems-rfs-bitmaps-ut.c,
libfs/src/rfs/rtems-rfs-bitmaps.c,
libfs/src/rfs/rtems-rfs-block.c,
libfs/src/rfs/rtems-rfs-buffer-bdbuf.c,
libfs/src/rfs/rtems-rfs-buffer-devio.c,
libfs/src/rfs/rtems-rfs-buffer.c,
libfs/src/rfs/rtems-rfs-dir-hash.c, libfs/src/rfs/rtems-rfs-dir.c,
libfs/src/rfs/rtems-rfs-file-system.c,
libfs/src/rfs/rtems-rfs-file.c, libfs/src/rfs/rtems-rfs-format.c,
libfs/src/rfs/rtems-rfs-group.c, libfs/src/rfs/rtems-rfs-inode.c,
libfs/src/rfs/rtems-rfs-link.c, libfs/src/rfs/rtems-rfs-mutex.c,
libfs/src/rfs/rtems-rfs-rtems-dev.c,
libfs/src/rfs/rtems-rfs-rtems-dir.c,
libfs/src/rfs/rtems-rfs-rtems-file.c,
libfs/src/rfs/rtems-rfs-rtems-utils.c,
libfs/src/rfs/rtems-rfs-rtems.c, libfs/src/rfs/rtems-rfs-shell.c,
libfs/src/rfs/rtems-rfs-trace.c: Add HAVE_CONFIG_H support to let
files receive configure defines.

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