diff options
Diffstat (limited to 'fs/dcookies.c')
-rw-r--r-- | fs/dcookies.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/fs/dcookies.c b/fs/dcookies.c index 855d4b1d619a..a21cabdbd87b 100644 --- a/fs/dcookies.c +++ b/fs/dcookies.c | |||
@@ -93,10 +93,15 @@ static struct dcookie_struct *alloc_dcookie(struct path *path) | |||
93 | { | 93 | { |
94 | struct dcookie_struct *dcs = kmem_cache_alloc(dcookie_cache, | 94 | struct dcookie_struct *dcs = kmem_cache_alloc(dcookie_cache, |
95 | GFP_KERNEL); | 95 | GFP_KERNEL); |
96 | struct dentry *d; | ||
96 | if (!dcs) | 97 | if (!dcs) |
97 | return NULL; | 98 | return NULL; |
98 | 99 | ||
99 | path->dentry->d_cookie = dcs; | 100 | d = path->dentry; |
101 | spin_lock(&d->d_lock); | ||
102 | d->d_flags |= DCACHE_COOKIE; | ||
103 | spin_unlock(&d->d_lock); | ||
104 | |||
100 | dcs->path = *path; | 105 | dcs->path = *path; |
101 | path_get(path); | 106 | path_get(path); |
102 | hash_dcookie(dcs); | 107 | hash_dcookie(dcs); |
@@ -119,14 +124,14 @@ int get_dcookie(struct path *path, unsigned long *cookie) | |||
119 | goto out; | 124 | goto out; |
120 | } | 125 | } |
121 | 126 | ||
122 | dcs = path->dentry->d_cookie; | 127 | if (path->dentry->d_flags & DCACHE_COOKIE) { |
123 | 128 | dcs = find_dcookie((unsigned long)path->dentry); | |
124 | if (!dcs) | 129 | } else { |
125 | dcs = alloc_dcookie(path); | 130 | dcs = alloc_dcookie(path); |
126 | 131 | if (!dcs) { | |
127 | if (!dcs) { | 132 | err = -ENOMEM; |
128 | err = -ENOMEM; | 133 | goto out; |
129 | goto out; | 134 | } |
130 | } | 135 | } |
131 | 136 | ||
132 | *cookie = dcookie_value(dcs); | 137 | *cookie = dcookie_value(dcs); |
@@ -140,7 +145,7 @@ out: | |||
140 | /* And here is where the userspace process can look up the cookie value | 145 | /* And here is where the userspace process can look up the cookie value |
141 | * to retrieve the path. | 146 | * to retrieve the path. |
142 | */ | 147 | */ |
143 | asmlinkage long sys_lookup_dcookie(u64 cookie64, char __user * buf, size_t len) | 148 | SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len) |
144 | { | 149 | { |
145 | unsigned long cookie = (unsigned long)cookie64; | 150 | unsigned long cookie = (unsigned long)cookie64; |
146 | int err = -EINVAL; | 151 | int err = -EINVAL; |
@@ -193,7 +198,13 @@ out: | |||
193 | mutex_unlock(&dcookie_mutex); | 198 | mutex_unlock(&dcookie_mutex); |
194 | return err; | 199 | return err; |
195 | } | 200 | } |
196 | 201 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | |
202 | asmlinkage long SyS_lookup_dcookie(u64 cookie64, long buf, long len) | ||
203 | { | ||
204 | return SYSC_lookup_dcookie(cookie64, (char __user *) buf, (size_t) len); | ||
205 | } | ||
206 | SYSCALL_ALIAS(sys_lookup_dcookie, SyS_lookup_dcookie); | ||
207 | #endif | ||
197 | 208 | ||
198 | static int dcookie_init(void) | 209 | static int dcookie_init(void) |
199 | { | 210 | { |
@@ -251,7 +262,12 @@ out_kmem: | |||
251 | 262 | ||
252 | static void free_dcookie(struct dcookie_struct * dcs) | 263 | static void free_dcookie(struct dcookie_struct * dcs) |
253 | { | 264 | { |
254 | dcs->path.dentry->d_cookie = NULL; | 265 | struct dentry *d = dcs->path.dentry; |
266 | |||
267 | spin_lock(&d->d_lock); | ||
268 | d->d_flags &= ~DCACHE_COOKIE; | ||
269 | spin_unlock(&d->d_lock); | ||
270 | |||
255 | path_put(&dcs->path); | 271 | path_put(&dcs->path); |
256 | kmem_cache_free(dcookie_cache, dcs); | 272 | kmem_cache_free(dcookie_cache, dcs); |
257 | } | 273 | } |