]> git.proxmox.com Git - pve-kernel-2.6.32.git/blame - dlm-make-plock-operation-killable.patch
update to vzkernel-2.6.32-042stab045.1.src.rpm
[pve-kernel-2.6.32.git] / dlm-make-plock-operation-killable.patch
CommitLineData
ed2a6bee
DM
1From 901025d2f3194b4868980c8ba80df4cc0aa1282c Mon Sep 17 00:00:00 2001
2From: David Teigland <teigland@redhat.com>
3Date: Wed, 2 Mar 2011 14:20:04 -0600
4Subject: [PATCH 1/1] dlm: make plock operation killable
5
6Allow processes blocked on plock requests to be interrupted
7when they are killed. This leaves the problem of cleaning
8up the lock state in userspace. This has three parts:
9
101. Add a flag to unlock operations sent to userspace
11indicating the file is being closed. Userspace will
12then look for and clear any waiting plock operations that
13were abandoned by an interrupted process.
14
152. Queue an unlock-close operation (like in 1) to clean up
16userspace from an interrupted plock request. This is needed
17because the vfs will not send a cleanup-unlock if it sees no
18locks on the file, which it won't if the interrupted operation
19was the only one.
20
213. Do not use replies from userspace for unlock-close operations
22because they are unnecessary (they are just cleaning up for the
23process which did not make an unlock call). This also simplifies
24the new unlock-close generated from point 2.
25
26Signed-off-by: David Teigland <teigland@redhat.com>
27---
28 fs/dlm/plock.c | 65 ++++++++++++++++++++++++++++++++++++++++++---
29 include/linux/dlm_plock.h | 6 +++-
30 2 files changed, 65 insertions(+), 6 deletions(-)
31
32diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
33index 30d8b85..e2b8780 100644
34--- a/fs/dlm/plock.c
35+++ b/fs/dlm/plock.c
36@@ -71,6 +71,36 @@ static void send_op(struct plock_op *op)
37 wake_up(&send_wq);
38 }
39
40+/* If a process was killed while waiting for the only plock on a file,
41+ locks_remove_posix will not see any lock on the file so it won't
42+ send an unlock-close to us to pass on to userspace to clean up the
43+ abandoned waiter. So, we have to insert the unlock-close when the
44+ lock call is interrupted. */
45+
46+static void do_unlock_close(struct dlm_ls *ls, u64 number,
47+ struct file *file, struct file_lock *fl)
48+{
49+ struct plock_op *op;
50+
51+ op = kzalloc(sizeof(*op), GFP_NOFS);
52+ if (!op)
53+ return;
54+
55+ op->info.optype = DLM_PLOCK_OP_UNLOCK;
56+ op->info.pid = fl->fl_pid;
57+ op->info.fsid = ls->ls_global_id;
58+ op->info.number = number;
59+ op->info.start = 0;
60+ op->info.end = OFFSET_MAX;
61+ if (fl->fl_lmops && fl->fl_lmops->fl_grant)
62+ op->info.owner = (__u64) fl->fl_pid;
63+ else
64+ op->info.owner = (__u64)(long) fl->fl_owner;
65+
66+ op->info.flags |= DLM_PLOCK_FL_CLOSE;
67+ send_op(op);
68+}
69+
70 int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
71 int cmd, struct file_lock *fl)
72 {
73@@ -114,9 +144,19 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
74
75 send_op(op);
76
77- if (xop->callback == NULL)
78- wait_event(recv_wq, (op->done != 0));
79- else {
80+ if (xop->callback == NULL) {
81+ rv = wait_event_killable(recv_wq, (op->done != 0));
82+ if (rv == -ERESTARTSYS) {
83+ log_debug(ls, "dlm_posix_lock: wait killed %llx",
84+ (unsigned long long)number);
85+ spin_lock(&ops_lock);
86+ list_del(&op->list);
87+ spin_unlock(&ops_lock);
88+ kfree(xop);
89+ do_unlock_close(ls, number, file, fl);
90+ goto out;
91+ }
92+ } else {
93 rv = FILE_LOCK_DEFERRED;
94 goto out;
95 }
96@@ -233,6 +273,13 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
97 else
98 op->info.owner = (__u64)(long) fl->fl_owner;
99
100+ if (fl->fl_flags & FL_CLOSE) {
101+ op->info.flags |= DLM_PLOCK_FL_CLOSE;
102+ send_op(op);
103+ rv = 0;
104+ goto out;
105+ }
106+
107 send_op(op);
108 wait_event(recv_wq, (op->done != 0));
109
110@@ -334,7 +381,10 @@ static ssize_t dev_read(struct file *file, char __user *u, size_t count,
111 spin_lock(&ops_lock);
112 if (!list_empty(&send_list)) {
113 op = list_entry(send_list.next, struct plock_op, list);
114- list_move(&op->list, &recv_list);
115+ if (op->info.flags & DLM_PLOCK_FL_CLOSE)
116+ list_del(&op->list);
117+ else
118+ list_move(&op->list, &recv_list);
119 memcpy(&info, &op->info, sizeof(info));
120 }
121 spin_unlock(&ops_lock);
122@@ -342,6 +392,13 @@ static ssize_t dev_read(struct file *file, char __user *u, size_t count,
123 if (!op)
124 return -EAGAIN;
125
126+ /* there is no need to get a reply from userspace for unlocks
127+ that were generated by the vfs cleaning up for a close
128+ (the process did not make an unlock call). */
129+
130+ if (op->info.flags & DLM_PLOCK_FL_CLOSE)
131+ kfree(op);
132+
133 if (copy_to_user(u, &info, sizeof(info)))
134 return -EFAULT;
135 return sizeof(info);
136diff --git a/include/linux/dlm_plock.h b/include/linux/dlm_plock.h
137index 2dd2124..3b1cc1b 100644
138--- a/include/linux/dlm_plock.h
139+++ b/include/linux/dlm_plock.h
140@@ -14,7 +14,7 @@
141 #define DLM_PLOCK_MISC_NAME "dlm_plock"
142
143 #define DLM_PLOCK_VERSION_MAJOR 1
144-#define DLM_PLOCK_VERSION_MINOR 1
145+#define DLM_PLOCK_VERSION_MINOR 2
146 #define DLM_PLOCK_VERSION_PATCH 0
147
148 enum {
149@@ -23,12 +23,14 @@ enum {
150 DLM_PLOCK_OP_GET,
151 };
152
153+#define DLM_PLOCK_FL_CLOSE 1
154+
155 struct dlm_plock_info {
156 __u32 version[3];
157 __u8 optype;
158 __u8 ex;
159 __u8 wait;
160- __u8 pad;
161+ __u8 flags;
162 __u32 pid;
163 __s32 nodeid;
164 __s32 rv;
165--
1661.7.2.5
167