Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44f46410 authored by Martin Brandenburg's avatar Martin Brandenburg
Browse files

orangefs: clean up debugfs globals



Mostly this is moving code into orangefs-debugfs.c so that globals turn
into static globals.

Then gossip_debug_mask is renamed orangefs_gossip_debug_mask but keeps
global visibility, so it can be used from a macro.

Signed-off-by: default avatarMartin Brandenburg <martin@omnibond.com>
parent a21aae3b
Loading
Loading
Loading
Loading
+4 −128
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include "orangefs-kernel.h"
#include "orangefs-dev-proto.h"
#include "orangefs-bufmap.h"
#include "orangefs-debugfs.h"

#include <linux/debugfs.h>
#include <linux/slab.h>
@@ -576,8 +577,6 @@ static long dispatch_ioctl_command(unsigned int command, unsigned long arg)
	static __s32 max_down_size = MAX_DEV_REQ_DOWNSIZE;
	struct ORANGEFS_dev_map_desc user_desc;
	int ret = 0;
	struct dev_mask_info_s mask_info = { 0 };
	struct dev_mask2_info_s mask2_info = { 0, 0 };
	int upstream_kmod = 1;
	struct orangefs_sb_info_s *orangefs_sb;

@@ -668,134 +667,11 @@ static long dispatch_ioctl_command(unsigned int command, unsigned long arg)
			return ret;

	case ORANGEFS_DEV_CLIENT_MASK:
		ret = copy_from_user(&mask2_info,
				     (void __user *)arg,
				     sizeof(struct dev_mask2_info_s));

		if (ret != 0)
			return -EIO;

		client_debug_mask.mask1 = mask2_info.mask1_value;
		client_debug_mask.mask2 = mask2_info.mask2_value;

		pr_info("%s: client debug mask has been been received "
			":%llx: :%llx:\n",
			__func__,
			(unsigned long long)client_debug_mask.mask1,
			(unsigned long long)client_debug_mask.mask2);

		return ret;

		return orangefs_debugfs_new_client_mask((void __user *)arg);
	case ORANGEFS_DEV_CLIENT_STRING:
		ret = copy_from_user(&client_debug_array_string,
				     (void __user *)arg,
				     ORANGEFS_MAX_DEBUG_STRING_LEN);
		/*
		 * The real client-core makes an effort to ensure
		 * that actual strings that aren't too long to fit in
		 * this buffer is what we get here. We're going to use
		 * string functions on the stuff we got, so we'll make
		 * this extra effort to try and keep from
		 * flowing out of this buffer when we use the string
		 * functions, even if somehow the stuff we end up
		 * with here is garbage.
		 */
		client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN - 1] =
			'\0';
		
		if (ret != 0) {
			pr_info("%s: CLIENT_STRING: copy_from_user failed\n",
				__func__);
			return -EIO;
		}

		pr_info("%s: client debug array string has been received.\n",
			__func__);

		if (!help_string_initialized) {

			/* Free the "we don't know yet" default string... */
			kfree(debug_help_string);

			/* build a proper debug help string */
			if (orangefs_prepare_debugfs_help_string(0)) {
				gossip_err("%s: no debug help string \n",
					   __func__);
				return -EIO;
			}

			/* Replace the boilerplate boot-time debug-help file. */
			debugfs_remove(help_file_dentry);

			help_file_dentry =
				debugfs_create_file(
					ORANGEFS_KMOD_DEBUG_HELP_FILE,
					0444,
					debug_dir,
					debug_help_string,
					&debug_help_fops);

			if (!help_file_dentry) {
				gossip_err("%s: debugfs_create_file failed for"
					   " :%s:!\n",
					   __func__,
					   ORANGEFS_KMOD_DEBUG_HELP_FILE);
				return -EIO;
			}
		}

		debug_mask_to_string(&client_debug_mask, 1);

		debugfs_remove(client_debug_dentry);

		orangefs_client_debug_init();

		help_string_initialized++;

		return ret;

		return orangefs_debugfs_new_client_string((void __user *)arg);
	case ORANGEFS_DEV_DEBUG:
		ret = copy_from_user(&mask_info,
				     (void __user *)arg,
				     sizeof(mask_info));

		if (ret != 0)
			return -EIO;

		if (mask_info.mask_type == KERNEL_MASK) {
			if ((mask_info.mask_value == 0)
			    && (kernel_mask_set_mod_init)) {
				/*
				 * the kernel debug mask was set when the
				 * kernel module was loaded; don't override
				 * it if the client-core was started without
				 * a value for ORANGEFS_KMODMASK.
				 */
				return 0;
			}
			debug_mask_to_string(&mask_info.mask_value,
					     mask_info.mask_type);
			gossip_debug_mask = mask_info.mask_value;
			pr_info("%s: kernel debug mask has been modified to "
				":%s: :%llx:\n",
				__func__,
				kernel_debug_string,
				(unsigned long long)gossip_debug_mask);
		} else if (mask_info.mask_type == CLIENT_MASK) {
			debug_mask_to_string(&mask_info.mask_value,
					     mask_info.mask_type);
			pr_info("%s: client debug mask has been modified to"
				":%s: :%llx:\n",
				__func__,
				client_debug_string,
				llu(mask_info.mask_value));
		} else {
			gossip_lerr("Invalid mask type....\n");
			return -EINVAL;
		}

		return ret;

		return orangefs_debugfs_new_debug((void __user *)arg);
	default:
		return -ENOIOCTLCMD;
	}
