summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorAndrew Morton <akpm@digeo.com>2003-04-02 16:28:58 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2003-04-02 16:28:58 -0800
commit723c6e83134f78035b93cb3e70503ad4d04a7dfa (patch)
tree5f592fd50d2b74a5a5e5016d66fb98edd24c5e45 /include/linux
parent1b8910cf1042f2de2cdd1dc26e4fb677b6dad7ed (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.h38
-rw-r--r--include/linux/dnotify.h19
-rw-r--r--include/linux/fs.h5
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;
}