X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=include%2Flinux%2Fdcache.h;h=63f64a9a5bf7b207b674be433d1c3b218ff39813;hb=refs%2Fheads%2Fvserver;hp=74f22a171e19c4cdcf774e385f0654b3a15e08e7;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 74f22a171..63f64a9a5 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -8,7 +8,6 @@ #include #include #include -#include struct nameidata; struct vfsmount; @@ -27,12 +26,14 @@ struct vfsmount; /* * "quick string" -- eases parameter passing, but more importantly * saves "metadata" about the string (ie length and the hash). + * + * hash comes first so it snuggles against d_parent in the + * dentry. */ struct qstr { - const unsigned char * name; - unsigned int len; unsigned int hash; - char name_str[0]; + unsigned int len; + const unsigned char *name; }; struct dentry_stat_t { @@ -74,38 +75,57 @@ full_name_hash(const unsigned char *name, unsigned int len) return end_name_hash(hash); } -#define DNAME_INLINE_LEN_MIN 24 - struct dcookie_struct; - + +#define DNAME_INLINE_LEN_MIN 36 + struct dentry { atomic_t d_count; + unsigned int d_flags; /* protected by d_lock */ spinlock_t d_lock; /* per dentry lock */ - unsigned long d_vfs_flags; /* moved here to be on same cacheline */ - struct inode * d_inode; /* Where the name belongs to - NULL is negative */ + struct inode *d_inode; /* Where the name belongs to - NULL is + * negative */ + /* + * The next three fields are touched by __d_lookup. Place them here + * so they all fit in a cache line. + */ + struct hlist_node d_hash; /* lookup hash list */ + struct dentry *d_parent; /* parent directory */ + struct qstr d_name; + struct list_head d_lru; /* LRU list */ - struct list_head d_child; /* child of parent list */ + /* + * d_child and d_rcu can share memory + */ + union { + struct list_head d_child; /* child of parent list */ + struct rcu_head d_rcu; + } d_u; struct list_head d_subdirs; /* our children */ struct list_head d_alias; /* inode alias list */ unsigned long d_time; /* used by d_revalidate */ - struct dentry_operations *d_op; - struct super_block * d_sb; /* The root of the dentry tree */ - unsigned int d_flags; + struct dentry_operations *d_op; + struct super_block *d_sb; /* The root of the dentry tree */ + void *d_fsdata; /* fs-specific data */ +#ifdef CONFIG_PROFILING + struct dcookie_struct *d_cookie; /* cookie, if any */ +#endif int d_mounted; - void * d_fsdata; /* fs-specific data */ - struct rcu_head d_rcu; - struct dcookie_struct * d_cookie; /* cookie, if any */ - unsigned long d_move_count; /* to indicated moved dentry while lockless lookup */ - struct qstr * d_qstr; /* quick str ptr used in lockless lookup and concurrent d_move */ - struct dentry * d_parent; /* parent directory */ - struct qstr d_name; - struct hlist_node d_hash; /* lookup hash list */ - struct hlist_head * d_bucket; /* lookup hash bucket */ - unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */ + unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */ +}; + +/* + * dentry->d_lock spinlock nesting subclasses: + * + * 0: normal + * 1: nested + */ +enum dentry_d_lock_class +{ + DENTRY_D_LOCK_NORMAL, /* implicitly used by plain spin_lock() APIs. */ + DENTRY_D_LOCK_NESTED }; -#define DNAME_INLINE_LEN (sizeof(struct dentry)-offsetof(struct dentry,d_iname)) - struct dentry_operations { int (*d_revalidate)(struct dentry *, struct nameidata *); int (*d_hash) (struct dentry *, struct qstr *); @@ -124,13 +144,13 @@ struct dentry_operations { /* locking rules: - big lock dcache_lock may block -d_revalidate: no no yes -d_hash no no yes -d_compare: no yes no -d_delete: no yes no -d_release: no no yes -d_iput: no no yes + big lock dcache_lock d_lock may block +d_revalidate: no no no yes +d_hash no no no yes +d_compare: no yes yes no +d_delete: no yes no no +d_release: no no no yes +d_iput: no no no yes */ /* d_flags entries */ @@ -154,29 +174,30 @@ d_iput: no no yes #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ #define DCACHE_UNHASHED 0x0010 +#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched */ + extern spinlock_t dcache_lock; /** * d_drop - drop a dentry * @dentry: dentry to drop * - * d_drop() unhashes the entry from the parent - * dentry hashes, so that it won't be found through - * a VFS lookup any more. Note that this is different - * from deleting the dentry - d_delete will try to - * mark the dentry negative if possible, giving a - * successful _negative_ lookup, while d_drop will + * d_drop() unhashes the entry from the parent dentry hashes, so that it won't + * be found through a VFS lookup any more. Note that this is different from + * deleting the dentry - d_delete will try to mark the dentry negative if + * possible, giving a successful _negative_ lookup, while d_drop will * just make the cache lookup fail. * - * d_drop() is used mainly for stuff that wants - * to invalidate a dentry for some reason (NFS - * timeouts or autofs deletes). + * d_drop() is used mainly for stuff that wants to invalidate a dentry for some + * reason (NFS timeouts or autofs deletes). + * + * __d_drop requires dentry->d_lock. */ static inline void __d_drop(struct dentry *dentry) { - if (!(dentry->d_vfs_flags & DCACHE_UNHASHED)) { - dentry->d_vfs_flags |= DCACHE_UNHASHED; + if (!(dentry->d_flags & DCACHE_UNHASHED)) { + dentry->d_flags |= DCACHE_UNHASHED; hlist_del_rcu(&dentry->d_hash); } } @@ -184,19 +205,23 @@ static inline void __d_drop(struct dentry *dentry) static inline void d_drop(struct dentry *dentry) { spin_lock(&dcache_lock); + spin_lock(&dentry->d_lock); __d_drop(dentry); + spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); } -static inline int dname_external(struct dentry *d) +static inline int dname_external(struct dentry *dentry) { - return d->d_name.name != d->d_iname; + return dentry->d_name.name != dentry->d_iname; } /* * These are the low-level FS interfaces to the dcache.. */ extern void d_instantiate(struct dentry *, struct inode *); +extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *); +extern struct dentry * d_materialise_unique(struct dentry *, struct inode *); extern void d_delete(struct dentry *); /* allocate/de-allocate */ @@ -205,7 +230,7 @@ extern struct dentry * d_alloc_anon(struct inode *); extern struct dentry * d_splice_alias(struct inode *, struct dentry *); extern void shrink_dcache_sb(struct super_block *); extern void shrink_dcache_parent(struct dentry *); -extern void shrink_dcache_anon(struct hlist_head *); +extern void shrink_dcache_for_umount(struct super_block *); extern int d_invalidate(struct dentry *); /* only used at mount-time */ @@ -240,12 +265,30 @@ static inline void d_add(struct dentry *entry, struct inode *inode) d_rehash(entry); } +/** + * d_add_unique - add dentry to hash queues without aliasing + * @entry: dentry to add + * @inode: The inode to attach to this dentry + * + * This adds the entry to the hash queues and initializes @inode. + * The entry was actually filled in earlier during d_alloc(). + */ +static inline struct dentry *d_add_unique(struct dentry *entry, struct inode *inode) +{ + struct dentry *res; + + res = d_instantiate_unique(entry, inode); + d_rehash(res != NULL ? res : entry); + return res; +} + /* used for rename() and baskets */ extern void d_move(struct dentry *, struct dentry *); /* appendix may either be NULL or be used for transname suffixes */ extern struct dentry * d_lookup(struct dentry *, struct qstr *); extern struct dentry * __d_lookup(struct dentry *, struct qstr *); +extern struct dentry * d_hash_and_lookup(struct dentry *, struct qstr *); /* validate "insecure" dentry pointer */ extern int d_validate(struct dentry *, struct dentry *); @@ -287,7 +330,7 @@ extern struct dentry * dget_locked(struct dentry *); static inline int d_unhashed(struct dentry *dentry) { - return (dentry->d_vfs_flags & DCACHE_UNHASHED); + return (dentry->d_flags & DCACHE_UNHASHED); } static inline struct dentry *dget_parent(struct dentry *dentry) @@ -308,8 +351,11 @@ static inline int d_mountpoint(struct dentry *dentry) } extern struct vfsmount *lookup_mnt(struct vfsmount *, struct dentry *); +extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int); extern struct dentry *lookup_create(struct nameidata *nd, int is_dir); +extern int sysctl_vfs_cache_pressure; + #endif /* __KERNEL__ */ #endif /* __LINUX_DCACHE_H */