@@ -192,13 +192,32 @@ static int spufs_fill_dir(struct dentry *dir,
192
192
return - ENOMEM ;
193
193
ret = spufs_new_file (dir -> d_sb , dentry , files -> ops ,
194
194
files -> mode & mode , files -> size , ctx );
195
- if (ret )
195
+ if (ret ) {
196
+ dput (dentry );
196
197
return ret ;
198
+ }
197
199
files ++ ;
198
200
}
199
201
return 0 ;
200
202
}
201
203
204
+ static void unuse_gang (struct dentry * dir )
205
+ {
206
+ struct inode * inode = dir -> d_inode ;
207
+ struct spu_gang * gang = SPUFS_I (inode )-> i_gang ;
208
+
209
+ if (gang ) {
210
+ bool dead ;
211
+
212
+ inode_lock (inode ); // exclusion with spufs_create_context()
213
+ dead = !-- gang -> alive ;
214
+ inode_unlock (inode );
215
+
216
+ if (dead )
217
+ simple_recursive_removal (dir , NULL );
218
+ }
219
+ }
220
+
202
221
static int spufs_dir_close (struct inode * inode , struct file * file )
203
222
{
204
223
struct inode * parent ;
@@ -213,6 +232,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
213
232
inode_unlock (parent );
214
233
WARN_ON (ret );
215
234
235
+ unuse_gang (dir -> d_parent );
216
236
return dcache_dir_close (inode , file );
217
237
}
218
238
@@ -405,7 +425,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
405
425
{
406
426
int ret ;
407
427
int affinity ;
408
- struct spu_gang * gang ;
428
+ struct spu_gang * gang = SPUFS_I ( inode ) -> i_gang ;
409
429
struct spu_context * neighbor ;
410
430
struct path path = {.mnt = mnt , .dentry = dentry };
411
431
@@ -420,11 +440,15 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
420
440
if ((flags & SPU_CREATE_ISOLATE ) && !isolated_loader )
421
441
return - ENODEV ;
422
442
423
- gang = NULL ;
443
+ if (gang ) {
444
+ if (!gang -> alive )
445
+ return - ENOENT ;
446
+ gang -> alive ++ ;
447
+ }
448
+
424
449
neighbor = NULL ;
425
450
affinity = flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU );
426
451
if (affinity ) {
427
- gang = SPUFS_I (inode )-> i_gang ;
428
452
if (!gang )
429
453
return - EINVAL ;
430
454
mutex_lock (& gang -> aff_mutex );
@@ -436,8 +460,11 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
436
460
}
437
461
438
462
ret = spufs_mkdir (inode , dentry , flags , mode & 0777 );
439
- if (ret )
463
+ if (ret ) {
464
+ if (neighbor )
465
+ put_spu_context (neighbor );
440
466
goto out_aff_unlock ;
467
+ }
441
468
442
469
if (affinity ) {
443
470
spufs_set_affinity (flags , SPUFS_I (d_inode (dentry ))-> i_ctx ,
@@ -453,6 +480,8 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
453
480
out_aff_unlock :
454
481
if (affinity )
455
482
mutex_unlock (& gang -> aff_mutex );
483
+ if (ret && gang )
484
+ gang -> alive -- ; // can't reach 0
456
485
return ret ;
457
486
}
458
487
@@ -482,6 +511,7 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, umode_t mode)
482
511
inode -> i_fop = & simple_dir_operations ;
483
512
484
513
d_instantiate (dentry , inode );
514
+ dget (dentry );
485
515
inc_nlink (dir );
486
516
inc_nlink (d_inode (dentry ));
487
517
return ret ;
@@ -492,6 +522,21 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, umode_t mode)
492
522
return ret ;
493
523
}
494
524
525
+ static int spufs_gang_close (struct inode * inode , struct file * file )
526
+ {
527
+ unuse_gang (file -> f_path .dentry );
528
+ return dcache_dir_close (inode , file );
529
+ }
530
+
531
+ static const struct file_operations spufs_gang_fops = {
532
+ .open = dcache_dir_open ,
533
+ .release = spufs_gang_close ,
534
+ .llseek = dcache_dir_lseek ,
535
+ .read = generic_read_dir ,
536
+ .iterate_shared = dcache_readdir ,
537
+ .fsync = noop_fsync ,
538
+ };
539
+
495
540
static int spufs_gang_open (const struct path * path )
496
541
{
497
542
int ret ;
@@ -511,7 +556,7 @@ static int spufs_gang_open(const struct path *path)
511
556
return PTR_ERR (filp );
512
557
}
513
558
514
- filp -> f_op = & simple_dir_operations ;
559
+ filp -> f_op = & spufs_gang_fops ;
515
560
fd_install (ret , filp );
516
561
return ret ;
517
562
}
@@ -526,10 +571,8 @@ static int spufs_create_gang(struct inode *inode,
526
571
ret = spufs_mkgang (inode , dentry , mode & 0777 );
527
572
if (!ret ) {
528
573
ret = spufs_gang_open (& path );
529
- if (ret < 0 ) {
530
- int err = simple_rmdir (inode , dentry );
531
- WARN_ON (err );
532
- }
574
+ if (ret < 0 )
575
+ unuse_gang (dentry );
533
576
}
534
577
return ret ;
535
578
}
0 commit comments