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

4.115
Last change on this file since 6cd2074 was 2dd1e75e, checked in by Joel Sherrill <joel.sherrill@…>, on 09/03/14 at 14:59:10

rtems-rfs-buffer.c: Correct printf() format specifiers to eliminate warnings

  • Property mode set to 100644
File size: 14.1 KB
Line 
1/**
2 * @file
3 *
4 * @brief RTEMS File Systems Buffer Routines
5 * @ingroup rtems_rfs
6 */
7
8/*
9 *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
13 *  http://www.rtems.org/license/LICENSE.
14 */
15
16#if HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#include <sys/stat.h>
21#include <inttypes.h>
22#include <errno.h>
23#include <fcntl.h>
24#include <string.h>
25
26#include <rtems/rfs/rtems-rfs-buffer.h>
27#include <rtems/rfs/rtems-rfs-file-system.h>
28
29/**
30 * Scan the chain for a buffer that matches the block number.
31 *
32 * @param chain The chain to scan.
33 * @param count The number of items on the chain.
34 * @param block The block number to find.
35 * @return  rtems_rfs_buffer* The buffer if found else NULL.
36 */
37static rtems_rfs_buffer*
38rtems_rfs_scan_chain (rtems_chain_control*   chain,
39                      uint32_t*              count,
40                      rtems_rfs_buffer_block block)
41{
42  rtems_rfs_buffer* buffer;
43  rtems_chain_node* node;
44
45  node = rtems_chain_last (chain);
46
47  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
48    printf ("rtems-rfs: buffer-scan: count=%" PRIu32 ", block=%" PRIu32 ": ", *count, block);
49
50  while (!rtems_chain_is_head (chain, node))
51  {
52    buffer = (rtems_rfs_buffer*) node;
53
54    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
55      printf ("%p ", buffer->user);
56
57    if (((rtems_rfs_buffer_block) ((intptr_t)(buffer->user))) == block)
58    {
59      if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
60        printf (": found block=%p\n", buffer->user);
61
62      (*count)--;
63      rtems_chain_extract_unprotected (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: %" PRIu32 "\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=%" PRIu32 "\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    if (rc > 0)
169    {
170      if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
171        printf ("rtems-rfs: buffer-request: block=%" PRIu32 ": bdbuf-%s: %d: %s\n",
172                block, read ? "read" : "get", rc, strerror (rc));
173      return rc;
174    }
175
176    rtems_chain_set_off_chain (rtems_rfs_buffer_link(handle));
177  }
178
179  /*
180   * Increase the reference count of the buffer.
181   */
182  rtems_rfs_buffer_refs_up (handle);
183  rtems_chain_append_unprotected (&fs->buffers,
184                                  rtems_rfs_buffer_link (handle));
185  fs->buffers_count++;
186
187  handle->buffer->user = (void*) ((intptr_t) block);
188  handle->bnum = block;
189
190  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
191    printf ("rtems-rfs: buffer-request: block=%" PRIu32 " bdbuf-%s=%" PRIu32 " refs=%d\n",
192            block, read ? "read" : "get", handle->buffer->block,
193            handle->buffer->references);
194
195  return 0;
196}
197
198int
199rtems_rfs_buffer_handle_release (rtems_rfs_file_system*   fs,
200                                 rtems_rfs_buffer_handle* handle)
201{
202  int rc = 0;
203
204  if (rtems_rfs_buffer_handle_has_block (handle))
205  {
206    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_RELEASE))
207      printf ("rtems-rfs: buffer-release: block=%" PRIu32 " %s refs=%d %s\n",
208              rtems_rfs_buffer_bnum (handle),
209              rtems_rfs_buffer_dirty (handle) ? "(dirty)" : "",
210              rtems_rfs_buffer_refs (handle),
211              rtems_rfs_buffer_refs (handle) == 0 ? "BAD REF COUNT" : "");
212
213    if (rtems_rfs_buffer_refs (handle) > 0)
214      rtems_rfs_buffer_refs_down (handle);
215
216    if (rtems_rfs_buffer_refs (handle) == 0)
217    {
218      rtems_chain_extract_unprotected (rtems_rfs_buffer_link (handle));
219      fs->buffers_count--;
220
221      if (rtems_rfs_fs_no_local_cache (fs))
222      {
223        handle->buffer->user = (void*) 0;
224        rc = rtems_rfs_buffer_io_release (handle->buffer,
225                                          rtems_rfs_buffer_dirty (handle));
226      }
227      else
228      {
229        /*
230         * If the total number of held buffers is higher than the configured
231         * value remove a buffer from the queue with the most buffers and
232         * release. The buffers are held on the queues with the newest at the
233         * head.
234         *
235         * This code stops a large series of transactions causing all the
236         * buffers in the cache being held in queues of this file system.
237         */
238        if ((fs->release_count +
239             fs->release_modified_count) >= fs->max_held_buffers)
240        {
241          rtems_rfs_buffer* buffer;
242          bool              modified;
243
244          if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_RELEASE))
245            printf ("rtems-rfs: buffer-release: local cache overflow:"
246                    " %" PRIu32 "\n", fs->release_count + fs->release_modified_count);
247
248          if (fs->release_count > fs->release_modified_count)
249          {
250            buffer = (rtems_rfs_buffer*)
251              rtems_chain_get_unprotected (&fs->release);
252            fs->release_count--;
253            modified = false;
254          }
255          else
256          {
257            buffer = (rtems_rfs_buffer*)
258              rtems_chain_get_unprotected (&fs->release_modified);
259            fs->release_modified_count--;
260            modified = true;
261          }
262          buffer->user = (void*) 0;
263          rc = rtems_rfs_buffer_io_release (buffer, modified);
264        }
265
266        if (rtems_rfs_buffer_dirty (handle))
267        {
268          rtems_chain_append_unprotected (&fs->release_modified,
269                                          rtems_rfs_buffer_link (handle));
270          fs->release_modified_count++;
271        }
272        else
273        {
274          rtems_chain_append_unprotected (&fs->release,
275                                          rtems_rfs_buffer_link (handle));
276          fs->release_count++;
277        }
278      }
279    }
280    handle->buffer = NULL;
281  }
282
283  return rc;
284}
285
286int
287rtems_rfs_buffer_open (const char* name, rtems_rfs_file_system* fs)
288{
289  struct stat st;
290#if RTEMS_RFS_USE_LIBBLOCK
291  int rv;
292#endif
293
294  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
295    printf ("rtems-rfs: buffer-open: opening: %s\n", name);
296
297  fs->device = open (name, O_RDWR);
298  if (fs->device < 0)
299  {
300    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
301      printf ("rtems-rfs: buffer-open: cannot open file\n");
302    return ENXIO;
303  }
304
305  if (fstat (fs->device, &st) < 0)
306  {
307    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
308      printf ("rtems-rfs: buffer-open: stat '%s' failed: %s\n",
309              name, strerror (errno));
310    return ENXIO;
311  }
312
313#if RTEMS_RFS_USE_LIBBLOCK
314  /*
315   * Is the device a block device ?
316   */
317  if (!S_ISBLK (st.st_mode))
318  {
319    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
320      printf ("rtems-rfs: buffer-open: '%s' is not a block device\n", name);
321    return ENXIO;
322  }
323
324  /*
325   * Check that device is registred as a block device and lock it.
326   */
327  rv = rtems_disk_fd_get_disk_device (fs->device, &fs->disk);
328  if (rv != 0)
329  {
330    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
331      printf ("rtems-rfs: buffer-open: cannot obtain the disk\n");
332    return ENXIO;
333  }
334#else
335  fs->media_size = st.st_size;
336  strcat (fs->name, name);
337#endif
338
339  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
340    printf ("rtems-rfs: buffer-open: blks=%" PRId32 ", blk-size=%" PRId32 "\n",
341            rtems_rfs_fs_media_blocks (fs),
342            rtems_rfs_fs_media_block_size (fs));
343
344  return 0;
345}
346
347int
348rtems_rfs_buffer_close (rtems_rfs_file_system* fs)
349{
350  int rc = 0;
351
352  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
353    printf ("rtems-rfs: buffer-close: closing\n");
354
355  /*
356   * Change the block size to the media device size. It will release and sync
357   * all buffers.
358   */
359  rc = rtems_rfs_buffer_setblksize (fs, rtems_rfs_fs_media_block_size (fs));
360
361  if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
362    printf ("rtems-rfs: buffer-close: set media block size failed: %d: %s\n",
363            rc, strerror (rc));
364
365  if (close (fs->device) < 0)
366  {
367    rc = errno;
368    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
369      printf ("rtems-rfs: buffer-close: file close failed: %d: %s\n",
370              rc, strerror (rc));
371  }
372
373  return rc;
374}
375
376int
377rtems_rfs_buffer_sync (rtems_rfs_file_system* fs)
378{
379  int result = 0;
380#if RTEMS_RFS_USE_LIBBLOCK
381  rtems_status_code sc;
382#endif
383
384  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
385    printf ("rtems-rfs: buffer-sync: syncing\n");
386
387  /*
388   * @todo Split in the separate files for each type.
389   */
390#if RTEMS_RFS_USE_LIBBLOCK
391  sc = rtems_bdbuf_syncdev (rtems_rfs_fs_device (fs));
392  if (sc != RTEMS_SUCCESSFUL)
393  {
394    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
395      printf ("rtems-rfs: buffer-sync: device sync failed: %s\n",
396              rtems_status_text (sc));
397    result = EIO;
398  }
399  rtems_disk_release (fs->disk);
400#else
401  if (fsync (fs->device) < 0)
402  {
403    result = errno;
404    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
405      printf ("rtems-rfs: buffer-sync: file sync failed: %d: %s\n",
406              result, strerror (result));
407  }
408#endif
409  return result;
410}
411
412int
413rtems_rfs_buffer_setblksize (rtems_rfs_file_system* fs, size_t size)
414{
415  int rc;
416
417  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE))
418    printf ("rtems-rfs: buffer-setblksize: block size: %zu\n", size);
419
420  rc = rtems_rfs_buffers_release (fs);
421  if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE))
422    printf ("rtems-rfs: buffer-setblksize: buffer release failed: %d: %s\n",
423            rc, strerror (rc));
424
425  rc = rtems_rfs_buffer_sync (fs);
426  if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE))
427    printf ("rtems-rfs: buffer-setblksize: device sync failed: %d: %s\n",
428            rc, strerror (rc));
429
430#if RTEMS_RFS_USE_LIBBLOCK
431  rc = fs->disk->ioctl (fs->disk, RTEMS_BLKIO_SETBLKSIZE, &size);
432  if (rc < 0)
433    rc = errno;
434#endif
435  return rc;
436}
437
438static int
439rtems_rfs_release_chain (rtems_chain_control* chain,
440                         uint32_t*            count,
441                         bool                 modified)
442{
443  rtems_rfs_buffer* buffer;
444  int               rrc = 0;
445  int               rc;
446
447  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
448    printf ("rtems-rfs: release-chain: count=%" PRIu32 "\n", *count);
449
450  while (!rtems_chain_is_empty (chain))
451  {
452    buffer = (rtems_rfs_buffer*) rtems_chain_get_unprotected (chain);
453    (*count)--;
454
455    buffer->user = (void*) 0;
456
457    rc = rtems_rfs_buffer_io_release (buffer, modified);
458    if ((rc > 0) && (rrc == 0))
459      rrc = rc;
460  }
461  return rrc;
462}
463
464int
465rtems_rfs_buffers_release (rtems_rfs_file_system* fs)
466{
467  int rrc = 0;
468  int rc;
469
470  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_RELEASE))
471    printf ("rtems-rfs: buffers-release: active:%" PRIu32 " "
472            "release:%" PRIu32 " release-modified:%" PRIu32 "\n",
473            fs->buffers_count, fs->release_count, fs->release_modified_count);
474
475  rc = rtems_rfs_release_chain (&fs->release,
476                                &fs->release_count,
477                                false);
478  if ((rc > 0) && (rrc == 0))
479    rrc = rc;
480  rc = rtems_rfs_release_chain (&fs->release_modified,
481                                &fs->release_modified_count,
482                                true);
483  if ((rc > 0) && (rrc == 0))
484    rrc = rc;
485
486  return rrc;
487}
Note: See TracBrowser for help on using the repository browser.