+691 −70
Original line number Diff line number Diff line
@@ -43,36 +43,35 @@
#include "protocol.h"
#include "orangefs-kernel.h"

static int orangefs_debug_disabled = 1;

static int orangefs_debug_help_open(struct inode *, struct file *);
#define DEBUG_HELP_STRING_SIZE 4096
#define HELP_STRING_UNINITIALIZED \
	"Client Debug Keywords are unknown until the first time\n" \
	"the client is started after boot.\n"
#define ORANGEFS_KMOD_DEBUG_HELP_FILE "debug-help"
#define ORANGEFS_KMOD_DEBUG_FILE "kernel-debug"
#define ORANGEFS_CLIENT_DEBUG_FILE "client-debug"
#define ORANGEFS_VERBOSE "verbose"
#define ORANGEFS_ALL "all"

const struct file_operations debug_help_fops = {
	.open           = orangefs_debug_help_open,
	.read           = seq_read,
	.release        = seq_release,
	.llseek         = seq_lseek,
/*
 * An array of client_debug_mask will be built to hold debug keyword/mask
 * values fetched from userspace.
 */
struct client_debug_mask {
	char *keyword;
	__u64 mask1;
	__u64 mask2;
};

static int orangefs_kernel_debug_init(void);

static int orangefs_debug_help_open(struct inode *, struct file *);
static void *help_start(struct seq_file *, loff_t *);
static void *help_next(struct seq_file *, void *, loff_t *);
static void help_stop(struct seq_file *, void *);
static int help_show(struct seq_file *, void *);

static const struct seq_operations help_debug_ops = {
	.start	= help_start,
	.next	= help_next,
	.stop	= help_stop,
	.show	= help_show,
};

/*
 * Used to protect data in ORANGEFS_KMOD_DEBUG_FILE and
 * ORANGEFS_KMOD_DEBUG_FILE.
 */
static DEFINE_MUTEX(orangefs_debug_lock);

int orangefs_debug_open(struct inode *, struct file *);
static int orangefs_debug_open(struct inode *, struct file *);

static ssize_t orangefs_debug_read(struct file *,
				 char __user *,
@@ -84,6 +83,43 @@ static ssize_t orangefs_debug_write(struct file *,
				  size_t,
				  loff_t *);

static int orangefs_prepare_cdm_array(char *);
static void debug_mask_to_string(void *, int);
static void do_k_string(void *, int);
static void do_c_string(void *, int);
static int keyword_is_amalgam(char *);
static int check_amalgam_keyword(void *, int);
static void debug_string_to_mask(char *, void *, int);
static void do_c_mask(int, char *, struct client_debug_mask **);
static void do_k_mask(int, char *, __u64 **);

static char kernel_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN] = "none";
static char *debug_help_string;
static char client_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN];
static char client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN];

