dev command deteriorates with new kernels

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



With respect to character devices:

Sometime way back in the 2.6ish kernel, the fops field of struct
char_device_struct ceased to be used for anything, and on those kernels
(like 2.6.18), dev always reports the OPERATIONS field as "(none)":

crash-4.0-8.10> dev
CHRDEV    NAME            OPERATIONS
   1      mem                     (none)
   2      pty                     (none)
   3      ttyp                    (none)
   4      /dev/vc/0               (none)
   4      tty                     (none)
   4      ttyS                    (none)
   5      /dev/tty                (none)
   5      /dev/console            (none)
   5      /dev/ptmx               (none)
   7      vcs                     (none)
  10      misc                    (none)
  13      input                   (none)
  21      sg                      (none)
  29      fb                      (none)
...

Then recently (by 2.6.28, anyway), someone noticed that the fops field
was unused and removed it from struct char_device_struct altogether, so
now we get:

crash-4.0-8.10> dev

dev: invalid structure member offset: char_device_struct_fops
     FILE: dev.c  LINE: 221  FUNCTION: dump_chrdevs()

[/home/bobm/bin/crash-4.0-8.10] error trace: 452e75 => 4cf528 => 4cf957
=> 50d8d3
CHRDEV    NAME            OPERATIONS

  50d8d3: OFFSET_verify+168
  4cf957: dump_chrdevs+1043
  4cf528: cmd_dev+198
  452e75: exec_command+306

dev: invalid structure member offset: char_device_struct_fops
     FILE: dev.c  LINE: 221  FUNCTION: dump_chrdevs()

crash-4.0-8.10>

The attached patch changes the behavior in both cases to something like
this:

crash-4.0-8.10fix> dev
CHRDEV    NAME            OPERATIONS
   1      mem           ffffffff8043ee00  <memory_fops>
   2      pty                     (none)
   3      ttyp                    (none)
   4      /dev/vc/0               (none)
   4      tty                     (none)
   4      ttyS                    (none)
   5      /dev/tty                (none)
   5      /dev/console            (none)
   5      /dev/ptmx               (none)
   7      vcs           ffffffff8043ff40  <vcs_fops>
  10      misc          ffffffff8043fe40  <misc_fops>
  13      input         ffffffff805413c0  <input_fops>
  21      sg                      (none)
  29      fb            ffffffff80531c60  <fb_fops>

Which is definitely an improvement.
  
But wondering about those remaining (none) entries, I found that if I
pursue info through the cdev_map with a series of crash commands like
this:

crash-4.0-8.10fix> p (*cdev_map.probes[2]).data
$7 = (void *) 0xffff81013a66c408
crash-4.0-8.10fix> p (*(struct cdev *)0xffff81013a66c408).ops
$8 = (const struct file_operations *) 0xffffffff8043f860
crash-4.0-8.10fix> sym 0xffffffff8043f860
ffffffff8043f860 (r) tty_fops


crash-4.0-8.10fix> p (*cdev_map.probes[21]).data
$9 = (void *) 0xffff81013acf8d80
crash-4.0-8.10fix> p (*(struct cdev *)0xffff81013acf8d80).ops
$10 = (const struct file_operations *) 0xffffffff8820ee00
crash-4.0-8.10fix> sym 0xffffffff8820ee00
ffffffff8820ee00 (d) sg_fops

I can come up with believable file_ops values for (most? all?) of the
others.  And this leads me to wonder if crash shouldn't be collecting
this info in a similar manner to fill in the other OPERATIONS fields.
But now I'm quite a bit past what I know about how the character device
stuff works.


Thanks,
Bob Montgomery
Working at HP










