Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 18 Sep 2010 11:28:00 +0200
From:      Norberto Lopes <nlopes.ml@gmail.com>
To:        Kostik Belousov <kostikbel@gmail.com>
Cc:        freebsd-current@freebsd.org, netchild@freebsd.org
Subject:   Re: Extend ktrace/kdump output
Message-ID:  <AANLkTimCwNA2BGbm9N-iFo%2BomR06h%2BXJDxOFSrT0AnJ7@mail.gmail.com>
In-Reply-To: <AANLkTikWEzjeA8miRXkkSBuK65sBi%2BtDvx7F=mirTZ7g@mail.gmail.com>
References:  <8C5C36F5-A070-4CBA-8B8C-6751F8D636E1@gmail.com> <20100917203645.GS2389@deviant.kiev.zoral.com.ua> <AANLkTikWEzjeA8miRXkkSBuK65sBi%2BtDvx7F=mirTZ7g@mail.gmail.com>

index | next in thread | previous in thread | raw e-mail

[-- Attachment #1 --]
Anyway, attached is the patch.
All (constructive) criticism is welcome, even if it has to deal with
"how I should do things freebsd way (in case there is one)".

On Fri, Sep 17, 2010 at 10:48 PM, Norberto Lopes <nlopes.ml@gmail.com> wrote:
> On Fri, Sep 17, 2010 at 10:36 PM, Kostik Belousov <kostikbel@gmail.com> wrote:
>> On Fri, Sep 17, 2010 at 09:55:26PM +0200, Norberto Lopes wrote:
>>> Hi.
>>> I've been taking a look at ktrace and kdump in order to get (1) familiar with the sources and (2) to finally try to give back something to the community.
>>>
>>> So far from what I've seen, and after reading this thread http://lists.freebsd.org/pipermail/freebsd-arch/2006-April/005107.html it seems that most of those points got done.
>>>
>>> To warm up I changed the output of the stat structure in order to provide me with the device name (something I actually find useful for me sometimes)
>>>
>>> Instead of:
>>>  22596 cat      STRU  struct stat {dev=89, ino=3320836, mode=-r--r--r-- , nlink=1, uid=0, gid=0, atime=1284725358, stime=1284485510, ctime=1284485510, birthtime=1284485509, size=1172220, blksize=16384, blocks=2336, flags=0x20000 }
>>>
>>> I get this now (including major and minor):
>>>  22596 cat      STRU  struct stat {dev=<id=89:M=0:m=89> (/dev/ad4s1a), ino=3320836, mode=-r--r--r-- , nlink=1, uid=0, gid=0, atime=1284725358, stime=1284485510, ctime=1284485510, birthtime=1284485509, size=1172220, blksize=16384, blocks=2336, flags=0x20000 }
>>>
>>> I wouldn't mind having someone help me whenever and if I get stuck on the technical side (*wink* Alexander Leidinger *wink*) and also to give me more insight on what the road to help in this should be.
>>>
>>> P.S.: I'm still going through "man style" hence no patch attached. If anyone finds this one useful, I'll reply with the patch though.
>>>
>> How do you look up the device name by st_dev ? Note that the number is
>> generated by devfs at the moment of cdev creation. It is only valid on
>> the machine where stat(2) is done, and only due to the next reboot.
>>
>
> Through a really ugly hack...
> opendir("/dev")
> readdir("/dev")
> go through them and find the one...
>
> Yes, I know, painful and ugly, but as I usually use kdump with no
> reboots between analysis (I hardly ever reboot actually), and because
> I find it exhausting to keep going back to look up the device name,
> this kept me happy enough. :)
>

