History

Btrfs: avoid deadlocks from GFP_KERNEL allocations during btrfs_real_readdir

Btrfs has an optimization where it will preallocate dentries during readdir to fill in enough information to open the inode without an extra lookup. But, we're calling d_alloc, which is doing GFP_KERNEL allocations, and that leads to deadlocks because our readdir code has tree locks held. For now, disable this optimization. We'll fix the gfp mask in the next merge window.

Chris Mason committed 14 years ago

Commit fede7661 parent 7654b721 file · +1 −29Browse files

Unified · Split

fs/btrfs/inode.c+1−29
@@ -4192,7 +4192,6 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, · 4191 unmodified lines
41924192 struct btrfs_path *path;
41934193 struct list_head ins_list;
41944194 struct list_head del_list;
4195− struct qstr q;
41964195 int ret;
41974196 struct extent_buffer *leaf;
41984197 int slot;
@@ -4283,7 +4282,6 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, · 84 unmodified lines
42834282
42844283 while (di_cur < di_total) {
42854284 struct btrfs_key location;
4286− struct dentry *tmp;
42874285
42884286 if (verify_dir_item(root, leaf, di))
42894287 break;
@@ -4304,33 +4302,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, · 14 unmodified lines
43044302 d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
43054303 btrfs_dir_item_key_to_cpu(leaf, di, &location);
43064304
4307− q.name = name_ptr;
4308− q.len = name_len;
4309− q.hash = full_name_hash(q.name, q.len);
4310− tmp = d_lookup(filp->f_dentry, &q);
4311− if (!tmp) {
4312− struct btrfs_key *newkey;
4313−
4314− newkey = kzalloc(sizeof(struct btrfs_key),
4315− GFP_NOFS);
4316− if (!newkey)
4317− goto no_dentry;
4318− tmp = d_alloc(filp->f_dentry, &q);
4319− if (!tmp) {
4320− kfree(newkey);
4321− dput(tmp);
4322− goto no_dentry;
4323− }
4324− memcpy(newkey, &location,
4325− sizeof(struct btrfs_key));
4326− tmp->d_fsdata = newkey;
4327− tmp->d_flags |= DCACHE_NEED_LOOKUP;
4328− d_rehash(tmp);
4329− dput(tmp);
4330− } else {
4331− dput(tmp);
4332− }
4333−no_dentry:
4305+
43344306 /* is this a reference to our own snapshot? If so
43354307 * skip it.
43364308 *