diff options
Diffstat (limited to 'nuttx/drivers/bch/bchdev_driver.c')
-rw-r--r-- | nuttx/drivers/bch/bchdev_driver.c | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/nuttx/drivers/bch/bchdev_driver.c b/nuttx/drivers/bch/bchdev_driver.c index 33e26032f..9f579bbab 100644 --- a/nuttx/drivers/bch/bchdev_driver.c +++ b/nuttx/drivers/bch/bchdev_driver.c @@ -102,9 +102,26 @@ struct file_operations bch_fops = static int bch_open(FAR struct file *filp) { FAR struct inode *inode = filp->f_inode; + FAR struct bchlib_s *bch; + int ret; DEBUGASSERT(inode && inode->i_private); - return bchlib_incref((FAR struct bchlib_s *)inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + /* Increment the reference count */ + + bchlib_semtake(bch); + if (bch->refs == MAX_OPENCNT) + { + return -EMFILE; + } + else + { + bch->refs++; + } + bchlib_semgive(bch); + + return ret; } /**************************************************************************** @@ -117,9 +134,32 @@ static int bch_open(FAR struct file *filp) static int bch_close(FAR struct file *filp) { FAR struct inode *inode = filp->f_inode; + FAR struct bchlib_s *bch; + int ret; DEBUGASSERT(inode && inode->i_private); - return bchlib_decref((FAR struct bchlib_s *)inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + /* Flush any dirty pages remaining in the cache */ + + bchlib_semtake(bch); + (void)bchlib_flushsector(bch); + + /* Decrement the reference count (I don't use bchlib_decref() because I + * want the entire close operation to be atomic wrt other driver operations. + */ + + if (bch->refs == 0) + { + ret = -EIO; + } + else + { + bch->refs--; + } + bchlib_semgive(bch); + + return ret; } /**************************************************************************** @@ -192,15 +232,17 @@ static int bch_ioctl(FAR struct file *filp, int cmd, unsigned long arg) { FAR struct bchlib_s **bchr = (FAR struct bchlib_s **)arg; - if (!bchr) + bchlib_semtake(bch); + if (!bchr && bch->refs < 255) { ret = -EINVAL; } else { - ret = bchlib_incref(bch); + bch->refs++; *bchr = bch; } + bchlib_semgive(bch); } return ret; |