[-- Attachment #2 --]
Index: kdump.c
===================================================================
--- kdump.c	(revision 212820)
+++ kdump.c	(working copy)
@@ -82,6 +82,8 @@ extern int errno;
 #include <time.h>
 #include <unistd.h>
 #include <vis.h>
+#include <dirent.h>
+#include <stdbool.h>
 #include "ktrace.h"
 #include "kdump_subr.h"
 
@@ -1249,6 +1251,11 @@ ktrstat(struct stat *statp)
 	struct passwd *pwd;
 	struct group  *grp;
 	struct tm *tm;
+	DIR *od = NULL;
+	struct stat *dev_stat;
+	struct dirent *dev_entry;
+	char *dev_name, *dev_path="/dev/";
+	bool found_dev = false;
 
 	/*
 	 * note: ktrstruct() has already verified that statp points to a
@@ -1256,9 +1263,73 @@ ktrstat(struct stat *statp)
 	 */
 	printf("struct stat {");
 	strmode(statp->st_mode, mode);
-	printf("dev=%ju, ino=%ju, mode=%s, nlink=%ju, ",
-		(uintmax_t)statp->st_dev, (uintmax_t)statp->st_ino, mode,
-		(uintmax_t)statp->st_nlink);
+
+	dev_stat = (struct stat *)malloc(sizeof(struct stat));
+	if (dev_stat == NULL)
+		errx(1, "%s", strerror(ENOMEM));
+
+	/* check if we can reach it and open it */
+	if (!stat(dev_path, dev_stat) && (od = opendir(dev_path)) == NULL)
+		free(dev_stat);
+	else {
+		while ((dev_entry = readdir(od)) != NULL && found_dev == false) {
+			/* ignore "." and ".." */
+			if ((strcmp(dev_entry->d_name, ".") == 0) || 
+			    (strcmp(dev_entry->d_name, "..") == 0))
+				continue;
+			
+			dev_name = (char *)malloc(sizeof(char)*
+			        (strlen(dev_path)+strlen(dev_entry->d_name)));
+
+			if (dev_name == NULL)
+				errx(1, "%s", strerror(ENOMEM));
+			
+			(void)sprintf(dev_name, "%s%s", dev_path, 
+			                dev_entry->d_name);
+	    
+			dev_stat = (struct stat *)malloc(sizeof(struct stat));
+			if (dev_stat == NULL)
+				errx(1, "%s", strerror(ENOMEM));
+
+			if (stat(dev_name, dev_stat) == -1) {
+				free(dev_stat);
+				continue;
+			}
+
+			/* 
+			 * If the file device number equals the device inode 
+			 * we have the device that contains the file.
+			 *
+			 * In the chance that we find that the "file" inode
+			 * equals the device inode, then they are the same too.
+			 */
+			if ((uintmax_t)statp->st_dev == 
+			    (uintmax_t)dev_stat->st_ino) {
+				found_dev = true;
+				break;
+			}
+			else if ((uintmax_t)statp->st_ino == 
+			        (uintmax_t)dev_stat->st_ino) {
+				found_dev = true;
+				break;
+			}
+
+			free(dev_name);			
+			free(dev_stat);
+		}
+	}
+	if (found_dev) {
+		printf("dev=<id=%ju:M=%d:m=%d> (%s),", 
+		        (uintmax_t)statp->st_dev, major(statp->st_dev),
+		        minor(statp->st_dev), dev_name);
+		free(dev_name);
+	}
+	else
+		printf("dev=<id=%ju:M=%d:m=%d>,", (uintmax_t)statp->st_dev, 
+		        major(statp->st_dev), minor(statp->st_dev));
+
+	printf(" ino=%ju, mode=%s, nlink=%ju, ",
+	        (uintmax_t)statp->st_ino, mode, (uintmax_t)statp->st_nlink);
+
 	if (resolv == 0 || (pwd = getpwuid(statp->st_uid)) == NULL)
 		printf("uid=%ju, ", (uintmax_t)statp->st_uid);
 	else
@@ -1267,7 +1338,11 @@ ktrstat(struct stat *statp)
 		printf("gid=%ju, ", (uintmax_t)statp->st_gid);
 	else
 		printf("gid=\"%s\", ", grp->gr_name);
+
+	/* XXX: Do we really need rdev in case it's not character or block? */
+	/* if (S_ISCHR(statp->st_mode) || S_ISBLK(statp->st_mode)) */
 	printf("rdev=%ju, ", (uintmax_t)statp->st_rdev);
+
 	printf("atime=");
 	if (resolv == 0)
 		printf("%jd", (intmax_t)statp->st_atim.tv_sec);
@@ -1317,8 +1392,8 @@ ktrstat(struct stat *statp)
 	else
 		printf(", ");
 	printf("size=%jd, blksize=%ju, blocks=%jd, flags=0x%x",
-		(uintmax_t)statp->st_size, (uintmax_t)statp->st_blksize,
-		(intmax_t)statp->st_blocks, statp->st_flags);
+	        (uintmax_t)statp->st_size, (uintmax_t)statp->st_blksize,
+	        (intmax_t)statp->st_blocks, statp->st_flags);
 	printf(" }\n");
 }
 
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?AANLkTimCwNA2BGbm9N-iFo%2BomR06h%2BXJDxOFSrT0AnJ7>