--- defs.h.orig	2009-06-02 14:13:50.000000000 -0600
+++ defs.h	2009-06-02 14:49:27.000000000 -0600
@@ -1385,6 +1385,8 @@ struct offset_table {                   
 	long char_device_struct_name;
 	long char_device_struct_fops;
 	long char_device_struct_major;
+	long char_device_struct_cdev;
+	long cdev_ops;
 	long gendisk_major;
 	long gendisk_disk_name;
 	long gendisk_fops;
@@ -1548,6 +1550,7 @@ struct size_table {         /* stash of 
 	long gendisk;
 	long address_space;
 	long char_device_struct;
+	long cdev;
 	long inet_sock;
 	long in6_addr;
 	long socket;
--- dev.c.orig	2009-06-02 14:05:59.000000000 -0600
+++ dev.c	2009-06-02 15:26:47.000000000 -0600
@@ -138,8 +138,8 @@ dump_chrdevs(ulong flags)
 		ulong ops;
 	} chrdevs[MAX_DEV], *cp;
 	ulong *cdp;
-	char *char_device_struct_buf;
-	ulong next, savenext, name, fops; 
+	char *char_device_struct_buf, *cdev_buf;
+	ulong next, savenext, name, fops, cdev; 
 	int major;
 	int name_typecode;
 	size_t name_size;
@@ -217,8 +217,24 @@ char_device_struct:
 				break;
 		}
 
-		fops = ULONG(char_device_struct_buf + 
-			OFFSET(char_device_struct_fops));
+		fops = NULL;
+		if (VALID_MEMBER(char_device_struct_cdev) &&
+				VALID_STRUCT(cdev)) {
+			cdev = ULONG(char_device_struct_buf + 
+				OFFSET(char_device_struct_cdev));
+			cdev_buf = GETBUF(SIZE(cdev));
+			if (cdev) {
+				readmem(cdev, KVADDR, cdev_buf, 
+					SIZE(cdev),
+					"cdev", FAULT_ON_ERROR);
+				fops = ULONG(cdev_buf + 
+					OFFSET(cdev_ops));
+			}
+		} else {
+			fops = ULONG(char_device_struct_buf + 
+				OFFSET(char_device_struct_fops));
+		}
+
 		major = INT(char_device_struct_buf + 
 			OFFSET(char_device_struct_major));
 
@@ -267,8 +283,24 @@ char_device_struct:
 				break;
 			}
 
-	                fops = ULONG(char_device_struct_buf +
-	                        OFFSET(char_device_struct_fops));
+			fops = NULL;
+			if (VALID_MEMBER(char_device_struct_cdev) &&
+					VALID_STRUCT(cdev)) {
+				cdev = ULONG(char_device_struct_buf + 
+					OFFSET(char_device_struct_cdev));
+				cdev_buf = GETBUF(SIZE(cdev));
+				if (cdev) {
+					readmem(cdev, KVADDR, cdev_buf,
+						SIZE(cdev),
+						"cdev", FAULT_ON_ERROR);
+					fops = ULONG(cdev_buf + 
+						OFFSET(cdev_ops));
+				}
+			} else {
+				fops = ULONG(char_device_struct_buf + 
+					OFFSET(char_device_struct_fops));
+			}
+ 
 	                major = INT(char_device_struct_buf +
 	                        OFFSET(char_device_struct_major));
 
--- kernel.c.orig	2009-06-02 14:13:38.000000000 -0600
+++ kernel.c	2009-06-02 14:49:27.000000000 -0600
@@ -463,8 +463,15 @@ kernel_init()
 			"char_device_struct", "fops");
 		MEMBER_OFFSET_INIT(char_device_struct_major,
 			"char_device_struct", "major");
+		MEMBER_OFFSET_INIT(char_device_struct_cdev,
+			"char_device_struct", "cdev");
 	}
 
+	STRUCT_SIZE_INIT(cdev, "cdev");
+	if (VALID_STRUCT(cdev)) 
+		MEMBER_OFFSET_INIT(cdev_ops,
+			"cdev", "ops");
+
 	MEMBER_OFFSET_INIT(module_kallsyms_start, "module", 
 		"kallsyms_start");
 
--- symbols.c.orig	2009-06-02 14:13:44.000000000 -0600
+++ symbols.c	2009-06-02 14:49:27.000000000 -0600
@@ -7024,6 +7024,11 @@ dump_offset_table(char *spec, ulong make
 		OFFSET(char_device_struct_fops));
 	fprintf(fp, "      char_device_struct_major: %ld\n",
 		OFFSET(char_device_struct_major));
+	fprintf(fp, "      char_device_struct_cdev: %ld\n",
+		OFFSET(char_device_struct_cdev));
+
+	fprintf(fp, "      cdev_ops: %ld\n",
+		OFFSET(cdev_ops));
 
 	fprintf(fp, "           blk_major_name_next: %ld\n",
 		OFFSET(blk_major_name_next));
--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux