Whamcloud - gitweb
LU-5443 lustre: replace direct HZ access with kernel APIs
[fs/lustre-release.git] / lustre / kernel_patches / patches / module-load-deadlock-rhel6.patch
1 module: Fix a few concurrent module loading races
2
3 Concurrently starting multiple OSTs on a single OSS frequently
4 triggers 30s deadlocks on module_mutex.  This RHEL 6 kernel bug
5 applies to any module that results in additional request_module()
6 calls in its init callback.  In Lustre, at least ptlrpc and libcfs are
7 affected.  This patch adapts fixes from the following upstream
8 commits:
9
10   9bea7f2 module: fix bne2 "gave up waiting for init of module
11                   libcrc32c"
12   be593f4 module: verify_export_symbols under the lock
13   3bafeb6 module: move find_module check to end
14   80a3d1b module: move sysfs exposure to end of load_module
15
16 diff -rNup linux-2.6.32-431.20.3.el6.orig/kernel/module.c linux-2.6.32-431.20.3.el6/kernel/module.c
17 --- linux-2.6.32-431.20.3.el6.orig/kernel/module.c      2014-06-07 05:42:39.000000000 +0800
18 +++ linux-2.6.32-431.20.3.el6/kernel/module.c   2014-07-28 00:04:43.000000000 +0800
19 @@ -658,6 +658,33 @@ static int already_uses(struct module *a
20  }
21  
22  /* Module a uses b */
23 +static int ref_module(struct module *a, struct module *b)
24 +{
25 +       struct module_use *use;
26 +       int err;
27 +
28 +       if (b == NULL || already_uses(a, b))
29 +               return 0;
30 +
31 +       /* If module isn't available, we fail. */
32 +       err = strong_try_module_get(b);
33 +       if (err)
34 +               return err;
35 +
36 +       DEBUGP("Allocating new usage for %s.\n", a->name);
37 +       use = kmalloc(sizeof(*use), GFP_ATOMIC);
38 +       if (!use) {
39 +               printk("%s: out of memory loading\n", a->name);
40 +               module_put(b);
41 +               return -ENOMEM;
42 +       }
43 +
44 +       use->module_which_uses = a;
45 +       list_add(&use->list, &b->modules_which_use_me);
46 +       return 0;
47 +}
48 +
49 +/* Module a uses b */
50  int use_module(struct module *a, struct module *b)
51  {
52         struct module_use *use;
53 @@ -707,7 +734,6 @@ static void module_unload_free(struct mo
54                                 module_put(i);
55                                 list_del(&use->list);
56                                 kfree(use);
57 -                               sysfs_remove_link(i->holders_dir, mod->name);
58                                 /* There can be at most one match. */
59                                 break;
60                         }
61 @@ -962,6 +988,11 @@ static inline void module_unload_free(st
62  {
63  }
64  
65 +static inline int ref_module(struct module *a, struct module *b)
66 +{
67 +       return strong_try_module_get(b);
68 +}
69 +
70  int use_module(struct module *a, struct module *b)
71  {
72         return strong_try_module_get(b) == 0;
73 @@ -1130,24 +1161,60 @@ static inline int same_magic(const char 
74  static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs,
75                                                   unsigned int versindex,
76                                                   const char *name,
77 -                                                 struct module *mod)
78 +                                                 struct module *mod,
79 +                                                 char ownername[])
80  {
81         struct module *owner;
82         const struct kernel_symbol *sym;
83         const unsigned long *crc;
84 +       int err;
85  
86 +       mutex_lock(&module_mutex);
87         sym = find_symbol(name, &owner, &crc,
88                           !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
89 -       /* use_module can fail due to OOM,
90 -          or module initialization or unloading */
91 -       if (sym) {
92 -               if (!check_version(sechdrs, versindex, name, mod, crc, owner)
93 -                   || !use_module(mod, owner))
94 -                       sym = NULL;
95 +       if (!sym)
96 +               goto unlock;
97 +
98 +       if (!check_version(sechdrs, versindex, name, mod, crc, owner)) {
99 +               sym = ERR_PTR(-EINVAL);
100 +               goto getname;
101         }
102 +
103 +       err = ref_module(mod, owner);
104 +       if (err) {
105 +               sym = ERR_PTR(err);
106 +               goto getname;
107 +       }
108 +
109 +getname:
110 +       /* We must make copy under the lock if we failed to get ref. */
111 +       strncpy(ownername, module_name(owner), MODULE_NAME_LEN);
112 +unlock:
113 +       mutex_unlock(&module_mutex);
114         return sym;
115  }
116  
117 +static const struct kernel_symbol *resolve_symbol_wait(Elf_Shdr *sechdrs,
118 +                                                      unsigned int versindex,
119 +                                                      const char *name,
120 +                                                      struct module *mod)
121 +{
122 +       const struct kernel_symbol *ksym;
123 +       char ownername[MODULE_NAME_LEN];
124 +
125 +       mutex_unlock(&module_mutex);
126 +       if (wait_event_interruptible_timeout(module_wq,
127 +                       !IS_ERR(ksym = resolve_symbol(sechdrs, versindex, name,
128 +                                                     mod, ownername)) ||
129 +                       PTR_ERR(ksym) != -EBUSY,
130 +                               msecs_to_jiffies(30 * MSEC_PER_SEC)) <= 0) {
131 +               printk(KERN_WARNING "%s: gave up waiting for init of module %s.\n",
132 +                      mod->name, ownername);
133 +       }
134 +       mutex_lock(&module_mutex);
135 +       return ksym;
136 +}
137 +
138  /*
139   * /sys/module/foo/sections stuff
140   * J. Corbet <corbet@lwn.net>
141 @@ -1375,6 +1442,30 @@ static inline void remove_notes_attrs(st
142  #endif
143  
144  #ifdef CONFIG_SYSFS
145 +static void add_usage_links(struct module *mod)
146 +{
147 +#ifdef CONFIG_MODULE_UNLOAD
148 +       struct module_use *use;
149 +       int nowarn;
150 +
151 +       list_for_each_entry(use, &mod->modules_which_use_me, list) {
152 +               nowarn = sysfs_create_link(use->module_which_uses->holders_dir,
153 +                                          &mod->mkobj.kobj, mod->name);
154 +       }
155 +#endif
156 +}
157 +
158 +static void del_usage_links(struct module *mod)
159 +{
160 +#ifdef CONFIG_MODULE_UNLOAD
161 +       struct module_use *use;
162 +
163 +       list_for_each_entry(use, &mod->modules_which_use_me, list)
164 +               sysfs_remove_link(use->module_which_uses->holders_dir, mod->name);
165 +#endif
166 +}
167 +
168 +
169  int module_add_modinfo_attrs(struct module *mod)
170  {
171         struct module_attribute *attr;
172 @@ -1456,6 +1547,10 @@ int mod_sysfs_setup(struct module *mod,
173  {
174         int err;
175  
176 +       err = mod_sysfs_init(mod);
177 +       if (err)
178 +               goto out;
179 +
180         mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj);
181         if (!mod->holders_dir) {
182                 err = -ENOMEM;
183 @@ -1470,6 +1565,8 @@ int mod_sysfs_setup(struct module *mod,
184         if (err)
185                 goto out_unreg_param;
186  
187 +       add_usage_links(mod);
188 +
189         kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
190         return 0;
191  
192 @@ -1479,6 +1576,7 @@ out_unreg_holders:
193         kobject_put(mod->holders_dir);
194  out_unreg:
195         kobject_put(&mod->mkobj.kobj);
196 +out:
197         return err;
198  }
199  
200 @@ -1493,10 +1591,15 @@ static void mod_sysfs_fini(struct module
201  {
202  }
203  
204 +static void del_usage_links(struct module *mod)
205 +{
206 +}
207 +
208  #endif /* CONFIG_SYSFS */
209  
210  static void mod_kobject_remove(struct module *mod)
211  {
212 +       del_usage_links(mod);
213         module_remove_modinfo_attrs(mod);
214         module_param_sysfs_remove(mod);
215         kobject_put(mod->mkobj.drivers_dir);
216 @@ -1576,6 +1679,8 @@ EXPORT_SYMBOL_GPL(__symbol_get);
217  /*
218   * Ensure that an exported symbol [global namespace] does not already exist
219   * in the kernel or in some other module's exported symbol table.
220 + *
221 + * You must hold the module_mutex.
222   */
223  static int verify_export_symbols(struct module *mod)
224  {
225 @@ -1641,21 +1746,23 @@ static int simplify_symbols(Elf_Shdr *se
226                         break;
227  
228                 case SHN_UNDEF:
229 -                       ksym = resolve_symbol(sechdrs, versindex,
230 -                                             strtab + sym[i].st_name, mod);
231 +                       ksym = resolve_symbol_wait(sechdrs, versindex,
232 +                                                  strtab + sym[i].st_name,
233 +                                                  mod);
234                         /* Ok if resolved.  */
235 -                       if (ksym) {
236 +                       if (ksym && !IS_ERR(ksym)) {
237                                 sym[i].st_value = ksym->value;
238                                 break;
239                         }
240  
241                         /* Ok if weak.  */
242 -                       if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
243 +                       if (!ksym && ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
244                                 break;
245  
246 -                       printk(KERN_WARNING "%s: Unknown symbol %s\n",
247 -                              mod->name, strtab + sym[i].st_name);
248 -                       ret = -ENOENT;
249 +                       printk(KERN_WARNING "%s: Unknown symbol %s (err %li)\n",
250 +                              mod->name, strtab + sym[i].st_name,
251 +                              PTR_ERR(ksym));
252 +                       ret = PTR_ERR(ksym) ?: -ENOENT;
253                         break;
254  
255                 default:
256 @@ -2240,11 +2347,6 @@ static noinline struct module *load_modu
257                 goto free_mod;
258         }
259  
260 -       if (find_module(mod->name)) {
261 -               err = -EEXIST;
262 -               goto free_mod;
263 -       }
264 -
265         mod->state = MODULE_STATE_COMING;
266  
267         /* Allow arches to frob section contents and sizes.  */
268 @@ -2338,11 +2440,6 @@ static noinline struct module *load_modu
269         /* Now we've moved module, initialize linked lists, etc. */
270         module_unload_init(mod);
271  
272 -       /* add kobject, so we can reference it. */
273 -       err = mod_sysfs_init(mod);
274 -       if (err)
275 -               goto free_unload;
276 -
277         /* Set up license info based on the info section */
278         set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
279  
280 @@ -2461,11 +2558,6 @@ static noinline struct module *load_modu
281                         goto cleanup;
282         }
283  
284 -        /* Find duplicate symbols */
285 -       err = verify_export_symbols(mod);
286 -       if (err < 0)
287 -               goto cleanup;
288 -
289         /* Set up and sort exception table */
290         mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table",
291                                     sizeof(*mod->extable), &mod->num_exentries);
292 @@ -2521,6 +2613,16 @@ static noinline struct module *load_modu
293          * function to insert in a way safe to concurrent readers.
294          * The mutex protects against concurrent writers.
295          */
296 +       if (find_module(mod->name)) {
297 +               err = -EEXIST;
298 +               goto already_exists;
299 +       }
300 +
301 +        /* Find duplicate symbols */
302 +       err = verify_export_symbols(mod);
303 +       if (err < 0)
304 +               goto already_exists;
305 +
306         list_add_rcu(&mod->list, &modules);
307  
308         err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL);
309 @@ -2530,6 +2632,7 @@ static noinline struct module *load_modu
310         err = mod_sysfs_setup(mod, mod->kp, mod->num_kp);
311         if (err < 0)
312                 goto unlink;
313 +
314         add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
315         add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
316  
317 @@ -2544,15 +2647,13 @@ static noinline struct module *load_modu
318   unlink:
319         /* Unlink carefully: kallsyms could be walking list. */
320         list_del_rcu(&mod->list);
321 + already_exists:
322         synchronize_sched();
323         module_arch_cleanup(mod);
324   ddebug:
325         dynamic_debug_remove(debug);
326   cleanup:
327         free_modinfo(mod);
328 -       kobject_del(&mod->mkobj.kobj);
329 -       kobject_put(&mod->mkobj.kobj);
330 - free_unload:
331         module_unload_free(mod);
332  #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
333         percpu_modfree(mod->refptr);