diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2010-06-06 22:31:14 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-08-09 16:48:13 -0400 |
commit | c103135c14e03fc9a9e5f0adc01df9ad272cf2a1 (patch) | |
tree | 0c75bd6a56385697cd0e79fb695a833c5225e45e | |
parent | d0352d3ed722b134dacc21836c1763e7e3523662 (diff) |
new helper: __dentry_path()
builds path relative to fs root, called under dcache_lock,
doesn't append any nonsense to unlinked ones.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/dcache.c | 27 | ||||
-rw-r--r-- | include/linux/dcache.h | 1 |
2 files changed, 23 insertions, 5 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 86d4db15473e..caf08574982f 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -2049,16 +2049,12 @@ char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen, | |||
2049 | /* | 2049 | /* |
2050 | * Write full pathname from the root of the filesystem into the buffer. | 2050 | * Write full pathname from the root of the filesystem into the buffer. |
2051 | */ | 2051 | */ |
2052 | char *dentry_path(struct dentry *dentry, char *buf, int buflen) | 2052 | char *__dentry_path(struct dentry *dentry, char *buf, int buflen) |
2053 | { | 2053 | { |
2054 | char *end = buf + buflen; | 2054 | char *end = buf + buflen; |
2055 | char *retval; | 2055 | char *retval; |
2056 | 2056 | ||
2057 | spin_lock(&dcache_lock); | ||
2058 | prepend(&end, &buflen, "\0", 1); | 2057 | prepend(&end, &buflen, "\0", 1); |
2059 | if (d_unlinked(dentry) && | ||
2060 | (prepend(&end, &buflen, "//deleted", 9) != 0)) | ||
2061 | goto Elong; | ||
2062 | if (buflen < 1) | 2058 | if (buflen < 1) |
2063 | goto Elong; | 2059 | goto Elong; |
2064 | /* Get '/' right */ | 2060 | /* Get '/' right */ |
@@ -2076,7 +2072,28 @@ char *dentry_path(struct dentry *dentry, char *buf, int buflen) | |||
2076 | retval = end; | 2072 | retval = end; |
2077 | dentry = parent; | 2073 | dentry = parent; |
2078 | } | 2074 | } |
2075 | return retval; | ||
2076 | Elong: | ||
2077 | return ERR_PTR(-ENAMETOOLONG); | ||
2078 | } | ||
2079 | EXPORT_SYMBOL(__dentry_path); | ||
2080 | |||
2081 | char *dentry_path(struct dentry *dentry, char *buf, int buflen) | ||
2082 | { | ||
2083 | char *p = NULL; | ||
2084 | char *retval; | ||
2085 | |||
2086 | spin_lock(&dcache_lock); | ||
2087 | if (d_unlinked(dentry)) { | ||
2088 | p = buf + buflen; | ||
2089 | if (prepend(&p, &buflen, "//deleted", 10) != 0) | ||
2090 | goto Elong; | ||
2091 | buflen++; | ||
2092 | } | ||
2093 | retval = __dentry_path(dentry, buf, buflen); | ||
2079 | spin_unlock(&dcache_lock); | 2094 | spin_unlock(&dcache_lock); |
2095 | if (!IS_ERR(retval) && p) | ||
2096 | *p = '/'; /* restore '/' overriden with '\0' */ | ||
2080 | return retval; | 2097 | return retval; |
2081 | Elong: | 2098 | Elong: |
2082 | spin_unlock(&dcache_lock); | 2099 | spin_unlock(&dcache_lock); |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index eebb617c17d8..d23be0386e2d 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -315,6 +315,7 @@ extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...); | |||
315 | 315 | ||
316 | extern char *__d_path(const struct path *path, struct path *root, char *, int); | 316 | extern char *__d_path(const struct path *path, struct path *root, char *, int); |
317 | extern char *d_path(const struct path *, char *, int); | 317 | extern char *d_path(const struct path *, char *, int); |
318 | extern char *__dentry_path(struct dentry *, char *, int); | ||
318 | extern char *dentry_path(struct dentry *, char *, int); | 319 | extern char *dentry_path(struct dentry *, char *, int); |
319 | 320 | ||
320 | /* Allocation counts.. */ | 321 | /* Allocation counts.. */ |