[Cbe-oss-dev] [PATCH] fix state_mutex leaks

Luke Browning lukebr at linux.vnet.ibm.com
Wed Jan 30 02:59:19 EST 2008


On Thu, 2008-01-17 at 14:51 +0100, Christoph Hellwig wrote:
> Fix various state_mutex leaks.  The worst one was introduced by the
> interrutible state_mutex conversion but there've been a few before
> aswell.   Notably spufs_wait now returns without the state_mutex held
> when returning an error, which actually cleans up some code aswell.
> 
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> 

I like this approach a lot better.  You mispelled bookkeeping
(bookkepping) in a couple of places and you have a bug below.

> Index: powerpc/arch/powerpc/platforms/cell/spufs/file.c
> ===================================================================
> --- powerpc.orig/arch/powerpc/platforms/cell/spufs/file.c	2008-01-14 18:11:42.000000000 +0100
> +++ powerpc/arch/powerpc/platforms/cell/spufs/file.c	2008-01-17 14:49:01.000000000 +0100
> @@ -357,6 +357,7 @@ static unsigned long spufs_ps_nopfn(stru
>  {
>  	struct spu_context *ctx = vma->vm_file->private_data;
>  	unsigned long area, offset = address - vma->vm_start;
> +	int ret = 0;
> 
>  	offset += vma->vm_pgoff << PAGE_SHIFT;
>  	if (offset >= ps_size)
> @@ -375,14 +376,15 @@ static unsigned long spufs_ps_nopfn(stru
> 
>  	if (ctx->state == SPU_STATE_SAVED) {
>  		up_read(&current->mm->mmap_sem);
> -		spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
> +		ret = spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
>  		down_read(&current->mm->mmap_sem);
>  	} else {
>  		area = ctx->spu->problem_phys + ps_offs;
>  		vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT);
>  	}
> 
> -	spu_release(ctx);
> +	if (!ret)
> +		spu_release(ctx);
>  	return NOPFN_REFAULT;
>  }
> 
> @@ -749,23 +751,25 @@ static ssize_t spufs_ibox_read(struct fi
> 
>  	count = spu_acquire(ctx);
>  	if (count)
> -		return count;
> +		goto out;
> 
>  	/* wait only for the first element */
>  	count = 0;
>  	if (file->f_flags & O_NONBLOCK) {
> -		if (!spu_ibox_read(ctx, &ibox_data))
> +		if (!spu_ibox_read(ctx, &ibox_data)) {
>  			count = -EAGAIN;
> +			goto out_unlock;
> +		}
>  	} else {
>  		count = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
> +		if (count)
> +			goto out;
>  	}
> -	if (count)
> -		goto out;
> 
>  	/* if we can't write at all, return -EFAULT */
>  	count = __put_user(ibox_data, udata);
>  	if (count)
> -		goto out;
> +		goto out_unlock;
> 
>  	for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
>  		int ret;
> @@ -782,9 +786,9 @@ static ssize_t spufs_ibox_read(struct fi
>  			break;
>  	}
> 
> -out:
> +out_unlock:
>  	spu_release(ctx);
> -
> +out:
>  	return count;
>  }
> 
> @@ -899,7 +903,7 @@ static ssize_t spufs_wbox_write(struct f
> 
>  	count = spu_acquire(ctx);
>  	if (count)
> -		return count;
> +		goto out;
> 
>  	/*
>  	 * make sure we can at least write one element, by waiting
> @@ -907,14 +911,16 @@ static ssize_t spufs_wbox_write(struct f
>  	 */
>  	count = 0;
>  	if (file->f_flags & O_NONBLOCK) {
> -		if (!spu_wbox_write(ctx, wbox_data))
> +		if (!spu_wbox_write(ctx, wbox_data)) {
>  			count = -EAGAIN;
> +			goto out_unlock;
> +		}
>  	} else {
>  		count = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
> +		if (count)
> +			goto out;
>  	}
> 
> -	if (count)
> -		goto out;
> 
>  	/* write as much as possible */
>  	for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
> @@ -928,8 +934,9 @@ static ssize_t spufs_wbox_write(struct f
>  			break;
>  	}
> 
> -out:
> +out_unlock:
>  	spu_release(ctx);
> +out:
>  	return count;
>  }
> 
> @@ -1589,15 +1596,15 @@ static ssize_t spufs_mfc_read(struct fil
>  		else
>  			/* XXX(hch): shouldn't we clear ret here? */
>  			ctx->tagwait &= ~status;
> +		spu_release(ctx);
>  	} else {
>  		ret = spufs_wait(ctx->mfc_wq,
>  			   spufs_read_mfc_tagstatus(ctx, &status));
> +		if (ret)
> +			goto out;
>  	}
>  	spu_release(ctx);

You have two spu_releases() in a row here.

Cheers, Luke





More information about the cbe-oss-dev mailing list