static struct dentry *help_file_dentry;
static struct dentry *client_debug_dentry;
static struct dentry *debug_dir;

static unsigned int kernel_mask_set_mod_init;
static int orangefs_debug_disabled = 1;
static int help_string_initialized;

static const struct seq_operations help_debug_ops = {
	.start	= help_start,
	.next	= help_next,
	.stop	= help_stop,
	.show	= help_show,
};

const struct file_operations debug_help_fops = {
	.open           = orangefs_debug_help_open,
	.read           = seq_read,
	.release        = seq_release,
	.llseek         = seq_lseek,
};

static const struct file_operations kernel_debug_fops = {
	.open           = orangefs_debug_open,
	.read           = orangefs_debug_read,
@@ -91,15 +127,55 @@ static const struct file_operations kernel_debug_fops = {
	.llseek         = generic_file_llseek,
};

static int client_all_index;
static int client_verbose_index;

static struct client_debug_mask *cdm_array;
static int cdm_element_count;

static struct client_debug_mask client_debug_mask;

/*
 * Used to protect data in ORANGEFS_KMOD_DEBUG_FILE and
 * ORANGEFS_KMOD_DEBUG_FILE.
 */
static DEFINE_MUTEX(orangefs_debug_lock);

/*
 * initialize kmod debug operations, create orangefs debugfs dir and
 * ORANGEFS_KMOD_DEBUG_HELP_FILE.
 */
int orangefs_debugfs_init(void)
int orangefs_debugfs_init(int debug_mask)
{

	int rc = -ENOMEM;

	/* convert input debug mask to a 64-bit unsigned integer */
        orangefs_gossip_debug_mask = (unsigned long long)debug_mask;

	/*
	 * set the kernel's gossip debug string; invalid mask values will
	 * be ignored.
	 */
	debug_mask_to_string(&orangefs_gossip_debug_mask, 0);

	/* remove any invalid values from the mask */
	debug_string_to_mask(kernel_debug_string, &orangefs_gossip_debug_mask,
	    0);

	/*
	 * if the mask has a non-zero value, then indicate that the mask
	 * was set when the kernel module was loaded.  The orangefs dev ioctl
	 * command will look at this boolean to determine if the kernel's
	 * debug mask should be overwritten when the client-core is started.
	 */
	if (orangefs_gossip_debug_mask != 0)
		kernel_mask_set_mod_init = true;

	pr_info("%s: called with debug mask: :%s: :%llx:\n",
		__func__,
		kernel_debug_string,
		(unsigned long long)orangefs_gossip_debug_mask);

	debug_dir = debugfs_create_dir("orangefs", NULL);
	if (!debug_dir) {
		pr_info("%s: debugfs_create_dir failed.\n", __func__);
@@ -117,13 +193,58 @@ int orangefs_debugfs_init(void)
	}

	orangefs_debug_disabled = 0;

	rc = orangefs_kernel_debug_init();

out:

	return rc;
}

/*
 * initialize the kernel-debug file.
 */
static int orangefs_kernel_debug_init(void)
{
	int rc = -ENOMEM;
	struct dentry *ret;
	char *k_buffer = NULL;

	gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);

	k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
	if (!k_buffer)
		goto out;

	if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
		strcpy(k_buffer, kernel_debug_string);
		strcat(k_buffer, "\n");
	} else {
		strcpy(k_buffer, "none\n");
		pr_info("%s: overflow 1!\n", __func__);
	}

	ret = debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE,
				  0444,
				  debug_dir,
				  k_buffer,
				  &kernel_debug_fops);
	if (!ret) {
		pr_info("%s: failed to create %s.\n",
			__func__,
			ORANGEFS_KMOD_DEBUG_FILE);
		goto out;
	}

	rc = 0;

out:

	gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc);
	return rc;
}


