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 debugfs_remove_recursive(debug_dir); 130 } 131 132 /* open ORANGEFS_KMOD_DEBUG_HELP_FILE */ 133 static int orangefs_debug_help_open(struct inode *inode, struct file *file) 134 { 135 int rc = -ENODEV; 136 int ret; 137 138 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 139 "orangefs_debug_help_open: start\n"); 140 141 if (orangefs_debug_disabled) 142 goto out; 143 144 ret = seq_open(file, &help_debug_ops); 145 if (ret) 146 goto out; 147 148 ((struct seq_file *)(file->private_data))->private = inode->i_private; 149 150 rc = 0; 151 152 out: 153 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 154 "orangefs_debug_help_open: rc:%d:\n", 155 rc); 156 return rc; 157 } 158 159 /* 160 * I think start always gets called again after stop. Start 161 * needs to return NULL when it is done. The whole "payload" 162 * in this case is a single (long) string, so by the second 163 * time we get to start (pos = 1), we're done. 164 */ 165 static void *help_start(struct seq_file *m, loff_t *pos) 166 { 167 void *payload = NULL; 168 169 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n"); 170 171 if (*pos == 0) 172 payload = m->private; 173 174 return payload; 175 } 176 177 static void *help_next(struct seq_file *m, void *v, loff_t *pos) 178 { 179 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_next: start\n"); 180 181 return NULL; 182 } 183 184 static void help_stop(struct seq_file *m, void *p) 185 { 186 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n"); 187 } 188 189 static int help_show(struct seq_file *m, void *v) 190 { 191 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_show: start\n"); 192 193 seq_puts(m, v); 194 195 return 0; 196 } 197 198 /* 199 * initialize the kernel-debug file. 200 */ 201 int orangefs_kernel_debug_init(void) 202 { 203 int rc = -ENOMEM; 204 struct dentry *ret; 205 char *k_buffer = NULL; 206 207 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); 208 209 k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 210 if (!k_buffer) 211 goto out; 212 213 if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { 214 strcpy(k_buffer, kernel_debug_string); 215 strcat(k_buffer, "\n"); 216 } else { 217 strcpy(k_buffer, "none\n"); 218 pr_info("%s: overflow 1!\n", __func__); 219 } 220 221 ret = debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE, 222 0444, 223 debug_dir, 224 k_buffer, 225 &kernel_debug_fops); 226 if (!ret) { 227 pr_info("%s: failed to create %s.\n", 228 __func__, 229 ORANGEFS_KMOD_DEBUG_FILE); 230 goto out; 231 } 232 233 rc = 0; 234 235 out: 236 237 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc); 238 return rc; 239 } 240 241 /* 242 * initialize the client-debug file. 243 */ 244 int orangefs_client_debug_init(void) 245 { 246 247 int rc = -ENOMEM; 248 char *c_buffer = NULL; 249 250 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); 251 252 c_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 253 if (!c_buffer) 254 goto out; 255 256 if (strlen(client_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { 257 strcpy(c_buffer, client_debug_string); 258 strcat(c_buffer, "\n"); 259 } else { 260 strcpy(c_buffer, "none\n"); 261 pr_info("%s: overflow! 2\n", __func__); 262 } 263 264 client_debug_dentry = debugfs_create_file(ORANGEFS_CLIENT_DEBUG_FILE, 265 0444, 266 debug_dir, 267 c_buffer, 268 &kernel_debug_fops); 269 if (!client_debug_dentry) { 270 pr_info("%s: failed to create updated %s.\n", 271 __func__, 272 ORANGEFS_CLIENT_DEBUG_FILE); 273 goto out; 274 } 275 276 rc = 0; 277 278 out: 279 280 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc); 281 return rc; 282 } 283 284 /* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/ 285 int orangefs_debug_open(struct inode *inode, struct file *file) 286 { 287 int rc = -ENODEV; 288 289 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 290 "%s: orangefs_debug_disabled: %d\n", 291 __func__, 292 orangefs_debug_disabled); 293 294 if (orangefs_debug_disabled) 295 goto out; 296 297 rc = 0; 298 mutex_lock(&orangefs_debug_lock); 299 file->private_data = inode->i_private; 300 mutex_unlock(&orangefs_debug_lock); 301 302 out: 303 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 304 "orangefs_debug_open: rc: %d\n", 305 rc); 306 return rc; 307 } 308 309 static ssize_t orangefs_debug_read(struct file *file, 310 char __user *ubuf, 311 size_t count, 312 loff_t *ppos) 313 { 314 char *buf; 315 int sprintf_ret; 316 ssize_t read_ret = -ENOMEM; 317 318 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "orangefs_debug_read: start\n"); 319 320 buf = kmalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 321 if (!buf) 322 goto out; 323 324 mutex_lock(&orangefs_debug_lock); 325 sprintf_ret = sprintf(buf, "%s", (char *)file->private_data); 326 mutex_unlock(&orangefs_debug_lock); 327 328 read_ret = simple_read_from_buffer(ubuf, count, ppos, buf, sprintf_ret); 329 330 kfree(buf); 331 332 out: 333 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 334 "orangefs_debug_read: ret: %zu\n", 335 read_ret); 336 337 return read_ret; 338 } 339 340 static ssize_t orangefs_debug_write(struct file *file, 341 const char __user *ubuf, 342 size_t count, 343 loff_t *ppos) 344 { 345 char *buf; 346 int rc = -EFAULT; 347 size_t silly = 0; 348 char *debug_string; 349 struct orangefs_kernel_op_s *new_op = NULL; 350 struct client_debug_mask c_mask = { NULL, 0, 0 }; 351 352 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 353 "orangefs_debug_write: %s\n", 354 file->f_path.dentry->d_name.name); 355 356 /* 357 * Thwart users who try to jamb a ridiculous number 358 * of bytes into the debug file... 359 */ 360 if (count > ORANGEFS_MAX_DEBUG_STRING_LEN + 1) { 361 silly = count; 362 count = ORANGEFS_MAX_DEBUG_STRING_LEN + 1; 363 } 364 365 buf = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 366 if (!buf) 367 goto out; 368 369 if (copy_from_user(buf, ubuf, count - 1)) { 370 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 371 "%s: copy_from_user failed!\n", 372 __func__); 373 goto out; 374 } 375 376 /* 377 * Map the keyword string from userspace into a valid debug mask. 378 * The mapping process involves mapping the human-inputted string 379 * into a valid mask, and then rebuilding the string from the 380 * verified valid mask. 381 * 382 * A service operation is required to set a new client-side 383 * debug mask. 384 */ 385 if (!strcmp(file->f_path.dentry->d_name.name, 386 ORANGEFS_KMOD_DEBUG_FILE)) { 387 debug_string_to_mask(buf, &gossip_debug_mask, 0); 388 debug_mask_to_string(&gossip_debug_mask, 0); 389 debug_string = kernel_debug_string; 390 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 391 "New kernel debug string is %s\n", 392 kernel_debug_string); 393 } else { 394 /* Can't reset client debug mask if client is not running. */ 395 if (is_daemon_in_service()) { 396 pr_info("%s: Client not running :%d:\n", 397 __func__, 398 is_daemon_in_service()); 399 goto out; 400 } 401 402 debug_string_to_mask(buf, &c_mask, 1); 403 debug_mask_to_string(&c_mask, 1); 404 debug_string = client_debug_string; 405 406 new_op = op_alloc(ORANGEFS_VFS_OP_PARAM); 407 if (!new_op) { 408 pr_info("%s: op_alloc failed!\n", __func__); 409 goto out; 410 } 411 412 new_op->upcall.req.param.op = 413 ORANGEFS_PARAM_REQUEST_OP_TWO_MASK_VALUES; 414 new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET; 415 memset(new_op->upcall.req.param.s_value, 416 0, 417 ORANGEFS_MAX_DEBUG_STRING_LEN); 418 sprintf(new_op->upcall.req.param.s_value, 419 "%llx %llx\n", 420 c_mask.mask1, 421 c_mask.mask2); 422 423 /* service_operation returns 0 on success... */ 424 rc = service_operation(new_op, 425 "orangefs_param", 426 ORANGEFS_OP_INTERRUPTIBLE); 427 428 if (rc) 429 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 430 "%s: service_operation failed! rc:%d:\n", 431 __func__, 432 rc); 433 434 op_release(new_op); 435 } 436 437 mutex_lock(&orangefs_debug_lock); 438 memset(file->f_inode->i_private, 0, ORANGEFS_MAX_DEBUG_STRING_LEN); 439 sprintf((char *)file->f_inode->i_private, "%s\n", debug_string); 440 mutex_unlock(&orangefs_debug_lock); 441 442 *ppos += count; 443 if (silly) 444 rc = silly; 445 else 446 rc = count; 447 448 out: 449 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 450 "orangefs_debug_write: rc: %d\n", 451 rc); 452 kfree(buf); 453 return rc; 454 } 455