diff options
Diffstat (limited to 'fs/overlayfs/super.c')
-rw-r--r-- | fs/overlayfs/super.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index ef64984c9bbc..5d972e6cd3fe 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -295,6 +295,37 @@ static void ovl_dentry_release(struct dentry *dentry) | |||
295 | } | 295 | } |
296 | } | 296 | } |
297 | 297 | ||
298 | static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode) | ||
299 | { | ||
300 | struct dentry *real; | ||
301 | |||
302 | if (d_is_dir(dentry)) { | ||
303 | if (!inode || inode == d_inode(dentry)) | ||
304 | return dentry; | ||
305 | goto bug; | ||
306 | } | ||
307 | |||
308 | real = ovl_dentry_upper(dentry); | ||
309 | if (real && (!inode || inode == d_inode(real))) | ||
310 | return real; | ||
311 | |||
312 | real = ovl_dentry_lower(dentry); | ||
313 | if (!real) | ||
314 | goto bug; | ||
315 | |||
316 | if (!inode || inode == d_inode(real)) | ||
317 | return real; | ||
318 | |||
319 | /* Handle recursion */ | ||
320 | if (real->d_flags & DCACHE_OP_REAL) | ||
321 | return real->d_op->d_real(real, inode); | ||
322 | |||
323 | bug: | ||
324 | WARN(1, "ovl_d_real(%pd4, %s:%lu\n): real dentry not found\n", dentry, | ||
325 | inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0); | ||
326 | return dentry; | ||
327 | } | ||
328 | |||
298 | static int ovl_dentry_revalidate(struct dentry *dentry, unsigned int flags) | 329 | static int ovl_dentry_revalidate(struct dentry *dentry, unsigned int flags) |
299 | { | 330 | { |
300 | struct ovl_entry *oe = dentry->d_fsdata; | 331 | struct ovl_entry *oe = dentry->d_fsdata; |
@@ -339,11 +370,13 @@ static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags) | |||
339 | static const struct dentry_operations ovl_dentry_operations = { | 370 | static const struct dentry_operations ovl_dentry_operations = { |
340 | .d_release = ovl_dentry_release, | 371 | .d_release = ovl_dentry_release, |
341 | .d_select_inode = ovl_d_select_inode, | 372 | .d_select_inode = ovl_d_select_inode, |
373 | .d_real = ovl_d_real, | ||
342 | }; | 374 | }; |
343 | 375 | ||
344 | static const struct dentry_operations ovl_reval_dentry_operations = { | 376 | static const struct dentry_operations ovl_reval_dentry_operations = { |
345 | .d_release = ovl_dentry_release, | 377 | .d_release = ovl_dentry_release, |
346 | .d_select_inode = ovl_d_select_inode, | 378 | .d_select_inode = ovl_d_select_inode, |
379 | .d_real = ovl_d_real, | ||
347 | .d_revalidate = ovl_dentry_revalidate, | 380 | .d_revalidate = ovl_dentry_revalidate, |
348 | .d_weak_revalidate = ovl_dentry_weak_revalidate, | 381 | .d_weak_revalidate = ovl_dentry_weak_revalidate, |
349 | }; | 382 | }; |