void orangefs_debugfs_cleanup(void)
{
	debugfs_remove_recursive(debug_dir);
@@ -195,49 +316,6 @@ static int help_show(struct seq_file *m, void *v)
	return 0;
}

/*
 * initialize the kernel-debug file.
 */
int orangefs_kernel_debug_init(void)
{
	int rc = -ENOMEM;
	struct dentry *ret;
	char *k_buffer = NULL;

	gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);

	k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
	if (!k_buffer)
		goto out;

	if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
		strcpy(k_buffer, kernel_debug_string);
		strcat(k_buffer, "\n");
	} else {
		strcpy(k_buffer, "none\n");
		pr_info("%s: overflow 1!\n", __func__);
	}

	ret = debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE,
				  0444,
				  debug_dir,
				  k_buffer,
				  &kernel_debug_fops);
	if (!ret) {
		pr_info("%s: failed to create %s.\n",
			__func__,
			ORANGEFS_KMOD_DEBUG_FILE);
		goto out;
	}

	rc = 0;

out:

	gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc);
	return rc;
}

/*
 * initialize the client-debug file.
 */
@@ -282,7 +360,7 @@ int orangefs_client_debug_init(void)
}

/* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/
int orangefs_debug_open(struct inode *inode, struct file *file)
static int orangefs_debug_open(struct inode *inode, struct file *file)
{
	int rc = -ENODEV;

@@ -384,8 +462,8 @@ static ssize_t orangefs_debug_write(struct file *file,
	 */
	if (!strcmp(file->f_path.dentry->d_name.name,
		    ORANGEFS_KMOD_DEBUG_FILE)) {
		debug_string_to_mask(buf, &gossip_debug_mask, 0);
		debug_mask_to_string(&gossip_debug_mask, 0);
		debug_string_to_mask(buf, &orangefs_gossip_debug_mask, 0);
		debug_mask_to_string(&orangefs_gossip_debug_mask, 0);
		debug_string = kernel_debug_string;
		gossip_debug(GOSSIP_DEBUGFS_DEBUG,
			     "New kernel debug string is %s\n",
@@ -452,3 +530,546 @@ static ssize_t orangefs_debug_write(struct file *file,
	kfree(buf);
	return rc;
}

/*
 * After obtaining a string representation of the client's debug
 * keywords and their associated masks, this function is called to build an
 * array of these values.
 */
static int orangefs_prepare_cdm_array(char *debug_array_string)
{
	int i;
	int rc = -EINVAL;
	char *cds_head = NULL;
	char *cds_delimiter = NULL;
	int keyword_len = 0;

	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);

	/*
	 * figure out how many elements the cdm_array needs.
	 */
	for (i = 0; i < strlen(debug_array_string); i++)
		if (debug_array_string[i] == '\n')
			cdm_element_count++;

	if (!cdm_element_count) {
		pr_info("No elements in client debug array string!\n");
		goto out;
	}

	cdm_array =
		kzalloc(cdm_element_count * sizeof(struct client_debug_mask),
			GFP_KERNEL);
	if (!cdm_array) {
		pr_info("malloc failed for cdm_array!\n");
		rc = -ENOMEM;
		goto out;
	}

	cds_head = debug_array_string;

	for (i = 0; i < cdm_element_count; i++) {
		cds_delimiter = strchr(cds_head, '\n');
		*cds_delimiter = '\0';

		keyword_len = strcspn(cds_head, " ");

		cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL);
		if (!cdm_array[i].keyword) {
			rc = -ENOMEM;
			goto out;
		}

		sscanf(cds_head,
		       "%s %llx %llx",
		       cdm_array[i].keyword,
		       (unsigned long long *)&(cdm_array[i].mask1),
		       (unsigned long long *)&(cdm_array[i].mask2));

		if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
			client_verbose_index = i;

		if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
			client_all_index = i;

		cds_head = cds_delimiter + 1;
	}

	rc = cdm_element_count;

	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc);

out:

	return rc;

}

