diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2016-07-27 05:36:03 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2016-07-27 05:36:03 -0400 |
commit | 1b91dbdd2938a0102fea2d8853073159f2b08deb (patch) | |
tree | 6c1c54e4b15a1efbcd15a4d68d6366c71abf9979 | |
parent | 523d939ef98fd712632d93a5a2b588e477a7565e (diff) | |
parent | 0cac643c102c0632dc2cc81e2490b0fec1cac0af (diff) |
Merge branch 'd_real' into overlayfs-next
-rw-r--r-- | Documentation/filesystems/Locking | 5 | ||||
-rw-r--r-- | Documentation/filesystems/vfs.txt | 40 | ||||
-rw-r--r-- | fs/dcache.c | 3 | ||||
-rw-r--r-- | fs/namei.c | 2 | ||||
-rw-r--r-- | fs/open.c | 8 | ||||
-rw-r--r-- | fs/overlayfs/inode.c | 31 | ||||
-rw-r--r-- | fs/overlayfs/overlayfs.h | 2 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 20 | ||||
-rw-r--r-- | include/linux/dcache.h | 40 | ||||
-rw-r--r-- | include/linux/fs.h | 7 |
10 files changed, 80 insertions, 78 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 75eea7ce3d7c..d4def7b78a62 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
@@ -20,6 +20,8 @@ prototypes: | |||
20 | char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen); | 20 | char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen); |
21 | struct vfsmount *(*d_automount)(struct path *path); | 21 | struct vfsmount *(*d_automount)(struct path *path); |
22 | int (*d_manage)(struct dentry *, bool); | 22 | int (*d_manage)(struct dentry *, bool); |
23 | struct dentry *(*d_real)(struct dentry *, const struct inode *, | ||
24 | unsigned int); | ||
23 | 25 | ||
24 | locking rules: | 26 | locking rules: |
25 | rename_lock ->d_lock may block rcu-walk | 27 | rename_lock ->d_lock may block rcu-walk |
@@ -34,6 +36,7 @@ d_iput: no no yes no | |||
34 | d_dname: no no no no | 36 | d_dname: no no no no |
35 | d_automount: no no yes no | 37 | d_automount: no no yes no |
36 | d_manage: no no yes (ref-walk) maybe | 38 | d_manage: no no yes (ref-walk) maybe |
39 | d_real no no yes no | ||
37 | 40 | ||
38 | --------------------------- inode_operations --------------------------- | 41 | --------------------------- inode_operations --------------------------- |
39 | prototypes: | 42 | prototypes: |
@@ -66,7 +69,6 @@ prototypes: | |||
66 | struct file *, unsigned open_flag, | 69 | struct file *, unsigned open_flag, |
67 | umode_t create_mode, int *opened); | 70 | umode_t create_mode, int *opened); |
68 | int (*tmpfile) (struct inode *, struct dentry *, umode_t); | 71 | int (*tmpfile) (struct inode *, struct dentry *, umode_t); |
69 | int (*dentry_open)(struct dentry *, struct file *, const struct cred *); | ||
70 | 72 | ||
71 | locking rules: | 73 | locking rules: |
72 | all may block | 74 | all may block |
@@ -95,7 +97,6 @@ fiemap: no | |||
95 | update_time: no | 97 | update_time: no |
96 | atomic_open: yes | 98 | atomic_open: yes |
97 | tmpfile: no | 99 | tmpfile: no |
98 | dentry_open: no | ||
99 | 100 | ||
100 | Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on | 101 | Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on |
101 | victim. | 102 | victim. |
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index c61a223ef3ff..01c4f1741c20 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
@@ -364,7 +364,6 @@ struct inode_operations { | |||
364 | int (*atomic_open)(struct inode *, struct dentry *, struct file *, | 364 | int (*atomic_open)(struct inode *, struct dentry *, struct file *, |
365 | unsigned open_flag, umode_t create_mode, int *opened); | 365 | unsigned open_flag, umode_t create_mode, int *opened); |
366 | int (*tmpfile) (struct inode *, struct dentry *, umode_t); | 366 | int (*tmpfile) (struct inode *, struct dentry *, umode_t); |
367 | int (*dentry_open)(struct dentry *, struct file *, const struct cred *); | ||
368 | }; | 367 | }; |
369 | 368 | ||
370 | Again, all methods are called without any locks being held, unless | 369 | Again, all methods are called without any locks being held, unless |
@@ -696,13 +695,6 @@ struct address_space_operations { | |||
696 | but instead uses bmap to find out where the blocks in the file | 695 | but instead uses bmap to find out where the blocks in the file |
697 | are and uses those addresses directly. | 696 | are and uses those addresses directly. |
698 | 697 | ||
699 | dentry_open: *WARNING: probably going away soon, do not use!* This is an | ||
700 | alternative to f_op->open(), the difference is that this method may open | ||
701 | a file not necessarily originating from the same filesystem as the one | ||
702 | i_op->open() was called on. It may be useful for stacking filesystems | ||
703 | which want to allow native I/O directly on underlying files. | ||
704 | |||
705 | |||
706 | invalidatepage: If a page has PagePrivate set, then invalidatepage | 698 | invalidatepage: If a page has PagePrivate set, then invalidatepage |
707 | will be called when part or all of the page is to be removed | 699 | will be called when part or all of the page is to be removed |
708 | from the address space. This generally corresponds to either a | 700 | from the address space. This generally corresponds to either a |
@@ -938,6 +930,8 @@ struct dentry_operations { | |||
938 | char *(*d_dname)(struct dentry *, char *, int); | 930 | char *(*d_dname)(struct dentry *, char *, int); |
939 | struct vfsmount *(*d_automount)(struct path *); | 931 | struct vfsmount *(*d_automount)(struct path *); |
940 | int (*d_manage)(struct dentry *, bool); | 932 | int (*d_manage)(struct dentry *, bool); |
933 | struct dentry *(*d_real)(struct dentry *, const struct inode *, | ||
934 | unsigned int); | ||
941 | }; | 935 | }; |
942 | 936 | ||
943 | d_revalidate: called when the VFS needs to revalidate a dentry. This | 937 | d_revalidate: called when the VFS needs to revalidate a dentry. This |
@@ -1022,6 +1016,14 @@ struct dentry_operations { | |||
1022 | at the end of the buffer, and returns a pointer to the first char. | 1016 | at the end of the buffer, and returns a pointer to the first char. |
1023 | dynamic_dname() helper function is provided to take care of this. | 1017 | dynamic_dname() helper function is provided to take care of this. |
1024 | 1018 | ||
1019 | Example : | ||
1020 | |||
1021 | static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen) | ||
1022 | { | ||
1023 | return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]", | ||
1024 | dentry->d_inode->i_ino); | ||
1025 | } | ||
1026 | |||
1025 | d_automount: called when an automount dentry is to be traversed (optional). | 1027 | d_automount: called when an automount dentry is to be traversed (optional). |
1026 | This should create a new VFS mount record and return the record to the | 1028 | This should create a new VFS mount record and return the record to the |
1027 | caller. The caller is supplied with a path parameter giving the | 1029 | caller. The caller is supplied with a path parameter giving the |
@@ -1060,13 +1062,23 @@ struct dentry_operations { | |||
1060 | This function is only used if DCACHE_MANAGE_TRANSIT is set on the | 1062 | This function is only used if DCACHE_MANAGE_TRANSIT is set on the |
1061 | dentry being transited from. | 1063 | dentry being transited from. |
1062 | 1064 | ||
1063 | Example : | 1065 | d_real: overlay/union type filesystems implement this method to return one of |
1066 | the underlying dentries hidden by the overlay. It is used in three | ||
1067 | different modes: | ||
1064 | 1068 | ||
1065 | static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen) | 1069 | Called from open it may need to copy-up the file depending on the |
1066 | { | 1070 | supplied open flags. This mode is selected with a non-zero flags |
1067 | return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]", | 1071 | argument. In this mode the d_real method can return an error. |
1068 | dentry->d_inode->i_ino); | 1072 | |
1069 | } | 1073 | Called from file_dentry() it returns the real dentry matching the inode |
1074 | argument. The real dentry may be from a lower layer already copied up, | ||
1075 | but still referenced from the file. This mode is selected with a | ||
1076 | non-NULL inode argument. This will always succeed. | ||
1077 | |||
1078 | With NULL inode and zero flags the topmost real underlying dentry is | ||
1079 | returned. This will always succeed. | ||
1080 | |||
1081 | This method is never called with both non-NULL inode and non-zero flags. | ||
1070 | 1082 | ||
1071 | Each dentry has a pointer to its parent dentry, as well as a hash list | 1083 | Each dentry has a pointer to its parent dentry, as well as a hash list |
1072 | of child dentries. Child dentries are basically like files in a | 1084 | of child dentries. Child dentries are basically like files in a |
diff --git a/fs/dcache.c b/fs/dcache.c index d6847d7b123d..5405b89fe8ec 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -1729,7 +1729,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op) | |||
1729 | DCACHE_OP_REVALIDATE | | 1729 | DCACHE_OP_REVALIDATE | |
1730 | DCACHE_OP_WEAK_REVALIDATE | | 1730 | DCACHE_OP_WEAK_REVALIDATE | |
1731 | DCACHE_OP_DELETE | | 1731 | DCACHE_OP_DELETE | |
1732 | DCACHE_OP_SELECT_INODE | | ||
1733 | DCACHE_OP_REAL)); | 1732 | DCACHE_OP_REAL)); |
1734 | dentry->d_op = op; | 1733 | dentry->d_op = op; |
1735 | if (!op) | 1734 | if (!op) |
@@ -1746,8 +1745,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op) | |||
1746 | dentry->d_flags |= DCACHE_OP_DELETE; | 1745 | dentry->d_flags |= DCACHE_OP_DELETE; |
1747 | if (op->d_prune) | 1746 | if (op->d_prune) |
1748 | dentry->d_flags |= DCACHE_OP_PRUNE; | 1747 | dentry->d_flags |= DCACHE_OP_PRUNE; |
1749 | if (op->d_select_inode) | ||
1750 | dentry->d_flags |= DCACHE_OP_SELECT_INODE; | ||
1751 | if (op->d_real) | 1748 | if (op->d_real) |
1752 | dentry->d_flags |= DCACHE_OP_REAL; | 1749 | dentry->d_flags |= DCACHE_OP_REAL; |
1753 | 1750 | ||
diff --git a/fs/namei.c b/fs/namei.c index 70580ab1445c..bb7a2e0b959c 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -4328,7 +4328,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
4328 | * Check source == target. | 4328 | * Check source == target. |
4329 | * On overlayfs need to look at underlying inodes. | 4329 | * On overlayfs need to look at underlying inodes. |
4330 | */ | 4330 | */ |
4331 | if (vfs_select_inode(old_dentry, 0) == vfs_select_inode(new_dentry, 0)) | 4331 | if (d_real_inode(old_dentry) == d_real_inode(new_dentry)) |
4332 | return 0; | 4332 | return 0; |
4333 | 4333 | ||
4334 | error = may_delete(old_dir, old_dentry, is_dir); | 4334 | error = may_delete(old_dir, old_dentry, is_dir); |
@@ -840,13 +840,13 @@ EXPORT_SYMBOL(file_path); | |||
840 | int vfs_open(const struct path *path, struct file *file, | 840 | int vfs_open(const struct path *path, struct file *file, |
841 | const struct cred *cred) | 841 | const struct cred *cred) |
842 | { | 842 | { |
843 | struct inode *inode = vfs_select_inode(path->dentry, file->f_flags); | 843 | struct dentry *dentry = d_real(path->dentry, NULL, file->f_flags); |
844 | 844 | ||
845 | if (IS_ERR(inode)) | 845 | if (IS_ERR(dentry)) |
846 | return PTR_ERR(inode); | 846 | return PTR_ERR(dentry); |
847 | 847 | ||
848 | file->f_path = *path; | 848 | file->f_path = *path; |
849 | return do_dentry_open(file, inode, NULL, cred); | 849 | return do_dentry_open(file, d_backing_inode(dentry), NULL, cred); |
850 | } | 850 | } |
851 | 851 | ||
852 | struct file *dentry_open(const struct path *path, int flags, | 852 | struct file *dentry_open(const struct path *path, int flags, |
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index d1cdc60dd68f..d554e86abbe3 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -351,36 +351,25 @@ static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type, | |||
351 | return true; | 351 | return true; |
352 | } | 352 | } |
353 | 353 | ||
354 | struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags) | 354 | int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags) |
355 | { | 355 | { |
356 | int err; | 356 | int err = 0; |
357 | struct path realpath; | 357 | struct path realpath; |
358 | enum ovl_path_type type; | 358 | enum ovl_path_type type; |
359 | 359 | ||
360 | if (d_is_dir(dentry)) | ||
361 | return d_backing_inode(dentry); | ||
362 | |||
363 | type = ovl_path_real(dentry, &realpath); | 360 | type = ovl_path_real(dentry, &realpath); |
364 | if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { | 361 | if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { |
365 | err = ovl_want_write(dentry); | 362 | err = ovl_want_write(dentry); |
366 | if (err) | 363 | if (!err) { |
367 | return ERR_PTR(err); | 364 | if (file_flags & O_TRUNC) |
368 | 365 | err = ovl_copy_up_truncate(dentry); | |
369 | if (file_flags & O_TRUNC) | 366 | else |
370 | err = ovl_copy_up_truncate(dentry); | 367 | err = ovl_copy_up(dentry); |
371 | else | 368 | ovl_drop_write(dentry); |
372 | err = ovl_copy_up(dentry); | 369 | } |
373 | ovl_drop_write(dentry); | ||
374 | if (err) | ||
375 | return ERR_PTR(err); | ||
376 | |||
377 | ovl_path_upper(dentry, &realpath); | ||
378 | } | 370 | } |
379 | 371 | ||
380 | if (realpath.dentry->d_flags & DCACHE_OP_SELECT_INODE) | 372 | return err; |
381 | return realpath.dentry->d_op->d_select_inode(realpath.dentry, file_flags); | ||
382 | |||
383 | return d_backing_inode(realpath.dentry); | ||
384 | } | 373 | } |
385 | 374 | ||
386 | static const struct inode_operations ovl_file_inode_operations = { | 375 | static const struct inode_operations ovl_file_inode_operations = { |
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index cfbca53590d0..0d3f2ad45708 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h | |||
@@ -179,7 +179,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, | |||
179 | const char *name, void *value, size_t size); | 179 | const char *name, void *value, size_t size); |
180 | ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); | 180 | ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); |
181 | int ovl_removexattr(struct dentry *dentry, const char *name); | 181 | int ovl_removexattr(struct dentry *dentry, const char *name); |
182 | struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags); | 182 | int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags); |
183 | 183 | ||
184 | struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, | 184 | struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, |
185 | struct ovl_entry *oe); | 185 | struct ovl_entry *oe); |
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 9a7693d5f8ff..5e254b3a8c56 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -304,7 +304,9 @@ static void ovl_dentry_release(struct dentry *dentry) | |||
304 | } | 304 | } |
305 | } | 305 | } |
306 | 306 | ||
307 | static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode) | 307 | static struct dentry *ovl_d_real(struct dentry *dentry, |
308 | const struct inode *inode, | ||
309 | unsigned int open_flags) | ||
308 | { | 310 | { |
309 | struct dentry *real; | 311 | struct dentry *real; |
310 | 312 | ||
@@ -314,6 +316,16 @@ static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode) | |||
314 | goto bug; | 316 | goto bug; |
315 | } | 317 | } |
316 | 318 | ||
319 | if (d_is_negative(dentry)) | ||
320 | return dentry; | ||
321 | |||
322 | if (open_flags) { | ||
323 | int err = ovl_open_maybe_copy_up(dentry, open_flags); | ||
324 | |||
325 | if (err) | ||
326 | return ERR_PTR(err); | ||
327 | } | ||
328 | |||
317 | real = ovl_dentry_upper(dentry); | 329 | real = ovl_dentry_upper(dentry); |
318 | if (real && (!inode || inode == d_inode(real))) | 330 | if (real && (!inode || inode == d_inode(real))) |
319 | return real; | 331 | return real; |
@@ -326,9 +338,7 @@ static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode) | |||
326 | return real; | 338 | return real; |
327 | 339 | ||
328 | /* Handle recursion */ | 340 | /* Handle recursion */ |
329 | if (real->d_flags & DCACHE_OP_REAL) | 341 | return d_real(real, inode, open_flags); |
330 | return real->d_op->d_real(real, inode); | ||
331 | |||
332 | bug: | 342 | bug: |
333 | WARN(1, "ovl_d_real(%pd4, %s:%lu\n): real dentry not found\n", dentry, | 343 | WARN(1, "ovl_d_real(%pd4, %s:%lu\n): real dentry not found\n", dentry, |
334 | inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0); | 344 | inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0); |
@@ -378,13 +388,11 @@ static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags) | |||
378 | 388 | ||
379 | static const struct dentry_operations ovl_dentry_operations = { | 389 | static const struct dentry_operations ovl_dentry_operations = { |
380 | .d_release = ovl_dentry_release, | 390 | .d_release = ovl_dentry_release, |
381 | .d_select_inode = ovl_d_select_inode, | ||
382 | .d_real = ovl_d_real, | 391 | .d_real = ovl_d_real, |
383 | }; | 392 | }; |
384 | 393 | ||
385 | static const struct dentry_operations ovl_reval_dentry_operations = { | 394 | static const struct dentry_operations ovl_reval_dentry_operations = { |
386 | .d_release = ovl_dentry_release, | 395 | .d_release = ovl_dentry_release, |
387 | .d_select_inode = ovl_d_select_inode, | ||
388 | .d_real = ovl_d_real, | 396 | .d_real = ovl_d_real, |
389 | .d_revalidate = ovl_dentry_revalidate, | 397 | .d_revalidate = ovl_dentry_revalidate, |
390 | .d_weak_revalidate = ovl_dentry_weak_revalidate, | 398 | .d_weak_revalidate = ovl_dentry_weak_revalidate, |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index f53fa055021a..14df83609c7f 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -139,8 +139,8 @@ struct dentry_operations { | |||
139 | char *(*d_dname)(struct dentry *, char *, int); | 139 | char *(*d_dname)(struct dentry *, char *, int); |
140 | struct vfsmount *(*d_automount)(struct path *); | 140 | struct vfsmount *(*d_automount)(struct path *); |
141 | int (*d_manage)(struct dentry *, bool); | 141 | int (*d_manage)(struct dentry *, bool); |
142 | struct inode *(*d_select_inode)(struct dentry *, unsigned); | 142 | struct dentry *(*d_real)(struct dentry *, const struct inode *, |
143 | struct dentry *(*d_real)(struct dentry *, struct inode *); | 143 | unsigned int); |
144 | } ____cacheline_aligned; | 144 | } ____cacheline_aligned; |
145 | 145 | ||
146 | /* | 146 | /* |
@@ -206,10 +206,8 @@ struct dentry_operations { | |||
206 | 206 | ||
207 | #define DCACHE_MAY_FREE 0x00800000 | 207 | #define DCACHE_MAY_FREE 0x00800000 |
208 | #define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */ | 208 | #define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */ |
209 | #define DCACHE_OP_SELECT_INODE 0x02000000 /* Unioned entry: dcache op selects inode */ | 209 | #define DCACHE_ENCRYPTED_WITH_KEY 0x02000000 /* dir is encrypted with a valid key */ |
210 | 210 | #define DCACHE_OP_REAL 0x04000000 | |
211 | #define DCACHE_ENCRYPTED_WITH_KEY 0x04000000 /* dir is encrypted with a valid key */ | ||
212 | #define DCACHE_OP_REAL 0x08000000 | ||
213 | 211 | ||
214 | #define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */ | 212 | #define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */ |
215 | #define DCACHE_DENTRY_CURSOR 0x20000000 | 213 | #define DCACHE_DENTRY_CURSOR 0x20000000 |
@@ -557,25 +555,27 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper) | |||
557 | return upper; | 555 | return upper; |
558 | } | 556 | } |
559 | 557 | ||
560 | static inline struct dentry *d_real(struct dentry *dentry) | 558 | /** |
559 | * d_real - Return the real dentry | ||
560 | * @dentry: the dentry to query | ||
561 | * @inode: inode to select the dentry from multiple layers (can be NULL) | ||
562 | * @flags: open flags to control copy-up behavior | ||
563 | * | ||
564 | * If dentry is on an union/overlay, then return the underlying, real dentry. | ||
565 | * Otherwise return the dentry itself. | ||
566 | * | ||
567 | * See also: Documentation/filesystems/vfs.txt | ||
568 | */ | ||
569 | static inline struct dentry *d_real(struct dentry *dentry, | ||
570 | const struct inode *inode, | ||
571 | unsigned int flags) | ||
561 | { | 572 | { |
562 | if (unlikely(dentry->d_flags & DCACHE_OP_REAL)) | 573 | if (unlikely(dentry->d_flags & DCACHE_OP_REAL)) |
563 | return dentry->d_op->d_real(dentry, NULL); | 574 | return dentry->d_op->d_real(dentry, inode, flags); |
564 | else | 575 | else |
565 | return dentry; | 576 | return dentry; |
566 | } | 577 | } |
567 | 578 | ||
568 | static inline struct inode *vfs_select_inode(struct dentry *dentry, | ||
569 | unsigned open_flags) | ||
570 | { | ||
571 | struct inode *inode = d_inode(dentry); | ||
572 | |||
573 | if (inode && unlikely(dentry->d_flags & DCACHE_OP_SELECT_INODE)) | ||
574 | inode = dentry->d_op->d_select_inode(dentry, open_flags); | ||
575 | |||
576 | return inode; | ||
577 | } | ||
578 | |||
579 | /** | 579 | /** |
580 | * d_real_inode - Return the real inode | 580 | * d_real_inode - Return the real inode |
581 | * @dentry: The dentry to query | 581 | * @dentry: The dentry to query |
@@ -585,7 +585,7 @@ static inline struct inode *vfs_select_inode(struct dentry *dentry, | |||
585 | */ | 585 | */ |
586 | static inline struct inode *d_real_inode(struct dentry *dentry) | 586 | static inline struct inode *d_real_inode(struct dentry *dentry) |
587 | { | 587 | { |
588 | return d_backing_inode(d_real(dentry)); | 588 | return d_backing_inode(d_real(dentry, NULL, 0)); |
589 | } | 589 | } |
590 | 590 | ||
591 | 591 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index dd288148a6b1..bacc0733663c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1272,12 +1272,7 @@ static inline struct inode *file_inode(const struct file *f) | |||
1272 | 1272 | ||
1273 | static inline struct dentry *file_dentry(const struct file *file) | 1273 | static inline struct dentry *file_dentry(const struct file *file) |
1274 | { | 1274 | { |
1275 | struct dentry *dentry = file->f_path.dentry; | 1275 | return d_real(file->f_path.dentry, file_inode(file), 0); |
1276 | |||
1277 | if (unlikely(dentry->d_flags & DCACHE_OP_REAL)) | ||
1278 | return dentry->d_op->d_real(dentry, file_inode(file)); | ||
1279 | else | ||
1280 | return dentry; | ||
1281 | } | 1276 | } |
1282 | 1277 | ||
1283 | static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl) | 1278 | static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl) |