orangefs-debugfs.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /*
  2. * What: /sys/kernel/debug/orangefs/debug-help
  3. * Date: June 2015
  4. * Contact: Mike Marshall <hubcap@omnibond.com>
  5. * Description:
  6. * List of client and kernel debug keywords.
  7. *
  8. *
  9. * What: /sys/kernel/debug/orangefs/client-debug
  10. * Date: June 2015
  11. * Contact: Mike Marshall <hubcap@omnibond.com>
  12. * Description:
  13. * Debug setting for "the client", the userspace
  14. * helper for the kernel module.
  15. *
  16. *
  17. * What: /sys/kernel/debug/orangefs/kernel-debug
  18. * Date: June 2015
  19. * Contact: Mike Marshall <hubcap@omnibond.com>
  20. * Description:
  21. * Debug setting for the orangefs kernel module.
  22. *
  23. * Any of the keywords, or comma-separated lists
  24. * of keywords, from debug-help can be catted to
  25. * client-debug or kernel-debug.
  26. *
  27. * "none", "all" and "verbose" are special keywords
  28. * for client-debug. Setting client-debug to "all"
  29. * is kind of like trying to drink water from a
  30. * fire hose, "verbose" triggers most of the same
  31. * output except for the constant flow of output
  32. * from the main wait loop.
  33. *
  34. * "none" and "all" are similar settings for kernel-debug
  35. * no need for a "verbose".
  36. */
  37. #include <linux/debugfs.h>
  38. #include <linux/slab.h>
  39. #include <linux/uaccess.h>
  40. #include "orangefs-debugfs.h"
  41. #include "protocol.h"
  42. #include "orangefs-kernel.h"
  43. static int orangefs_debug_disabled = 1;
  44. static int orangefs_debug_help_open(struct inode *, struct file *);
  45. const struct file_operations debug_help_fops = {
  46. .open = orangefs_debug_help_open,
  47. .read = seq_read,
  48. .release = seq_release,
  49. .llseek = seq_lseek,
  50. };
  51. static void *help_start(struct seq_file *, loff_t *);
  52. static void *help_next(struct seq_file *, void *, loff_t *);
  53. static void help_stop(struct seq_file *, void *);
  54. static int help_show(struct seq_file *, void *);
  55. static const struct seq_operations help_debug_ops = {
  56. .start = help_start,
  57. .next = help_next,
  58. .stop = help_stop,
  59. .show = help_show,
  60. };
  61. /*
  62. * Used to protect data in ORANGEFS_KMOD_DEBUG_FILE and
  63. * ORANGEFS_KMOD_DEBUG_FILE.
  64. */
  65. static DEFINE_MUTEX(orangefs_debug_lock);
  66. int orangefs_debug_open(struct inode *, struct file *);
  67. static ssize_t orangefs_debug_read(struct file *,
  68. char __user *,
  69. size_t,
  70. loff_t *);
  71. static ssize_t orangefs_debug_write(struct file *,
  72. const char __user *,
  73. size_t,
  74. loff_t *);
  75. static const struct file_operations kernel_debug_fops = {
  76. .open = orangefs_debug_open,
  77. .read = orangefs_debug_read,
  78. .write = orangefs_debug_write,
  79. .llseek = generic_file_llseek,
  80. };
  81. /*
  82. * initialize kmod debug operations, create orangefs debugfs dir and
  83. * ORANGEFS_KMOD_DEBUG_HELP_FILE.
  84. */
  85. int orangefs_debugfs_init(void)
  86. {
  87. int rc = -ENOMEM;
  88. debug_dir = debugfs_create_dir("orangefs", NULL);
  89. if (!debug_dir) {
  90. pr_info("%s: debugfs_create_dir failed.\n", __func__);
  91. goto out;
  92. }
  93. help_file_dentry = debugfs_create_file(ORANGEFS_KMOD_DEBUG_HELP_FILE,
  94. 0444,
  95. debug_dir,
  96. debug_help_string,
  97. &debug_help_fops);
  98. if (!help_file_dentry) {
  99. pr_info("%s: debugfs_create_file failed.\n", __func__);
  100. goto out;
  101. }
  102. orangefs_debug_disabled = 0;
  103. rc = 0;
  104. out:
  105. return rc;
  106. }
  107. void orangefs_debugfs_cleanup(void)
  108. {
  109. debugfs_remove_recursive(debug_dir);
  110. }
  111. /* open ORANGEFS_KMOD_DEBUG_HELP_FILE */
  112. static int orangefs_debug_help_open(struct inode *inode, struct file *file)
  113. {
  114. int rc = -ENODEV;
  115. int ret;
  116. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  117. "orangefs_debug_help_open: start\n");
  118. if (orangefs_debug_disabled)
  119. goto out;
  120. ret = seq_open(file, &help_debug_ops);
  121. if (ret)
  122. goto out;
  123. ((struct seq_file *)(file->private_data))->private = inode->i_private;
  124. rc = 0;
  125. out:
  126. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  127. "orangefs_debug_help_open: rc:%d:\n",
  128. rc);
  129. return rc;
  130. }
  131. /*
  132. * I think start always gets called again after stop. Start
  133. * needs to return NULL when it is done. The whole "payload"
  134. * in this case is a single (long) string, so by the second
  135. * time we get to start (pos = 1), we're done.
  136. */
  137. static void *help_start(struct seq_file *m, loff_t *pos)
  138. {
  139. void *payload = NULL;
  140. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n");
  141. if (*pos == 0)
  142. payload = m->private;
  143. return payload;
  144. }
  145. static void *help_next(struct seq_file *m, void *v, loff_t *pos)
  146. {
  147. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_next: start\n");
  148. return NULL;
  149. }
  150. static void help_stop(struct seq_file *m, void *p)
  151. {
  152. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n");
  153. }
  154. static int help_show(struct seq_file *m, void *v)
  155. {
  156. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_show: start\n");
  157. seq_puts(m, v);
  158. return 0;
  159. }
  160. /*
  161. * initialize the kernel-debug file.
  162. */
  163. int orangefs_kernel_debug_init(void)
  164. {
  165. int rc = -ENOMEM;
  166. struct dentry *ret;
  167. char *k_buffer = NULL;
  168. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);
  169. k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
  170. if (!k_buffer)
  171. goto out;
  172. if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
  173. strcpy(k_buffer, kernel_debug_string);
  174. strcat(k_buffer, "\n");
  175. } else {
  176. strcpy(k_buffer, "none\n");
  177. pr_info("%s: overflow 1!\n", __func__);
  178. }
  179. ret = debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE,
  180. 0444,
  181. debug_dir,
  182. k_buffer,
  183. &kernel_debug_fops);
  184. if (!ret) {
  185. pr_info("%s: failed to create %s.\n",
  186. __func__,
  187. ORANGEFS_KMOD_DEBUG_FILE);
  188. goto out;
  189. }
  190. rc = 0;
  191. out:
  192. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc);
  193. return rc;
  194. }
  195. /*
  196. * initialize the client-debug file.
  197. */
  198. int orangefs_client_debug_init(void)
  199. {
  200. int rc = -ENOMEM;
  201. char *c_buffer = NULL;
  202. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);
  203. c_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
  204. if (!c_buffer)
  205. goto out;
  206. if (strlen(client_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
  207. strcpy(c_buffer, client_debug_string);
  208. strcat(c_buffer, "\n");
  209. } else {
  210. strcpy(c_buffer, "none\n");
  211. pr_info("%s: overflow! 2\n", __func__);
  212. }
  213. client_debug_dentry = debugfs_create_file(ORANGEFS_CLIENT_DEBUG_FILE,
  214. 0444,
  215. debug_dir,
  216. c_buffer,
  217. &kernel_debug_fops);
  218. if (!client_debug_dentry) {
  219. pr_info("%s: failed to create updated %s.\n",
  220. __func__,
  221. ORANGEFS_CLIENT_DEBUG_FILE);
  222. goto out;
  223. }
  224. rc = 0;
  225. out:
  226. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc);
  227. return rc;
  228. }
  229. /* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/
  230. int orangefs_debug_open(struct inode *inode, struct file *file)
  231. {
  232. int rc = -ENODEV;
  233. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  234. "%s: orangefs_debug_disabled: %d\n",
  235. __func__,
  236. orangefs_debug_disabled);
  237. if (orangefs_debug_disabled)
  238. goto out;
  239. rc = 0;
  240. mutex_lock(&orangefs_debug_lock);
  241. file->private_data = inode->i_private;
  242. mutex_unlock(&orangefs_debug_lock);
  243. out:
  244. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  245. "orangefs_debug_open: rc: %d\n",
  246. rc);
  247. return rc;
  248. }
  249. static ssize_t orangefs_debug_read(struct file *file,
  250. char __user *ubuf,
  251. size_t count,
  252. loff_t *ppos)
  253. {
  254. char *buf;
  255. int sprintf_ret;
  256. ssize_t read_ret = -ENOMEM;
  257. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "orangefs_debug_read: start\n");
  258. buf = kmalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
  259. if (!buf)
  260. goto out;
  261. mutex_lock(&orangefs_debug_lock);
  262. sprintf_ret = sprintf(buf, "%s", (char *)file->private_data);
  263. mutex_unlock(&orangefs_debug_lock);
  264. read_ret = simple_read_from_buffer(ubuf, count, ppos, buf, sprintf_ret);
  265. kfree(buf);
  266. out:
  267. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  268. "orangefs_debug_read: ret: %zu\n",
  269. read_ret);
  270. return read_ret;
  271. }
  272. static ssize_t orangefs_debug_write(struct file *file,
  273. const char __user *ubuf,
  274. size_t count,
  275. loff_t *ppos)
  276. {
  277. char *buf;
  278. int rc = -EFAULT;
  279. size_t silly = 0;
  280. char *debug_string;
  281. struct orangefs_kernel_op_s *new_op = NULL;
  282. struct client_debug_mask c_mask = { NULL, 0, 0 };
  283. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  284. "orangefs_debug_write: %s\n",
  285. file->f_path.dentry->d_name.name);
  286. /*
  287. * Thwart users who try to jamb a ridiculous number
  288. * of bytes into the debug file...
  289. */
  290. if (count > ORANGEFS_MAX_DEBUG_STRING_LEN + 1) {
  291. silly = count;
  292. count = ORANGEFS_MAX_DEBUG_STRING_LEN + 1;
  293. }
  294. buf = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
  295. if (!buf)
  296. goto out;
  297. if (copy_from_user(buf, ubuf, count - 1)) {
  298. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  299. "%s: copy_from_user failed!\n",
  300. __func__);
  301. goto out;
  302. }
  303. /*
  304. * Map the keyword string from userspace into a valid debug mask.
  305. * The mapping process involves mapping the human-inputted string
  306. * into a valid mask, and then rebuilding the string from the
  307. * verified valid mask.
  308. *
  309. * A service operation is required to set a new client-side
  310. * debug mask.
  311. */
  312. if (!strcmp(file->f_path.dentry->d_name.name,
  313. ORANGEFS_KMOD_DEBUG_FILE)) {
  314. debug_string_to_mask(buf, &gossip_debug_mask, 0);
  315. debug_mask_to_string(&gossip_debug_mask, 0);
  316. debug_string = kernel_debug_string;
  317. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  318. "New kernel debug string is %s\n",
  319. kernel_debug_string);
  320. } else {
  321. /* Can't reset client debug mask if client is not running. */
  322. if (is_daemon_in_service()) {
  323. pr_info("%s: Client not running :%d:\n",
  324. __func__,
  325. is_daemon_in_service());
  326. goto out;
  327. }
  328. debug_string_to_mask(buf, &c_mask, 1);
  329. debug_mask_to_string(&c_mask, 1);
  330. debug_string = client_debug_string;
  331. new_op = op_alloc(ORANGEFS_VFS_OP_PARAM);
  332. if (!new_op) {
  333. pr_info("%s: op_alloc failed!\n", __func__);
  334. goto out;
  335. }
  336. new_op->upcall.req.param.op =
  337. ORANGEFS_PARAM_REQUEST_OP_TWO_MASK_VALUES;
  338. new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET;
  339. memset(new_op->upcall.req.param.s_value,
  340. 0,
  341. ORANGEFS_MAX_DEBUG_STRING_LEN);
  342. sprintf(new_op->upcall.req.param.s_value,
  343. "%llx %llx\n",
  344. c_mask.mask1,
  345. c_mask.mask2);
  346. /* service_operation returns 0 on success... */
  347. rc = service_operation(new_op,
  348. "orangefs_param",
  349. ORANGEFS_OP_INTERRUPTIBLE);
  350. if (rc)
  351. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  352. "%s: service_operation failed! rc:%d:\n",
  353. __func__,
  354. rc);
  355. op_release(new_op);
  356. }
  357. mutex_lock(&orangefs_debug_lock);
  358. memset(file->f_inode->i_private, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
  359. sprintf((char *)file->f_inode->i_private, "%s\n", debug_string);
  360. mutex_unlock(&orangefs_debug_lock);
  361. *ppos += count;
  362. if (silly)
  363. rc = silly;
  364. else
  365. rc = count;
  366. out:
  367. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  368. "orangefs_debug_write: rc: %d\n",
  369. rc);
  370. kfree(buf);
  371. return rc;
  372. }