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