From 4db8c826d7158fdde485e158d5d30c2105d7b2fc Mon Sep 17 00:00:00 2001 From: Yang ChungFan Date: Tue, 6 Aug 2019 07:31:57 -0600 Subject: [PATCH] drivers/pipes: Use inode reference counter instead of device reference counter to handle dup(). I found that if I dup() a pipe, the reference counter d_refs is not increased. If I close any of the fd, backed by the same pipe, the pipe will be freed. This causes any further usage on the fd referencing a non existent pipe. This change uses the inode reference counter, which is properly maintained during dup(). --- drivers/pipes/pipe.c | 2 +- drivers/pipes/pipe_common.c | 16 ++++++---------- drivers/pipes/pipe_common.h | 1 - 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/pipes/pipe.c b/drivers/pipes/pipe.c index 4a82bdb931..3ce23ab211 100644 --- a/drivers/pipes/pipe.c +++ b/drivers/pipes/pipe.c @@ -149,7 +149,7 @@ static int pipe_close(FAR struct file *filep) /* Perform common close operations */ ret = pipecommon_close(filep); - if (ret == 0 && dev->d_refs == 0) + if (ret == 0 && inode->i_crefs == 1) { /* Release the pipe when there are no further open references to it. */ diff --git a/drivers/pipes/pipe_common.c b/drivers/pipes/pipe_common.c index 39b258014f..9fc5da07f0 100644 --- a/drivers/pipes/pipe_common.c +++ b/drivers/pipes/pipe_common.c @@ -231,7 +231,7 @@ int pipecommon_open(FAR struct file *filep) * is first opened. */ - if (dev->d_refs == 0 && dev->d_buffer == NULL) + if (inode->i_crefs == 1 && dev->d_buffer == NULL) { dev->d_buffer = (FAR uint8_t *)kmm_malloc(dev->d_bufsize); if (!dev->d_buffer) @@ -241,9 +241,6 @@ int pipecommon_open(FAR struct file *filep) } } - /* Increment the reference count on the pipe instance */ - - dev->d_refs++; /* If opened for writing, increment the count of writers on the pipe instance */ @@ -321,7 +318,7 @@ int pipecommon_close(FAR struct file *filep) FAR struct pipe_dev_s *dev = inode->i_private; int sval; - DEBUGASSERT(dev && dev->d_refs > 0); + DEBUGASSERT(dev && filep->f_inode->i_crefs > 0); /* Make sure that we have exclusive access to the device structure. * NOTE: close() is supposed to return EINTR if interrupted, however @@ -334,11 +331,11 @@ int pipecommon_close(FAR struct file *filep) * still outstanding references to the pipe. */ - /* Check if the decremented reference count would go to zero */ + /* Check if the decremented inode reference count would go to zero */ - if (--dev->d_refs > 0) + if (inode->i_crefs > 1) { - /* No more references.. If opened for writing, decrement the count of + /* More references.. If opened for writing, decrement the count of * writers on the pipe instance. */ @@ -396,7 +393,6 @@ int pipecommon_close(FAR struct file *filep) dev->d_wrndx = 0; dev->d_rdndx = 0; - dev->d_refs = 0; dev->d_nwriters = 0; dev->d_nreaders = 0; @@ -896,7 +892,7 @@ int pipecommon_unlink(FAR struct inode *inode) /* Are the any open references to the driver? */ - if (dev->d_refs == 0) + if (inode->i_crefs == 1) { /* No.. free the buffer (if there is one) */ diff --git a/drivers/pipes/pipe_common.h b/drivers/pipes/pipe_common.h index 3c4204a4cb..5a822b8285 100644 --- a/drivers/pipes/pipe_common.h +++ b/drivers/pipes/pipe_common.h @@ -135,7 +135,6 @@ struct pipe_dev_s pipe_ndx_t d_wrndx; /* Index in d_buffer to save next byte written */ pipe_ndx_t d_rdndx; /* Index in d_buffer to return the next byte read */ pipe_ndx_t d_bufsize; /* allocated size of d_buffer in bytes */ - uint8_t d_refs; /* References counts on pipe (limited to 255) */ uint8_t d_nwriters; /* Number of reference counts for write access */ uint8_t d_nreaders; /* Number of reference counts for read access */ uint8_t d_pipeno; /* Pipe minor number */