[Cbe-oss-dev] [PATCH 4/6] spufs: extension of spu_create to support affinity definition

André Detsch adetsch at br.ibm.com
Tue Feb 13 04:48:57 EST 2007


Arnd Bergmann wrote:
> On Monday 12 February 2007 02:14, Andre Detsch wrote:
>> Subject: spufs: extension of spu_create to support affinity definition
>> From: Andre Detsch <adetsch at br.ibm.com>
>>
>> This patch adds support for additional flags at spu_create, which relate
>> to the establishment of affinity between contexts and contexts to memory.
>> A fourth, optional, parameter is supported. This parameter represent
>> a affinity neighbor of the context being created, and is used when defining
>> SPU-SPU affinity.
>> Affinity is represented as a doubly linked list of spu_contexts.
> 
> I couldn't see a place where you get a reference count for the contexts
> you link to each other. Have you checked that this is safe to do?
> Did I miss something there?
> 
>> @@ -307,11 +307,102 @@ out:
>>  	return ret;
>>  }
>>  
>> -static int spufs_create_context(struct inode *inode,
>> -			struct dentry *dentry,
>> -			struct vfsmount *mnt, int flags, int mode)
>> +static struct spu_context *
>> +spufs_assert_affinity(unsigned int flags, struct spu_gang *gang,
>> +						struct file *filp)
>> +{
>> +	struct spu_context *tmp, *neighbor = NULL;
>> +	int count, node;
>> +	int aff_supp;
>> +
>> +	aff_supp = !list_empty(&(list_entry(be_spu_info[0].available_spus.next,
>> +					struct spu, available_list))->aff_list);
>> +
>> +	if (!aff_supp)
>> +		return ERR_PTR(-ENOTSUPP);
> 
> ENOTSUPP is an NFS specific error code, you shouldn't use it here, especially
> if this is passed back to user space. I'd say it should either be silently
> ignored so that programs with affinity definitions still run on the PS3
> without changes, or return -EINVAL.

Ok, I'll change to -EINVAL.

> 
>> +static void
>> +spufs_set_affinity(unsigned int flags, struct spu_context *ctx,
>> +					struct spu_context *neighbor)
>> +{
>> +	if (flags & SPU_CREATE_AFFINITY_MEM) {
>> +		ctx->gang->aff_ref_point = ctx;
>> +		ctx->aff_flags |= AFF_HAS_MEM_AFFINITY;
>> +	}
>> +	if (flags & SPU_CREATE_AFFINITY_SPU) {
>> +		if (list_empty(&neighbor->aff_list)) {
>> +			list_add_tail(&neighbor->aff_list,
>> +				&ctx->gang->aff_list_head);
>> +			neighbor->aff_flags |= AFF_SUBLIST_HEAD;
>> +		}
> 
> Why do we need the extra aff_flags property? The information seems
> a little redundant considering we already have ctx->flags and we
> can look into list_empty(aff_list) etc.

I agree AFF_HAS_SPU_AFFINITY flag is redundant with 
list_empty(aff_list). However, as I see, AFF_HAS_MEM_AFFINITY and 
AFF_SUBLIST_HEAD are not.

> 
>> +static int
>> +spufs_create_context(struct inode *inode, struct dentry *dentry,
>> +			struct vfsmount *mnt, int flags, int mode,
>> +			struct file *aff_filp)
>>  {
>>  	int ret;
>> +	struct spu_gang *gang = NULL;
>> +	struct spu_context *neighbor = NULL;
>>  
>>  	ret = -EPERM;
>>  	if ((flags & SPU_CREATE_NOSCHED) &&
> 
> style: don't initialize local variables in their definition.

Ok.

>> @@ -326,10 +417,29 @@ static int spufs_create_context(struct i
>>  	ret = -ENODEV;
>>  	if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader)
>>  		goto out_unlock;
>> +	if (flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU)) {
>> +		gang = SPUFS_I(inode)->i_gang;
>> +		mutex_lock(&gang->aff_mutex);
>> +		neighbor = spufs_assert_affinity(flags, gang, aff_filp);
>> +		if (IS_ERR(neighbor)) {
>> +			ret = PTR_ERR(neighbor);
>> +			mutex_unlock(&gang->aff_mutex);
>> +			goto out_unlock;
>> +		}
>> +	}
> 
> this looks wrong, you shouldn't release a mutex in the error path
> before the goto, better jump to a target where you unlock.
> 
> It's too easy to introduce a bug here if you add another failure
> path and forget the unlock there.

Ok, I'll try to adjust this.

>>  	ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO);
>> -	if (ret)
>> +	if (ret) {
>> +		if (flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU))
>> +			mutex_unlock(&gang->aff_mutex);
>>  		goto out_unlock;
>> +	}
>> +
>> +	if (flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU)) {
>> +		spufs_set_affinity(flags, SPUFS_I(dentry->d_inode)->i_ctx,
>> +					neighbor);
>> +		mutex_unlock(&gang->aff_mutex);
>> +	}
> 
> same for these two.

Ok.

>> -asmlinkage long sys_spu_create(const char __user *pathname,
>> -					unsigned int flags, mode_t mode)
>> +asmlinkage long do_spu_create(const char __user *pathname, unsigned int 
>> flags,
>> +				mode_t mode, struct file *filp)
>>  {
>>  	char *tmp;
>>  	int ret;
> 
> calling the fourth argument filp in all these functions is a little
> misleading, since it's not the filp for the spu itself. Better call
> it 'neighbor' or something like that.

Ok.

>> @@ -90,7 +90,10 @@ asmlinkage long sys_spu_create(const cha
>>  		ret = path_lookup(tmp, LOOKUP_PARENT|
>>  				LOOKUP_OPEN|LOOKUP_CREATE, &nd);
>>  		if (!ret) {
>> -			ret = spufs_create(&nd, flags, mode);
>> +			if (flags & SPU_CREATE_AFFINITY_SPU)
>> +				ret = spufs_create(&nd, flags, mode, filp);
>> +			else
>> +				ret = spufs_create(&nd, flags, mode, NULL);
>>  			path_release(&nd);
>>  		}
>>  		putname(tmp);
> 
> Do you need that check again here? It looks like filp is already
> NULL when not SPU_CREATE_AFFINITY_SPU.

Right, the check is not actually needed.



More information about the cbe-oss-dev mailing list