* Best way of getting a pathname for error reporting?
@ 2012-04-20 18:08 Theodore Ts'o
2012-04-20 18:13 ` Al Viro
0 siblings, 1 reply; 2+ messages in thread
From: Theodore Ts'o @ 2012-04-20 18:08 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel
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;
}
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: Best way of getting a pathname for error reporting?
2012-04-20 18:08 Best way of getting a pathname for error reporting? Theodore Ts'o
@ 2012-04-20 18:13 ` Al Viro
0 siblings, 0 replies; 2+ messages in thread
From: Al Viro @ 2012-04-20 18:13 UTC (permalink / raw)
To: Theodore Ts'o; +Cc: linux-fsdevel
On Fri, Apr 20, 2012 at 02:08:37PM -0400, Theodore Ts'o wrote:
> 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?
Just use dentry_path_raw() - it _is_ exported and the only difference is
the lack of //deleted for unlinked ones.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-04-20 18:13 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-20 18:08 Best way of getting a pathname for error reporting? Theodore Ts'o
2012-04-20 18:13 ` Al Viro
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.