Re: [PATCH] cifs: clean up page array when uncached write send fails

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu,  6 Feb 2014 14:42:44 -0500
Jeff Layton <jlayton@xxxxxxxxxx> wrote:

> In the event that a send fails in an uncached write, or we end up
> needing to reissue it (-EAGAIN case), we'll kfree the wdata but
> the pages currently leak.
> 
> Fix this by adding a new kref release routine for uncached writedata
> that releases the pages, and have the uncached codepaths use that.
> 
> Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
> ---
>  fs/cifs/file.c | 24 +++++++++++++++---------
>  1 file changed, 15 insertions(+), 9 deletions(-)
> 
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index 853d6d1..d76c935 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -2331,9 +2331,20 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
>  }
>  
>  static void
> -cifs_uncached_writev_complete(struct work_struct *work)
> +cifs_uncached_writedata_release(struct kref *refcount)
>  {
>  	int i;
> +	struct cifs_writedata *wdata = container_of(refcount,
> +					struct cifs_writedata, refcount);
> +
> +	for (i = 0; i < wdata->nr_pages; i++)
> +		put_page(wdata->pages[i]);
> +	cifs_writedata_release(refcount);
> +}
> +
> +static void
> +cifs_uncached_writev_complete(struct work_struct *work)
> +{
>  	struct cifs_writedata *wdata = container_of(work,
>  					struct cifs_writedata, work);
>  	struct inode *inode = wdata->cfile->dentry->d_inode;
> @@ -2347,12 +2358,7 @@ cifs_uncached_writev_complete(struct work_struct *work)
>  
>  	complete(&wdata->done);
>  
> -	if (wdata->result != -EAGAIN) {
> -		for (i = 0; i < wdata->nr_pages; i++)
> -			put_page(wdata->pages[i]);
> -	}
> -
> -	kref_put(&wdata->refcount, cifs_writedata_release);
> +	kref_put(&wdata->refcount, cifs_uncached_writedata_release);
>  }
>  
>  /* attempt to send write to server, retry on any -EAGAIN errors */
> @@ -2454,7 +2460,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
>  		wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
>  		rc = cifs_uncached_retry_writev(wdata);
>  		if (rc) {
> -			kref_put(&wdata->refcount, cifs_writedata_release);
> +			kref_put(&wdata->refcount, cifs_uncached_writedata_release);
>  			break;
>  		}
>  
> @@ -2496,7 +2502,7 @@ restart_loop:
>  			}
>  		}
>  		list_del_init(&wdata->list);
> -		kref_put(&wdata->refcount, cifs_writedata_release);
> +		kref_put(&wdata->refcount, cifs_uncached_writedata_release);
>  	}
>  
>  	if (total_written > 0)


Hi Stevem

I just realized this patch isn't quite right. We have to propagate
the kref release function to the ->async_writev code. Please hold off
on merging this yet until I can do a v2.

Thanks,
-- 
Jeff Layton <jlayton@xxxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux