diff options
| author | Andrew Morton <akpm@digeo.com> | 2003-04-02 16:28:58 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-04-02 16:28:58 -0800 |
| commit | 723c6e83134f78035b93cb3e70503ad4d04a7dfa (patch) | |
| tree | 5f592fd50d2b74a5a5e5016d66fb98edd24c5e45 /include/linux | |
| parent | 1b8910cf1042f2de2cdd1dc26e4fb677b6dad7ed (diff) | |
[PATCH] remove dparent_lock
The big SMP machines are seeing quite some contention in dnotify_parent()
(via vfs_write). This function is hammering the global dparent_lock.
However we don't actually need a global dparent_lock for pinning down
dentry->d_parent. We can use dentry->d_lock for this. That is already being
held across d_move.
This patch speeds up SDET on the 16-way by 5% and wipes dnotify_parent() off
the profiles.
It also uninlines dnofity_parent().
It also uses spin_lock(), which is faster than read_lock().
I'm not sure that we need to take both the source and target dentry's d_lock
in d_move.
The patch also does lots of s/__inline__/inline/ in dcache.h
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/dcache.h | 38 | ||||
| -rw-r--r-- | include/linux/dnotify.h | 19 | ||||
| -rw-r--r-- | include/linux/fs.h | 5 |
3 files changed, 30 insertions, 32 deletions
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 2dd37351d92e..db979c3cf890 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -48,19 +48,24 @@ extern struct dentry_stat_t dentry_stat; #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) +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) +/* + * 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. */ -static __inline__ unsigned int full_name_hash(const unsigned char * name, unsigned int len) +static inline unsigned int +full_name_hash(const unsigned char *name, unsigned int len) { unsigned long hash = init_name_hash(); while (len--) @@ -149,7 +154,6 @@ d_iput: no no yes #define DCACHE_UNHASHED 0x0010 extern spinlock_t dcache_lock; -extern rwlock_t dparent_lock; /** * d_drop - drop a dentry @@ -168,20 +172,20 @@ extern rwlock_t dparent_lock; * timeouts or autofs deletes). */ -static __inline__ void __d_drop(struct dentry * dentry) +static inline void __d_drop(struct dentry *dentry) { dentry->d_vfs_flags |= DCACHE_UNHASHED; hlist_del_rcu(&dentry->d_hash); } -static __inline__ void d_drop(struct dentry * dentry) +static inline void d_drop(struct dentry *dentry) { spin_lock(&dcache_lock); __d_drop(dentry); spin_unlock(&dcache_lock); } -static __inline__ int dname_external(struct dentry *d) +static inline int dname_external(struct dentry *d) { return d->d_name.name != d->d_iname; } @@ -227,7 +231,7 @@ extern void d_rehash(struct dentry *); * The entry was actually filled in earlier during d_alloc(). */ -static __inline__ void d_add(struct dentry * entry, struct inode * inode) +static inline void d_add(struct dentry *entry, struct inode *inode) { d_instantiate(entry, inode); d_rehash(entry); @@ -260,7 +264,7 @@ extern char * d_path(struct dentry *, struct vfsmount *, char *, int); * and call dget_locked() instead of dget(). */ -static __inline__ struct dentry * dget(struct dentry *dentry) +static inline struct dentry *dget(struct dentry *dentry) { if (dentry) { if (!atomic_read(&dentry->d_count)) @@ -280,14 +284,24 @@ extern struct dentry * dget_locked(struct dentry *); * Returns true if the dentry passed is not currently hashed. */ -static __inline__ int d_unhashed(struct dentry *dentry) +static inline int d_unhashed(struct dentry *dentry) { return (dentry->d_vfs_flags & DCACHE_UNHASHED); } +static inline struct dentry *dget_parent(struct dentry *dentry) +{ + struct dentry *ret; + + spin_lock(&dentry->d_lock); + ret = dget(dentry->d_parent); + spin_unlock(&dentry->d_lock); + return ret; +} + extern void dput(struct dentry *); -static __inline__ int d_mountpoint(struct dentry *dentry) +static inline int d_mountpoint(struct dentry *dentry) { return dentry->d_mounted; } diff --git a/include/linux/dnotify.h b/include/linux/dnotify.h index 2db6774c9330..5cffeedac412 100644 --- a/include/linux/dnotify.h +++ b/include/linux/dnotify.h @@ -18,27 +18,10 @@ struct dnotify_struct { extern void __inode_dir_notify(struct inode *, unsigned long); extern void dnotify_flush(struct file *filp, fl_owner_t id); extern int fcntl_dirnotify(int, struct file *, unsigned long); +void dnotify_parent(struct dentry *dentry, unsigned long event); static inline void inode_dir_notify(struct inode *inode, unsigned long event) { if ((inode)->i_dnotify_mask & (event)) __inode_dir_notify(inode, event); } - -/* - * This is hopelessly wrong, but unfixable without API changes. At - * least it doesn't oops the kernel... - */ -static inline void dnotify_parent(struct dentry *dentry, unsigned long event) -{ - struct dentry *parent; - read_lock(&dparent_lock); - parent = dentry->d_parent; - if (parent->d_inode->i_dnotify_mask & event) { - dget(parent); - read_unlock(&dparent_lock); - __inode_dir_notify(parent->d_inode, event); - dput(parent); - } else - read_unlock(&dparent_lock); -} diff --git a/include/linux/fs.h b/include/linux/fs.h index 3ee3bf870ff1..af3852b4281d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1306,9 +1306,10 @@ extern void inode_update_time(struct inode *inode, int ctime_too); static inline ino_t parent_ino(struct dentry *dentry) { ino_t res; - read_lock(&dparent_lock); + + spin_lock(&dentry->d_lock); res = dentry->d_parent->d_inode->i_ino; - read_unlock(&dparent_lock); + spin_unlock(&dentry->d_lock); return res; } |
