Skip to content

Instantly share code, notes, and snippets.

@dvdhrm
Created November 17, 2014 07:31
Show Gist options
  • Select an option

  • Save dvdhrm/b4a1c506bf929a9fadeb to your computer and use it in GitHub Desktop.

Select an option

Save dvdhrm/b4a1c506bf929a9fadeb to your computer and use it in GitHub Desktop.
diff --git a/fs/namei.c b/fs/namei.c
index db5fe86..ea1478d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -111,6 +111,16 @@
* any extra contention...
*/
+#define PRINT(format, ...) do { \
+ rcu_read_lock(); \
+ if (current->comm && !strcmp(current->comm, "kdbus-test")) \
+ pr_err("PRINT:%s:%d: " format "\n", __func__, __LINE__, ##__VA_ARGS__); \
+ rcu_read_unlock(); \
+ } while (0)
+#define ENTER PRINT("enter")
+#define LEAVE PRINT("leave")
+#define HINT PRINT("hint")
+
/* In order to reduce some races, while at the same time doing additional
* checking and hopefully speeding things up, we copy filenames to the
* kernel data space before using them..
@@ -1298,16 +1308,22 @@ static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir,
struct dentry *dentry;
int error;
+ ENTER;
+
*need_lookup = false;
dentry = d_lookup(dir, name);
if (dentry) {
+ HINT;
if (dentry->d_flags & DCACHE_OP_REVALIDATE) {
+ HINT;
error = d_revalidate(dentry, flags);
if (unlikely(error <= 0)) {
if (error < 0) {
dput(dentry);
+ LEAVE;
return ERR_PTR(error);
} else {
+ HINT;
d_invalidate(dentry);
dput(dentry);
dentry = NULL;
@@ -1316,13 +1332,18 @@ static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir,
}
}
+ HINT;
if (!dentry) {
+ HINT;
dentry = d_alloc(dir, name);
- if (unlikely(!dentry))
+ if (unlikely(!dentry)) {
+ LEAVE;
return ERR_PTR(-ENOMEM);
+ }
*need_lookup = true;
}
+ LEAVE;
return dentry;
}
@@ -1337,17 +1358,23 @@ static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry,
{
struct dentry *old;
+ ENTER;
+
/* Don't create child dentry for a dead directory. */
if (unlikely(IS_DEADDIR(dir))) {
dput(dentry);
+ LEAVE;
return ERR_PTR(-ENOENT);
}
+ HINT;
old = dir->i_op->lookup(dir, dentry, flags);
if (unlikely(old)) {
dput(dentry);
dentry = old;
+ HINT;
}
+ LEAVE;
return dentry;
}
@@ -1357,10 +1384,15 @@ static struct dentry *__lookup_hash(struct qstr *name,
bool need_lookup;
struct dentry *dentry;
+ ENTER;
+
dentry = lookup_dcache(name, base, flags, &need_lookup);
- if (!need_lookup)
+ if (!need_lookup) {
+ LEAVE;
return dentry;
+ }
+ LEAVE;
return lookup_real(base->d_inode, dentry, flags);
}
@@ -1378,6 +1410,8 @@ static int lookup_fast(struct nameidata *nd,
int status = 1;
int err;
+ ENTER;
+
/*
* Rename seqlock is not required here because in the off chance
* of a false negative due to a concurrent rename, we're going to
@@ -1385,6 +1419,7 @@ static int lookup_fast(struct nameidata *nd,
*/
if (nd->flags & LOOKUP_RCU) {
unsigned seq;
+ HINT;
dentry = __d_lookup_rcu(parent, &nd->last, &seq);
if (!dentry)
goto unlazy;
@@ -1393,9 +1428,12 @@ static int lookup_fast(struct nameidata *nd,
* This sequence count validates that the inode matches
* the dentry name information from lookup.
*/
+ HINT;
*inode = dentry->d_inode;
- if (read_seqcount_retry(&dentry->d_seq, seq))
+ if (read_seqcount_retry(&dentry->d_seq, seq)) {
+ LEAVE;
return -ECHILD;
+ }
/*
* This sequence count validates that the parent had no
@@ -1404,10 +1442,14 @@ static int lookup_fast(struct nameidata *nd,
* The memory barrier in read_seqcount_begin of child is
* enough, we can use __read_seqcount_retry here.
*/
- if (__read_seqcount_retry(&parent->d_seq, nd->seq))
+ HINT;
+ if (__read_seqcount_retry(&parent->d_seq, nd->seq)) {
+ LEAVE;
return -ECHILD;
+ }
nd->seq = seq;
+ HINT;
if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) {
status = d_revalidate(dentry, nd->flags);
if (unlikely(status <= 0)) {
@@ -1416,45 +1458,61 @@ static int lookup_fast(struct nameidata *nd,
goto unlazy;
}
}
+
+ HINT;
path->mnt = mnt;
path->dentry = dentry;
- if (likely(__follow_mount_rcu(nd, path, inode)))
+ if (likely(__follow_mount_rcu(nd, path, inode))) {
+ LEAVE;
return 0;
+ }
unlazy:
- if (unlazy_walk(nd, dentry))
+ HINT;
+ if (unlazy_walk(nd, dentry)) {
+ LEAVE;
return -ECHILD;
+ }
} else {
+ HINT;
dentry = __d_lookup(parent, &nd->last);
}
if (unlikely(!dentry))
goto need_lookup;
+ HINT;
if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE) && need_reval)
status = d_revalidate(dentry, nd->flags);
if (unlikely(status <= 0)) {
+ HINT;
if (status < 0) {
dput(dentry);
+ LEAVE;
return status;
}
+ HINT;
d_invalidate(dentry);
dput(dentry);
goto need_lookup;
}
+ HINT;
path->mnt = mnt;
path->dentry = dentry;
err = follow_managed(path, nd->flags);
if (unlikely(err < 0)) {
path_put_conditional(path, nd);
+ LEAVE;
return err;
}
if (err)
nd->flags |= LOOKUP_JUMPED;
*inode = path->dentry->d_inode;
+ LEAVE;
return 0;
need_lookup:
+ LEAVE;
return 1;
}
@@ -1464,23 +1522,30 @@ static int lookup_slow(struct nameidata *nd, struct path *path)
struct dentry *dentry, *parent;
int err;
+ ENTER;
+
parent = nd->path.dentry;
BUG_ON(nd->inode != parent->d_inode);
mutex_lock(&parent->d_inode->i_mutex);
dentry = __lookup_hash(&nd->last, parent, nd->flags);
mutex_unlock(&parent->d_inode->i_mutex);
- if (IS_ERR(dentry))
+ if (IS_ERR(dentry)) {
+ LEAVE;
return PTR_ERR(dentry);
+ }
+ HINT;
path->mnt = nd->path.mnt;
path->dentry = dentry;
err = follow_managed(path, nd->flags);
if (unlikely(err < 0)) {
path_put_conditional(path, nd);
+ LEAVE;
return err;
}
if (err)
nd->flags |= LOOKUP_JUMPED;
+ LEAVE;
return 0;
}
@@ -1536,13 +1601,18 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
{
struct inode *inode;
int err;
+
+ ENTER;
+
/*
* "." and ".." are special - ".." especially so because it has
* to be able to know about the current root directory and
* parent relationships.
*/
- if (unlikely(nd->last_type != LAST_NORM))
+ if (unlikely(nd->last_type != LAST_NORM)) {
+ LEAVE;
return handle_dots(nd, nd->last_type);
+ }
err = lookup_fast(nd, path, &inode);
if (unlikely(err)) {
if (err < 0)
@@ -1566,16 +1636,19 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
}
}
BUG_ON(inode != path->dentry->d_inode);
+ LEAVE;
return 1;
}
path_to_nameidata(path, nd);
nd->inode = inode;
+ LEAVE;
return 0;
out_path_put:
path_to_nameidata(path, nd);
out_err:
terminate_walk(nd);
+ LEAVE;
return err;
}
@@ -1744,11 +1817,15 @@ static int link_path_walk(const char *name, struct nameidata *nd)
{
struct path next;
int err;
-
+
+ ENTER;
+
while (*name=='/')
name++;
- if (!*name)
+ if (!*name) {
+ LEAVE;
return 0;
+ }
/* At this point we know we have a real path component. */
for(;;) {
@@ -1790,8 +1867,10 @@ static int link_path_walk(const char *name, struct nameidata *nd)
nd->last_type = type;
name += hashlen_len(hash_len);
- if (!*name)
+ if (!*name) {
+ LEAVE;
return 0;
+ }
/*
* If it wasn't NUL, we know it was '/'. Skip that
* slash, and continue until no more slashes.
@@ -1799,17 +1878,23 @@ static int link_path_walk(const char *name, struct nameidata *nd)
do {
name++;
} while (unlikely(*name == '/'));
- if (!*name)
+ if (!*name) {
+ LEAVE;
return 0;
+ }
err = walk_component(nd, &next, LOOKUP_FOLLOW);
- if (err < 0)
+ if (err < 0) {
+ LEAVE;
return err;
+ }
if (err) {
err = nested_symlink(&next, nd);
- if (err)
+ if (err) {
+ LEAVE;
return err;
+ }
}
if (!d_can_lookup(nd->path.dentry)) {
err = -ENOTDIR;
@@ -1817,6 +1902,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
}
}
terminate_walk(nd);
+ LEAVE;
return err;
}
@@ -1934,6 +2020,7 @@ static int path_lookupat(int dfd, const char *name,
struct path path;
int err;
+ ENTER;
/*
* Path walking is largely split up into 2 different synchronisation
* schemes, rcu-walk and ref-walk (explained in
@@ -1991,6 +2078,7 @@ out:
path_put(&nd->root);
nd->root.mnt = NULL;
}
+ LEAVE;
return err;
}
@@ -1998,6 +2086,9 @@ static int filename_lookup(int dfd, struct filename *name,
unsigned int flags, struct nameidata *nd)
{
int retval = path_lookupat(dfd, name->name, flags | LOOKUP_RCU, nd);
+
+ ENTER;
+
if (unlikely(retval == -ECHILD))
retval = path_lookupat(dfd, name->name, flags, nd);
if (unlikely(retval == -ESTALE))
@@ -2006,6 +2097,8 @@ static int filename_lookup(int dfd, struct filename *name,
if (likely(!retval))
audit_inode(name, nd->path.dentry, flags & LOOKUP_PARENT);
+
+ LEAVE;
return retval;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment