1 /* 2 * What: /sys/kernel/debug/orangefs/debug-help 3 * Date: June 2015 4 * Contact: Mike Marshall <hubcap@omnibond.com> 5 * Description: 6 * List of client and kernel debug keywords. 7 * 8 * 9 * What: /sys/kernel/debug/orangefs/client-debug 10 * Date: June 2015 11 * Contact: Mike Marshall <hubcap@omnibond.com> 12 * Description: 13 * Debug setting for "the client", the userspace 14 * helper for the kernel module. 15 * 16 * 17 * What: /sys/kernel/debug/orangefs/kernel-debug 18 * Date: June 2015 19 * Contact: Mike Marshall <hubcap@omnibond.com> 20 * Description: 21 * Debug setting for the orangefs kernel module. 22 * 23 * Any of the keywords, or comma-separated lists 24 * of keywords, from debug-help can be catted to 25 * client-debug or kernel-debug. 26 * 27 * "none", "all" and "verbose" are special keywords 28 * for client-debug. Setting client-debug to "all" 29 * is kind of like trying to drink water from a 30 * fire hose, "verbose" triggers most of the same 31 * output except for the constant flow of output 32 * from the main wait loop. 33 * 34 * "none" and "all" are similar settings for kernel-debug 35 * no need for a "verbose". 36 */ 37 #include <linux/debugfs.h> 38 #include <linux/slab.h> 39 40 #include <linux/uaccess.h> 41 42 #include "orangefs-debugfs.h" 43 #include "protocol.h" 44 #include "orangefs-kernel.h" 45 46 static int orangefs_debug_disabled = 1; 47 48 static int orangefs_debug_help_open(struct inode *, struct file *); 49 50 const struct file_operations debug_help_fops = { 51 .open = orangefs_debug_help_open, 52 .read = seq_read, 53 .release = seq_release, 54 .llseek = seq_lseek, 55 }; 56 57 static void *help_start(struct seq_file *, loff_t *); 58 static void *help_next(struct seq_file *, void *, loff_t *); 59 static void help_stop(struct seq_file *, void *); 60 static int help_show(struct seq_file *, void *); 61 62 static const struct seq_operations help_debug_ops = { 63 .start = help_start, 64 .next = help_next, 65 .stop = help_stop, 66 .show = help_show, 67 }; 68 69 /* 70 * Used to protect data in ORANGEFS_KMOD_DEBUG_FILE and 71 * ORANGEFS_KMOD_DEBUG_FILE. 72 */ 73 static DEFINE_MUTEX(orangefs_debug_lock); 74 75 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 const struct file_operations kernel_debug_fops = { 88 .open = orangefs_debug_open, 89 .read = orangefs_debug_read, 90 .write = orangefs_debug_write, 91 .llseek = generic_file_llseek, 92 }; 93 94 /* 95 * initialize kmod debug operations, create orangefs debugfs dir and 96 * ORANGEFS_KMOD_DEBUG_HELP_FILE. 97 */ 98 int orangefs_debugfs_init(void) 99 { 100 101 int rc = -ENOMEM; 102 103 debug_dir = debugfs_create_dir("orangefs", NULL); 104 if (!debug_dir) { 105 pr_info("%s: debugfs_create_dir failed.\n", __func__); 106 goto out; 107 } 108 109 help_file_dentry = debugfs_create_file(ORANGEFS_KMOD_DEBUG_HELP_FILE, 110 0444, 111 debug_dir, 112 debug_help_string, 113 &debug_help_fops); 114 if (!help_file_dentry) { 115 pr_info("%s: debugfs_create_file failed.\n", __func__); 116 goto out; 117 } 118 119 orangefs_debug_disabled = 0; 120 rc = 0; 121 122 out: 123 124 return rc; 125 } 126 127 void orangefs_debugfs_cleanup(void) 128 { 129 if (debug_dir) 130 debugfs_remove_recursive(debug_dir); 131 } 132 133 /* open ORANGEFS_KMOD_DEBUG_HELP_FILE */ 134 static int orangefs_debug_help_open(struct inode *inode, struct file *file) 135 { 136 int rc = -ENODEV; 137 int ret; 138 139 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 140 "orangefs_debug_help_open: start\n"); 141 142 if (orangefs_debug_disabled) 143 goto out; 144 145 ret = seq_open(file, &help_debug_ops); 146 if (ret) 147 goto out; 148 149 ((struct seq_file *)(file->private_data))->private = inode->i_private; 150 151 rc = 0; 152 153 out: 154 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 155 "orangefs_debug_help_open: rc:%d:\n", 156 rc); 157 return rc; 158 } 159 160 /* 161 * I think start always gets called again after stop. Start 162 * needs to return NULL when it is done. The whole "payload" 163 * in this case is a single (long) string, so by the second 164 * time we get to start (pos = 1), we're done. 165 */ 166 static void *help_start(struct seq_file *m, loff_t *pos) 167 { 168 void *payload = NULL; 169 170 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n"); 171 172 if (*pos == 0) 173 payload = m->private; 174 175 return payload; 176 } 177 178 static void *help_next(struct seq_file *m, void *v, loff_t *pos) 179 { 180 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_next: start\n"); 181 182 return NULL; 183 } 184 185 static void help_stop(struct seq_file *m, void *p) 186 { 187 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n"); 188 } 189 190 static int help_show(struct seq_file *m, void *v) 191 { 192 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_show: start\n"); 193 194 seq_puts(m, v); 195 196 return 0; 197 } 198 199 /* 200 * initialize the kernel-debug file. 201 */ 202 int orangefs_kernel_debug_init(void) 203 { 204 int rc = -ENOMEM; 205 struct dentry *ret; 206 char *k_buffer = NULL; 207 208 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); 209 210 k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 211 if (!k_buffer) 212 goto out; 213 214 if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { 215 strcpy(k_buffer, kernel_debug_string); 216 strcat(k_buffer, "\n"); 217 } else { 218 strcpy(k_buffer, "none\n"); 219 pr_info("%s: overflow 1!\n", __func__); 220 } 221 222 ret = debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE, 223 0444, 224 debug_dir, 225 k_buffer, 226 &kernel_debug_fops); 227 if (!ret) { 228 pr_info("%s: failed to create %s.\n", 229 __func__, 230 ORANGEFS_KMOD_DEBUG_FILE); 231 goto out; 232 } 233 234 rc = 0; 235 236 out: 237 238 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc); 239 return rc; 240 } 241 242 /* 243 * initialize the client-debug file. 244 */ 245 int orangefs_client_debug_init(void) 246 { 247 248 int rc = -ENOMEM; 249 char *c_buffer = NULL; 250 251 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); 252 253 c_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 254 if (!c_buffer) 255 goto out; 256 257 if (strlen(client_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { 258 strcpy(c_buffer, client_debug_string); 259 strcat(c_buffer, "\n"); 260 } else { 261 strcpy(c_buffer, "none\n"); 262 pr_info("%s: overflow! 2\n", __func__); 263 } 264 265 client_debug_dentry = debugfs_create_file(ORANGEFS_CLIENT_DEBUG_FILE, 266 0444, 267 debug_dir, 268 c_buffer, 269 &kernel_debug_fops); 270 if (!client_debug_dentry) { 271 pr_info("%s: failed to create updated %s.\n", 272 __func__, 273 ORANGEFS_CLIENT_DEBUG_FILE); 274 goto out; 275 } 276 277 rc = 0; 278 279 out: 280 281 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc); 282 return rc; 283 } 284 285 /* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/ 286 int orangefs_debug_open(struct inode *inode, struct file *file) 287 { 288 int rc = -ENODEV; 289 290 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 291 "%s: orangefs_debug_disabled: %d\n", 292 __func__, 293 orangefs_debug_disabled); 294 295 if (orangefs_debug_disabled) 296 goto out; 297 298 rc = 0; 299 mutex_lock(&orangefs_debug_lock); 300 file->private_data = inode->i_private; 301 mutex_unlock(&orangefs_debug_lock); 302 303 out: 304 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 305 "orangefs_debug_open: rc: %d\n", 306 rc); 307 return rc; 308 } 309 310 static ssize_t orangefs_debug_read(struct file *file, 311 char __user *ubuf, 312 size_t count, 313 loff_t *ppos) 314 { 315 char *buf; 316 int sprintf_ret; 317 ssize_t read_ret = -ENOMEM; 318 319 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "orangefs_debug_read: start\n"); 320 321 buf = kmalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 322 if (!buf) 323 goto out; 324 325 mutex_lock(&orangefs_debug_lock); 326 sprintf_ret = sprintf(buf, "%s", (char *)file->private_data); 327 mutex_unlock(&orangefs_debug_lock); 328 329 read_ret = simple_read_from_buffer(ubuf, count, ppos, buf, sprintf_ret); 330 331 kfree(buf); 332 333 out: 334 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 335 "orangefs_debug_read: ret: %zu\n", 336 read_ret); 337 338 return read_ret; 339 } 340 341 static ssize_t orangefs_debug_write(struct file *file, 342 const char __user *ubuf, 343 size_t count, 344 loff_t *ppos) 345 { 346 char *buf; 347 int rc = -EFAULT; 348 size_t silly = 0; 349 char *debug_string; 350 struct orangefs_kernel_op_s *new_op = NULL; 351 struct client_debug_mask c_mask = { NULL, 0, 0 }; 352 353 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 354 "orangefs_debug_write: %s\n", 355 file->f_path.dentry->d_name.name); 356 357 /* 358 * Thwart users who try to jamb a ridiculous number 359 * of bytes into the debug file... 360 */ 361 if (count > ORANGEFS_MAX_DEBUG_STRING_LEN + 1) { 362 silly = count; 363 count = ORANGEFS_MAX_DEBUG_STRING_LEN + 1; 364 } 365 366 buf = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 367 if (!buf) 368 goto out; 369 370 if (copy_from_user(buf, ubuf, count - 1)) { 371 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 372 "%s: copy_from_user failed!\n", 373 __func__); 374 goto out; 375 } 376 377 /* 378 * Map the keyword string from userspace into a valid debug mask. 379 * The mapping process involves mapping the human-inputted string 380 * into a valid mask, and then rebuilding the string from the 381 * verified valid mask. 382 * 383 * A service operation is required to set a new client-side 384 * debug mask. 385 */ 386 if (!strcmp(file->f_path.dentry->d_name.name, 387 ORANGEFS_KMOD_DEBUG_FILE)) { 388 debug_string_to_mask(buf, &gossip_debug_mask, 0); 389 debug_mask_to_string(&gossip_debug_mask, 0); 390 debug_string = kernel_debug_string; 391 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 392 "New kernel debug string is %s\n", 393 kernel_debug_string); 394 } else { 395 /* Can't reset client debug mask if client is not running. */ 396 if (is_daemon_in_service()) { 397 pr_info("%s: Client not running :%d:\n", 398 __func__, 399 is_daemon_in_service()); 400 goto out; 401 } 402 403 debug_string_to_mask(buf, &c_mask, 1); 404 debug_mask_to_string(&c_mask, 1); 405 debug_string = client_debug_string; 406 407 new_op = op_alloc(ORANGEFS_VFS_OP_PARAM); 408 if (!new_op) { 409 pr_info("%s: op_alloc failed!\n", __func__); 410 goto out; 411 } 412 413 new_op->upcall.req.param.op = 414 ORANGEFS_PARAM_REQUEST_OP_TWO_MASK_VALUES; 415 new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET; 416 memset(new_op->upcall.req.param.s_value, 417 0, 418 ORANGEFS_MAX_DEBUG_STRING_LEN); 419 sprintf(new_op->upcall.req.param.s_value, 420 "%llx %llx\n", 421 c_mask.mask1, 422 c_mask.mask2); 423 424 /* service_operation returns 0 on success... */ 425 rc = service_operation(new_op, 426 "orangefs_param", 427 ORANGEFS_OP_INTERRUPTIBLE); 428 429 if (rc) 430 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 431 "%s: service_operation failed! rc:%d:\n", 432 __func__, 433 rc); 434 435 op_release(new_op); 436 } 437 438 mutex_lock(&orangefs_debug_lock); 439 memset(file->f_inode->i_private, 0, ORANGEFS_MAX_DEBUG_STRING_LEN); 440 sprintf((char *)file->f_inode->i_private, "%s\n", debug_string); 441 mutex_unlock(&orangefs_debug_lock); 442 443 *ppos += count; 444 if (silly) 445 rc = silly; 446 else 447 rc = count; 448 449 out: 450 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 451 "orangefs_debug_write: rc: %d\n", 452 rc); 453 kfree(buf); 454 return rc; 455 } 456