Created
November 17, 2014 07:31
-
-
Save dvdhrm/b4a1c506bf929a9fadeb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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