Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pull-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull dcache fixes from Al Viro:
"Fixes for bugs caught as part of tree-in-dcache work.

Mostly dentry refcount mishandling"

* tag 'pull-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
hypfs_create_cpu_files(): add missing check for hypfs_mkdir() failure
qibfs: fix _another_ leak
spufs: fix a leak in spufs_create_context()
spufs: fix gang directory lifetimes
spufs: fix a leak on spufs_new_file() failure

+59 -10
+1
arch/powerpc/platforms/cell/spufs/gang.c
··· 25 25 mutex_init(&gang->aff_mutex); 26 26 INIT_LIST_HEAD(&gang->list); 27 27 INIT_LIST_HEAD(&gang->aff_list_head); 28 + gang->alive = 1; 28 29 29 30 out: 30 31 return gang;
+53 -10
arch/powerpc/platforms/cell/spufs/inode.c
··· 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; 202 + } 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 + } 200 219 } 201 220 202 221 static int spufs_dir_close(struct inode *inode, struct file *file) ··· 232 213 inode_unlock(parent); 233 214 WARN_ON(ret); 234 215 216 + unuse_gang(dir->d_parent); 235 217 return dcache_dir_close(inode, file); 236 218 } 237 219 ··· 425 405 { 426 406 int ret; 427 407 int affinity; 428 - struct spu_gang *gang; 408 + struct spu_gang *gang = SPUFS_I(inode)->i_gang; 429 409 struct spu_context *neighbor; 430 410 struct path path = {.mnt = mnt, .dentry = dentry}; 431 411 ··· 440 420 if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader) 441 421 return -ENODEV; 442 422 443 - gang = NULL; 423 + if (gang) { 424 + if (!gang->alive) 425 + return -ENOENT; 426 + gang->alive++; 427 + } 428 + 444 429 neighbor = NULL; 445 430 affinity = flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU); 446 431 if (affinity) { 447 - gang = SPUFS_I(inode)->i_gang; 448 432 if (!gang) 449 433 return -EINVAL; 450 434 mutex_lock(&gang->aff_mutex); ··· 460 436 } 461 437 462 438 ret = spufs_mkdir(inode, dentry, flags, mode & 0777); 463 - if (ret) 439 + if (ret) { 440 + if (neighbor) 441 + put_spu_context(neighbor); 464 442 goto out_aff_unlock; 443 + } 465 444 466 445 if (affinity) { 467 446 spufs_set_affinity(flags, SPUFS_I(d_inode(dentry))->i_ctx, ··· 480 453 out_aff_unlock: 481 454 if (affinity) 482 455 mutex_unlock(&gang->aff_mutex); 456 + if (ret && gang) 457 + gang->alive--; // can't reach 0 483 458 return ret; 484 459 } 485 460 ··· 511 482 inode->i_fop = &simple_dir_operations; 512 483 513 484 d_instantiate(dentry, inode); 485 + dget(dentry); 514 486 inc_nlink(dir); 515 487 inc_nlink(d_inode(dentry)); 516 488 return ret; ··· 521 491 out: 522 492 return ret; 523 493 } 494 + 495 + static int spufs_gang_close(struct inode *inode, struct file *file) 496 + { 497 + unuse_gang(file->f_path.dentry); 498 + return dcache_dir_close(inode, file); 499 + } 500 + 501 + static const struct file_operations spufs_gang_fops = { 502 + .open = dcache_dir_open, 503 + .release = spufs_gang_close, 504 + .llseek = dcache_dir_lseek, 505 + .read = generic_read_dir, 506 + .iterate_shared = dcache_readdir, 507 + .fsync = noop_fsync, 508 + }; 524 509 525 510 static int spufs_gang_open(const struct path *path) 526 511 { ··· 556 511 return PTR_ERR(filp); 557 512 } 558 513 559 - filp->f_op = &simple_dir_operations; 514 + filp->f_op = &spufs_gang_fops; 560 515 fd_install(ret, filp); 561 516 return ret; 562 517 } ··· 571 526 ret = spufs_mkgang(inode, dentry, mode & 0777); 572 527 if (!ret) { 573 528 ret = spufs_gang_open(&path); 574 - if (ret < 0) { 575 - int err = simple_rmdir(inode, dentry); 576 - WARN_ON(err); 577 - } 529 + if (ret < 0) 530 + unuse_gang(dentry); 578 531 } 579 532 return ret; 580 533 }
+2
arch/powerpc/platforms/cell/spufs/spufs.h
··· 151 151 int aff_flags; 152 152 struct spu *aff_ref_spu; 153 153 atomic_t aff_sched_count; 154 + 155 + int alive; 154 156 }; 155 157 156 158 /* Flag bits for spu_gang aff_flags */
+2
arch/s390/hypfs/hypfs_diag_fs.c
··· 209 209 snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_get_info_type(), 210 210 cpu_info)); 211 211 cpu_dir = hypfs_mkdir(cpus_dir, buffer); 212 + if (IS_ERR(cpu_dir)) 213 + return PTR_ERR(cpu_dir); 212 214 rc = hypfs_create_u64(cpu_dir, "mgmtime", 213 215 cpu_info__acc_time(diag204_get_info_type(), cpu_info) - 214 216 cpu_info__lp_time(diag204_get_info_type(), cpu_info));
+1
drivers/infiniband/hw/qib/qib_fs.c
··· 55 55 struct inode *inode = new_inode(dir->i_sb); 56 56 57 57 if (!inode) { 58 + dput(dentry); 58 59 error = -EPERM; 59 60 goto bail; 60 61 }