Linux Audio

Check our new training course

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