diff options
Diffstat (limited to 'fs/ocfs2/dcache.c')
| -rw-r--r-- | fs/ocfs2/dcache.c | 42 | 
1 files changed, 39 insertions, 3 deletions
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index b1cc7c381e8..e9d7c2038c0 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -38,6 +38,7 @@  #include "dlmglue.h"  #include "file.h"  #include "inode.h" +#include "super.h"  static int ocfs2_dentry_revalidate(struct dentry *dentry, @@ -294,6 +295,34 @@ out_attach:  	return ret;  } +static DEFINE_SPINLOCK(dentry_list_lock); + +/* We limit the number of dentry locks to drop in one go. We have + * this limit so that we don't starve other users of ocfs2_wq. */ +#define DL_INODE_DROP_COUNT 64 + +/* Drop inode references from dentry locks */ +void ocfs2_drop_dl_inodes(struct work_struct *work) +{ +	struct ocfs2_super *osb = container_of(work, struct ocfs2_super, +					       dentry_lock_work); +	struct ocfs2_dentry_lock *dl; +	int drop_count = DL_INODE_DROP_COUNT; + +	spin_lock(&dentry_list_lock); +	while (osb->dentry_lock_list && drop_count--) { +		dl = osb->dentry_lock_list; +		osb->dentry_lock_list = dl->dl_next; +		spin_unlock(&dentry_list_lock); +		iput(dl->dl_inode); +		kfree(dl); +		spin_lock(&dentry_list_lock); +	} +	if (osb->dentry_lock_list) +		queue_work(ocfs2_wq, &osb->dentry_lock_work); +	spin_unlock(&dentry_list_lock); +} +  /*   * ocfs2_dentry_iput() and friends.   * @@ -318,16 +347,23 @@ out_attach:  static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,  				   struct ocfs2_dentry_lock *dl)  { -	iput(dl->dl_inode);  	ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);  	ocfs2_lock_res_free(&dl->dl_lockres); -	kfree(dl); + +	/* We leave dropping of inode reference to ocfs2_wq as that can +	 * possibly lead to inode deletion which gets tricky */ +	spin_lock(&dentry_list_lock); +	if (!osb->dentry_lock_list) +		queue_work(ocfs2_wq, &osb->dentry_lock_work); +	dl->dl_next = osb->dentry_lock_list; +	osb->dentry_lock_list = dl; +	spin_unlock(&dentry_list_lock);  }  void ocfs2_dentry_lock_put(struct ocfs2_super *osb,  			   struct ocfs2_dentry_lock *dl)  { -	int unlock = 0; +	int unlock;  	BUG_ON(dl->dl_count == 0);  |