From 155e35d4daa804582f75acaa2c74ec797a89c615 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 29 Jan 2015 12:02:27 +0000 Subject: VFS: Introduce inode-getting helpers for layered/unioned fs environments Introduce some function for getting the inode (and also the dentry) in an environment where layered/unioned filesystems are in operation. The problem is that we have places where we need *both* the union dentry and the lower source or workspace inode or dentry available, but we can only have a handle on one of them. Therefore we need to derive the handle to the other from that. The idea is to introduce an extra field in struct dentry that allows the union dentry to refer to and pin the lower dentry. Signed-off-by: David Howells Signed-off-by: Al Viro --- include/linux/dcache.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'include/linux') diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 92c08cf7670e..047c0db5763f 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -464,4 +464,61 @@ static inline unsigned long vfs_pressure_ratio(unsigned long val) { return mult_frac(val, sysctl_vfs_cache_pressure, 100); } + +/** + * d_inode - Get the actual inode of this dentry + * @dentry: The dentry to query + * + * This is the helper normal filesystems should use to get at their own inodes + * in their own dentries and ignore the layering superimposed upon them. + */ +static inline struct inode *d_inode(const struct dentry *dentry) +{ + return dentry->d_inode; +} + +/** + * d_inode_rcu - Get the actual inode of this dentry with ACCESS_ONCE() + * @dentry: The dentry to query + * + * This is the helper normal filesystems should use to get at their own inodes + * in their own dentries and ignore the layering superimposed upon them. + */ +static inline struct inode *d_inode_rcu(const struct dentry *dentry) +{ + return ACCESS_ONCE(dentry->d_inode); +} + +/** + * d_backing_inode - Get upper or lower inode we should be using + * @upper: The upper layer + * + * This is the helper that should be used to get at the inode that will be used + * if this dentry were to be opened as a file. The inode may be on the upper + * dentry or it may be on a lower dentry pinned by the upper. + * + * Normal filesystems should not use this to access their own inodes. + */ +static inline struct inode *d_backing_inode(const struct dentry *upper) +{ + struct inode *inode = upper->d_inode; + + return inode; +} + +/** + * d_backing_dentry - Get upper or lower dentry we should be using + * @upper: The upper layer + * + * This is the helper that should be used to get the dentry of the inode that + * will be used if this dentry were opened as a file. It may be the upper + * dentry or it may be a lower dentry pinned by the upper. + * + * Normal filesystems should not use this to access their own dentries. + */ +static inline struct dentry *d_backing_dentry(struct dentry *upper) +{ + return upper; +} + #endif /* __LINUX_DCACHE_H */ -- cgit v1.2.3 From e7f7d2253c05143ed76ddc5e11f4cf0a9b814a27 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 29 Jan 2015 12:02:27 +0000 Subject: VFS: Add a whiteout dentry type Add DCACHE_WHITEOUT_TYPE and provide a d_is_whiteout() accessor function. A d_is_miss() accessor is also added for ordinary cache misses and d_is_negative() is modified to indicate either an ordinary miss or an enforced miss (whiteout). Signed-off-by: David Howells Signed-off-by: Al Viro --- include/linux/dcache.h | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 047c0db5763f..98d2a948a08e 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -215,11 +215,12 @@ struct dentry_operations { #define DCACHE_LRU_LIST 0x00080000 #define DCACHE_ENTRY_TYPE 0x00700000 -#define DCACHE_MISS_TYPE 0x00000000 /* Negative dentry */ -#define DCACHE_DIRECTORY_TYPE 0x00100000 /* Normal directory */ -#define DCACHE_AUTODIR_TYPE 0x00200000 /* Lookupless directory (presumed automount) */ -#define DCACHE_SYMLINK_TYPE 0x00300000 /* Symlink */ -#define DCACHE_FILE_TYPE 0x00400000 /* Other file type */ +#define DCACHE_MISS_TYPE 0x00000000 /* Negative dentry (maybe fallthru to nowhere) */ +#define DCACHE_WHITEOUT_TYPE 0x00100000 /* Whiteout dentry (stop pathwalk) */ +#define DCACHE_DIRECTORY_TYPE 0x00200000 /* Normal directory */ +#define DCACHE_AUTODIR_TYPE 0x00300000 /* Lookupless directory (presumed automount) */ +#define DCACHE_SYMLINK_TYPE 0x00400000 /* Symlink (or fallthru to such) */ +#define DCACHE_FILE_TYPE 0x00500000 /* Other file type (or fallthru to such) */ #define DCACHE_MAY_FREE 0x00800000 @@ -423,6 +424,16 @@ static inline unsigned __d_entry_type(const struct dentry *dentry) return dentry->d_flags & DCACHE_ENTRY_TYPE; } +static inline bool d_is_miss(const struct dentry *dentry) +{ + return __d_entry_type(dentry) == DCACHE_MISS_TYPE; +} + +static inline bool d_is_whiteout(const struct dentry *dentry) +{ + return __d_entry_type(dentry) == DCACHE_WHITEOUT_TYPE; +} + static inline bool d_can_lookup(const struct dentry *dentry) { return __d_entry_type(dentry) == DCACHE_DIRECTORY_TYPE; @@ -450,7 +461,8 @@ static inline bool d_is_file(const struct dentry *dentry) static inline bool d_is_negative(const struct dentry *dentry) { - return __d_entry_type(dentry) == DCACHE_MISS_TYPE; + // TODO: check d_is_whiteout(dentry) also. + return d_is_miss(dentry); } static inline bool d_is_positive(const struct dentry *dentry) -- cgit v1.2.3 From df1a085af1f652a02238168c4f2b730c8c90dd4a Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 29 Jan 2015 12:02:28 +0000 Subject: VFS: Add a fallthrough flag for marking virtual dentries Add a DCACHE_FALLTHRU flag to indicate that, in a layered filesystem, this is a virtual dentry that covers another one in a lower layer that should be used instead. This may be recorded on medium if directory integration is stored there. The flag can be set with d_set_fallthru() and tested with d_is_fallthru(). Original-author: Valerie Aurora Signed-off-by: David Howells Signed-off-by: Al Viro --- include/linux/dcache.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include/linux') diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 98d2a948a08e..728f5d31b5e6 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -223,6 +223,7 @@ struct dentry_operations { #define DCACHE_FILE_TYPE 0x00500000 /* Other file type (or fallthru to such) */ #define DCACHE_MAY_FREE 0x00800000 +#define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */ extern seqlock_t rename_lock; @@ -470,6 +471,14 @@ static inline bool d_is_positive(const struct dentry *dentry) return !d_is_negative(dentry); } +extern void d_set_fallthru(struct dentry *dentry); + +static inline bool d_is_fallthru(const struct dentry *dentry) +{ + return dentry->d_flags & DCACHE_FALLTHRU; +} + + extern int sysctl_vfs_cache_pressure; static inline unsigned long vfs_pressure_ratio(unsigned long val) -- cgit v1.2.3 From 44bdb5e5f6382ba88f7678d6f535f879324522ae Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 29 Jan 2015 12:02:29 +0000 Subject: VFS: Split DCACHE_FILE_TYPE into regular and special types Split DCACHE_FILE_TYPE into DCACHE_REGULAR_TYPE (dentries representing regular files) and DCACHE_SPECIAL_TYPE (representing blockdev, chardev, FIFO and socket files). d_is_reg() and d_is_special() are added to detect these subtypes and d_is_file() is left as the union of the two. This allows a number of places that use S_ISREG(dentry->d_inode->i_mode) to use d_is_reg(dentry) instead. Signed-off-by: David Howells Signed-off-by: Al Viro --- include/linux/dcache.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 728f5d31b5e6..d8358799c594 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -219,8 +219,9 @@ struct dentry_operations { #define DCACHE_WHITEOUT_TYPE 0x00100000 /* Whiteout dentry (stop pathwalk) */ #define DCACHE_DIRECTORY_TYPE 0x00200000 /* Normal directory */ #define DCACHE_AUTODIR_TYPE 0x00300000 /* Lookupless directory (presumed automount) */ -#define DCACHE_SYMLINK_TYPE 0x00400000 /* Symlink (or fallthru to such) */ -#define DCACHE_FILE_TYPE 0x00500000 /* Other file type (or fallthru to such) */ +#define DCACHE_REGULAR_TYPE 0x00400000 /* Regular file type (or fallthru to such) */ +#define DCACHE_SPECIAL_TYPE 0x00500000 /* Other file type (or fallthru to such) */ +#define DCACHE_SYMLINK_TYPE 0x00600000 /* Symlink (or fallthru to such) */ #define DCACHE_MAY_FREE 0x00800000 #define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */ @@ -455,9 +456,19 @@ static inline bool d_is_symlink(const struct dentry *dentry) return __d_entry_type(dentry) == DCACHE_SYMLINK_TYPE; } +static inline bool d_is_reg(const struct dentry *dentry) +{ + return __d_entry_type(dentry) == DCACHE_REGULAR_TYPE; +} + +static inline bool d_is_special(const struct dentry *dentry) +{ + return __d_entry_type(dentry) == DCACHE_SPECIAL_TYPE; +} + static inline bool d_is_file(const struct dentry *dentry) { - return __d_entry_type(dentry) == DCACHE_FILE_TYPE; + return d_is_reg(dentry) || d_is_special(dentry); } static inline bool d_is_negative(const struct dentry *dentry) -- cgit v1.2.3