1 From: "Jun'ichi Nomura" <j-nomura@ce.jp.nec.com>
2 Subject: dm-path-selector: fix refcount corruption
6 Refcounting of path-selector module is not safe in SMP environment.
7 The counter may corrupt and trigger BUG() like this:
8 kernel BUG at linux-2.6.29-rc3/drivers/md/dm-path-selector.c:90!
9 though it's rare under normal usage.
12 void dm_put_path_selector(struct path_selector_type *pst)
16 psi = __find_path_selector_type(pst->name);
21 module_put(psi->pst.module);
25 The code manipulates the counter without exclusive lock or atomic ops.
26 So if 2 processors come in, the counter may corrupt.
28 While it could be fixed using atomic ops for the counter manipulation,
29 we can just drop the 'use' counter like Cheng Renquan did for dm-target:
30 https://www.redhat.com/archives/dm-devel/2008-December/msg00075.html
32 (Actually, without his patch, dm-target.c hits the same problem.)
34 Signed-off-by: Hannes Reinecke <hare@suse.de>
37 Jun'ichi Nomura, NEC Corporation
40 Fix refcount corruption in dm-path-selector
42 Refcounting with non-atomic ops under shared lock will corrupt the counter
43 in multi-processor system and may trigger BUG_ON().
45 # same approach as dm-target-use-module-refcount-directly.patch here
46 # https://www.redhat.com/archives/dm-devel/2008-December/msg00075.html
49 kernel BUG at linux-2.6.29-rc3/drivers/md/dm-path-selector.c:90!
50 Pid: 11148, comm: dmsetup Not tainted 2.6.29-rc3-nm #1
51 dm_put_path_selector+0x4d/0x61 [dm_multipath]
53 [<ffffffffa031d3f9>] free_priority_group+0x33/0xb3 [dm_multipath]
54 [<ffffffffa031d4aa>] free_multipath+0x31/0x67 [dm_multipath]
55 [<ffffffffa031d50d>] multipath_dtr+0x2d/0x32 [dm_multipath]
56 [<ffffffffa015d6c2>] dm_table_destroy+0x64/0xd8 [dm_mod]
57 [<ffffffffa015b73a>] __unbind+0x46/0x4b [dm_mod]
58 [<ffffffffa015b79f>] dm_swap_table+0x60/0x14d [dm_mod]
59 [<ffffffffa015f963>] dev_suspend+0xfd/0x177 [dm_mod]
60 [<ffffffffa0160250>] dm_ctl_ioctl+0x24c/0x29c [dm_mod]
61 [<ffffffff80288cd3>] ? get_page_from_freelist+0x49c/0x61d
62 [<ffffffffa015f866>] ? dev_suspend+0x0/0x177 [dm_mod]
63 [<ffffffff802bf05c>] vfs_ioctl+0x2a/0x77
64 [<ffffffff802bf4f1>] do_vfs_ioctl+0x448/0x4a0
65 [<ffffffff802bf5a0>] sys_ioctl+0x57/0x7a
66 [<ffffffff8020c05b>] system_call_fastpath+0x16/0x1b
68 Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
70 drivers/md/dm-path-selector.c | 21 +++------------------
71 1 file changed, 3 insertions(+), 18 deletions(-)
73 --- a/drivers/md/dm-path-selector.c
74 +++ b/drivers/md/dm-path-selector.c
78 struct path_selector_type pst;
80 struct list_head list;
84 #define pst_to_psi(__pst) container_of((__pst), struct ps_internal, pst)
85 @@ -44,12 +42,8 @@ static struct ps_internal *get_path_sele
88 psi = __find_path_selector_type(name);
90 - if ((psi->use == 0) && !try_module_get(psi->pst.module))
95 + if (psi && !try_module_get(psi->pst.module))
100 @@ -83,11 +77,7 @@ void dm_put_path_selector(struct path_se
104 - if (--psi->use == 0)
105 - module_put(psi->pst.module);
107 - BUG_ON(psi->use < 0);
109 + module_put(psi->pst.module);
113 @@ -135,11 +125,6 @@ int dm_unregister_path_selector(struct p
118 - up_write(&_ps_lock);
122 list_del(&psi->list);