diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2010-06-03 03:03:39 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-06-03 03:03:39 -0400 |
commit | f324e4cb2cadd9a42932c8a158e761ae31b88e72 (patch) | |
tree | deb742349c87becaa711a807c0c13b5b7a857c02 /fs | |
parent | 5869d2c387e75814334697c9d702d91b7c63a308 (diff) |
jffs2: Fix in-core inode leaks on error paths
Pointed out by Al Viro.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/jffs2/dir.c | 115 |
1 files changed, 56 insertions, 59 deletions
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 7aa4417e085f..cb7ef34d384c 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -360,8 +360,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
360 | /* Eeek. Wave bye bye */ | 360 | /* Eeek. Wave bye bye */ |
361 | mutex_unlock(&f->sem); | 361 | mutex_unlock(&f->sem); |
362 | jffs2_complete_reservation(c); | 362 | jffs2_complete_reservation(c); |
363 | jffs2_clear_inode(inode); | 363 | ret = PTR_ERR(fn); |
364 | return PTR_ERR(fn); | 364 | goto fail; |
365 | } | 365 | } |
366 | 366 | ||
367 | /* We use f->target field to store the target path. */ | 367 | /* We use f->target field to store the target path. */ |
@@ -370,8 +370,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
370 | printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); | 370 | printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); |
371 | mutex_unlock(&f->sem); | 371 | mutex_unlock(&f->sem); |
372 | jffs2_complete_reservation(c); | 372 | jffs2_complete_reservation(c); |
373 | jffs2_clear_inode(inode); | 373 | ret = -ENOMEM; |
374 | return -ENOMEM; | 374 | goto fail; |
375 | } | 375 | } |
376 | 376 | ||
377 | memcpy(f->target, target, targetlen + 1); | 377 | memcpy(f->target, target, targetlen + 1); |
@@ -386,30 +386,24 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
386 | jffs2_complete_reservation(c); | 386 | jffs2_complete_reservation(c); |
387 | 387 | ||
388 | ret = jffs2_init_security(inode, dir_i); | 388 | ret = jffs2_init_security(inode, dir_i); |
389 | if (ret) { | 389 | if (ret) |
390 | jffs2_clear_inode(inode); | 390 | goto fail; |
391 | return ret; | 391 | |
392 | } | ||
393 | ret = jffs2_init_acl_post(inode); | 392 | ret = jffs2_init_acl_post(inode); |
394 | if (ret) { | 393 | if (ret) |
395 | jffs2_clear_inode(inode); | 394 | goto fail; |
396 | return ret; | ||
397 | } | ||
398 | 395 | ||
399 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, | 396 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, |
400 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 397 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
401 | if (ret) { | 398 | if (ret) |
402 | /* Eep. */ | 399 | goto fail; |
403 | jffs2_clear_inode(inode); | ||
404 | return ret; | ||
405 | } | ||
406 | 400 | ||
407 | rd = jffs2_alloc_raw_dirent(); | 401 | rd = jffs2_alloc_raw_dirent(); |
408 | if (!rd) { | 402 | if (!rd) { |
409 | /* Argh. Now we treat it like a normal delete */ | 403 | /* Argh. Now we treat it like a normal delete */ |
410 | jffs2_complete_reservation(c); | 404 | jffs2_complete_reservation(c); |
411 | jffs2_clear_inode(inode); | 405 | ret = -ENOMEM; |
412 | return -ENOMEM; | 406 | goto fail; |
413 | } | 407 | } |
414 | 408 | ||
415 | dir_f = JFFS2_INODE_INFO(dir_i); | 409 | dir_f = JFFS2_INODE_INFO(dir_i); |
@@ -437,8 +431,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
437 | jffs2_complete_reservation(c); | 431 | jffs2_complete_reservation(c); |
438 | jffs2_free_raw_dirent(rd); | 432 | jffs2_free_raw_dirent(rd); |
439 | mutex_unlock(&dir_f->sem); | 433 | mutex_unlock(&dir_f->sem); |
440 | jffs2_clear_inode(inode); | 434 | ret = PTR_ERR(fd); |
441 | return PTR_ERR(fd); | 435 | goto fail; |
442 | } | 436 | } |
443 | 437 | ||
444 | dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); | 438 | dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); |
@@ -454,6 +448,11 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
454 | 448 | ||
455 | d_instantiate(dentry, inode); | 449 | d_instantiate(dentry, inode); |
456 | return 0; | 450 | return 0; |
451 | |||
452 | fail: | ||
453 | make_bad_inode(inode); | ||
454 | iput(inode); | ||
455 | return ret; | ||
457 | } | 456 | } |
458 | 457 | ||
459 | 458 | ||
@@ -519,8 +518,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
519 | /* Eeek. Wave bye bye */ | 518 | /* Eeek. Wave bye bye */ |
520 | mutex_unlock(&f->sem); | 519 | mutex_unlock(&f->sem); |
521 | jffs2_complete_reservation(c); | 520 | jffs2_complete_reservation(c); |
522 | jffs2_clear_inode(inode); | 521 | ret = PTR_ERR(fn); |
523 | return PTR_ERR(fn); | 522 | goto fail; |
524 | } | 523 | } |
525 | /* No data here. Only a metadata node, which will be | 524 | /* No data here. Only a metadata node, which will be |
526 | obsoleted by the first data write | 525 | obsoleted by the first data write |
@@ -531,30 +530,24 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
531 | jffs2_complete_reservation(c); | 530 | jffs2_complete_reservation(c); |
532 | 531 | ||
533 | ret = jffs2_init_security(inode, dir_i); | 532 | ret = jffs2_init_security(inode, dir_i); |
534 | if (ret) { | 533 | if (ret) |
535 | jffs2_clear_inode(inode); | 534 | goto fail; |
536 | return ret; | 535 | |
537 | } | ||
538 | ret = jffs2_init_acl_post(inode); | 536 | ret = jffs2_init_acl_post(inode); |
539 | if (ret) { | 537 | if (ret) |
540 | jffs2_clear_inode(inode); | 538 | goto fail; |
541 | return ret; | ||
542 | } | ||
543 | 539 | ||
544 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, | 540 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, |
545 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 541 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
546 | if (ret) { | 542 | if (ret) |
547 | /* Eep. */ | 543 | goto fail; |
548 | jffs2_clear_inode(inode); | ||
549 | return ret; | ||
550 | } | ||
551 | 544 | ||
552 | rd = jffs2_alloc_raw_dirent(); | 545 | rd = jffs2_alloc_raw_dirent(); |
553 | if (!rd) { | 546 | if (!rd) { |
554 | /* Argh. Now we treat it like a normal delete */ | 547 | /* Argh. Now we treat it like a normal delete */ |
555 | jffs2_complete_reservation(c); | 548 | jffs2_complete_reservation(c); |
556 | jffs2_clear_inode(inode); | 549 | ret = -ENOMEM; |
557 | return -ENOMEM; | 550 | goto fail; |
558 | } | 551 | } |
559 | 552 | ||
560 | dir_f = JFFS2_INODE_INFO(dir_i); | 553 | dir_f = JFFS2_INODE_INFO(dir_i); |
@@ -582,8 +575,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
582 | jffs2_complete_reservation(c); | 575 | jffs2_complete_reservation(c); |
583 | jffs2_free_raw_dirent(rd); | 576 | jffs2_free_raw_dirent(rd); |
584 | mutex_unlock(&dir_f->sem); | 577 | mutex_unlock(&dir_f->sem); |
585 | jffs2_clear_inode(inode); | 578 | ret = PTR_ERR(fd); |
586 | return PTR_ERR(fd); | 579 | goto fail; |
587 | } | 580 | } |
588 | 581 | ||
589 | dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); | 582 | dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); |
@@ -600,6 +593,11 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
600 | 593 | ||
601 | d_instantiate(dentry, inode); | 594 | d_instantiate(dentry, inode); |
602 | return 0; | 595 | return 0; |
596 | |||
597 | fail: | ||
598 | make_bad_inode(inode); | ||
599 | iput(inode); | ||
600 | return ret; | ||
603 | } | 601 | } |
604 | 602 | ||
605 | static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) | 603 | static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) |
@@ -693,8 +691,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
693 | /* Eeek. Wave bye bye */ | 691 | /* Eeek. Wave bye bye */ |
694 | mutex_unlock(&f->sem); | 692 | mutex_unlock(&f->sem); |
695 | jffs2_complete_reservation(c); | 693 | jffs2_complete_reservation(c); |
696 | jffs2_clear_inode(inode); | 694 | ret = PTR_ERR(fn); |
697 | return PTR_ERR(fn); | 695 | goto fail; |
698 | } | 696 | } |
699 | /* No data here. Only a metadata node, which will be | 697 | /* No data here. Only a metadata node, which will be |
700 | obsoleted by the first data write | 698 | obsoleted by the first data write |
@@ -705,30 +703,24 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
705 | jffs2_complete_reservation(c); | 703 | jffs2_complete_reservation(c); |
706 | 704 | ||
707 | ret = jffs2_init_security(inode, dir_i); | 705 | ret = jffs2_init_security(inode, dir_i); |
708 | if (ret) { | 706 | if (ret) |
709 | jffs2_clear_inode(inode); | 707 | goto fail; |
710 | return ret; | 708 | |
711 | } | ||
712 | ret = jffs2_init_acl_post(inode); | 709 | ret = jffs2_init_acl_post(inode); |
713 | if (ret) { | 710 | if (ret) |
714 | jffs2_clear_inode(inode); | 711 | goto fail; |
715 | return ret; | ||
716 | } | ||
717 | 712 | ||
718 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, | 713 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, |
719 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 714 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
720 | if (ret) { | 715 | if (ret) |
721 | /* Eep. */ | 716 | goto fail; |
722 | jffs2_clear_inode(inode); | ||
723 | return ret; | ||
724 | } | ||
725 | 717 | ||
726 | rd = jffs2_alloc_raw_dirent(); | 718 | rd = jffs2_alloc_raw_dirent(); |
727 | if (!rd) { | 719 | if (!rd) { |
728 | /* Argh. Now we treat it like a normal delete */ | 720 | /* Argh. Now we treat it like a normal delete */ |
729 | jffs2_complete_reservation(c); | 721 | jffs2_complete_reservation(c); |
730 | jffs2_clear_inode(inode); | 722 | ret = -ENOMEM; |
731 | return -ENOMEM; | 723 | goto fail; |
732 | } | 724 | } |
733 | 725 | ||
734 | dir_f = JFFS2_INODE_INFO(dir_i); | 726 | dir_f = JFFS2_INODE_INFO(dir_i); |
@@ -759,8 +751,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
759 | jffs2_complete_reservation(c); | 751 | jffs2_complete_reservation(c); |
760 | jffs2_free_raw_dirent(rd); | 752 | jffs2_free_raw_dirent(rd); |
761 | mutex_unlock(&dir_f->sem); | 753 | mutex_unlock(&dir_f->sem); |
762 | jffs2_clear_inode(inode); | 754 | ret = PTR_ERR(fd); |
763 | return PTR_ERR(fd); | 755 | goto fail; |
764 | } | 756 | } |
765 | 757 | ||
766 | dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); | 758 | dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); |
@@ -777,6 +769,11 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
777 | d_instantiate(dentry, inode); | 769 | d_instantiate(dentry, inode); |
778 | 770 | ||
779 | return 0; | 771 | return 0; |
772 | |||
773 | fail: | ||
774 | make_bad_inode(inode); | ||
775 | iput(inode); | ||
776 | return ret; | ||
780 | } | 777 | } |
781 | 778 | ||
782 | static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | 779 | static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, |