aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2012-04-27 14:23:22 -0400
committerChris Mason <chris.mason@oracle.com>2012-04-27 14:23:22 -0400
commitfede766f28dd766d4e8feb321fdb19edb21ef6fb (patch)
tree86e59f6bf94ad77c2fa1b232faa8f8b63b8675cb /fs
parent7654b72417e10e294563496e25211200f9b8b6d3 (diff)
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. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/inode.c30
1 files changed, 1 insertions, 29 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index d953f8820464..3ce7805d1117 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4192,7 +4192,6 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
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,
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,
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 so 4306 /* is this a reference to our own snapshot? If so
4335 * skip it. 4307 * skip it.
4336 * 4308 *