]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.fixes/ocfs2-push-out-dropping-of-dentry-lock-to-ocfs2_wq.patch
Reenabled linux-xen and xen-image build
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.fixes / ocfs2-push-out-dropping-of-dentry-lock-to-ocfs2_wq.patch
CommitLineData
00e5a55c
BS
1From: Jan Kara <jack@suse.cz>
2Date: Mon, 12 Jan 2009 23:20:31 +0100
3Subject: [PATCH] ocfs2: Push out dropping of dentry lock to ocfs2_wq
4Patch-mainline: 2.6.29
5
6Dropping of last reference to dentry lock is a complicated operation involving
7dropping of reference to inode. This can get complicated and quota code in
8particular needs to obtain some quota locks which leads to potential deadlock.
9Thus we defer dropping of inode reference to ocfs2_wq.
10
11Signed-off-by: Jan Kara <jack@suse.cz>
12Signed-off-by: Mark Fasheh <mfasheh@suse.com>
13---
14 fs/ocfs2/dcache.c | 42 +++++++++++++++++++++++++++++++++++++++---
15 fs/ocfs2/dcache.h | 9 ++++++++-
16 fs/ocfs2/ocfs2.h | 6 ++++++
17 fs/ocfs2/super.c | 3 +++
18 4 files changed, 56 insertions(+), 4 deletions(-)
19
20--- a/fs/ocfs2/dcache.c
21+++ b/fs/ocfs2/dcache.c
22@@ -38,6 +38,7 @@
23 #include "dlmglue.h"
24 #include "file.h"
25 #include "inode.h"
26+#include "super.h"
27
28
29 static int ocfs2_dentry_revalidate(struct dentry *dentry,
30@@ -294,6 +295,34 @@ out_attach:
31 return ret;
32 }
33
34+static DEFINE_SPINLOCK(dentry_list_lock);
35+
36+/* We limit the number of dentry locks to drop in one go. We have
37+ * this limit so that we don't starve other users of ocfs2_wq. */
38+#define DL_INODE_DROP_COUNT 64
39+
40+/* Drop inode references from dentry locks */
41+void ocfs2_drop_dl_inodes(struct work_struct *work)
42+{
43+ struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
44+ dentry_lock_work);
45+ struct ocfs2_dentry_lock *dl;
46+ int drop_count = DL_INODE_DROP_COUNT;
47+
48+ spin_lock(&dentry_list_lock);
49+ while (osb->dentry_lock_list && drop_count--) {
50+ dl = osb->dentry_lock_list;
51+ osb->dentry_lock_list = dl->dl_next;
52+ spin_unlock(&dentry_list_lock);
53+ iput(dl->dl_inode);
54+ kfree(dl);
55+ spin_lock(&dentry_list_lock);
56+ }
57+ if (osb->dentry_lock_list)
58+ queue_work(ocfs2_wq, &osb->dentry_lock_work);
59+ spin_unlock(&dentry_list_lock);
60+}
61+
62 /*
63 * ocfs2_dentry_iput() and friends.
64 *
65@@ -318,16 +347,23 @@ out_attach:
66 static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
67 struct ocfs2_dentry_lock *dl)
68 {
69- iput(dl->dl_inode);
70 ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
71 ocfs2_lock_res_free(&dl->dl_lockres);
72- kfree(dl);
73+
74+ /* We leave dropping of inode reference to ocfs2_wq as that can
75+ * possibly lead to inode deletion which gets tricky */
76+ spin_lock(&dentry_list_lock);
77+ if (!osb->dentry_lock_list)
78+ queue_work(ocfs2_wq, &osb->dentry_lock_work);
79+ dl->dl_next = osb->dentry_lock_list;
80+ osb->dentry_lock_list = dl;
81+ spin_unlock(&dentry_list_lock);
82 }
83
84 void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
85 struct ocfs2_dentry_lock *dl)
86 {
87- int unlock = 0;
88+ int unlock;
89
90 BUG_ON(dl->dl_count == 0);
91
92--- a/fs/ocfs2/dcache.h
93+++ b/fs/ocfs2/dcache.h
94@@ -29,8 +29,13 @@
95 extern struct dentry_operations ocfs2_dentry_ops;
96
97 struct ocfs2_dentry_lock {
98+ /* Use count of dentry lock */
99 unsigned int dl_count;
100- u64 dl_parent_blkno;
101+ union {
102+ /* Linked list of dentry locks to release */
103+ struct ocfs2_dentry_lock *dl_next;
104+ u64 dl_parent_blkno;
105+ };
106
107 /*
108 * The ocfs2_dentry_lock keeps an inode reference until
109@@ -47,6 +52,8 @@ int ocfs2_dentry_attach_lock(struct dent
110 void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
111 struct ocfs2_dentry_lock *dl);
112
113+void ocfs2_drop_dl_inodes(struct work_struct *work);
114+
115 struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno,
116 int skip_unhashed);
117
118--- a/fs/ocfs2/ocfs2.h
119+++ b/fs/ocfs2/ocfs2.h
120@@ -210,6 +210,7 @@ struct ocfs2_journal;
121 struct ocfs2_slot_info;
122 struct ocfs2_recovery_map;
123 struct ocfs2_quota_recovery;
124+struct ocfs2_dentry_lock;
125 struct ocfs2_super
126 {
127 struct task_struct *commit_task;
128@@ -325,6 +326,11 @@ struct ocfs2_super
129 struct list_head blocked_lock_list;
130 unsigned long blocked_lock_count;
131
132+ /* List of dentry locks to release. Anyone can add locks to
133+ * the list, ocfs2_wq processes the list */
134+ struct ocfs2_dentry_lock *dentry_lock_list;
135+ struct work_struct dentry_lock_work;
136+
137 wait_queue_head_t osb_mount_event;
138
139 /* Truncate log info */
140--- a/fs/ocfs2/super.c
141+++ b/fs/ocfs2/super.c
142@@ -1888,6 +1888,9 @@ static int ocfs2_initialize_super(struct
143 INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery);
144 journal->j_state = OCFS2_JOURNAL_FREE;
145
146+ INIT_WORK(&osb->dentry_lock_work, ocfs2_drop_dl_inodes);
147+ osb->dentry_lock_list = NULL;
148+
149 /* get some pseudo constants for clustersize bits */
150 osb->s_clustersize_bits =
151 le32_to_cpu(di->id2.i_super.s_clustersize_bits);