root/fs/orangefs/orangefs-debugfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. orangefs_debugfs_init
  2. orangefs_kernel_debug_init
  3. orangefs_debugfs_cleanup
  4. orangefs_debug_help_open
  5. help_start
  6. help_next
  7. help_stop
  8. help_show
  9. orangefs_client_debug_init
  10. orangefs_debug_open
  11. orangefs_debug_read
  12. orangefs_debug_write
  13. orangefs_prepare_cdm_array
  14. orangefs_prepare_debugfs_help_string
  15. debug_mask_to_string
  16. do_k_string
  17. do_c_string
  18. keyword_is_amalgam
  19. check_amalgam_keyword
  20. debug_string_to_mask
  21. do_c_mask
  22. do_k_mask
  23. orangefs_debugfs_new_client_mask
  24. orangefs_debugfs_new_client_string
  25. orangefs_debugfs_new_debug

   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  */
  61 struct client_debug_mask {
  62         char *keyword;
  63         __u64 mask1;
  64         __u64 mask2;
  65 };
  66 
  67 static void orangefs_kernel_debug_init(void);
  68 
  69 static int orangefs_debug_help_open(struct inode *, struct file *);
  70 static void *help_start(struct seq_file *, loff_t *);
  71 static void *help_next(struct seq_file *, void *, loff_t *);
  72 static void help_stop(struct seq_file *, void *);
  73 static int help_show(struct seq_file *, void *);
  74 
  75 static int orangefs_debug_open(struct inode *, struct file *);
  76 
  77 static ssize_t orangefs_debug_read(struct file *,
  78                                  char __user *,
  79                                  size_t,
  80                                  loff_t *);
  81 
  82 static ssize_t orangefs_debug_write(struct file *,
  83                                   const char __user *,
  84                                   size_t,
  85                                   loff_t *);
  86 
  87 static int orangefs_prepare_cdm_array(char *);
  88 static void debug_mask_to_string(void *, int);
  89 static void do_k_string(void *, int);
  90 static void do_c_string(void *, int);
  91 static int keyword_is_amalgam(char *);
  92 static int check_amalgam_keyword(void *, int);
  93 static void debug_string_to_mask(char *, void *, int);
  94 static void do_c_mask(int, char *, struct client_debug_mask **);
  95 static void do_k_mask(int, char *, __u64 **);
  96 
  97 static char kernel_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN] = "none";
  98 static char *debug_help_string;
  99 static char client_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN];
 100 static char client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN];
 101 
 102 static struct dentry *client_debug_dentry;
 103 static struct dentry *debug_dir;
 104 
 105 static unsigned int kernel_mask_set_mod_init;
 106 static int orangefs_debug_disabled = 1;
 107 static int help_string_initialized;
 108 
 109 static 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 
 116 static 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 
 124 static 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 
 132 static int client_all_index;
 133 static int client_verbose_index;
 134 
 135 static struct client_debug_mask *cdm_array;
 136 static int cdm_element_count;
 137 
 138 static 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  */
 144 static DEFINE_MUTEX(orangefs_debug_lock);
 145 
 146 /* Used to protect data in ORANGEFS_KMOD_DEBUG_HELP_FILE */
 147 static 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  */
 153 void 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  */
 195 static 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 
 217 out:
 218         gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc);
 219 }
 220 
 221 
 222 void orangefs_debugfs_cleanup(void)
 223 {
 224         debugfs_remove_recursive(debug_dir);
 225 }
 226 
 227 /* open ORANGEFS_KMOD_DEBUG_HELP_FILE */
 228 static 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 
 247 out:
 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  */
 260 static 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 
 274 static 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 
 282 static 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 
 288 static 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  */
 300 static 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 
 328 out:
 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.*/
 335 static 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 
 352 out:
 353         gossip_debug(GOSSIP_DEBUGFS_DEBUG,
 354                      "orangefs_debug_open: rc: %d\n",
 355                      rc);
 356         return rc;
 357 }
 358 
 359 static 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 
 382 out:
 383         gossip_debug(GOSSIP_DEBUGFS_DEBUG,
 384                      "orangefs_debug_read: ret: %zu\n",
 385                      read_ret);
 386 
 387         return read_ret;
 388 }
 389 
 390 static 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 
 503 out:
 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  */
 516 static 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 
 577 out:
 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  */
 598 int 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 
 678 out:    return rc;
 679 
 680 }
 681 
 682 /*
 683  * kernel = type 0
 684  * client = type 1
 685  */
 686 static 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 
 732 out:
 733 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
 734 
 735         return;
 736 
 737 }
 738 
 739 static 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 
 760 out:
 761 
 762         return;
 763 }
 764 
 765 static 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         }
 786 out:
 787         return;
 788 }
 789 
 790 static 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  */
 806 static 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 
 840 out:
 841 
 842         return rc;
 843 }
 844 
 845 /*
 846  * kernel = type 0
 847  * client = type 1
 848  */
 849 static 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 
 887 static 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 
 897 static 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 
 905 int 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 
 929 int 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 
 982 int 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 }

/* [<][>][^][v][top][bottom][index][help] */