| From ed8b45a3679eb49069b094c0711b30833f27c734 Mon Sep 17 00:00:00 2001 |
| From: Joe Thornber <ejt@redhat.com> |
| Date: Thu, 10 Dec 2015 14:37:53 +0000 |
| Subject: dm btree: fix bufio buffer leaks in dm_btree_del() error path |
| |
| commit ed8b45a3679eb49069b094c0711b30833f27c734 upstream. |
| |
| If dm_btree_del()'s call to push_frame() fails, e.g. due to |
| btree_node_validator finding invalid metadata, the dm_btree_del() error |
| path must unlock all frames (which have active dm-bufio buffers) that |
| were pushed onto the del_stack. |
| |
| Otherwise, dm_bufio_client_destroy() will BUG_ON() because dm-bufio |
| buffers have leaked, e.g.: |
| device-mapper: bufio: leaked buffer 3, hold count 1, list 0 |
| |
| Signed-off-by: Joe Thornber <ejt@redhat.com> |
| Signed-off-by: Mike Snitzer <snitzer@redhat.com> |
| Signed-off-by: Zefan Li <lizefan@huawei.com> |
| --- |
| drivers/md/persistent-data/dm-btree.c | 16 +++++++++++++++- |
| 1 file changed, 15 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/md/persistent-data/dm-btree.c |
| +++ b/drivers/md/persistent-data/dm-btree.c |
| @@ -230,6 +230,16 @@ static void pop_frame(struct del_stack * |
| dm_tm_unlock(s->tm, f->b); |
| } |
| |
| +static void unlock_all_frames(struct del_stack *s) |
| +{ |
| + struct frame *f; |
| + |
| + while (unprocessed_frames(s)) { |
| + f = s->spine + s->top--; |
| + dm_tm_unlock(s->tm, f->b); |
| + } |
| +} |
| + |
| int dm_btree_del(struct dm_btree_info *info, dm_block_t root) |
| { |
| int r; |
| @@ -285,9 +295,13 @@ int dm_btree_del(struct dm_btree_info *i |
| f->current_child = f->nr_children; |
| } |
| } |
| - |
| out: |
| + if (r) { |
| + /* cleanup all frames of del_stack */ |
| + unlock_all_frames(s); |
| + } |
| kfree(s); |
| + |
| return r; |
| } |
| EXPORT_SYMBOL_GPL(dm_btree_del); |