/*
 * /sys/kernel/debug/orangefs/debug-help can be catted to
 * see all the available kernel and client debug keywords.
 *
 * When the kernel boots, we have no idea what keywords the
 * client supports, nor their associated masks.
 *
 * We pass through this function once at boot and stamp a
 * boilerplate "we don't know" message for the client in the
 * debug-help file. We pass through here again when the client
 * starts and then we can fill out the debug-help file fully.
 *
 * The client might be restarted any number of times between
 * reboots, we only build the debug-help file the first time.
 */
int orangefs_prepare_debugfs_help_string(int at_boot)
{
	int rc = -EINVAL;
	int i;
	int byte_count = 0;
	char *client_title = "Client Debug Keywords:\n";
	char *kernel_title = "Kernel Debug Keywords:\n";

	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);

	if (at_boot) {
		byte_count += strlen(HELP_STRING_UNINITIALIZED);
		client_title = HELP_STRING_UNINITIALIZED;
	} else {
		/*
		 * fill the client keyword/mask array and remember
		 * how many elements there were.
		 */
		cdm_element_count =
			orangefs_prepare_cdm_array(client_debug_array_string);
		if (cdm_element_count <= 0)
			goto out;

		/* Count the bytes destined for debug_help_string. */
		byte_count += strlen(client_title);

		for (i = 0; i < cdm_element_count; i++) {
			byte_count += strlen(cdm_array[i].keyword + 2);
			if (byte_count >= DEBUG_HELP_STRING_SIZE) {
				pr_info("%s: overflow 1!\n", __func__);
				goto out;
			}
		}

		gossip_debug(GOSSIP_UTILS_DEBUG,
			     "%s: cdm_element_count:%d:\n",
			     __func__,
			     cdm_element_count);
	}

	byte_count += strlen(kernel_title);
	for (i = 0; i < num_kmod_keyword_mask_map; i++) {
		byte_count +=
			strlen(s_kmod_keyword_mask_map[i].keyword + 2);
		if (byte_count >= DEBUG_HELP_STRING_SIZE) {
			pr_info("%s: overflow 2!\n", __func__);
			goto out;
		}
	}

	/* build debug_help_string. */
	debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL);
	if (!debug_help_string) {
		rc = -ENOMEM;
		goto out;
	}

	strcat(debug_help_string, client_title);

	if (!at_boot) {
		for (i = 0; i < cdm_element_count; i++) {
			strcat(debug_help_string, "\t");
			strcat(debug_help_string, cdm_array[i].keyword);
			strcat(debug_help_string, "\n");
		}
	}

	strcat(debug_help_string, "\n");
	strcat(debug_help_string, kernel_title);

	for (i = 0; i < num_kmod_keyword_mask_map; i++) {
		strcat(debug_help_string, "\t");
		strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword);
		strcat(debug_help_string, "\n");
	}

	rc = 0;

out:

	return rc;

}

/*
 * kernel = type 0
 * client = type 1
 */
static void debug_mask_to_string(void *mask, int type)
{
	int i;
	int len = 0;
	char *debug_string;
	int element_count = 0;

	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);

	if (type) {
		debug_string = client_debug_string;
		element_count = cdm_element_count;
	} else {
		debug_string = kernel_debug_string;
		element_count = num_kmod_keyword_mask_map;
	}

	memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);

	/*
	 * Some keywords, like "all" or "verbose", are amalgams of
	 * numerous other keywords. Make a special check for those
	 * before grinding through the whole mask only to find out
	 * later...
	 */
	if (check_amalgam_keyword(mask, type))
		goto out;

	/* Build the debug string. */
	for (i = 0; i < element_count; i++)
		if (type)
			do_c_string(mask, i);
		else
			do_k_string(mask, i);

	len = strlen(debug_string);

	if ((len) && (type))
		client_debug_string[len - 1] = '\0';
	else if (len)
		kernel_debug_string[len - 1] = '\0';
	else if (type)
		strcpy(client_debug_string, "none");
	else
		strcpy(kernel_debug_string, "none");

out:
gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);

	return;

}

static void do_k_string(void *k_mask, int index)
{
	__u64 *mask = (__u64 *) k_mask;

	if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword))
		goto out;

	if (*mask & s_kmod_keyword_mask_map[index].mask_val) {
		if ((strlen(kernel_debug_string) +
		     strlen(s_kmod_keyword_mask_map[index].keyword))
			< ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
				strcat(kernel_debug_string,
				       s_kmod_keyword_mask_map[index].keyword);
				strcat(kernel_debug_string, ",");
			} else {
				gossip_err("%s: overflow!\n", __func__);
				strcpy(kernel_debug_string, ORANGEFS_ALL);
				goto out;
			}
	}

out:

	return;
}

static void do_c_string(void *c_mask, int index)
{
	struct client_debug_mask *mask = (struct client_debug_mask *) c_mask;

	if (keyword_is_amalgam(cdm_array[index].keyword))
		goto out;

	if ((mask->mask1 & cdm_array[index].mask1) ||
	    (mask->mask2 & cdm_array[index].mask2)) {
		if ((strlen(client_debug_string) +
		     strlen(cdm_array[index].keyword) + 1)
			< ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
				strcat(client_debug_string,
				       cdm_array[index].keyword);
				strcat(client_debug_string, ",");
			} else {
				gossip_err("%s: overflow!\n", __func__);
				strcpy(client_debug_string, ORANGEFS_ALL);
				goto out;
			}
	}
out:
	return;
}

static int keyword_is_amalgam(char *keyword)
{
	int rc = 0;

	if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
		rc = 1;

	return rc;
}

/*
 * kernel = type 0
 * client = type 1
 *
 * return 1 if we found an amalgam.
 */
static int check_amalgam_keyword(void *mask, int type)
{
	__u64 *k_mask;
	struct client_debug_mask *c_mask;
	int k_all_index = num_kmod_keyword_mask_map - 1;
	int rc = 0;

	if (type) {
		c_mask = (struct client_debug_mask *) mask;

		if ((c_mask->mask1 == cdm_array[client_all_index].mask1) &&
		    (c_mask->mask2 == cdm_array[client_all_index].mask2)) {
			strcpy(client_debug_string, ORANGEFS_ALL);
			rc = 1;
			goto out;
		}

		if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) &&
		    (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) {
			strcpy(client_debug_string, ORANGEFS_VERBOSE);
			rc = 1;
			goto out;
		}

	} else {
		k_mask = (__u64 *) mask;

		if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) {
			strcpy(kernel_debug_string, ORANGEFS_ALL);
			rc = 1;
			goto out;
		}
	}

out:

	return rc;
}

/*
 * kernel = type 0
 * client = type 1
 */
static void debug_string_to_mask(char *debug_string, void *mask, int type)
{
	char *unchecked_keyword;
	int i;
	char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL);
	char *original_pointer;
	int element_count = 0;
	struct client_debug_mask *c_mask = NULL;
	__u64 *k_mask = NULL;

	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);

	if (type) {
		c_mask = (struct client_debug_mask *)mask;
		element_count = cdm_element_count;
	} else {
		k_mask = (__u64 *)mask;
		*k_mask = 0;
		element_count = num_kmod_keyword_mask_map;
	}

	original_pointer = strsep_fodder;
	while ((unchecked_keyword = strsep(&strsep_fodder, ",")))
		if (strlen(unchecked_keyword)) {
			for (i = 0; i < element_count; i++)
				if (type)
					do_c_mask(i,
						  unchecked_keyword,
						  &c_mask);
				else
					do_k_mask(i,
						  unchecked_keyword,
						  &k_mask);
		}

	kfree(original_pointer);
}

static void do_c_mask(int i, char *unchecked_keyword,
    struct client_debug_mask **sane_mask)
{

	if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) {
		(**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1;
		(**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2;
	}
}

static void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask)
{

	if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword))
		**sane_mask = (**sane_mask) |
				s_kmod_keyword_mask_map[i].mask_val;
}

int orangefs_debugfs_new_client_mask(void __user *arg)
{
	struct dev_mask2_info_s mask2_info = {0};
	int ret;

	ret = copy_from_user(&mask2_info,
			     (void __user *)arg,
			     sizeof(struct dev_mask2_info_s));

	if (ret != 0)
		return -EIO;

	client_debug_mask.mask1 = mask2_info.mask1_value;
	client_debug_mask.mask2 = mask2_info.mask2_value;

	pr_info("%s: client debug mask has been been received "
		":%llx: :%llx:\n",
		__func__,
		(unsigned long long)client_debug_mask.mask1,
		(unsigned long long)client_debug_mask.mask2);

	return ret;
}

int orangefs_debugfs_new_client_string(void __user *arg) 
{
	int ret;

	ret = copy_from_user(&client_debug_array_string,
                                     (void __user *)arg,
                                     ORANGEFS_MAX_DEBUG_STRING_LEN);
	if (ret != 0)
		return -EIO;

	/*
	 * The real client-core makes an effort to ensure
	 * that actual strings that aren't too long to fit in
	 * this buffer is what we get here. We're going to use
	 * string functions on the stuff we got, so we'll make
	 * this extra effort to try and keep from
	 * flowing out of this buffer when we use the string
	 * functions, even if somehow the stuff we end up
	 * with here is garbage.
	 */
	client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN - 1] =
		'\0';
	
	if (ret != 0) {
		pr_info("%s: CLIENT_STRING: copy_from_user failed\n",
			__func__);
		return -EIO;
	}

	pr_info("%s: client debug array string has been received.\n",
		__func__);

	if (!help_string_initialized) {

		/* Free the "we don't know yet" default string... */
		kfree(debug_help_string);

		/* build a proper debug help string */
		if (orangefs_prepare_debugfs_help_string(0)) {
			gossip_err("%s: no debug help string \n",
				   __func__);
			return -EIO;
		}

		/* Replace the boilerplate boot-time debug-help file. */
		debugfs_remove(help_file_dentry);

		help_file_dentry =
			debugfs_create_file(
				ORANGEFS_KMOD_DEBUG_HELP_FILE,
				0444,
				debug_dir,
				debug_help_string,
				&debug_help_fops);

		if (!help_file_dentry) {
			gossip_err("%s: debugfs_create_file failed for"
				   " :%s:!\n",
				   __func__,
				   ORANGEFS_KMOD_DEBUG_HELP_FILE);
			return -EIO;
		}
	}

	debug_mask_to_string(&client_debug_mask, 1);

	debugfs_remove(client_debug_dentry);

	orangefs_client_debug_init();

	help_string_initialized++;

	return ret;
}

int orangefs_debugfs_new_debug(void __user *arg) 
{
	struct dev_mask_info_s mask_info = {0};
	int ret;

	ret = copy_from_user(&mask_info,
			     (void __user *)arg,
			     sizeof(mask_info));

	if (ret != 0)
		return -EIO;

	if (mask_info.mask_type == KERNEL_MASK) {
		if ((mask_info.mask_value == 0)
		    && (kernel_mask_set_mod_init)) {
			/*
			 * the kernel debug mask was set when the
			 * kernel module was loaded; don't override
			 * it if the client-core was started without
			 * a value for ORANGEFS_KMODMASK.
			 */
			return 0;
		}
		debug_mask_to_string(&mask_info.mask_value,
				     mask_info.mask_type);
		orangefs_gossip_debug_mask = mask_info.mask_value;
		pr_info("%s: kernel debug mask has been modified to "
			":%s: :%llx:\n",
			__func__,
			kernel_debug_string,
			(unsigned long long)orangefs_gossip_debug_mask);
	} else if (mask_info.mask_type == CLIENT_MASK) {
		debug_mask_to_string(&mask_info.mask_value,
				     mask_info.mask_type);
		pr_info("%s: client debug mask has been modified to"
			":%s: :%llx:\n",
			__func__,
			client_debug_string,
			llu(mask_info.mask_value));
	} else {
		gossip_lerr("Invalid mask type....\n");
		return -EINVAL;
	}

	return ret;
}
Loading