On Wed, Jun 17, 2020 at 11:13:32PM +0530, Souptick Joarder wrote: > On Wed, Jun 17, 2020 at 4:43 PM Dan Carpenter <dan.carpenter@xxxxxxxxxx> wrote: > > > > On Wed, Jun 17, 2020 at 07:57:20AM +0530, Souptick Joarder wrote: > > > There is a bug, when get_user_pages() failed but partially pinned > > > pages are not unpinned. Fixed it. > > > > > > Also, int is more appropriate type for rv. Changed it. > > > > > > Signed-off-by: Souptick Joarder <jrdr.linux@xxxxxxxxx> > > > Cc: John Hubbard <jhubbard@xxxxxxxxxx> > > > Cc: Bharath Vedartham <linux.bhar@xxxxxxxxx> > > > Cc: Dan Carpenter <dan.carpenter@xxxxxxxxxx> > > > --- > > > drivers/staging/kpc2000/kpc_dma/fileops.c | 6 +++++- > > > 1 file changed, 5 insertions(+), 1 deletion(-) > > > > > > diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c > > > index 8975346..b136353 100644 > > > --- a/drivers/staging/kpc2000/kpc_dma/fileops.c > > > +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c > > > @@ -35,7 +35,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv, > > > unsigned long iov_base, size_t iov_len) > > > { > > > unsigned int i = 0; > > > - long rv = 0; > > > + int rv = 0; > > > struct kpc_dma_device *ldev; > > > struct aio_cb_data *acd; > > > DECLARE_COMPLETION_ONSTACK(done); > > > @@ -193,6 +193,10 @@ static int kpc_dma_transfer(struct dev_private_data *priv, > > > put_page(acd->user_pages[i]); > > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > > > > > err_get_user_pages: > > > + if (rv > 0) { > > > + for (i = 0; i < rv; i++) > > > + put_pages(acd->user_pages[i]) > > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > > > > + } > > > > This isn't a complete fix. "rv" is the negative error code but here we > > are returning a positive value on this path. > > In case of error of get_user_pages(), it will return -errno, 0 and 3rd one is > (rv > 0 && rv != acd->page_count). When rv is -errno or 0 there is no need > to call put_pages() in error path. But for 3rd case partially mapped pages > need to unpin. > > Correct me if I am missing anything. > 182 kfree(acd); 183 } 184 return rv; 185 186 err_descr_too_many: 187 unlock_engine(ldev); 188 dma_unmap_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, ldev->dir); 189 sg_free_table(&acd->sgt); 190 err_dma_map_sg: 191 err_alloc_sg_table: 192 for (i = 0 ; i < acd->page_count ; i++) 193 put_page(acd->user_pages[i]); 194 195 err_get_user_pages: 196 if (rv > 0) { ^^^^^^ "rv" is positive. 197 for (i = 0; i < rv; i++) 198 put_pages(acd->user_pages[i]) 199 } 200 kfree(acd->user_pages); 201 err_alloc_userpages: 202 kfree(acd); 203 dev_dbg(&priv->ldev->pldev->dev, "%s returning with error %ld\n", __func__, rv); 204 return rv; ^^ "rv" is still positive but it should be -EFAULT. 205 } regards, dan carpenter _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel