Commit d9013aae authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[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).
parent 772fd530
...@@ -88,7 +88,7 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe ...@@ -88,7 +88,7 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
return 0; return 0;
} }
qbh->data = data = (char *)kmalloc(2048, GFP_KERNEL); qbh->data = data = (char *)kmalloc(2048, GFP_NOFS);
if (!data) { if (!data) {
printk("HPFS: hpfs_map_4sectors: out of memory\n"); printk("HPFS: hpfs_map_4sectors: out of memory\n");
goto bail; goto bail;
...@@ -140,7 +140,7 @@ void *hpfs_get_4sectors(struct super_block *s, unsigned secno, ...@@ -140,7 +140,7 @@ void *hpfs_get_4sectors(struct super_block *s, unsigned secno,
} }
/*return hpfs_map_4sectors(s, secno, qbh, 0);*/ /*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"); printk("HPFS: hpfs_get_4sectors: out of memory\n");
return NULL; return NULL;
} }
......
...@@ -32,7 +32,7 @@ void hpfs_add_pos(struct inode *inode, loff_t *pos) ...@@ -32,7 +32,7 @@ void hpfs_add_pos(struct inode *inode, loff_t *pos)
for (; hpfs_inode->i_rddir_off[i]; i++) for (; hpfs_inode->i_rddir_off[i]; i++)
if (hpfs_inode->i_rddir_off[i] == pos) return; if (hpfs_inode->i_rddir_off[i] == pos) return;
if (!(i&0x0f)) { 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"); printk("HPFS: out of memory for position list\n");
return; return;
} }
...@@ -236,7 +236,7 @@ int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, unsigned char *name, uns ...@@ -236,7 +236,7 @@ int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, unsigned char *name, uns
struct buffer_head *bh; struct buffer_head *bh;
struct fnode *fnode; struct fnode *fnode;
int c1, c2 = 0; 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"); printk("HPFS: out of memory, can't add to dnode\n");
return 1; return 1;
} }
...@@ -273,7 +273,7 @@ int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, unsigned char *name, uns ...@@ -273,7 +273,7 @@ int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, unsigned char *name, uns
kfree(nname); kfree(nname);
return 0; 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 /* 0x924 is a max size of dnode after adding a dirent with
max name length. We alloc this only once. There must max name length. We alloc this only once. There must
not be any error while splitting dnodes, otherwise the 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) ...@@ -478,7 +478,7 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)
t = get_pos(dnode, de); t = get_pos(dnode, de);
for_all_poss(i, hpfs_pos_subst, t, 4); for_all_poss(i, hpfs_pos_subst, t, 4);
for_all_poss(i, hpfs_pos_subst, t + 1, 5); 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_error(i->i_sb, "out of memory for dirent - directory will be corrupted");
hpfs_brelse4(&qbh); hpfs_brelse4(&qbh);
return 0; return 0;
...@@ -588,7 +588,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) ...@@ -588,7 +588,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
struct quad_buffer_head qbh1; struct quad_buffer_head qbh1;
if (!de_next->down) goto endm; if (!de_next->down) goto endm;
ndown = de_down_pointer(de_next); 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"); printk("HPFS: out of memory for dtree balancing\n");
goto endm; goto endm;
} }
...@@ -650,7 +650,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) ...@@ -650,7 +650,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
} else if (down) } else if (down)
*(dnode_secno *) ((void *) del + del->length - 4) = down; *(dnode_secno *) ((void *) del + del->length - 4) = down;
} else goto endm; } 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"); printk("HPFS: out of memory for dtree balancing\n");
hpfs_brelse4(&qbh1); hpfs_brelse4(&qbh1);
goto endm; goto endm;
...@@ -994,7 +994,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno, ...@@ -994,7 +994,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
int c1, c2 = 0; int c1, c2 = 0;
int d1, d2 = 0; int d1, d2 = 0;
name1 = f->name; 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"); printk("HPFS: out of memory, can't map dirent\n");
return NULL; return NULL;
} }
......
...@@ -52,7 +52,7 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len) ...@@ -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) static char *get_indirect_ea(struct super_block *s, int ano, secno a, int size)
{ {
char *ret; char *ret;
if (!(ret = kmalloc(size + 1, GFP_KERNEL))) { if (!(ret = kmalloc(size + 1, GFP_NOFS))) {
printk("HPFS: out of memory for EA\n"); printk("HPFS: out of memory for EA\n");
return NULL; return NULL;
} }
...@@ -140,7 +140,7 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si ...@@ -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 (!strcmp(ea->name, key)) {
if (ea->indirect) if (ea->indirect)
return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); 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"); printk("HPFS: out of memory for EA\n");
return NULL; return NULL;
} }
...@@ -166,7 +166,7 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si ...@@ -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 (!strcmp(ea->name, key)) {
if (ea->indirect) if (ea->indirect)
return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); 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"); printk("HPFS: out of memory for EA\n");
return NULL; return NULL;
} }
......
...@@ -165,7 +165,7 @@ static kmem_cache_t * hpfs_inode_cachep; ...@@ -165,7 +165,7 @@ static kmem_cache_t * hpfs_inode_cachep;
static struct inode *hpfs_alloc_inode(struct super_block *sb) static struct inode *hpfs_alloc_inode(struct super_block *sb)
{ {
struct hpfs_inode_info *ei; 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) if (!ei)
return NULL; return NULL;
ei->vfs_inode.i_version = 1; ei->vfs_inode.i_version = 1;
......
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