--- fs/hpfs/buffer.c | 4 - fs/hpfs/dnode.c | 14 +-- fs/hpfs/ea.c | 6 - fs/hpfs/hpfs_fn.h | 2 fs/hpfs/inode.c | 6 - fs/hpfs/namei.c | 211 ++++++++++++++++++++++++++++-------------------------- fs/hpfs/super.c | 2 7 files changed, 130 insertions(+), 115 deletions(-) diff -puN fs/hpfs/buffer.c~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/buffer.c --- 25/fs/hpfs/buffer.c~HPFS9-hpfs_deadlock-RC4-rc1 2004-02-29 12:49:52.000000000 -0800 +++ 25-akpm/fs/hpfs/buffer.c 2004-02-29 12:49:52.000000000 -0800 @@ -70,7 +70,7 @@ void *hpfs_map_4sectors(struct super_blo return 0; } - qbh->data = data = (char *)kmalloc(2048, GFP_KERNEL); + qbh->data = data = (char *)kmalloc(2048, GFP_NOFS); if (!data) { printk("HPFS: hpfs_map_4sectors: out of memory\n"); goto bail; @@ -122,7 +122,7 @@ void *hpfs_get_4sectors(struct super_blo } /*return hpfs_map_4sectors(s, secno, qbh, 0);*/ - if (!(qbh->data = kmalloc(2048, GFP_KERNEL))) { + if (!(qbh->data = kmalloc(2048, GFP_NOFS))) { printk("HPFS: hpfs_get_4sectors: out of memory\n"); return NULL; } diff -puN fs/hpfs/dnode.c~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/dnode.c --- 25/fs/hpfs/dnode.c~HPFS9-hpfs_deadlock-RC4-rc1 2004-02-29 12:49:52.000000000 -0800 +++ 25-akpm/fs/hpfs/dnode.c 2004-02-29 12:49:52.000000000 -0800 @@ -31,7 +31,7 @@ void hpfs_add_pos(struct inode *inode, l for (; hpfs_inode->i_rddir_off[i]; i++) if (hpfs_inode->i_rddir_off[i] == pos) return; if (!(i&0x0f)) { - if (!(ppos = kmalloc((i+0x11) * sizeof(loff_t*), GFP_KERNEL))) { + if (!(ppos = kmalloc((i+0x11) * sizeof(loff_t*), GFP_NOFS))) { printk("HPFS: out of memory for position list\n"); return; } @@ -235,7 +235,7 @@ int hpfs_add_to_dnode(struct inode *i, d struct buffer_head *bh; struct fnode *fnode; int c1, c2 = 0; - if (!(nname = kmalloc(256, GFP_KERNEL))) { + if (!(nname = kmalloc(256, GFP_NOFS))) { printk("HPFS: out of memory, can't add to dnode\n"); return 1; } @@ -272,7 +272,7 @@ int hpfs_add_to_dnode(struct inode *i, d kfree(nname); return 0; } - if (!nd) if (!(nd = kmalloc(0x924, GFP_KERNEL))) { + if (!nd) if (!(nd = kmalloc(0x924, GFP_NOFS))) { /* 0x924 is a max size of dnode after adding a dirent with max name length. We alloc this only once. There must not be any error while splitting dnodes, otherwise the @@ -477,7 +477,7 @@ static secno move_to_top(struct inode *i t = get_pos(dnode, de); for_all_poss(i, hpfs_pos_subst, t, 4); for_all_poss(i, hpfs_pos_subst, t + 1, 5); - if (!(nde = kmalloc(de->length, GFP_KERNEL))) { + if (!(nde = kmalloc(de->length, GFP_NOFS))) { hpfs_error(i->i_sb, "out of memory for dirent - directory will be corrupted"); hpfs_brelse4(&qbh); return 0; @@ -587,7 +587,7 @@ static void delete_empty_dnode(struct in struct quad_buffer_head qbh1; if (!de_next->down) goto endm; ndown = de_down_pointer(de_next); - if (!(de_cp = kmalloc(de->length, GFP_KERNEL))) { + if (!(de_cp = kmalloc(de->length, GFP_NOFS))) { printk("HPFS: out of memory for dtree balancing\n"); goto endm; } @@ -649,7 +649,7 @@ static void delete_empty_dnode(struct in } else if (down) *(dnode_secno *) ((void *) del + del->length - 4) = down; } else goto endm; - if (!(de_cp = kmalloc(de_prev->length, GFP_KERNEL))) { + if (!(de_cp = kmalloc(de_prev->length, GFP_NOFS))) { printk("HPFS: out of memory for dtree balancing\n"); hpfs_brelse4(&qbh1); goto endm; @@ -993,7 +993,7 @@ struct hpfs_dirent *map_fnode_dirent(str int c1, c2 = 0; int d1, d2 = 0; name1 = f->name; - if (!(name2 = kmalloc(256, GFP_KERNEL))) { + if (!(name2 = kmalloc(256, GFP_NOFS))) { printk("HPFS: out of memory, can't map dirent\n"); return NULL; } diff -puN fs/hpfs/ea.c~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/ea.c --- 25/fs/hpfs/ea.c~HPFS9-hpfs_deadlock-RC4-rc1 2004-02-29 12:49:52.000000000 -0800 +++ 25-akpm/fs/hpfs/ea.c 2004-02-29 12:49:52.000000000 -0800 @@ -50,7 +50,7 @@ void hpfs_ea_ext_remove(struct super_blo static char *get_indirect_ea(struct super_block *s, int ano, secno a, int size) { char *ret; - if (!(ret = kmalloc(size + 1, GFP_KERNEL))) { + if (!(ret = kmalloc(size + 1, GFP_NOFS))) { printk("HPFS: out of memory for EA\n"); return NULL; } @@ -138,7 +138,7 @@ char *hpfs_get_ea(struct super_block *s, if (!strcmp(ea->name, key)) { if (ea->indirect) return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); - if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_KERNEL))) { + if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_NOFS))) { printk("HPFS: out of memory for EA\n"); return NULL; } @@ -164,7 +164,7 @@ char *hpfs_get_ea(struct super_block *s, if (!strcmp(ea->name, key)) { if (ea->indirect) return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); - if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_KERNEL))) { + if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_NOFS))) { printk("HPFS: out of memory for EA\n"); return NULL; } diff -puN fs/hpfs/hpfs_fn.h~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/hpfs_fn.h --- 25/fs/hpfs/hpfs_fn.h~HPFS9-hpfs_deadlock-RC4-rc1 2004-02-29 12:49:52.000000000 -0800 +++ 25-akpm/fs/hpfs/hpfs_fn.h 2004-02-29 12:49:52.000000000 -0800 @@ -58,7 +58,7 @@ struct hpfs_inode_info { unsigned i_ea_gid : 1; /* file's gid is stored in ea */ unsigned i_dirty : 1; struct rw_semaphore i_sem; - struct semaphore i_parent; + struct rw_semaphore i_parent; loff_t **i_rddir_off; struct inode vfs_inode; }; diff -puN fs/hpfs/inode.c~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/inode.c --- 25/fs/hpfs/inode.c~HPFS9-hpfs_deadlock-RC4-rc1 2004-02-29 12:49:52.000000000 -0800 +++ 25-akpm/fs/hpfs/inode.c 2004-02-29 12:49:52.000000000 -0800 @@ -186,9 +186,9 @@ void hpfs_write_inode(struct inode *i) kfree(hpfs_inode->i_rddir_off); hpfs_inode->i_rddir_off = NULL; } - down(&hpfs_inode->i_parent); + down_read(&hpfs_inode->i_parent); if (!i->i_nlink) { - up(&hpfs_inode->i_parent); + up_read(&hpfs_inode->i_parent); return; } hpfs_inode->i_dirty = 0; @@ -204,7 +204,7 @@ void hpfs_write_inode(struct inode *i) up_read(&hpfs_i(parent)->i_sem); iput(parent); } - up(&hpfs_inode->i_parent); + up_read(&hpfs_inode->i_parent); } void hpfs_write_inode_nolock(struct inode *i) diff -puN fs/hpfs/namei.c~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/namei.c --- 25/fs/hpfs/namei.c~HPFS9-hpfs_deadlock-RC4-rc1 2004-02-29 12:49:52.000000000 -0800 +++ 25-akpm/fs/hpfs/namei.c 2004-02-29 12:49:52.000000000 -0800 @@ -39,13 +39,34 @@ static int hpfs_mkdir(struct inode *dir, dee.hidden = name[0] == '.'; dee.fnode = fno; dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds()); + result = new_inode(dir->i_sb); + if (!result) + goto bail2; + hpfs_init_inode(result); + result->i_ino = fno; + hpfs_i(result)->i_parent_dir = dir->i_ino; + hpfs_i(result)->i_dno = dno; + result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); + result->i_ctime.tv_nsec = 0; + result->i_mtime.tv_nsec = 0; + result->i_atime.tv_nsec = 0; + hpfs_i(result)->i_ea_size = 0; + result->i_mode |= S_IFDIR; + result->i_op = &hpfs_dir_iops; + result->i_fop = &hpfs_dir_ops; + result->i_blocks = 4; + result->i_size = 2048; + result->i_nlink = 2; + if (dee.read_only) + result->i_mode &= ~0222; + down_write(&hpfs_i(dir)->i_sem); r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0); if (r == 1) - goto bail2; + goto bail3; if (r == -1) { err = -EEXIST; - goto bail2; + goto bail3; } fnode->len = len; memcpy(fnode->name, name, len > 15 ? 15 : len); @@ -69,28 +90,8 @@ static int hpfs_mkdir(struct inode *dir, hpfs_mark_4buffers_dirty(&qbh0); hpfs_brelse4(&qbh0); dir->i_nlink++; + insert_inode_hash(result); - result = iget_locked(dir->i_sb, fno); - if (!result) - goto out; - - hpfs_init_inode(result); - unlock_new_inode(result); - - hpfs_i(result)->i_parent_dir = dir->i_ino; - hpfs_i(result)->i_dno = dno; - result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); - result->i_ctime.tv_nsec = 0; - result->i_mtime.tv_nsec = 0; - result->i_atime.tv_nsec = 0; - hpfs_i(result)->i_ea_size = 0; - result->i_mode |= S_IFDIR; - result->i_op = &hpfs_dir_iops; - result->i_fop = &hpfs_dir_ops; - result->i_blocks = 4; - result->i_size = 2048; - result->i_nlink = 2; - if (dee.read_only) result->i_mode &= ~0222; if (result->i_uid != current->fsuid || result->i_gid != current->fsgid || result->i_mode != (mode | S_IFDIR)) { @@ -101,14 +102,16 @@ static int hpfs_mkdir(struct inode *dir, } d_instantiate(dentry, result); -out: up_write(&hpfs_i(dir)->i_sem); unlock_kernel(); return 0; + +bail3: + up_write(&hpfs_i(dir)->i_sem); + iput(result); bail2: hpfs_brelse4(&qbh0); hpfs_free_dnode(dir->i_sb, dno); - up_write(&hpfs_i(dir)->i_sem); bail1: brelse(bh); hpfs_free_sectors(dir->i_sb, fno, 1); @@ -141,32 +144,18 @@ static int hpfs_create(struct inode *dir dee.hidden = name[0] == '.'; dee.fnode = fno; dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds()); - down_write(&hpfs_i(dir)->i_sem); - r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0); - if (r == 1) - goto bail1; - if (r == -1) { - err = -EEXIST; - goto bail1; - } - fnode->len = len; - memcpy(fnode->name, name, len > 15 ? 15 : len); - fnode->up = dir->i_ino; - mark_buffer_dirty(bh); - brelse(bh); - result = iget_locked(dir->i_sb, fno); + result = new_inode(dir->i_sb); if (!result) - goto out; + goto bail1; hpfs_init_inode(result); - unlock_new_inode(result); + result->i_ino = fno; result->i_mode |= S_IFREG; result->i_mode &= ~0111; result->i_op = &hpfs_file_iops; result->i_fop = &hpfs_file_ops; result->i_nlink = 1; - hpfs_decide_conv(result, (char *)name, len); hpfs_i(result)->i_parent_dir = dir->i_ino; result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); @@ -174,13 +163,29 @@ static int hpfs_create(struct inode *dir result->i_mtime.tv_nsec = 0; result->i_atime.tv_nsec = 0; hpfs_i(result)->i_ea_size = 0; - if (dee.read_only) result->i_mode &= ~0222; - if (result->i_blocks == -1) result->i_blocks = 1; - if (result->i_size == -1) { - result->i_size = 0; - result->i_data.a_ops = &hpfs_aops; - hpfs_i(result)->mmu_private = 0; + if (dee.read_only) + result->i_mode &= ~0222; + result->i_blocks = 1; + result->i_size = 0; + result->i_data.a_ops = &hpfs_aops; + hpfs_i(result)->mmu_private = 0; + + down_write(&hpfs_i(dir)->i_sem); + r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0); + if (r == 1) + goto bail2; + if (r == -1) { + err = -EEXIST; + goto bail2; } + fnode->len = len; + memcpy(fnode->name, name, len > 15 ? 15 : len); + fnode->up = dir->i_ino; + mark_buffer_dirty(bh); + brelse(bh); + + insert_inode_hash(result); + if (result->i_uid != current->fsuid || result->i_gid != current->fsgid || result->i_mode != (mode | S_IFREG)) { @@ -190,14 +195,16 @@ static int hpfs_create(struct inode *dir hpfs_write_inode_nolock(result); } d_instantiate(dentry, result); -out: up_write(&hpfs_i(dir)->i_sem); unlock_kernel(); return 0; + +bail2: + up_write(&hpfs_i(dir)->i_sem); + iput(result); bail1: brelse(bh); hpfs_free_sectors(dir->i_sb, fno, 1); - up_write(&hpfs_i(dir)->i_sem); bail: unlock_kernel(); return err; @@ -229,26 +236,13 @@ static int hpfs_mknod(struct inode *dir, dee.hidden = name[0] == '.'; dee.fnode = fno; dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds()); - down_write(&hpfs_i(dir)->i_sem); - r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0); - if (r == 1) - goto bail1; - if (r == -1) { - err = -EEXIST; - goto bail1; - } - fnode->len = len; - memcpy(fnode->name, name, len > 15 ? 15 : len); - fnode->up = dir->i_ino; - mark_buffer_dirty(bh); - result = iget_locked(dir->i_sb, fno); + result = new_inode(dir->i_sb); if (!result) - goto out; + goto bail1; hpfs_init_inode(result); - unlock_new_inode(result); - + result->i_ino = fno; hpfs_i(result)->i_parent_dir = dir->i_ino; result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); result->i_ctime.tv_nsec = 0; @@ -261,18 +255,35 @@ static int hpfs_mknod(struct inode *dir, result->i_size = 0; result->i_blocks = 1; init_special_inode(result, mode, rdev); + + down_write(&hpfs_i(dir)->i_sem); + r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0); + if (r == 1) + goto bail2; + if (r == -1) { + err = -EEXIST; + goto bail2; + } + fnode->len = len; + memcpy(fnode->name, name, len > 15 ? 15 : len); + fnode->up = dir->i_ino; + mark_buffer_dirty(bh); + + insert_inode_hash(result); + hpfs_write_inode_nolock(result); d_instantiate(dentry, result); - -out: up_write(&hpfs_i(dir)->i_sem); brelse(bh); unlock_kernel(); return 0; + +bail2: + up_write(&hpfs_i(dir)->i_sem); + iput(result); bail1: brelse(bh); hpfs_free_sectors(dir->i_sb, fno, 1); - up_write(&hpfs_i(dir)->i_sem); bail: unlock_kernel(); return err; @@ -304,27 +315,12 @@ static int hpfs_symlink(struct inode *di dee.hidden = name[0] == '.'; dee.fnode = fno; dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds()); - down_write(&hpfs_i(dir)->i_sem); - r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0); - if (r == 1) - goto bail1; - if (r == -1) { - err = -EEXIST; - goto bail1; - } - fnode->len = len; - memcpy(fnode->name, name, len > 15 ? 15 : len); - fnode->up = dir->i_ino; - mark_buffer_dirty(bh); - brelse(bh); - result = iget_locked(dir->i_sb, fno); + result = new_inode(dir->i_sb); if (!result) - goto out; - + goto bail1; + result->i_ino = fno; hpfs_init_inode(result); - unlock_new_inode(result); - hpfs_i(result)->i_parent_dir = dir->i_ino; result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); result->i_ctime.tv_nsec = 0; @@ -339,6 +335,23 @@ static int hpfs_symlink(struct inode *di result->i_size = strlen(symlink); result->i_op = &page_symlink_inode_operations; result->i_data.a_ops = &hpfs_symlink_aops; + + down_write(&hpfs_i(dir)->i_sem); + r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0); + if (r == 1) + goto bail2; + if (r == -1) { + err = -EEXIST; + goto bail2; + } + fnode->len = len; + memcpy(fnode->name, name, len > 15 ? 15 : len); + fnode->up = dir->i_ino; + mark_buffer_dirty(bh); + brelse(bh); + + insert_inode_hash(result); + if ((fnode = hpfs_map_fnode(dir->i_sb, fno, &bh))) { hpfs_set_ea(result, fnode, "SYMLINK", (char *)symlink, strlen(symlink)); mark_buffer_dirty(bh); @@ -347,14 +360,16 @@ static int hpfs_symlink(struct inode *di hpfs_write_inode_nolock(result); d_instantiate(dentry, result); -out: up_write(&hpfs_i(dir)->i_sem); unlock_kernel(); return 0; + +bail2: + up_write(&hpfs_i(dir)->i_sem); + iput(result); bail1: brelse(bh); hpfs_free_sectors(dir->i_sb, fno, 1); - up_write(&hpfs_i(dir)->i_sem); bail: unlock_kernel(); return err; @@ -376,7 +391,7 @@ static int hpfs_unlink(struct inode *dir lock_kernel(); hpfs_adjust_length((char *)name, &len); again: - down(&hpfs_i(inode)->i_parent); + down_write(&hpfs_i(inode)->i_parent); down_write(&hpfs_i(dir)->i_sem); de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh); err = -ENOENT; @@ -405,7 +420,7 @@ again: break; up_write(&hpfs_i(dir)->i_sem); - up(&hpfs_i(inode)->i_parent); + up_write(&hpfs_i(inode)->i_parent); d_drop(dentry); spin_lock(&dentry->d_lock); if (atomic_read(&dentry->d_count) > 1 || @@ -437,7 +452,7 @@ out1: hpfs_brelse4(&qbh); out: up_write(&hpfs_i(dir)->i_sem); - up(&hpfs_i(inode)->i_parent); + up_write(&hpfs_i(inode)->i_parent); unlock_kernel(); return err; } @@ -457,7 +472,7 @@ static int hpfs_rmdir(struct inode *dir, hpfs_adjust_length((char *)name, &len); lock_kernel(); - down(&hpfs_i(inode)->i_parent); + down_write(&hpfs_i(inode)->i_parent); down_write(&hpfs_i(dir)->i_sem); err = -ENOENT; de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh); @@ -497,7 +512,7 @@ out1: hpfs_brelse4(&qbh); out: up_write(&hpfs_i(dir)->i_sem); - up(&hpfs_i(inode)->i_parent); + up_write(&hpfs_i(inode)->i_parent); unlock_kernel(); return err; } @@ -559,9 +574,9 @@ static int hpfs_rename(struct inode *old lock_kernel(); /* order doesn't matter, due to VFS exclusion */ - down(&hpfs_i(i)->i_parent); + down_write(&hpfs_i(i)->i_parent); if (new_inode) - down(&hpfs_i(new_inode)->i_parent); + down_write(&hpfs_i(new_inode)->i_parent); down_write(&hpfs_i(old_dir)->i_sem); if (new_dir != old_dir) down_write(&hpfs_i(new_dir)->i_sem); @@ -646,9 +661,9 @@ end1: if (old_dir != new_dir) up_write(&hpfs_i(new_dir)->i_sem); up_write(&hpfs_i(old_dir)->i_sem); - up(&hpfs_i(i)->i_parent); + up_write(&hpfs_i(i)->i_parent); if (new_inode) - up(&hpfs_i(new_inode)->i_parent); + up_write(&hpfs_i(new_inode)->i_parent); unlock_kernel(); return err; } diff -puN fs/hpfs/super.c~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/super.c --- 25/fs/hpfs/super.c~HPFS9-hpfs_deadlock-RC4-rc1 2004-02-29 12:49:52.000000000 -0800 +++ 25-akpm/fs/hpfs/super.c 2004-02-29 12:49:52.000000000 -0800 @@ -182,7 +182,7 @@ static void init_once(void * foo, kmem_c if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { init_rwsem(&ei->i_sem); - init_MUTEX(&ei->i_parent); + init_rwsem(&ei->i_parent); inode_init_once(&ei->vfs_inode); } } _