From 3d5515b6f7a63b40d09ea220927b8bc2feb0f7d8 Mon Sep 17 00:00:00 2001 From: Thomas Doerfler Date: Fri, 30 Oct 2009 10:57:39 +0000 Subject: Fixed group usage counting. See test "libtests/block02". --- cpukit/ChangeLog | 5 +++ cpukit/libblock/src/bdbuf.c | 103 +++++++++++++++++++++++--------------------- 2 files changed, 60 insertions(+), 48 deletions(-) diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog index 564314044d..730f361463 100644 --- a/cpukit/ChangeLog +++ b/cpukit/ChangeLog @@ -1,3 +1,8 @@ +2009-10-30 Sebastian Huber + + * libblock/src/bdbuf.c: Fixed group usage counting. See test + "libtests/block02". + 2009-10-30 Ralf Corsépius * aclocal/gcc-sanity.m4: New. diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c index 31173cb9f6..3007b16d40 100644 --- a/cpukit/libblock/src/bdbuf.c +++ b/cpukit/libblock/src/bdbuf.c @@ -1385,6 +1385,18 @@ error: return RTEMS_UNSATISFIED; } +static inline void +rtems_bdbuf_group_obtain (rtems_bdbuf_buffer *bd) +{ + ++bd->group->users; +} + +static inline void +rtems_bdbuf_group_release (rtems_bdbuf_buffer *bd) +{ + --bd->group->users; +} + /** * Get a buffer for this device and block. This function returns a buffer once * placed into the AVL tree. If no buffer is available and it is not a read @@ -1433,6 +1445,8 @@ error: * different the buffer size for the block has changed. The buffer needs to be * invalidated. * + * The returned buffer will be a user its group. + * * @param dd The disk device. Has the configured block size. * @param bds_per_group The number of BDs in a group for this block. * @param block Absolute media block number for the device @@ -1587,6 +1601,8 @@ rtems_bdbuf_get_buffer (rtems_disk_device* dd, if (rtems_bdbuf_avl_insert (&bdbuf_cache.tree, bd) != 0) rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_5); + rtems_bdbuf_group_obtain (bd); + return bd; } } @@ -1620,6 +1636,12 @@ rtems_bdbuf_get_buffer (rtems_disk_device* dd, if (read_ahead) return NULL; + /* + * Before we wait for the buffer, we have to obtain its group. This prevents + * a reallocation. + */ + rtems_bdbuf_group_obtain (bd); + /* * Loop waiting for the buffer to enter the cached state. If the buffer is in * the access or transfer state then wait until it is not. @@ -1659,6 +1681,12 @@ rtems_bdbuf_get_buffer (rtems_disk_device* dd, */ rtems_chain_extract (&bd->link); + /* + * The modified list is no longer a user of the buffers group. + */ + if (bd->state == RTEMS_BDBUF_STATE_MODIFIED) + rtems_bdbuf_group_release (bd); + return bd; } @@ -1717,21 +1745,16 @@ rtems_bdbuf_get (dev_t device, bd = rtems_bdbuf_get_buffer (dd, bds_per_group, media_block, false); /* - * This could be considered a bug in the caller because you should not be - * getting an already modified buffer but user may have modified a byte in a - * block then decided to seek the start and write the whole block and the - * file system will have no record of this so just gets the block to fill. + * To get a modified buffer could be considered a bug in the caller because + * you should not be getting an already modified buffer but user may have + * modified a byte in a block then decided to seek the start and write the + * whole block and the file system will have no record of this so just gets + * the block to fill. */ - if (bd->state == RTEMS_BDBUF_STATE_MODIFIED) - bd->state = RTEMS_BDBUF_STATE_ACCESS_MODIFIED; - else - { + if (bd->state != RTEMS_BDBUF_STATE_MODIFIED) bd->state = RTEMS_BDBUF_STATE_ACCESS; - /* - * Indicate a buffer in this group is being used. - */ - bd->group->users++; - } + else + bd->state = RTEMS_BDBUF_STATE_ACCESS_MODIFIED; if (rtems_bdbuf_tracer) { @@ -1781,6 +1804,7 @@ rtems_bdbuf_read (dev_t device, size_t bds_per_group; rtems_blkdev_bnum media_block; rtems_blkdev_bnum media_block_count; + bool read_ahead = false; if (!bdbuf_cache.initialised) return RTEMS_NOT_CONFIGURED; @@ -1859,7 +1883,7 @@ rtems_bdbuf_read (dev_t device, * caller. */ bd = rtems_bdbuf_get_buffer (dd, bds_per_group, media_block + dd->start, - req->bufnum == 0 ? false : true); + read_ahead); /* * Read ahead buffer is in the cache or none available. Read what we @@ -1873,16 +1897,16 @@ rtems_bdbuf_read (dev_t device, */ if ((bd->state == RTEMS_BDBUF_STATE_CACHED) || (bd->state == RTEMS_BDBUF_STATE_MODIFIED)) + { + if (read_ahead) + rtems_bdbuf_group_release (bd); + break; + } bd->state = RTEMS_BDBUF_STATE_TRANSFER; bd->error = 0; - /* - * The buffer will be passed to the driver so this buffer has a user. - */ - bd->group->users++; - if (rtems_bdbuf_tracer) rtems_bdbuf_show_users ("reading", bd); @@ -1905,6 +1929,11 @@ rtems_bdbuf_read (dev_t device, * disk device's set block size. */ media_block += media_block_count; + + /* + * After the first buffer we have read ahead buffers. + */ + read_ahead = true; } /* @@ -1978,7 +2007,8 @@ rtems_bdbuf_read (dev_t device, if (!bd->error) bd->error = req->error; bd->state = RTEMS_BDBUF_STATE_READ_AHEAD; - bd->group->users--; + + rtems_bdbuf_group_release (bd); if (rtems_bdbuf_tracer) rtems_bdbuf_show_users ("read-ahead", bd); @@ -2008,31 +2038,14 @@ rtems_bdbuf_read (dev_t device, bd = req->bufs[0].user; - /* - * One less user for the BD we return. The loop above is only for the read - * head buffers. We do this here then increment again so the case of the - * buffer in the cache or modified and no read leaves the user counts at - * the correct level. - */ - bd->group->users--; - if (rtems_bdbuf_tracer) rtems_bdbuf_show_users ("read-done", bd); } - /* - * The data for this block is cached in the buffer. - */ - if (bd->state == RTEMS_BDBUF_STATE_MODIFIED) - bd->state = RTEMS_BDBUF_STATE_ACCESS_MODIFIED; - else - { - /* - * The file system is a user of the buffer. - */ - bd->group->users++; + if (bd->state != RTEMS_BDBUF_STATE_MODIFIED) bd->state = RTEMS_BDBUF_STATE_ACCESS; - } + else + bd->state = RTEMS_BDBUF_STATE_ACCESS_MODIFIED; if (rtems_bdbuf_tracer) { @@ -2071,10 +2084,7 @@ rtems_bdbuf_release (rtems_bdbuf_buffer* bd) bd->state = RTEMS_BDBUF_STATE_CACHED; rtems_chain_append (&bdbuf_cache.lru, &bd->link); - /* - * One less user for the group of bds. - */ - bd->group->users--; + rtems_bdbuf_group_release (bd); } if (rtems_bdbuf_tracer) @@ -2411,10 +2421,7 @@ rtems_bdbuf_swapout_write (rtems_bdbuf_swapout_transfer* transfer) bd->state = RTEMS_BDBUF_STATE_CACHED; bd->error = 0; - /* - * The buffer is now not modified so lower the user count for the group. - */ - bd->group->users--; + rtems_bdbuf_group_release (bd); if (rtems_bdbuf_tracer) rtems_bdbuf_show_users ("write", bd); -- cgit v1.2.3