Advertisement
xosski

Blkdev_tree_builder

Jan 9th, 2025
5
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.35 KB | None | 0 0
  1. #include <linux/blkdev.h>
  2. #include <linux/fs.h>
  3. #include <linux/slab.h>
  4. #include <linux/dm-io.h>
  5. #include <linux/module.h>
  6. #include <linux/kthread.h>
  7. #include <linux/completion.h>
  8. #include <linux/delay.h>
  9. #include <linux/uaccess.h>
  10. #include <linux/errno.h>
  11. #include <linux/sched.h>
  12.  
  13. struct TreeNode {
  14. int data;
  15. struct TreeNode *left;
  16. struct TreeNode *right;
  17. };
  18.  
  19. // Function prototypes
  20. int read_sector(struct block_device *bdev, void *buffer, unsigned long sector, unsigned int count);
  21. int find_largest_number(struct TreeNode *root);
  22. int reconstruct_tree(struct block_device *bdev, unsigned long sector, struct TreeNode **node);
  23. void free_tree(struct TreeNode *node);
  24.  
  25. // Function to read a sector from the block device
  26. int read_sector(struct block_device *bdev, void *buffer, unsigned long sector, unsigned int count) {
  27. struct dm_io_region io_region;
  28. struct dm_io_request io_req;
  29. struct dm_io_client *io_client;
  30. int ret;
  31.  
  32. io_client = dm_io_client_create();
  33. if (IS_ERR(io_client)) {
  34. pr_err("Failed to create I/O client\n");
  35. return PTR_ERR(io_client);
  36. }
  37.  
  38. io_region.bdev = bdev;
  39. io_region.sector = sector;
  40. io_region.count = count;
  41.  
  42. io_req.bi_op = REQ_OP_READ;
  43. io_req.bi_op_flags = 0;
  44. io_req.mem.type = DM_IO_KMEM;
  45. io_req.mem.ptr.addr = buffer;
  46. io_req.client = io_client;
  47. io_req.notify.fn = NULL;
  48. io_req.notify.context = NULL;
  49.  
  50. ret = dm_io(&io_req, 1, &io_region, NULL);
  51. if (ret) {
  52. pr_err("I/O read failed\n");
  53. }
  54.  
  55. dm_io_client_destroy(io_client);
  56. return ret;
  57. }
  58.  
  59. // Function to find the largest number in the tree
  60. int find_largest_number(struct TreeNode *root) {
  61. if (!root) return INT_MIN;
  62.  
  63. int left_max = find_largest_number(root->left);
  64. int right_max = find_largest_number(root->right);
  65.  
  66. return max(root->data, max(left_max, right_max));
  67. }
  68.  
  69. // Structure for passing parameters to kernel threads
  70. struct reconstruct_params {
  71. struct block_device *bdev;
  72. unsigned long sector;
  73. struct TreeNode **node;
  74. struct completion *comp;
  75. };
  76.  
  77. // Thread function to reconstruct the tree
  78. static int reconstruct_tree_thread(void *data) {
  79. struct reconstruct_params *params = data;
  80. int ret;
  81.  
  82. ret = reconstruct_tree(params->bdev, params->sector, params->node);
  83.  
  84. complete(params->comp); // Signal completion
  85. kfree(params); // Free parameters
  86. return ret;
  87. }
  88.  
  89. // Function to recursively reconstruct the binary tree
  90. int reconstruct_tree(struct block_device *bdev, unsigned long sector, struct TreeNode **node) {
  91. void *buffer;
  92. int ret = 0;
  93.  
  94. // Allocate buffer for reading a sector
  95. buffer = kmalloc(4096, GFP_KERNEL);
  96. if (!buffer) {
  97. pr_err("Failed to allocate buffer\n");
  98. return -ENOMEM;
  99. }
  100.  
  101. // Read the current sector
  102. ret = read_sector(bdev, buffer, sector, 1);
  103. if (ret) {
  104. kfree(buffer);
  105. return ret;
  106. }
  107.  
  108. // Allocate TreeNode
  109. *node = kmalloc(sizeof(struct TreeNode), GFP_KERNEL);
  110. if (!*node) {
  111. kfree(buffer);
  112. pr_err("Failed to allocate TreeNode\n");
  113. return -ENOMEM;
  114. }
  115.  
  116. (*node)->data = *((int *)buffer); // The first 4 bytes of the buffer are the data of the node
  117. (*node)->left = NULL;
  118. (*node)->right = NULL;
  119.  
  120. // Move to the next sector
  121. sector++;
  122.  
  123. kfree(buffer);
  124.  
  125. // Reconstruct left subtree using a kernel thread
  126. if (sector % 2 == 0) {
  127. struct task_struct *left_thread;
  128. struct reconstruct_params *left_params;
  129. struct completion *left_comp;
  130.  
  131. left_params = kmalloc(sizeof(struct reconstruct_params), GFP_KERNEL);
  132. left_comp = kmalloc(sizeof(struct completion), GFP_KERNEL);
  133. if (!left_params || !left_comp) {
  134. pr_err("Failed to allocate left thread parameters\n");
  135. ret = -ENOMEM;
  136. goto free_node;
  137. }
  138. init_completion(left_comp);
  139. left_params->bdev = bdev;
  140. left_params->sector = sector; // Each thread gets its own sector value
  141. left_params->node = &(*node)->left;
  142. left_params->comp = left_comp;
  143.  
  144. left_thread = kthread_run(reconstruct_tree_thread, left_params, "left_reconstruct");
  145. if (IS_ERR(left_thread)) {
  146. pr_err("Failed to create left_thread\n");
  147. ret = PTR_ERR(left_thread);
  148. kfree(left_params);
  149. kfree(left_comp);
  150. goto free_node;
  151. }
  152.  
  153. // Wait for left_thread to complete
  154. wait_for_completion(left_comp);
  155. kfree(left_comp);
  156. }
  157.  
  158. // Reconstruct right subtree using a kernel thread
  159. if (sector % 3 == 0) {
  160. struct task_struct *right_thread;
  161. struct reconstruct_params *right_params;
  162. struct completion *right_comp;
  163.  
  164. right_params = kmalloc(sizeof(struct reconstruct_params), GFP_KERNEL);
  165. right_comp = kmalloc(sizeof(struct completion), GFP_KERNEL);
  166. if (!right_params || !right_comp) {
  167. pr_err("Failed to allocate right thread parameters\n");
  168. ret = -ENOMEM;
  169. goto free_left_subtree;
  170. }
  171. init_completion(right_comp);
  172. right_params->bdev = bdev;
  173. right_params->sector = sector; // Each thread gets its own sector value
  174. right_params->node = &(*node)->right;
  175. right_params->comp = right_comp;
  176.  
  177. right_thread = kthread_run(reconstruct_tree_thread, right_params, "right_reconstruct");
  178. if (IS_ERR(right_thread)) {
  179. pr_err("Failed to create right_thread\n");
  180. ret = PTR_ERR(right_thread);
  181. kfree(right_params);
  182. kfree(right_comp);
  183. goto free_left_subtree;
  184. }
  185.  
  186. // Wait for right_thread to complete
  187. wait_for_completion(right_comp);
  188. kfree(right_comp);
  189. }
  190.  
  191. return 0;
  192.  
  193. free_left_subtree:
  194. if ((*node)->left) {
  195. free_tree((*node)->left);
  196. }
  197. free_node:
  198. kfree(*node);
  199. return ret;
  200. }
  201.  
  202. // Function to free the entire tree
  203. void free_tree(struct TreeNode *node) {
  204. if (node == NULL)
  205. return;
  206.  
  207. free_tree(node->left);
  208. free_tree(node->right);
  209. kfree(node);
  210. }
  211.  
  212. static int __init hello_init(void) {
  213. struct block_device *bdev;
  214. struct TreeNode *root = NULL;
  215. int largest_number;
  216. int ret;
  217. unsigned long sector = 0; // Start from the first sector
  218.  
  219. // Open the block device for reading
  220. bdev = blkdev_get_by_path("/dev/sdb", FMODE_READ | FMODE_EXCL, NULL);
  221. if (IS_ERR(bdev)) {
  222. pr_err("Failed to open block device\n");
  223. return PTR_ERR(bdev);
  224. }
  225.  
  226. // Reconstruct the tree from the block device
  227. ret = reconstruct_tree(bdev, sector, &root);
  228. if (ret) {
  229. pr_err("Failed to reconstruct tree\n");
  230. blkdev_put(bdev, FMODE_READ | FMODE_EXCL);
  231. return ret;
  232. }
  233.  
  234. // Find the largest number in the tree
  235. largest_number = find_largest_number(root);
  236. pr_info("Largest number in the tree: %d\n", largest_number);
  237.  
  238. // Clean up
  239. free_tree(root); // Free the allocated tree
  240. blkdev_put(bdev, FMODE_READ | FMODE_EXCL);
  241. return 0;
  242. }
  243.  
  244. static void __exit hello_exit(void) {
  245. pr_info("Kernel module exited\n");
  246. }
  247.  
  248. MODULE_INFO(intree , "Y");
  249. module_init(hello_init);
  250. module_exit(hello_exit);
  251. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement