Commit 0e879ae6 authored by Andries E. Brouwer's avatar Andries E. Brouwer Committed by Linus Torvalds

[PATCH] minix_clear_inode fix

The patch below fixes two flaws in minix_clear_inode.

The first is that it tests bh which is never initialized.  (&bh is a
parameter of minix_V1_raw_inode, but that routine can fail and return
before it has set bh)

The second is that generic_delete_inode() goes BUG() in case inode->i_state
!= I_CLEAR.  Clearly, it is expected that inode->i_sb->s_op->delete_inode
does a clear_inode() at some point.  But minix_delete_inode() calls
minix_free_inode() and that routine can print an error and return early,
before calling clear_inode().
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a03142fb
...@@ -160,7 +160,8 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh) ...@@ -160,7 +160,8 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
static void minix_clear_inode(struct inode *inode) static void minix_clear_inode(struct inode *inode)
{ {
struct buffer_head *bh; struct buffer_head *bh = NULL;
if (INODE_VERSION(inode) == MINIX_V1) { if (INODE_VERSION(inode) == MINIX_V1) {
struct minix_inode *raw_inode; struct minix_inode *raw_inode;
raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh); raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
...@@ -188,24 +189,26 @@ void minix_free_inode(struct inode * inode) ...@@ -188,24 +189,26 @@ void minix_free_inode(struct inode * inode)
struct buffer_head * bh; struct buffer_head * bh;
unsigned long ino; unsigned long ino;
if (inode->i_ino < 1 || inode->i_ino > sbi->s_ninodes) {
printk("free_inode: inode 0 or nonexistent inode\n");
return;
}
ino = inode->i_ino; ino = inode->i_ino;
if (ino < 1 || ino > sbi->s_ninodes) {
printk("minix_free_inode: inode 0 or nonexistent inode\n");
goto out;
}
if ((ino >> 13) >= sbi->s_imap_blocks) { if ((ino >> 13) >= sbi->s_imap_blocks) {
printk("free_inode: nonexistent imap in superblock\n"); printk("minix_free_inode: nonexistent imap in superblock\n");
return; goto out;
} }
minix_clear_inode(inode); /* clear on-disk copy */
bh = sbi->s_imap[ino >> 13]; bh = sbi->s_imap[ino >> 13];
minix_clear_inode(inode);
clear_inode(inode);
lock_kernel(); lock_kernel();
if (!minix_test_and_clear_bit(ino & 8191, bh->b_data)) if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
printk("free_inode: bit %lu already cleared.\n",ino); printk("minix_free_inode: bit %lu already cleared.\n", ino);
unlock_kernel(); unlock_kernel();
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
out:
clear_inode(inode); /* clear in-memory copy */
} }
struct inode * minix_new_inode(const struct inode * dir, int * error) struct inode * minix_new_inode(const struct inode * dir, int * error)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment