Files
linux-apfs/include/linux/dcache.h
T

403 lines
12 KiB
C
Raw Normal View History

2005-04-16 15:20:36 -07:00
#ifndef __LINUX_DCACHE_H
#define __LINUX_DCACHE_H
2011-07-26 16:09:06 -07:00
#include <linux/atomic.h>
2005-04-16 15:20:36 -07:00
#include <linux/list.h>
#include <linux/rculist.h>
2011-01-07 17:50:05 +11:00
#include <linux/rculist_bl.h>
2005-04-16 15:20:36 -07:00
#include <linux/spinlock.h>
2011-01-07 17:49:52 +11:00
#include <linux/seqlock.h>
2005-04-16 15:20:36 -07:00
#include <linux/cache.h>
#include <linux/rcupdate.h>
#include <linux/lockref.h>
2005-04-16 15:20:36 -07:00
struct nameidata;
2008-02-14 19:38:44 -08:00
struct path;
2005-04-16 15:20:36 -07:00
struct vfsmount;
/*
* linux/include/linux/dcache.h
*
* Dirent cache data structures
*
* (C) Copyright 1997 Thomas Schoebel-Theuer,
* with heavy changes by Linus Torvalds
*/
#define IS_ROOT(x) ((x) == (x)->d_parent)
/* The hash is always the low bits of hash_len */
#ifdef __LITTLE_ENDIAN
#define HASH_LEN_DECLARE u32 hash; u32 len;
#else
#define HASH_LEN_DECLARE u32 len; u32 hash;
#endif
2005-04-16 15:20:36 -07:00
/*
* "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 {
union {
struct {
HASH_LEN_DECLARE;
};
u64 hash_len;
};
2005-04-16 15:20:36 -07:00
const unsigned char *name;
};
#define QSTR_INIT(n,l) { { { .len = l } }, .name = n }
#define hashlen_hash(hashlen) ((u32) (hashlen))
#define hashlen_len(hashlen) ((u32)((hashlen) >> 32))
2005-04-16 15:20:36 -07:00
struct dentry_stat_t {
2013-08-28 10:17:53 +10:00
long nr_dentry;
long nr_unused;
long age_limit; /* age in seconds */
long want_pages; /* pages requested by system */
long dummy[2];
2005-04-16 15:20:36 -07:00
};
extern struct dentry_stat_t dentry_stat;
/* Name hashing routines. Initial hash value */
/* Hash courtesy of the R5 hash in reiserfs modulo sign bits */
#define init_name_hash() 0
/* partial hash update function. Assume roughly 4 bits per character */
static inline unsigned long
partial_name_hash(unsigned long c, unsigned long prevhash)
{
return (prevhash + (c << 4) + (c >> 4)) * 11;
}
/*
* Finally: cut down the number of bits to a int value (and try to avoid
* losing bits)
*/
static inline unsigned long end_name_hash(unsigned long hash)
{
return (unsigned int) hash;
}
/* Compute the hash for a name string. */
2012-03-02 14:32:59 -08:00
extern unsigned int full_name_hash(const unsigned char *, unsigned int);
2005-04-16 15:20:36 -07:00
2008-12-01 09:33:43 +01:00
/*
* Try to keep struct dentry aligned on 64 byte cachelines (this will
* give reasonable cacheline footprint with larger lines without the
* large memory footprint increase).
*/
#ifdef CONFIG_64BIT
# define DNAME_INLINE_LEN 32 /* 192 bytes */
2008-12-01 09:33:43 +01:00
#else
# ifdef CONFIG_SMP
# define DNAME_INLINE_LEN 36 /* 128 bytes */
# else
# define DNAME_INLINE_LEN 40 /* 128 bytes */
# endif
2008-12-01 09:33:43 +01:00
#endif
2005-04-16 15:20:36 -07:00
#define d_lock d_lockref.lock
2005-04-16 15:20:36 -07:00
struct dentry {
/* RCU lookup touched fields */
2005-04-16 15:20:36 -07:00
unsigned int d_flags; /* protected by d_lock */
2011-01-07 17:49:52 +11:00
seqcount_t d_seq; /* per dentry seqlock */
2011-01-07 17:50:05 +11:00
struct hlist_bl_node d_hash; /* lookup hash list */
2005-04-16 15:20:36 -07:00
struct dentry *d_parent; /* parent directory */
struct qstr d_name;
struct inode *d_inode; /* Where the name belongs to - NULL is
* negative */
unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
/* Ref lookup also touches following */
struct lockref d_lockref; /* per-dentry lock and refcount */
const struct dentry_operations *d_op;
struct super_block *d_sb; /* The root of the dentry tree */
unsigned long d_time; /* used by d_revalidate */
void *d_fsdata; /* fs-specific data */
2005-04-16 15:20:36 -07:00
struct list_head d_lru; /* LRU list */
2006-01-08 01:03:32 -08:00
/*
* 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;
2005-04-16 15:20:36 -07:00
struct list_head d_subdirs; /* our children */
2012-06-09 13:51:19 -04:00
struct hlist_node d_alias; /* inode alias list */
2005-04-16 15:20:36 -07:00
};
2006-07-03 00:25:04 -07:00
/*
* 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
};
2005-04-16 15:20:36 -07:00
struct dentry_operations {
int (*d_revalidate)(struct dentry *, unsigned int);
int (*d_weak_revalidate)(struct dentry *, unsigned int);
int (*d_hash)(const struct dentry *, struct qstr *);
int (*d_compare)(const struct dentry *, const struct dentry *,
2011-01-07 17:49:27 +11:00
unsigned int, const char *, const struct qstr *);
2011-01-07 17:49:23 +11:00
int (*d_delete)(const struct dentry *);
2005-04-16 15:20:36 -07:00
void (*d_release)(struct dentry *);
2011-10-28 10:02:42 -07:00
void (*d_prune)(struct dentry *);
2005-04-16 15:20:36 -07:00
void (*d_iput)(struct dentry *, struct inode *);
char *(*d_dname)(struct dentry *, char *, int);
struct vfsmount *(*d_automount)(struct path *);
int (*d_manage)(struct dentry *, bool);
} ____cacheline_aligned;
2005-04-16 15:20:36 -07:00
2011-01-07 17:49:22 +11:00
/*
* Locking rules for dentry_operations callbacks are to be found in
* Documentation/filesystems/Locking. Keep it updated!
*
2011-01-07 17:49:27 +11:00
* FUrther descriptions are found in Documentation/filesystems/vfs.txt.
* Keep it updated too!
2005-04-16 15:20:36 -07:00
*/
/* d_flags entries */
#define DCACHE_OP_HASH 0x0001
#define DCACHE_OP_COMPARE 0x0002
#define DCACHE_OP_REVALIDATE 0x0004
#define DCACHE_OP_DELETE 0x0008
2011-10-28 10:02:42 -07:00
#define DCACHE_OP_PRUNE 0x0010
2011-01-07 17:49:54 +11:00
2011-10-28 10:02:42 -07:00
#define DCACHE_DISCONNECTED 0x0020
2011-01-07 17:49:54 +11:00
/* This dentry is possibly not currently connected to the dcache tree, in
* which case its parent will either be itself, or will have this flag as
* well. nfsd will not use a dentry with this bit set, but will first
* endeavour to clear the bit either by discovering that it is connected,
* or by performing lookup operations. Any filesystem which supports
* nfsd_operations MUST have a lookup function which, if it finds a
* directory inode with a DCACHE_DISCONNECTED dentry, will d_move that
* dentry into place and return that dentry rather than the passed one,
* typically using d_splice_alias. */
2005-04-16 15:20:36 -07:00
2011-10-28 10:02:42 -07:00
#define DCACHE_REFERENCED 0x0040 /* Recently used, don't discard. */
#define DCACHE_RCUACCESS 0x0080 /* Entry has ever been RCU-visible */
2009-05-21 17:01:29 -04:00
#define DCACHE_CANT_MOUNT 0x0100
#define DCACHE_GENOCIDE 0x0200
2012-01-10 18:22:25 +01:00
#define DCACHE_SHRINK_LIST 0x0400
2011-01-07 17:49:54 +11:00
#define DCACHE_OP_WEAK_REVALIDATE 0x0800
#define DCACHE_NFSFS_RENAMED 0x1000
/* this dentry has been "silly renamed" and has to be deleted on the last
* dput() */
#define DCACHE_COOKIE 0x2000 /* For use by dcookie subsystem */
#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x4000
/* Parent inode is watched by some fsnotify listener */
2011-01-07 17:49:55 +11:00
#define DCACHE_MOUNTED 0x10000 /* is a mountpoint */
#define DCACHE_NEED_AUTOMOUNT 0x20000 /* handle automount on this dir */
#define DCACHE_MANAGE_TRANSIT 0x40000 /* manage transit from this dirent */
#define DCACHE_MANAGED_DENTRY \
(DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
2013-09-08 13:26:18 -07:00
#define DCACHE_LRU_LIST 0x80000
#define DCACHE_DENTRY_KILLED 0x100000
2007-07-22 08:04:18 -04:00
extern seqlock_t rename_lock;
2005-04-16 15:20:36 -07:00
static inline int dname_external(const struct dentry *dentry)
2005-04-16 15:20:36 -07:00
{
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 *);
2006-08-22 20:06:07 -04:00
extern struct dentry * d_materialise_unique(struct dentry *, struct inode *);
2011-01-07 17:49:30 +11:00
extern void __d_drop(struct dentry *dentry);
extern void d_drop(struct dentry *dentry);
2005-04-16 15:20:36 -07:00
extern void d_delete(struct dentry *);
2011-01-07 17:49:55 +11:00
extern void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op);
2005-04-16 15:20:36 -07:00
/* allocate/de-allocate */
extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
extern struct dentry * d_alloc_pseudo(struct super_block *, const struct qstr *);
2005-04-16 15:20:36 -07:00
extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
2008-08-07 23:49:07 +02:00
extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
2012-01-10 09:04:37 -08:00
extern struct dentry *d_find_any_alias(struct inode *inode);
2008-08-11 15:48:57 +02:00
extern struct dentry * d_obtain_alias(struct inode *);
2005-04-16 15:20:36 -07:00
extern void shrink_dcache_sb(struct super_block *);
extern void shrink_dcache_parent(struct dentry *);
extern void shrink_dcache_for_umount(struct super_block *);
2005-04-16 15:20:36 -07:00
extern int d_invalidate(struct dentry *);
/* only used at mount-time */
2012-01-08 16:49:21 -05:00
extern struct dentry * d_make_root(struct inode *);
2005-04-16 15:20:36 -07:00
/* <clickety>-<click> the ramfs-type tree */
extern void d_genocide(struct dentry *);
extern void d_tmpfile(struct dentry *, struct inode *);
2005-04-16 15:20:36 -07:00
extern struct dentry *d_find_alias(struct inode *);
extern void d_prune_aliases(struct inode *);
/* test whether we have any submounts in a subdir tree */
extern int have_submounts(struct dentry *);
2013-09-05 11:44:36 +02:00
extern int check_submounts_and_drop(struct dentry *);
2005-04-16 15:20:36 -07:00
/*
* This adds the entry to the hash queues.
*/
extern void d_rehash(struct dentry *);
/**
* d_add - add dentry to hash queues
* @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 void d_add(struct dentry *entry, struct inode *inode)
{
d_instantiate(entry, 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;
}
2011-01-07 17:49:26 +11:00
extern void dentry_update_name_case(struct dentry *, struct qstr *);
2005-04-16 15:20:36 -07:00
/* used for rename() and baskets */
extern void d_move(struct dentry *, struct dentry *);
2008-10-16 07:50:28 +09:00
extern struct dentry *d_ancestor(struct dentry *, struct dentry *);
2005-04-16 15:20:36 -07:00
/* appendix may either be NULL or be used for transname suffixes */
2013-01-24 18:29:34 -05:00
extern struct dentry *d_lookup(const struct dentry *, const struct qstr *);
2011-01-07 17:49:52 +11:00
extern struct dentry *d_hash_and_lookup(struct dentry *, struct qstr *);
2013-01-24 18:27:00 -05:00
extern struct dentry *__d_lookup(const struct dentry *, const struct qstr *);
2012-03-02 14:23:30 -08:00
extern struct dentry *__d_lookup_rcu(const struct dentry *parent,
const struct qstr *name, unsigned *seq);
2011-01-07 17:49:52 +11:00
2013-07-18 22:09:08 +08:00
static inline unsigned d_count(const struct dentry *dentry)
2013-07-05 18:59:33 +04:00
{
return dentry->d_lockref.count;
2013-07-05 18:59:33 +04:00
}
2005-04-16 15:20:36 -07:00
/* validate "insecure" dentry pointer */
extern int d_validate(struct dentry *, struct dentry *);
/*
* helper function for dentry_operations.d_dname() members
*/
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
extern char *simple_dname(struct dentry *, char *, int);
extern char *__d_path(const struct path *, const struct path *, char *, int);
extern char *d_absolute_path(const struct path *, char *, int);
extern char *d_path(const struct path *, char *, int);
2011-01-07 17:49:29 +11:00
extern char *dentry_path_raw(struct dentry *, char *, int);
extern char *dentry_path(struct dentry *, char *, int);
2008-02-14 19:38:44 -08:00
2005-04-16 15:20:36 -07:00
/* Allocation counts.. */
/**
2011-01-07 17:49:43 +11:00
* dget, dget_dlock - get a reference to a dentry
2005-04-16 15:20:36 -07:00
* @dentry: dentry to get a reference to
*
* Given a dentry or %NULL pointer increment the reference count
* if appropriate and return the dentry. A dentry will not be
2011-01-07 17:49:43 +11:00
* destroyed when it has references.
2005-04-16 15:20:36 -07:00
*/
2011-01-07 17:49:32 +11:00
static inline struct dentry *dget_dlock(struct dentry *dentry)
{
2011-01-07 17:49:43 +11:00
if (dentry)
dentry->d_lockref.count++;
2011-01-07 17:49:32 +11:00
return dentry;
}
2011-01-07 17:49:34 +11:00
2005-04-16 15:20:36 -07:00
static inline struct dentry *dget(struct dentry *dentry)
{
if (dentry)
lockref_get(&dentry->d_lockref);
2005-04-16 15:20:36 -07:00
return dentry;
}
2011-01-07 17:49:32 +11:00
extern struct dentry *dget_parent(struct dentry *dentry);
2005-04-16 15:20:36 -07:00
/**
* d_unhashed - is dentry hashed
* @dentry: entry to check
*
* Returns true if the dentry passed is not currently hashed.
*/
static inline int d_unhashed(const struct dentry *dentry)
2005-04-16 15:20:36 -07:00
{
2011-04-24 07:58:46 -07:00
return hlist_bl_unhashed(&dentry->d_hash);
2005-04-16 15:20:36 -07:00
}
static inline int d_unlinked(const struct dentry *dentry)
2009-05-04 03:32:03 +04:00
{
return d_unhashed(dentry) && !IS_ROOT(dentry);
}
static inline int cant_mount(const struct dentry *dentry)
{
return (dentry->d_flags & DCACHE_CANT_MOUNT);
}
static inline void dont_mount(struct dentry *dentry)
{
spin_lock(&dentry->d_lock);
dentry->d_flags |= DCACHE_CANT_MOUNT;
spin_unlock(&dentry->d_lock);
}
2005-04-16 15:20:36 -07:00
extern void dput(struct dentry *);
static inline bool d_managed(const struct dentry *dentry)
{
return dentry->d_flags & DCACHE_MANAGED_DENTRY;
}
static inline bool d_mountpoint(const struct dentry *dentry)
2005-04-16 15:20:36 -07:00
{
2011-01-07 17:49:54 +11:00
return dentry->d_flags & DCACHE_MOUNTED;
2005-04-16 15:20:36 -07:00
}
extern int sysctl_vfs_cache_pressure;
static inline unsigned long vfs_pressure_ratio(unsigned long val)
{
return mult_frac(val, sysctl_vfs_cache_pressure, 100);
}
2005-04-16 15:20:36 -07:00
#endif /* __LINUX_DCACHE_H */