cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

orangefs-debugfs.c (25278B)


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