From 78b725907d46a34fc781f30be59955194becd821 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Fri, 9 Nov 2018 08:22:51 -0600 Subject: [PATCH] drivers/mtd/ftl.c: ADd support support unlink operation to avoid the memory leak --- drivers/mtd/ftl.c | 71 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index e7bd76bd09..fc2c39b464 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -85,6 +85,8 @@ struct ftl_struct_s struct rwbuffer_s rwb; /* Read-ahead/write buffer support */ #endif uint16_t blkper; /* R/W blocks per erase block */ + uint16_t refs; /* Number of references */ + bool unlinked;/* The driver has been unlinked */ #ifdef CONFIG_FS_WRITABLE FAR uint8_t *eblock; /* One, in-memory erase block */ #endif @@ -108,6 +110,9 @@ static ssize_t ftl_write(FAR struct inode *inode, const unsigned char *buffer, #endif static int ftl_geometry(FAR struct inode *inode, struct geometry *geometry); static int ftl_ioctl(FAR struct inode *inode, int cmd, unsigned long arg); +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int ftl_unlink(FAR struct inode *inode); +#endif /**************************************************************************** * Private Data @@ -126,7 +131,7 @@ static const struct block_operations g_bops = ftl_geometry, /* geometry */ ftl_ioctl /* ioctl */ #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS - , 0 /* unlink */ + , ftl_unlink /* unlink */ #endif }; @@ -143,7 +148,12 @@ static const struct block_operations g_bops = static int ftl_open(FAR struct inode *inode) { - finfo("Entry\n"); + FAR struct ftl_struct_s *dev; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct ftl_struct_s *)inode->i_private; + + dev->refs++; return OK; } @@ -156,11 +166,29 @@ static int ftl_open(FAR struct inode *inode) static int ftl_close(FAR struct inode *inode) { + FAR struct ftl_struct_s *dev; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct ftl_struct_s *)inode->i_private; + #ifdef CONFIG_FTL_WRITEBUFFER - struct ftl_struct_s *dev = (struct ftl_struct_s *)inode->i_private; rwb_flush(&dev->rwb); #endif + if (--dev->refs == 0 && dev->unlinked) + { +#ifdef FTL_HAVE_RWBUFFER + rwb_uninitialize(&dev->rwb); +#endif +#ifdef CONFIG_FS_WRITABLE + if (dev->eblock) + { + kmm_free(dev->eblock); + } +#endif + kmm_free(dev); + } + return OK; } @@ -541,6 +569,40 @@ static int ftl_ioctl(FAR struct inode *inode, int cmd, unsigned long arg) return ret; } +/**************************************************************************** + * Name: ftl_unlink + * + * Description: Unlink the device + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int ftl_unlink(FAR struct inode *inode) +{ + FAR struct ftl_struct_s *dev; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct ftl_struct_s *)inode->i_private; + + dev->unlinked = true; + if (dev->refs == 0) + { +#ifdef FTL_HAVE_RWBUFFER + rwb_uninitialize(&dev->rwb); +#endif +#ifdef CONFIG_FS_WRITABLE + if (dev->eblock) + { + kmm_free(dev->eblock); + } +#endif + kmm_free(dev); + } + + return OK; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -628,6 +690,9 @@ int ftl_initialize_by_path(FAR const char *path, FAR struct mtd_dev_s *mtd) if (ret < 0) { ferr("ERROR: register_blockdriver failed: %d\n", -ret); +#ifdef FTL_HAVE_RWBUFFER + rwb_uninitialize(&dev->rwb); +#endif kmm_free(dev); } }