mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
VFS: Put a small type field into struct dentry::d_flags
Put a type field into struct dentry::d_flags to indicate if the dentry is one of the following types that relate particularly to pathwalk: Miss (negative dentry) Directory "Automount" directory (defective - no i_op->lookup()) Symlink Other (regular, socket, fifo, device) The type field is set to one of the first five types on a dentry by calls to __d_instantiate() and d_obtain_alias() from information in the inode (if one is given). The type is cleared by dentry_unlink_inode() when it reconstitutes an existing dentry as a negative dentry. Accessors provided are: d_set_type(dentry, type) d_is_directory(dentry) d_is_autodir(dentry) d_is_symlink(dentry) d_is_file(dentry) d_is_negative(dentry) d_is_positive(dentry) A bunch of checks in pathname resolution switched to those. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
afabada957
commit
b18825a7c8
3 changed files with 158 additions and 82 deletions
42
fs/dcache.c
42
fs/dcache.c
|
@ -343,6 +343,7 @@ static void dentry_unlink_inode(struct dentry * dentry)
|
|||
__releases(dentry->d_inode->i_lock)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
__d_clear_type(dentry);
|
||||
dentry->d_inode = NULL;
|
||||
hlist_del_init(&dentry->d_alias);
|
||||
dentry_rcuwalk_barrier(dentry);
|
||||
|
@ -1648,14 +1649,42 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
|
|||
}
|
||||
EXPORT_SYMBOL(d_set_d_op);
|
||||
|
||||
static unsigned d_flags_for_inode(struct inode *inode)
|
||||
{
|
||||
unsigned add_flags = DCACHE_FILE_TYPE;
|
||||
|
||||
if (!inode)
|
||||
return DCACHE_MISS_TYPE;
|
||||
|
||||
if (S_ISDIR(inode->i_mode)) {
|
||||
add_flags = DCACHE_DIRECTORY_TYPE;
|
||||
if (unlikely(!(inode->i_opflags & IOP_LOOKUP))) {
|
||||
if (unlikely(!inode->i_op->lookup))
|
||||
add_flags = DCACHE_AUTODIR_TYPE;
|
||||
else
|
||||
inode->i_opflags |= IOP_LOOKUP;
|
||||
}
|
||||
} else if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) {
|
||||
if (unlikely(inode->i_op->follow_link))
|
||||
add_flags = DCACHE_SYMLINK_TYPE;
|
||||
else
|
||||
inode->i_opflags |= IOP_NOFOLLOW;
|
||||
}
|
||||
|
||||
if (unlikely(IS_AUTOMOUNT(inode)))
|
||||
add_flags |= DCACHE_NEED_AUTOMOUNT;
|
||||
return add_flags;
|
||||
}
|
||||
|
||||
static void __d_instantiate(struct dentry *dentry, struct inode *inode)
|
||||
{
|
||||
unsigned add_flags = d_flags_for_inode(inode);
|
||||
|
||||
spin_lock(&dentry->d_lock);
|
||||
if (inode) {
|
||||
if (unlikely(IS_AUTOMOUNT(inode)))
|
||||
dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
|
||||
dentry->d_flags &= ~DCACHE_ENTRY_TYPE;
|
||||
dentry->d_flags |= add_flags;
|
||||
if (inode)
|
||||
hlist_add_head(&dentry->d_alias, &inode->i_dentry);
|
||||
}
|
||||
dentry->d_inode = inode;
|
||||
dentry_rcuwalk_barrier(dentry);
|
||||
spin_unlock(&dentry->d_lock);
|
||||
|
@ -1860,6 +1889,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
|
|||
static const struct qstr anonstring = QSTR_INIT("/", 1);
|
||||
struct dentry *tmp;
|
||||
struct dentry *res;
|
||||
unsigned add_flags;
|
||||
|
||||
if (!inode)
|
||||
return ERR_PTR(-ESTALE);
|
||||
|
@ -1885,9 +1915,11 @@ struct dentry *d_obtain_alias(struct inode *inode)
|
|||
}
|
||||
|
||||
/* attach a disconnected dentry */
|
||||
add_flags = d_flags_for_inode(inode) | DCACHE_DISCONNECTED;
|
||||
|
||||
spin_lock(&tmp->d_lock);
|
||||
tmp->d_inode = inode;
|
||||
tmp->d_flags |= DCACHE_DISCONNECTED;
|
||||
tmp->d_flags |= add_flags;
|
||||
hlist_add_head(&tmp->d_alias, &inode->i_dentry);
|
||||
hlist_bl_lock(&tmp->d_sb->s_anon);
|
||||
hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue