|
@@ -38,6 +38,7 @@
|
|
#include "dlmglue.h"
|
|
#include "dlmglue.h"
|
|
#include "file.h"
|
|
#include "file.h"
|
|
#include "inode.h"
|
|
#include "inode.h"
|
|
|
|
+#include "super.h"
|
|
|
|
|
|
|
|
|
|
static int ocfs2_dentry_revalidate(struct dentry *dentry,
|
|
static int ocfs2_dentry_revalidate(struct dentry *dentry,
|
|
@@ -294,6 +295,34 @@ out_attach:
|
|
return ret;
|
|
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.
|
|
* ocfs2_dentry_iput() and friends.
|
|
*
|
|
*
|
|
@@ -318,16 +347,23 @@ out_attach:
|
|
static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
|
|
static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
|
|
struct ocfs2_dentry_lock *dl)
|
|
struct ocfs2_dentry_lock *dl)
|
|
{
|
|
{
|
|
- iput(dl->dl_inode);
|
|
|
|
ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
|
|
ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
|
|
ocfs2_lock_res_free(&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,
|
|
void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
|
|
struct ocfs2_dentry_lock *dl)
|
|
struct ocfs2_dentry_lock *dl)
|
|
{
|
|
{
|
|
- int unlock = 0;
|
|
|
|
|
|
+ int unlock;
|
|
|
|
|
|
BUG_ON(dl->dl_count == 0);
|
|
BUG_ON(dl->dl_count == 0);
|
|
|
|
|