proc_partitions.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. */
  9. #include "proc.h"
  10. #include "procfs.h"
  11. #include <rthw.h>
  12. #include <rtdbg.h>
  13. #include <fcntl.h>
  14. #include <errno.h>
  15. #include <dfs_dentry.h>
  16. #include <rthw.h>
  17. #include <rtthread.h>
  18. #include <string.h>
  19. #define LIST_FIND_OBJ_NR 8
  20. typedef struct
  21. {
  22. rt_list_t *list;
  23. rt_list_t **array;
  24. rt_uint8_t type;
  25. int nr; /* input: max nr, can't be 0 */
  26. int nr_out; /* out: got nr */
  27. } list_get_next_t;
  28. static void list_find_init(list_get_next_t *p, rt_uint8_t type, rt_list_t **array, int nr)
  29. {
  30. struct rt_object_information *info;
  31. rt_list_t *list;
  32. info = rt_object_get_information((enum rt_object_class_type)type);
  33. list = &info->object_list;
  34. p->list = list;
  35. p->type = type;
  36. p->array = array;
  37. p->nr = nr;
  38. p->nr_out = 0;
  39. }
  40. static rt_list_t *list_get_next(rt_list_t *current, list_get_next_t *arg)
  41. {
  42. int first_flag = 0;
  43. rt_base_t level;
  44. rt_list_t *node, *list;
  45. rt_list_t **array;
  46. struct rt_object_information *info;
  47. int nr;
  48. arg->nr_out = 0;
  49. if (!arg->nr || !arg->type)
  50. {
  51. return (rt_list_t *)RT_NULL;
  52. }
  53. list = arg->list;
  54. info = rt_list_entry(list, struct rt_object_information, object_list);
  55. if (!current) /* find first */
  56. {
  57. node = list;
  58. first_flag = 1;
  59. }
  60. else
  61. {
  62. node = current;
  63. }
  64. level = rt_spin_lock_irqsave(&info->spinlock);
  65. if (!first_flag)
  66. {
  67. struct rt_object *obj;
  68. /* The node in the list? */
  69. obj = rt_list_entry(node, struct rt_object, list);
  70. if ((obj->type & ~RT_Object_Class_Static) != arg->type)
  71. {
  72. rt_spin_unlock_irqrestore(&info->spinlock, level);
  73. return (rt_list_t *)RT_NULL;
  74. }
  75. }
  76. nr = 0;
  77. array = arg->array;
  78. while (1)
  79. {
  80. node = node->next;
  81. if (node == list)
  82. {
  83. node = (rt_list_t *)RT_NULL;
  84. break;
  85. }
  86. nr++;
  87. *array++ = node;
  88. if (nr == arg->nr)
  89. {
  90. break;
  91. }
  92. }
  93. rt_spin_unlock_irqrestore(&info->spinlock, level);
  94. arg->nr_out = nr;
  95. return node;
  96. }
  97. static int show_info(struct dfs_seq_file *seq)
  98. {
  99. rt_base_t level;
  100. list_get_next_t find_arg;
  101. struct rt_object_information *info;
  102. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  103. rt_list_t *next = (rt_list_t *)RT_NULL;
  104. list_find_init(&find_arg, RT_Object_Class_Device, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  105. info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
  106. do
  107. {
  108. next = list_get_next(next, &find_arg);
  109. {
  110. int i;
  111. for (i = 0; i < find_arg.nr_out; i++)
  112. {
  113. struct rt_object *obj;
  114. struct rt_device *device;
  115. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  116. level = rt_spin_lock_irqsave(&info->spinlock);
  117. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  118. {
  119. rt_spin_unlock_irqrestore(&info->spinlock, level);
  120. continue;
  121. }
  122. rt_spin_unlock_irqrestore(&info->spinlock, level);
  123. device = (struct rt_device *)obj;
  124. if (device->type == RT_Device_Class_Block)
  125. {
  126. struct rt_device_blk_geometry geometry = { 0 };
  127. rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
  128. dfs_seq_printf(seq, "%4d %7d %14llu %s\n", 0, 0,
  129. geometry.sector_count, device->parent.name);
  130. }
  131. }
  132. }
  133. } while (next != (rt_list_t *)RT_NULL);
  134. return 0;
  135. }
  136. static void *seq_start(struct dfs_seq_file *seq, off_t *index)
  137. {
  138. off_t i = *index; // seq->index
  139. return NULL + (i == 0);
  140. }
  141. static void seq_stop(struct dfs_seq_file *seq, void *data)
  142. {
  143. }
  144. static void *seq_next(struct dfs_seq_file *seq, void *data, off_t *index)
  145. {
  146. /* data: The return value of the start or next*/
  147. off_t i = *index + 1; // seq->index
  148. *index = i;
  149. return NULL;
  150. }
  151. static int seq_show(struct dfs_seq_file *seq, void *data)
  152. {
  153. dfs_seq_puts(seq, "major minor #blocks name\n\n");
  154. /* data: The return value of the start or next*/
  155. show_info(seq);
  156. return 0;
  157. }
  158. static const struct dfs_seq_ops seq_ops = {
  159. .start = seq_start,
  160. .stop = seq_stop,
  161. .next = seq_next,
  162. .show = seq_show,
  163. };
  164. int proc_partitions_init(void)
  165. {
  166. struct proc_dentry *dentry = proc_create_data("partitions", 0, NULL, NULL, NULL);
  167. if (dentry)
  168. {
  169. dentry->seq_ops = &seq_ops;
  170. }
  171. proc_release(dentry);
  172. return 0;
  173. }
  174. INIT_ENV_EXPORT(proc_partitions_init);