From d9013aaeb1258b30e169e904b5d4229118507b42 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Wed, 17 Mar 2004 21:24:12 -0800 Subject: [PATCH] [PATCH] hpfs: deadlock fixes We used to have GFP_KERNEL kmalloc() done by the code that held hpfs lock on directory. That could trigger a call of hpfs_write_inode() and deadlock; fixed by switch to GFP_NOFS. Same for hpfs inodes themselves - hpfs_write_inode() calls iget() and that could trigger both the deadlocks (avoidable with very baroque locking scheme) and stack overflows (unavoidable unless we kill potential recursion here). --- fs/hpfs/buffer.c | 4 ++-- fs/hpfs/dnode.c | 14 +++++++------- fs/hpfs/ea.c | 6 +++--- fs/hpfs/super.c | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c index 65f7e2f1667ee..7453c07976e79 100644 --- a/fs/hpfs/buffer.c +++ b/fs/hpfs/buffer.c @@ -88,7 +88,7 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe 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; @@ -140,7 +140,7 @@ void *hpfs_get_4sectors(struct super_block *s, unsigned secno, } /*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 --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c index fbe4b03e3ab46..fda1505a57179 100644 --- a/fs/hpfs/dnode.c +++ b/fs/hpfs/dnode.c @@ -32,7 +32,7 @@ void hpfs_add_pos(struct inode *inode, loff_t *pos) 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; } @@ -236,7 +236,7 @@ int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, unsigned char *name, uns 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; } @@ -273,7 +273,7 @@ int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, unsigned char *name, uns 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 @@ -478,7 +478,7 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to) 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; @@ -588,7 +588,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) 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; } @@ -650,7 +650,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) } 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; @@ -994,7 +994,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno, 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 --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c index 831429404b8ee..39caa7b03403d 100644 --- a/fs/hpfs/ea.c +++ b/fs/hpfs/ea.c @@ -52,7 +52,7 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len) 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; } @@ -140,7 +140,7 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si 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; } @@ -166,7 +166,7 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si 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 --git a/fs/hpfs/super.c b/fs/hpfs/super.c index ff630e40b5902..886760c4c9991 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -165,7 +165,7 @@ static kmem_cache_t * hpfs_inode_cachep; static struct inode *hpfs_alloc_inode(struct super_block *sb) { struct hpfs_inode_info *ei; - ei = (struct hpfs_inode_info *)kmem_cache_alloc(hpfs_inode_cachep, SLAB_KERNEL); + ei = (struct hpfs_inode_info *)kmem_cache_alloc(hpfs_inode_cachep, SLAB_NOFS); if (!ei) return NULL; ei->vfs_inode.i_version = 1; -- 2.53.0