File Index
Files and directories
Sign in
FILE

orangefs-debugfs.c

File preview with syntax highlighting.

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