dm-uevent.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * Device Mapper Uevent Support (dm-uevent)
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation; either version 2 of the License, or (at your
  7. * option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. *
  18. * Copyright IBM Corporation, 2007
  19. * Author: Mike Anderson <andmike@linux.vnet.ibm.com>
  20. */
  21. #include <linux/list.h>
  22. #include <linux/slab.h>
  23. #include <linux/kobject.h>
  24. #include <linux/dm-ioctl.h>
  25. #include <linux/export.h>
  26. #include "dm.h"
  27. #include "dm-uevent.h"
  28. #define DM_MSG_PREFIX "uevent"
  29. static const struct {
  30. enum dm_uevent_type type;
  31. enum kobject_action action;
  32. char *name;
  33. } _dm_uevent_type_names[] = {
  34. {DM_UEVENT_PATH_FAILED, KOBJ_CHANGE, "PATH_FAILED"},
  35. {DM_UEVENT_PATH_REINSTATED, KOBJ_CHANGE, "PATH_REINSTATED"},
  36. };
  37. static struct kmem_cache *_dm_event_cache;
  38. struct dm_uevent {
  39. struct mapped_device *md;
  40. enum kobject_action action;
  41. struct kobj_uevent_env ku_env;
  42. struct list_head elist;
  43. char name[DM_NAME_LEN];
  44. char uuid[DM_UUID_LEN];
  45. };
  46. static void dm_uevent_free(struct dm_uevent *event)
  47. {
  48. kmem_cache_free(_dm_event_cache, event);
  49. }
  50. static struct dm_uevent *dm_uevent_alloc(struct mapped_device *md)
  51. {
  52. struct dm_uevent *event;
  53. event = kmem_cache_zalloc(_dm_event_cache, GFP_ATOMIC);
  54. if (!event)
  55. return NULL;
  56. INIT_LIST_HEAD(&event->elist);
  57. event->md = md;
  58. return event;
  59. }
  60. static struct dm_uevent *dm_build_path_uevent(struct mapped_device *md,
  61. struct dm_target *ti,
  62. enum kobject_action action,
  63. const char *dm_action,
  64. const char *path,
  65. unsigned nr_valid_paths)
  66. {
  67. struct dm_uevent *event;
  68. event = dm_uevent_alloc(md);
  69. if (!event) {
  70. DMERR("%s: dm_uevent_alloc() failed", __func__);
  71. goto err_nomem;
  72. }
  73. event->action = action;
  74. if (add_uevent_var(&event->ku_env, "DM_TARGET=%s", ti->type->name)) {
  75. DMERR("%s: add_uevent_var() for DM_TARGET failed",
  76. __func__);
  77. goto err_add;
  78. }
  79. if (add_uevent_var(&event->ku_env, "DM_ACTION=%s", dm_action)) {
  80. DMERR("%s: add_uevent_var() for DM_ACTION failed",
  81. __func__);
  82. goto err_add;
  83. }
  84. if (add_uevent_var(&event->ku_env, "DM_SEQNUM=%u",
  85. dm_next_uevent_seq(md))) {
  86. DMERR("%s: add_uevent_var() for DM_SEQNUM failed",
  87. __func__);
  88. goto err_add;
  89. }
  90. if (add_uevent_var(&event->ku_env, "DM_PATH=%s", path)) {
  91. DMERR("%s: add_uevent_var() for DM_PATH failed", __func__);
  92. goto err_add;
  93. }
  94. if (add_uevent_var(&event->ku_env, "DM_NR_VALID_PATHS=%d",
  95. nr_valid_paths)) {
  96. DMERR("%s: add_uevent_var() for DM_NR_VALID_PATHS failed",
  97. __func__);
  98. goto err_add;
  99. }
  100. return event;
  101. err_add:
  102. dm_uevent_free(event);
  103. err_nomem:
  104. return ERR_PTR(-ENOMEM);
  105. }
  106. /**
  107. * dm_send_uevents - send uevents for given list
  108. *
  109. * @events: list of events to send
  110. * @kobj: kobject generating event
  111. *
  112. */
  113. void dm_send_uevents(struct list_head *events, struct kobject *kobj)
  114. {
  115. int r;
  116. struct dm_uevent *event, *next;
  117. list_for_each_entry_safe(event, next, events, elist) {
  118. list_del_init(&event->elist);
  119. /*
  120. * When a device is being removed this copy fails and we
  121. * discard these unsent events.
  122. */
  123. if (dm_copy_name_and_uuid(event->md, event->name,
  124. event->uuid)) {
  125. DMINFO("%s: skipping sending uevent for lost device",
  126. __func__);
  127. goto uevent_free;
  128. }
  129. if (add_uevent_var(&event->ku_env, "DM_NAME=%s", event->name)) {
  130. DMERR("%s: add_uevent_var() for DM_NAME failed",
  131. __func__);
  132. goto uevent_free;
  133. }
  134. if (add_uevent_var(&event->ku_env, "DM_UUID=%s", event->uuid)) {
  135. DMERR("%s: add_uevent_var() for DM_UUID failed",
  136. __func__);
  137. goto uevent_free;
  138. }
  139. r = kobject_uevent_env(kobj, event->action, event->ku_env.envp);
  140. if (r)
  141. DMERR("%s: kobject_uevent_env failed", __func__);
  142. uevent_free:
  143. dm_uevent_free(event);
  144. }
  145. }
  146. EXPORT_SYMBOL_GPL(dm_send_uevents);
  147. /**
  148. * dm_path_uevent - called to create a new path event and queue it
  149. *
  150. * @event_type: path event type enum
  151. * @ti: pointer to a dm_target
  152. * @path: string containing pathname
  153. * @nr_valid_paths: number of valid paths remaining
  154. *
  155. */
  156. void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti,
  157. const char *path, unsigned nr_valid_paths)
  158. {
  159. struct mapped_device *md = dm_table_get_md(ti->table);
  160. struct dm_uevent *event;
  161. if (event_type >= ARRAY_SIZE(_dm_uevent_type_names)) {
  162. DMERR("%s: Invalid event_type %d", __func__, event_type);
  163. return;
  164. }
  165. event = dm_build_path_uevent(md, ti,
  166. _dm_uevent_type_names[event_type].action,
  167. _dm_uevent_type_names[event_type].name,
  168. path, nr_valid_paths);
  169. if (IS_ERR(event))
  170. return;
  171. dm_uevent_add(md, &event->elist);
  172. }
  173. EXPORT_SYMBOL_GPL(dm_path_uevent);
  174. int dm_uevent_init(void)
  175. {
  176. _dm_event_cache = KMEM_CACHE(dm_uevent, 0);
  177. if (!_dm_event_cache)
  178. return -ENOMEM;
  179. DMINFO("version 1.0.3");
  180. return 0;
  181. }
  182. void dm_uevent_exit(void)
  183. {
  184. kmem_cache_destroy(_dm_event_cache);
  185. }