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
4192 struct btrfs_path *path;4192 struct btrfs_path *path;
4193 struct list_head ins_list;4193 struct list_head ins_list;
4194 struct list_head del_list;4194 struct list_head del_list;
4195 struct qstr q;
4196 int ret;4195 int ret;
4197 struct extent_buffer *leaf;4196 struct extent_buffer *leaf;
4198 int slot;4197 int slot;
@@ -4283,7 +4282,6 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, · 84 unmodified lines
4283 4282
4284 while (di_cur < di_total) {4283 while (di_cur < di_total) {
4285 struct btrfs_key location;4284 struct btrfs_key location;
4286 struct dentry *tmp;
4287 4285
4288 if (verify_dir_item(root, leaf, di))4286 if (verify_dir_item(root, leaf, di))
4289 break;4287 break;
@@ -4304,33 +4302,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, · 14 unmodified lines
4304 d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];4302 d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
4305 btrfs_dir_item_key_to_cpu(leaf, di, &location);4303 btrfs_dir_item_key_to_cpu(leaf, di, &location);
4306 4304
4307 q.name = name_ptr;4305
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 }
4333no_dentry:
4334 /* is this a reference to our own snapshot? If so4306 /* is this a reference to our own snapshot? If so
4335 * skip it.4307 * skip it.
4336 *4308 *