aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ufs/inode.c
diff options
context:
space:
mode:
authorEvgeniy Dushistov <dushistov@mail.ru>2007-04-17 01:53:24 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-04-17 19:36:27 -0400
commit07a0cfec30848319cc86f21cce0d2efeca593e1a (patch)
treeadf05a9b27e8298f0b8f810b5b2979f33350f097 /fs/ufs/inode.c
parent3d2c5b415ccd6c322e18adaed3a5b21f7ec555ef (diff)
ufs proper handling of zero link case
This patch should fix or partly fix this bug: http://bugzilla.kernel.org/show_bug.cgi?id=8276 The problem is: - if we see "zero link case" during reading inode operation, we call ufs_error(which remount fs readonly), but not "mark" inode as bad (1) - in readonly case we do not fill some data structures, which are used in read and write case (2) - VFS call ufs_delete_inode if link count is zero (3) so (1)->(3)->(2) cause oops, this patch should fix such scenario Signed-off-by: Evgeniy Dushistov <dushistov@mail.ru> Cc: Jim Paris <jim@jtan.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ufs/inode.c')
-rw-r--r--fs/ufs/inode.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 013d7afe7cde..f18b79122fa3 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -601,7 +601,7 @@ static void ufs_set_inode_ops(struct inode *inode)
601 ufs_get_inode_dev(inode->i_sb, UFS_I(inode))); 601 ufs_get_inode_dev(inode->i_sb, UFS_I(inode)));
602} 602}
603 603
604static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) 604static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
605{ 605{
606 struct ufs_inode_info *ufsi = UFS_I(inode); 606 struct ufs_inode_info *ufsi = UFS_I(inode);
607 struct super_block *sb = inode->i_sb; 607 struct super_block *sb = inode->i_sb;
@@ -613,8 +613,10 @@ static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
613 */ 613 */
614 inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode); 614 inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode);
615 inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink); 615 inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink);
616 if (inode->i_nlink == 0) 616 if (inode->i_nlink == 0) {
617 ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); 617 ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
618 return -1;
619 }
618 620
619 /* 621 /*
620 * Linux now has 32-bit uid and gid, so we can support EFT. 622 * Linux now has 32-bit uid and gid, so we can support EFT.
@@ -643,9 +645,10 @@ static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
643 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) 645 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
644 ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i]; 646 ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i];
645 } 647 }
648 return 0;
646} 649}
647 650
648static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) 651static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
649{ 652{
650 struct ufs_inode_info *ufsi = UFS_I(inode); 653 struct ufs_inode_info *ufsi = UFS_I(inode);
651 struct super_block *sb = inode->i_sb; 654 struct super_block *sb = inode->i_sb;
@@ -658,8 +661,10 @@ static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
658 */ 661 */
659 inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode); 662 inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode);
660 inode->i_nlink = fs16_to_cpu(sb, ufs2_inode->ui_nlink); 663 inode->i_nlink = fs16_to_cpu(sb, ufs2_inode->ui_nlink);
661 if (inode->i_nlink == 0) 664 if (inode->i_nlink == 0) {
662 ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); 665 ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
666 return -1;
667 }
663 668
664 /* 669 /*
665 * Linux now has 32-bit uid and gid, so we can support EFT. 670 * Linux now has 32-bit uid and gid, so we can support EFT.
@@ -690,6 +695,7 @@ static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
690 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) 695 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
691 ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i]; 696 ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i];
692 } 697 }
698 return 0;
693} 699}
694 700
695void ufs_read_inode(struct inode * inode) 701void ufs_read_inode(struct inode * inode)
@@ -698,6 +704,7 @@ void ufs_read_inode(struct inode * inode)
698 struct super_block * sb; 704 struct super_block * sb;
699 struct ufs_sb_private_info * uspi; 705 struct ufs_sb_private_info * uspi;
700 struct buffer_head * bh; 706 struct buffer_head * bh;
707 int err;
701 708
702 UFSD("ENTER, ino %lu\n", inode->i_ino); 709 UFSD("ENTER, ino %lu\n", inode->i_ino);
703 710
@@ -720,14 +727,17 @@ void ufs_read_inode(struct inode * inode)
720 if ((UFS_SB(sb)->s_flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { 727 if ((UFS_SB(sb)->s_flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
721 struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data; 728 struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data;
722 729
723 ufs2_read_inode(inode, 730 err = ufs2_read_inode(inode,
724 ufs2_inode + ufs_inotofsbo(inode->i_ino)); 731 ufs2_inode + ufs_inotofsbo(inode->i_ino));
725 } else { 732 } else {
726 struct ufs_inode *ufs_inode = (struct ufs_inode *)bh->b_data; 733 struct ufs_inode *ufs_inode = (struct ufs_inode *)bh->b_data;
727 734
728 ufs1_read_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino)); 735 err = ufs1_read_inode(inode,
736 ufs_inode + ufs_inotofsbo(inode->i_ino));
729 } 737 }
730 738
739 if (err)
740 goto bad_inode;
731 inode->i_version++; 741 inode->i_version++;
732 ufsi->i_lastfrag = 742 ufsi->i_lastfrag =
733 (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; 743 (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
@@ -888,6 +898,8 @@ void ufs_delete_inode (struct inode * inode)
888 loff_t old_i_size; 898 loff_t old_i_size;
889 899
890 truncate_inode_pages(&inode->i_data, 0); 900 truncate_inode_pages(&inode->i_data, 0);
901 if (is_bad_inode(inode))
902 goto no_delete;
891 /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ 903 /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/
892 lock_kernel(); 904 lock_kernel();
893 mark_inode_dirty(inode); 905 mark_inode_dirty(inode);
@@ -898,4 +910,7 @@ void ufs_delete_inode (struct inode * inode)
898 ufs_warning(inode->i_sb, __FUNCTION__, "ufs_truncate failed\n"); 910 ufs_warning(inode->i_sb, __FUNCTION__, "ufs_truncate failed\n");
899 ufs_free_inode (inode); 911 ufs_free_inode (inode);
900 unlock_kernel(); 912 unlock_kernel();
913 return;
914no_delete:
915 clear_inode(inode); /* We must guarantee clearing of inode... */
901} 916}