450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. From e5cf19bd8204925f3bd2067df9e867313eac388b Mon Sep 17 00:00:00 2001
  2. From: Daniel Golle <[email protected]>
  3. Date: Mon, 1 May 2023 11:57:51 +0100
  4. Subject: [PATCH 03/15] mtd: ubi: block: use notifier to create ubiblock from
  5. parameter
  6. Use UBI_VOLUME_ADDED notification to create ubiblock device specified
  7. on kernel cmdline or module parameter.
  8. This makes thing more simple and has the advantage that ubiblock devices
  9. on volumes which are not present at the time the ubi module is probed
  10. will still be created.
  11. Suggested-by: Zhihao Cheng <[email protected]>
  12. Signed-off-by: Daniel Golle <[email protected]>
  13. ---
  14. drivers/mtd/ubi/block.c | 154 ++++++++++++++++++++++------------------
  15. 1 file changed, 85 insertions(+), 69 deletions(-)
  16. --- a/drivers/mtd/ubi/block.c
  17. +++ b/drivers/mtd/ubi/block.c
  18. @@ -33,6 +33,7 @@
  19. #include <linux/kernel.h>
  20. #include <linux/list.h>
  21. #include <linux/mutex.h>
  22. +#include <linux/namei.h>
  23. #include <linux/slab.h>
  24. #include <linux/mtd/ubi.h>
  25. #include <linux/blkdev.h>
  26. @@ -65,10 +66,10 @@ struct ubiblock_pdu {
  27. };
  28. /* Numbers of elements set in the @ubiblock_param array */
  29. -static int ubiblock_devs __initdata;
  30. +static int ubiblock_devs;
  31. /* MTD devices specification parameters */
  32. -static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES] __initdata;
  33. +static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES];
  34. struct ubiblock {
  35. struct ubi_volume_desc *desc;
  36. @@ -469,7 +470,7 @@ int ubiblock_remove(struct ubi_volume_in
  37. }
  38. /* Found a device, let's lock it so we can check if it's busy */
  39. - mutex_lock(&dev->dev_mutex);
  40. + mutex_lock_nested(&dev->dev_mutex, SINGLE_DEPTH_NESTING);
  41. if (dev->refcnt > 0) {
  42. ret = -EBUSY;
  43. goto out_unlock_dev;
  44. @@ -532,6 +533,85 @@ static int ubiblock_resize(struct ubi_vo
  45. return 0;
  46. }
  47. +static bool
  48. +match_volume_desc(struct ubi_volume_info *vi, const char *name, int ubi_num, int vol_id)
  49. +{
  50. + int err, len;
  51. + struct path path;
  52. + struct kstat stat;
  53. +
  54. + if (ubi_num == -1) {
  55. + /* No ubi num, name must be a vol device path */
  56. + err = kern_path(name, LOOKUP_FOLLOW, &path);
  57. + if (err)
  58. + return false;
  59. +
  60. + err = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT);
  61. + path_put(&path);
  62. + if (err)
  63. + return false;
  64. +
  65. + if (!S_ISCHR(stat.mode))
  66. + return false;
  67. +
  68. + if (vi->ubi_num != ubi_major2num(MAJOR(stat.rdev)))
  69. + return false;
  70. +
  71. + if (vi->vol_id != MINOR(stat.rdev) - 1)
  72. + return false;
  73. +
  74. + return true;
  75. + }
  76. +
  77. + if (vol_id == -1) {
  78. + if (vi->ubi_num != ubi_num)
  79. + return false;
  80. +
  81. + len = strnlen(name, UBI_VOL_NAME_MAX + 1);
  82. + if (len < 1 || vi->name_len != len)
  83. + return false;
  84. +
  85. + if (strcmp(name, vi->name))
  86. + return false;
  87. +
  88. + return true;
  89. + }
  90. +
  91. + if (vi->ubi_num != ubi_num)
  92. + return false;
  93. +
  94. + if (vi->vol_id != vol_id)
  95. + return false;
  96. +
  97. + return true;
  98. +}
  99. +
  100. +static void
  101. +ubiblock_create_from_param(struct ubi_volume_info *vi)
  102. +{
  103. + int i, ret = 0;
  104. + struct ubiblock_param *p;
  105. +
  106. + /*
  107. + * Iterate over ubiblock cmdline parameters. If a parameter matches the
  108. + * newly added volume create the ubiblock device for it.
  109. + */
  110. + for (i = 0; i < ubiblock_devs; i++) {
  111. + p = &ubiblock_param[i];
  112. +
  113. + if (!match_volume_desc(vi, p->name, p->ubi_num, p->vol_id))
  114. + continue;
  115. +
  116. + ret = ubiblock_create(vi);
  117. + if (ret) {
  118. + pr_err(
  119. + "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n",
  120. + vi->name, p->ubi_num, p->vol_id, ret);
  121. + }
  122. + break;
  123. + }
  124. +}
  125. +
  126. static int ubiblock_notify(struct notifier_block *nb,
  127. unsigned long notification_type, void *ns_ptr)
  128. {
  129. @@ -539,10 +619,7 @@ static int ubiblock_notify(struct notifi
  130. switch (notification_type) {
  131. case UBI_VOLUME_ADDED:
  132. - /*
  133. - * We want to enforce explicit block device creation for
  134. - * volumes, so when a volume is added we do nothing.
  135. - */
  136. + ubiblock_create_from_param(&nt->vi);
  137. break;
  138. case UBI_VOLUME_REMOVED:
  139. ubiblock_remove(&nt->vi);
  140. @@ -568,56 +645,6 @@ static struct notifier_block ubiblock_no
  141. .notifier_call = ubiblock_notify,
  142. };
  143. -static struct ubi_volume_desc * __init
  144. -open_volume_desc(const char *name, int ubi_num, int vol_id)
  145. -{
  146. - if (ubi_num == -1)
  147. - /* No ubi num, name must be a vol device path */
  148. - return ubi_open_volume_path(name, UBI_READONLY);
  149. - else if (vol_id == -1)
  150. - /* No vol_id, must be vol_name */
  151. - return ubi_open_volume_nm(ubi_num, name, UBI_READONLY);
  152. - else
  153. - return ubi_open_volume(ubi_num, vol_id, UBI_READONLY);
  154. -}
  155. -
  156. -static void __init ubiblock_create_from_param(void)
  157. -{
  158. - int i, ret = 0;
  159. - struct ubiblock_param *p;
  160. - struct ubi_volume_desc *desc;
  161. - struct ubi_volume_info vi;
  162. -
  163. - /*
  164. - * If there is an error creating one of the ubiblocks, continue on to
  165. - * create the following ubiblocks. This helps in a circumstance where
  166. - * the kernel command-line specifies multiple block devices and some
  167. - * may be broken, but we still want the working ones to come up.
  168. - */
  169. - for (i = 0; i < ubiblock_devs; i++) {
  170. - p = &ubiblock_param[i];
  171. -
  172. - desc = open_volume_desc(p->name, p->ubi_num, p->vol_id);
  173. - if (IS_ERR(desc)) {
  174. - pr_err(
  175. - "UBI: block: can't open volume on ubi%d_%d, err=%ld\n",
  176. - p->ubi_num, p->vol_id, PTR_ERR(desc));
  177. - continue;
  178. - }
  179. -
  180. - ubi_get_volume_info(desc, &vi);
  181. - ubi_close_volume(desc);
  182. -
  183. - ret = ubiblock_create(&vi);
  184. - if (ret) {
  185. - pr_err(
  186. - "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n",
  187. - vi.name, p->ubi_num, p->vol_id, ret);
  188. - continue;
  189. - }
  190. - }
  191. -}
  192. -
  193. static void ubiblock_remove_all(void)
  194. {
  195. struct ubiblock *next;
  196. @@ -643,18 +670,7 @@ int __init ubiblock_init(void)
  197. if (ubiblock_major < 0)
  198. return ubiblock_major;
  199. - /*
  200. - * Attach block devices from 'block=' module param.
  201. - * Even if one block device in the param list fails to come up,
  202. - * still allow the module to load and leave any others up.
  203. - */
  204. - ubiblock_create_from_param();
  205. -
  206. - /*
  207. - * Block devices are only created upon user requests, so we ignore
  208. - * existing volumes.
  209. - */
  210. - ret = ubi_register_volume_notifier(&ubiblock_notifier, 1);
  211. + ret = ubi_register_volume_notifier(&ubiblock_notifier, 0);
  212. if (ret)
  213. goto err_unreg;
  214. return 0;