Best way of getting a pathname for error reporting?

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

 



Hi Al,

I did the following hack for a debugging patch recently, and one of the
things it brought up for me is the challenge of printing a pathname for
debugging purposes.  I don't necessary need the pathname used to open
the file, but often all I have is a dentry, because for whatever reason
(I suspect historical), we don't pass in the struct path into the
low-level file systems, but just the struct dentry instead.

So see the kludges I did below --- in one case, a stiched together a
struct path using the vfsmnt found in the struct nameidata passed to the
lookup function.  In another, much more grotesque case, I grabbed the
vfsmnt for the root file system from current->fs->root (which is wrong
wrong wrong, but I checked the code and experimentally speaking, it
looks like it should do the same thing as the non-exported dentry_path()
function).

I wonder if we would be better off simply exporting dentry_path(),
perhaps as EXPORT_SYMBOL_GPL, with a warning that it should only be used
for debugging purposes, or some such.  I suspect it's not worth changing
all of the inode_ops interfaces to pass in a struct path intead of a
struct dentry if it's only to be used for debugging.  Or maybe I should
just keep on doing these ugly things and justify them because it's only
for debugging (yelch).

What do you think?

Thanks,

						- Ted

diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 52e6201..faa230b 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -34,6 +34,9 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/bio.h>
+#include <linux/path.h>
+#include <linux/namei.h>
+#include <linux/fs_struct.h>
 #include "ext4.h"
 #include "ext4_jbd2.h"
 
@@ -337,6 +340,36 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
 }
 #endif /* DX_DEBUG */
 
+#define ext4_time_check(sb, start, duration, path)			\
+	__ext4_time_check((sb),(start),(duration),(path), __func__, __LINE__)
+
+#define TIME_DEADLINE 5*HZ
+
+static void __ext4_time_check(struct super_block *sb, unsigned long start,
+			      unsigned duration, const struct path *path,
+			      const char *where, unsigned int line)
+{
+	unsigned long t = jiffies - start;
+	char pathname[80], *fn = 0;
+
+	if (t < duration)
+		return;
+	if (path)
+		fn = d_path(path, pathname, sizeof(pathname));
+	if (fn)
+		warn_slowpath_fmt(where, line, 
+				  "EXT4-fs (%s): comm %s: %s: "
+				  "deadline exceeded: %lu.%02lus",
+				  sb->s_id, current->comm, fn,
+				  t / HZ, ((t * 100) / HZ) % 100);
+	else
+		warn_slowpath_fmt(where, line, 
+				  "EXT4-fs (%s): comm %s: "
+				  "deadline exceeded: %lu.%02lus",
+				  sb->s_id, current->comm,
+				  t / HZ, ((t * 100) / HZ) % 100);
+}
+
 /*
  * Probe for a directory leaf block to search.
  *
@@ -1052,6 +1085,9 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru
 	struct inode *inode;
 	struct ext4_dir_entry_2 *de;
 	struct buffer_head *bh;
+	unsigned long s_time = jiffies;
+	struct path path;
+	struct dentry *new;
 
 	if (dentry->d_name.len > EXT4_NAME_LEN)
 		return ERR_PTR(-ENAMETOOLONG);
@@ -1077,7 +1113,15 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru
 			}
 		}
 	}
+#if 0
 	return d_splice_alias(inode, dentry);
+#else
+	new = d_splice_alias(inode, dentry);
+	path.mnt = nd->path.mnt;
+	path.dentry = dentry;
+	ext4_time_check(dir->i_sb, s_time, TIME_DEADLINE, &path);
+	return new;
+#endif
 }
 
 
@@ -2424,6 +2468,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct buffer_head *old_bh, *new_bh, *dir_bh;
 	struct ext4_dir_entry_2 *old_de, *new_de;
 	int retval, force_da_alloc = 0;
+	unsigned long s_time = jiffies;
+	struct path path;
 
 	dquot_initialize(old_dir);
 	dquot_initialize(new_dir);
@@ -2580,12 +2626,16 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 	retval = 0;
 
 end_rename:
+	path.mnt = current->fs->root.mnt; /* hack hack hack */
+	path.dentry = old_dentry;
+	ext4_time_check(old_dir->i_sb, s_time, TIME_DEADLINE, &path);
 	brelse(dir_bh);
 	brelse(old_bh);
 	brelse(new_bh);
 	ext4_journal_stop(handle);
 	if (retval == 0 && force_da_alloc)
 		ext4_alloc_da_blocks(old_inode);
+	ext4_time_check(old_dir->i_sb, s_time, TIME_DEADLINE, &path);
 	return retval;
 }
 
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux