orangefs-debugfs.c 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * What: /sys/kernel/debug/orangefs/debug-help
  4. * Date: June 2015
  5. * Contact: Mike Marshall <[email protected]>
  6. * Description:
  7. * List of client and kernel debug keywords.
  8. *
  9. *
  10. * What: /sys/kernel/debug/orangefs/client-debug
  11. * Date: June 2015
  12. * Contact: Mike Marshall <[email protected]>
  13. * Description:
  14. * Debug setting for "the client", the userspace
  15. * helper for the kernel module.
  16. *
  17. *
  18. * What: /sys/kernel/debug/orangefs/kernel-debug
  19. * Date: June 2015
  20. * Contact: Mike Marshall <[email protected]>
  21. * Description:
  22. * Debug setting for the orangefs kernel module.
  23. *
  24. * Any of the keywords, or comma-separated lists
  25. * of keywords, from debug-help can be catted to
  26. * client-debug or kernel-debug.
  27. *
  28. * "none", "all" and "verbose" are special keywords
  29. * for client-debug. Setting client-debug to "all"
  30. * is kind of like trying to drink water from a
  31. * fire hose, "verbose" triggers most of the same
  32. * output except for the constant flow of output
  33. * from the main wait loop.
  34. *
  35. * "none" and "all" are similar settings for kernel-debug
  36. * no need for a "verbose".
  37. */
  38. #include <linux/debugfs.h>
  39. #include <linux/slab.h>
  40. #include <linux/uaccess.h>
  41. #include "orangefs-debugfs.h"
  42. #include "protocol.h"
  43. #include "orangefs-kernel.h"
  44. #define DEBUG_HELP_STRING_SIZE 4096
  45. #define HELP_STRING_UNINITIALIZED \
  46. "Client Debug Keywords are unknown until the first time\n" \
  47. "the client is started after boot.\n"
  48. #define ORANGEFS_KMOD_DEBUG_HELP_FILE "debug-help"
  49. #define ORANGEFS_KMOD_DEBUG_FILE "kernel-debug"
  50. #define ORANGEFS_CLIENT_DEBUG_FILE "client-debug"
  51. #define ORANGEFS_VERBOSE "verbose"
  52. #define ORANGEFS_ALL "all"
  53. /*
  54. * An array of client_debug_mask will be built to hold debug keyword/mask
  55. * values fetched from userspace.
  56. */
  57. struct client_debug_mask {
  58. char *keyword;
  59. __u64 mask1;
  60. __u64 mask2;
  61. };
  62. static void orangefs_kernel_debug_init(void);
  63. static int orangefs_debug_help_open(struct inode *, struct file *);
  64. static void *help_start(struct seq_file *, loff_t *);
  65. static void *help_next(struct seq_file *, void *, loff_t *);
  66. static void help_stop(struct seq_file *, void *);
  67. static int help_show(struct seq_file *, void *);
  68. static int orangefs_debug_open(struct inode *, struct file *);
  69. static ssize_t orangefs_debug_read(struct file *,
  70. char __user *,
  71. size_t,
  72. loff_t *);
  73. static ssize_t orangefs_debug_write(struct file *,
  74. const char __user *,
  75. size_t,
  76. loff_t *);
  77. static int orangefs_prepare_cdm_array(char *);
  78. static void debug_mask_to_string(void *, int);
  79. static void do_k_string(void *, int);
  80. static void do_c_string(void *, int);
  81. static int keyword_is_amalgam(char *);
  82. static int check_amalgam_keyword(void *, int);
  83. static void debug_string_to_mask(char *, void *, int);
  84. static void do_c_mask(int, char *, struct client_debug_mask **);
  85. static void do_k_mask(int, char *, __u64 **);
  86. static char kernel_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN] = "none";
  87. static char *debug_help_string;
  88. static char client_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN];
  89. static char client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN];
  90. static struct dentry *client_debug_dentry;
  91. static struct dentry *debug_dir;
  92. static unsigned int kernel_mask_set_mod_init;
  93. static int orangefs_debug_disabled = 1;
  94. static int help_string_initialized;
  95. static const struct seq_operations help_debug_ops = {
  96. .start = help_start,
  97. .next = help_next,
  98. .stop = help_stop,
  99. .show = help_show,
  100. };
  101. static const struct file_operations debug_help_fops = {
  102. .owner = THIS_MODULE,
  103. .open = orangefs_debug_help_open,
  104. .read = seq_read,
  105. .release = seq_release,
  106. .llseek = seq_lseek,
  107. };
  108. static const struct file_operations kernel_debug_fops = {
  109. .owner = THIS_MODULE,
  110. .open = orangefs_debug_open,
  111. .read = orangefs_debug_read,
  112. .write = orangefs_debug_write,
  113. .llseek = generic_file_llseek,
  114. };
  115. static int client_all_index;
  116. static int client_verbose_index;
  117. static struct client_debug_mask *cdm_array;
  118. static int cdm_element_count;
  119. static struct client_debug_mask client_debug_mask;
  120. /*
  121. * Used to protect data in ORANGEFS_KMOD_DEBUG_FILE and
  122. * ORANGEFS_KMOD_DEBUG_FILE.
  123. */
  124. static DEFINE_MUTEX(orangefs_debug_lock);
  125. /* Used to protect data in ORANGEFS_KMOD_DEBUG_HELP_FILE */
  126. static DEFINE_MUTEX(orangefs_help_file_lock);
  127. /*
  128. * initialize kmod debug operations, create orangefs debugfs dir and
  129. * ORANGEFS_KMOD_DEBUG_HELP_FILE.
  130. */
  131. void orangefs_debugfs_init(int debug_mask)
  132. {
  133. /* convert input debug mask to a 64-bit unsigned integer */
  134. orangefs_gossip_debug_mask = (unsigned long long)debug_mask;
  135. /*
  136. * set the kernel's gossip debug string; invalid mask values will
  137. * be ignored.
  138. */
  139. debug_mask_to_string(&orangefs_gossip_debug_mask, 0);
  140. /* remove any invalid values from the mask */
  141. debug_string_to_mask(kernel_debug_string, &orangefs_gossip_debug_mask,
  142. 0);
  143. /*
  144. * if the mask has a non-zero value, then indicate that the mask
  145. * was set when the kernel module was loaded. The orangefs dev ioctl
  146. * command will look at this boolean to determine if the kernel's
  147. * debug mask should be overwritten when the client-core is started.
  148. */
  149. if (orangefs_gossip_debug_mask != 0)
  150. kernel_mask_set_mod_init = true;
  151. pr_info("%s: called with debug mask: :%s: :%llx:\n",
  152. __func__,
  153. kernel_debug_string,
  154. (unsigned long long)orangefs_gossip_debug_mask);
  155. debug_dir = debugfs_create_dir("orangefs", NULL);
  156. debugfs_create_file(ORANGEFS_KMOD_DEBUG_HELP_FILE, 0444, debug_dir,
  157. debug_help_string, &debug_help_fops);
  158. orangefs_debug_disabled = 0;
  159. orangefs_kernel_debug_init();
  160. }
  161. /*
  162. * initialize the kernel-debug file.
  163. */
  164. static void orangefs_kernel_debug_init(void)
  165. {
  166. static char k_buffer[ORANGEFS_MAX_DEBUG_STRING_LEN] = { };
  167. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);
  168. if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
  169. strcpy(k_buffer, kernel_debug_string);
  170. strcat(k_buffer, "\n");
  171. } else {
  172. strcpy(k_buffer, "none\n");
  173. pr_info("%s: overflow 1!\n", __func__);
  174. }
  175. debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE, 0444, debug_dir, k_buffer,
  176. &kernel_debug_fops);
  177. }
  178. void orangefs_debugfs_cleanup(void)
  179. {
  180. debugfs_remove_recursive(debug_dir);
  181. kfree(debug_help_string);
  182. debug_help_string = NULL;
  183. }
  184. /* open ORANGEFS_KMOD_DEBUG_HELP_FILE */
  185. static int orangefs_debug_help_open(struct inode *inode, struct file *file)
  186. {
  187. int rc = -ENODEV;
  188. int ret;
  189. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  190. "orangefs_debug_help_open: start\n");
  191. if (orangefs_debug_disabled)
  192. goto out;
  193. ret = seq_open(file, &help_debug_ops);
  194. if (ret)
  195. goto out;
  196. ((struct seq_file *)(file->private_data))->private = inode->i_private;
  197. rc = 0;
  198. out:
  199. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  200. "orangefs_debug_help_open: rc:%d:\n",
  201. rc);
  202. return rc;
  203. }
  204. /*
  205. * I think start always gets called again after stop. Start
  206. * needs to return NULL when it is done. The whole "payload"
  207. * in this case is a single (long) string, so by the second
  208. * time we get to start (pos = 1), we're done.
  209. */
  210. static void *help_start(struct seq_file *m, loff_t *pos)
  211. {
  212. void *payload = NULL;
  213. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n");
  214. mutex_lock(&orangefs_help_file_lock);
  215. if (*pos == 0)
  216. payload = m->private;
  217. return payload;
  218. }
  219. static void *help_next(struct seq_file *m, void *v, loff_t *pos)
  220. {
  221. (*pos)++;
  222. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_next: start\n");
  223. return NULL;
  224. }
  225. static void help_stop(struct seq_file *m, void *p)
  226. {
  227. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n");
  228. mutex_unlock(&orangefs_help_file_lock);
  229. }
  230. static int help_show(struct seq_file *m, void *v)
  231. {
  232. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_show: start\n");
  233. seq_puts(m, v);
  234. return 0;
  235. }
  236. /*
  237. * initialize the client-debug file.
  238. */
  239. static void orangefs_client_debug_init(void)
  240. {
  241. static char c_buffer[ORANGEFS_MAX_DEBUG_STRING_LEN] = { };
  242. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);
  243. if (strlen(client_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
  244. strcpy(c_buffer, client_debug_string);
  245. strcat(c_buffer, "\n");
  246. } else {
  247. strcpy(c_buffer, "none\n");
  248. pr_info("%s: overflow! 2\n", __func__);
  249. }
  250. client_debug_dentry = debugfs_create_file(ORANGEFS_CLIENT_DEBUG_FILE,
  251. 0444,
  252. debug_dir,
  253. c_buffer,
  254. &kernel_debug_fops);
  255. }
  256. /* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/
  257. static int orangefs_debug_open(struct inode *inode, struct file *file)
  258. {
  259. int rc = -ENODEV;
  260. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  261. "%s: orangefs_debug_disabled: %d\n",
  262. __func__,
  263. orangefs_debug_disabled);
  264. if (orangefs_debug_disabled)
  265. goto out;
  266. rc = 0;
  267. mutex_lock(&orangefs_debug_lock);
  268. file->private_data = inode->i_private;
  269. mutex_unlock(&orangefs_debug_lock);
  270. out:
  271. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  272. "orangefs_debug_open: rc: %d\n",
  273. rc);
  274. return rc;
  275. }
  276. static ssize_t orangefs_debug_read(struct file *file,
  277. char __user *ubuf,
  278. size_t count,
  279. loff_t *ppos)
  280. {
  281. char *buf;
  282. int sprintf_ret;
  283. ssize_t read_ret = -ENOMEM;
  284. gossip_debug(GOSSIP_DEBUGFS_DEBUG, "orangefs_debug_read: start\n");
  285. buf = kmalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
  286. if (!buf)
  287. goto out;
  288. mutex_lock(&orangefs_debug_lock);
  289. sprintf_ret = sprintf(buf, "%s", (char *)file->private_data);
  290. mutex_unlock(&orangefs_debug_lock);
  291. read_ret = simple_read_from_buffer(ubuf, count, ppos, buf, sprintf_ret);
  292. kfree(buf);
  293. out:
  294. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  295. "orangefs_debug_read: ret: %zu\n",
  296. read_ret);
  297. return read_ret;
  298. }
  299. static ssize_t orangefs_debug_write(struct file *file,
  300. const char __user *ubuf,
  301. size_t count,
  302. loff_t *ppos)
  303. {
  304. char *buf;
  305. int rc = -EFAULT;
  306. size_t silly = 0;
  307. char *debug_string;
  308. struct orangefs_kernel_op_s *new_op = NULL;
  309. struct client_debug_mask c_mask = { NULL, 0, 0 };
  310. char *s;
  311. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  312. "orangefs_debug_write: %pD\n",
  313. file);
  314. if (count == 0)
  315. return 0;
  316. /*
  317. * Thwart users who try to jamb a ridiculous number
  318. * of bytes into the debug file...
  319. */
  320. if (count > ORANGEFS_MAX_DEBUG_STRING_LEN + 1) {
  321. silly = count;
  322. count = ORANGEFS_MAX_DEBUG_STRING_LEN + 1;
  323. }
  324. buf = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
  325. if (!buf)
  326. goto out;
  327. if (copy_from_user(buf, ubuf, count - 1)) {
  328. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  329. "%s: copy_from_user failed!\n",
  330. __func__);
  331. goto out;
  332. }
  333. /*
  334. * Map the keyword string from userspace into a valid debug mask.
  335. * The mapping process involves mapping the human-inputted string
  336. * into a valid mask, and then rebuilding the string from the
  337. * verified valid mask.
  338. *
  339. * A service operation is required to set a new client-side
  340. * debug mask.
  341. */
  342. if (!strcmp(file->f_path.dentry->d_name.name,
  343. ORANGEFS_KMOD_DEBUG_FILE)) {
  344. debug_string_to_mask(buf, &orangefs_gossip_debug_mask, 0);
  345. debug_mask_to_string(&orangefs_gossip_debug_mask, 0);
  346. debug_string = kernel_debug_string;
  347. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  348. "New kernel debug string is %s\n",
  349. kernel_debug_string);
  350. } else {
  351. /* Can't reset client debug mask if client is not running. */
  352. if (is_daemon_in_service()) {
  353. pr_info("%s: Client not running :%d:\n",
  354. __func__,
  355. is_daemon_in_service());
  356. goto out;
  357. }
  358. debug_string_to_mask(buf, &c_mask, 1);
  359. debug_mask_to_string(&c_mask, 1);
  360. debug_string = client_debug_string;
  361. new_op = op_alloc(ORANGEFS_VFS_OP_PARAM);
  362. if (!new_op) {
  363. pr_info("%s: op_alloc failed!\n", __func__);
  364. goto out;
  365. }
  366. new_op->upcall.req.param.op =
  367. ORANGEFS_PARAM_REQUEST_OP_TWO_MASK_VALUES;
  368. new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET;
  369. memset(new_op->upcall.req.param.s_value,
  370. 0,
  371. ORANGEFS_MAX_DEBUG_STRING_LEN);
  372. sprintf(new_op->upcall.req.param.s_value,
  373. "%llx %llx\n",
  374. c_mask.mask1,
  375. c_mask.mask2);
  376. /* service_operation returns 0 on success... */
  377. rc = service_operation(new_op,
  378. "orangefs_param",
  379. ORANGEFS_OP_INTERRUPTIBLE);
  380. if (rc)
  381. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  382. "%s: service_operation failed! rc:%d:\n",
  383. __func__,
  384. rc);
  385. op_release(new_op);
  386. }
  387. mutex_lock(&orangefs_debug_lock);
  388. s = file_inode(file)->i_private;
  389. memset(s, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
  390. sprintf(s, "%s\n", debug_string);
  391. mutex_unlock(&orangefs_debug_lock);
  392. *ppos += count;
  393. if (silly)
  394. rc = silly;
  395. else
  396. rc = count;
  397. out:
  398. gossip_debug(GOSSIP_DEBUGFS_DEBUG,
  399. "orangefs_debug_write: rc: %d\n",
  400. rc);
  401. kfree(buf);
  402. return rc;
  403. }
  404. /*
  405. * After obtaining a string representation of the client's debug
  406. * keywords and their associated masks, this function is called to build an
  407. * array of these values.
  408. */
  409. static int orangefs_prepare_cdm_array(char *debug_array_string)
  410. {
  411. int i;
  412. int rc = -EINVAL;
  413. char *cds_head = NULL;
  414. char *cds_delimiter = NULL;
  415. int keyword_len = 0;
  416. gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
  417. /*
  418. * figure out how many elements the cdm_array needs.
  419. */
  420. for (i = 0; i < strlen(debug_array_string); i++)
  421. if (debug_array_string[i] == '\n')
  422. cdm_element_count++;
  423. if (!cdm_element_count) {
  424. pr_info("No elements in client debug array string!\n");
  425. goto out;
  426. }
  427. cdm_array = kcalloc(cdm_element_count, sizeof(*cdm_array), GFP_KERNEL);
  428. if (!cdm_array) {
  429. rc = -ENOMEM;
  430. goto out;
  431. }
  432. cds_head = debug_array_string;
  433. for (i = 0; i < cdm_element_count; i++) {
  434. cds_delimiter = strchr(cds_head, '\n');
  435. *cds_delimiter = '\0';
  436. keyword_len = strcspn(cds_head, " ");
  437. cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL);
  438. if (!cdm_array[i].keyword) {
  439. rc = -ENOMEM;
  440. goto out;
  441. }
  442. sscanf(cds_head,
  443. "%s %llx %llx",
  444. cdm_array[i].keyword,
  445. (unsigned long long *)&(cdm_array[i].mask1),
  446. (unsigned long long *)&(cdm_array[i].mask2));
  447. if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
  448. client_verbose_index = i;
  449. if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
  450. client_all_index = i;
  451. cds_head = cds_delimiter + 1;
  452. }
  453. rc = cdm_element_count;
  454. gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc);
  455. out:
  456. return rc;
  457. }
  458. /*
  459. * /sys/kernel/debug/orangefs/debug-help can be catted to
  460. * see all the available kernel and client debug keywords.
  461. *
  462. * When orangefs.ko initializes, we have no idea what keywords the
  463. * client supports, nor their associated masks.
  464. *
  465. * We pass through this function once at module-load and stamp a
  466. * boilerplate "we don't know" message for the client in the
  467. * debug-help file. We pass through here again when the client
  468. * starts and then we can fill out the debug-help file fully.
  469. *
  470. * The client might be restarted any number of times between
  471. * module reloads, we only build the debug-help file the first time.
  472. */
  473. int orangefs_prepare_debugfs_help_string(int at_boot)
  474. {
  475. char *client_title = "Client Debug Keywords:\n";
  476. char *kernel_title = "Kernel Debug Keywords:\n";
  477. size_t string_size = DEBUG_HELP_STRING_SIZE;
  478. size_t result_size;
  479. size_t i;
  480. char *new;
  481. int rc = -EINVAL;
  482. gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
  483. if (at_boot)
  484. client_title = HELP_STRING_UNINITIALIZED;
  485. /* build a new debug_help_string. */
  486. new = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL);
  487. if (!new) {
  488. rc = -ENOMEM;
  489. goto out;
  490. }
  491. /*
  492. * strlcat(dst, src, size) will append at most
  493. * "size - strlen(dst) - 1" bytes of src onto dst,
  494. * null terminating the result, and return the total
  495. * length of the string it tried to create.
  496. *
  497. * We'll just plow through here building our new debug
  498. * help string and let strlcat take care of assuring that
  499. * dst doesn't overflow.
  500. */
  501. strlcat(new, client_title, string_size);
  502. if (!at_boot) {
  503. /*
  504. * fill the client keyword/mask array and remember
  505. * how many elements there were.
  506. */
  507. cdm_element_count =
  508. orangefs_prepare_cdm_array(client_debug_array_string);
  509. if (cdm_element_count <= 0) {
  510. kfree(new);
  511. goto out;
  512. }
  513. for (i = 0; i < cdm_element_count; i++) {
  514. strlcat(new, "\t", string_size);
  515. strlcat(new, cdm_array[i].keyword, string_size);
  516. strlcat(new, "\n", string_size);
  517. }
  518. }
  519. strlcat(new, "\n", string_size);
  520. strlcat(new, kernel_title, string_size);
  521. for (i = 0; i < num_kmod_keyword_mask_map; i++) {
  522. strlcat(new, "\t", string_size);
  523. strlcat(new, s_kmod_keyword_mask_map[i].keyword, string_size);
  524. result_size = strlcat(new, "\n", string_size);
  525. }
  526. /* See if we tried to put too many bytes into "new"... */
  527. if (result_size >= string_size) {
  528. kfree(new);
  529. goto out;
  530. }
  531. if (at_boot) {
  532. debug_help_string = new;
  533. } else {
  534. mutex_lock(&orangefs_help_file_lock);
  535. memset(debug_help_string, 0, DEBUG_HELP_STRING_SIZE);
  536. strlcat(debug_help_string, new, string_size);
  537. mutex_unlock(&orangefs_help_file_lock);
  538. kfree(new);
  539. }
  540. rc = 0;
  541. out: return rc;
  542. }
  543. /*
  544. * kernel = type 0
  545. * client = type 1
  546. */
  547. static void debug_mask_to_string(void *mask, int type)
  548. {
  549. int i;
  550. int len = 0;
  551. char *debug_string;
  552. int element_count = 0;
  553. gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
  554. if (type) {
  555. debug_string = client_debug_string;
  556. element_count = cdm_element_count;
  557. } else {
  558. debug_string = kernel_debug_string;
  559. element_count = num_kmod_keyword_mask_map;
  560. }
  561. memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
  562. /*
  563. * Some keywords, like "all" or "verbose", are amalgams of
  564. * numerous other keywords. Make a special check for those
  565. * before grinding through the whole mask only to find out
  566. * later...
  567. */
  568. if (check_amalgam_keyword(mask, type))
  569. goto out;
  570. /* Build the debug string. */
  571. for (i = 0; i < element_count; i++)
  572. if (type)
  573. do_c_string(mask, i);
  574. else
  575. do_k_string(mask, i);
  576. len = strlen(debug_string);
  577. if ((len) && (type))
  578. client_debug_string[len - 1] = '\0';
  579. else if (len)
  580. kernel_debug_string[len - 1] = '\0';
  581. else if (type)
  582. strcpy(client_debug_string, "none");
  583. else
  584. strcpy(kernel_debug_string, "none");
  585. out:
  586. gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
  587. return;
  588. }
  589. static void do_k_string(void *k_mask, int index)
  590. {
  591. __u64 *mask = (__u64 *) k_mask;
  592. if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword))
  593. goto out;
  594. if (*mask & s_kmod_keyword_mask_map[index].mask_val) {
  595. if ((strlen(kernel_debug_string) +
  596. strlen(s_kmod_keyword_mask_map[index].keyword))
  597. < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
  598. strcat(kernel_debug_string,
  599. s_kmod_keyword_mask_map[index].keyword);
  600. strcat(kernel_debug_string, ",");
  601. } else {
  602. gossip_err("%s: overflow!\n", __func__);
  603. strcpy(kernel_debug_string, ORANGEFS_ALL);
  604. goto out;
  605. }
  606. }
  607. out:
  608. return;
  609. }
  610. static void do_c_string(void *c_mask, int index)
  611. {
  612. struct client_debug_mask *mask = (struct client_debug_mask *) c_mask;
  613. if (keyword_is_amalgam(cdm_array[index].keyword))
  614. goto out;
  615. if ((mask->mask1 & cdm_array[index].mask1) ||
  616. (mask->mask2 & cdm_array[index].mask2)) {
  617. if ((strlen(client_debug_string) +
  618. strlen(cdm_array[index].keyword) + 1)
  619. < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
  620. strcat(client_debug_string,
  621. cdm_array[index].keyword);
  622. strcat(client_debug_string, ",");
  623. } else {
  624. gossip_err("%s: overflow!\n", __func__);
  625. strcpy(client_debug_string, ORANGEFS_ALL);
  626. goto out;
  627. }
  628. }
  629. out:
  630. return;
  631. }
  632. static int keyword_is_amalgam(char *keyword)
  633. {
  634. int rc = 0;
  635. if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
  636. rc = 1;
  637. return rc;
  638. }
  639. /*
  640. * kernel = type 0
  641. * client = type 1
  642. *
  643. * return 1 if we found an amalgam.
  644. */
  645. static int check_amalgam_keyword(void *mask, int type)
  646. {
  647. __u64 *k_mask;
  648. struct client_debug_mask *c_mask;
  649. int k_all_index = num_kmod_keyword_mask_map - 1;
  650. int rc = 0;
  651. if (type) {
  652. c_mask = (struct client_debug_mask *) mask;
  653. if ((c_mask->mask1 == cdm_array[client_all_index].mask1) &&
  654. (c_mask->mask2 == cdm_array[client_all_index].mask2)) {
  655. strcpy(client_debug_string, ORANGEFS_ALL);
  656. rc = 1;
  657. goto out;
  658. }
  659. if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) &&
  660. (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) {
  661. strcpy(client_debug_string, ORANGEFS_VERBOSE);
  662. rc = 1;
  663. goto out;
  664. }
  665. } else {
  666. k_mask = (__u64 *) mask;
  667. if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) {
  668. strcpy(kernel_debug_string, ORANGEFS_ALL);
  669. rc = 1;
  670. goto out;
  671. }
  672. }
  673. out:
  674. return rc;
  675. }
  676. /*
  677. * kernel = type 0
  678. * client = type 1
  679. */
  680. static void debug_string_to_mask(char *debug_string, void *mask, int type)
  681. {
  682. char *unchecked_keyword;
  683. int i;
  684. char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL);
  685. char *original_pointer;
  686. int element_count = 0;
  687. struct client_debug_mask *c_mask = NULL;
  688. __u64 *k_mask = NULL;
  689. gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
  690. if (type) {
  691. c_mask = (struct client_debug_mask *)mask;
  692. element_count = cdm_element_count;
  693. } else {
  694. k_mask = (__u64 *)mask;
  695. *k_mask = 0;
  696. element_count = num_kmod_keyword_mask_map;
  697. }
  698. original_pointer = strsep_fodder;
  699. while ((unchecked_keyword = strsep(&strsep_fodder, ",")))
  700. if (strlen(unchecked_keyword)) {
  701. for (i = 0; i < element_count; i++)
  702. if (type)
  703. do_c_mask(i,
  704. unchecked_keyword,
  705. &c_mask);
  706. else
  707. do_k_mask(i,
  708. unchecked_keyword,
  709. &k_mask);
  710. }
  711. kfree(original_pointer);
  712. }
  713. static void do_c_mask(int i, char *unchecked_keyword,
  714. struct client_debug_mask **sane_mask)
  715. {
  716. if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) {
  717. (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1;
  718. (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2;
  719. }
  720. }
  721. static void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask)
  722. {
  723. if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword))
  724. **sane_mask = (**sane_mask) |
  725. s_kmod_keyword_mask_map[i].mask_val;
  726. }
  727. int orangefs_debugfs_new_client_mask(void __user *arg)
  728. {
  729. struct dev_mask2_info_s mask2_info = {0};
  730. int ret;
  731. ret = copy_from_user(&mask2_info,
  732. (void __user *)arg,
  733. sizeof(struct dev_mask2_info_s));
  734. if (ret != 0)
  735. return -EIO;
  736. client_debug_mask.mask1 = mask2_info.mask1_value;
  737. client_debug_mask.mask2 = mask2_info.mask2_value;
  738. pr_info("%s: client debug mask has been been received "
  739. ":%llx: :%llx:\n",
  740. __func__,
  741. (unsigned long long)client_debug_mask.mask1,
  742. (unsigned long long)client_debug_mask.mask2);
  743. return ret;
  744. }
  745. int orangefs_debugfs_new_client_string(void __user *arg)
  746. {
  747. int ret;
  748. ret = copy_from_user(&client_debug_array_string,
  749. (void __user *)arg,
  750. ORANGEFS_MAX_DEBUG_STRING_LEN);
  751. if (ret != 0) {
  752. pr_info("%s: CLIENT_STRING: copy_from_user failed\n",
  753. __func__);
  754. return -EFAULT;
  755. }
  756. /*
  757. * The real client-core makes an effort to ensure
  758. * that actual strings that aren't too long to fit in
  759. * this buffer is what we get here. We're going to use
  760. * string functions on the stuff we got, so we'll make
  761. * this extra effort to try and keep from
  762. * flowing out of this buffer when we use the string
  763. * functions, even if somehow the stuff we end up
  764. * with here is garbage.
  765. */
  766. client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN - 1] =
  767. '\0';
  768. pr_info("%s: client debug array string has been received.\n",
  769. __func__);
  770. if (!help_string_initialized) {
  771. /* Build a proper debug help string. */
  772. ret = orangefs_prepare_debugfs_help_string(0);
  773. if (ret) {
  774. gossip_err("%s: no debug help string \n",
  775. __func__);
  776. return ret;
  777. }
  778. }
  779. debug_mask_to_string(&client_debug_mask, 1);
  780. debugfs_remove(client_debug_dentry);
  781. orangefs_client_debug_init();
  782. help_string_initialized++;
  783. return 0;
  784. }
  785. int orangefs_debugfs_new_debug(void __user *arg)
  786. {
  787. struct dev_mask_info_s mask_info = {0};
  788. int ret;
  789. ret = copy_from_user(&mask_info,
  790. (void __user *)arg,
  791. sizeof(mask_info));
  792. if (ret != 0)
  793. return -EIO;
  794. if (mask_info.mask_type == KERNEL_MASK) {
  795. if ((mask_info.mask_value == 0)
  796. && (kernel_mask_set_mod_init)) {
  797. /*
  798. * the kernel debug mask was set when the
  799. * kernel module was loaded; don't override
  800. * it if the client-core was started without
  801. * a value for ORANGEFS_KMODMASK.
  802. */
  803. return 0;
  804. }
  805. debug_mask_to_string(&mask_info.mask_value,
  806. mask_info.mask_type);
  807. orangefs_gossip_debug_mask = mask_info.mask_value;
  808. pr_info("%s: kernel debug mask has been modified to "
  809. ":%s: :%llx:\n",
  810. __func__,
  811. kernel_debug_string,
  812. (unsigned long long)orangefs_gossip_debug_mask);
  813. } else if (mask_info.mask_type == CLIENT_MASK) {
  814. debug_mask_to_string(&mask_info.mask_value,
  815. mask_info.mask_type);
  816. pr_info("%s: client debug mask has been modified to"
  817. ":%s: :%llx:\n",
  818. __func__,
  819. client_debug_string,
  820. llu(mask_info.mask_value));
  821. } else {
  822. gossip_err("Invalid mask type....\n");
  823. return -EINVAL;
  824. }
  825. return ret;
  826. }