2 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
4 * This copyrighted material is made available to anyone wishing to use,
5 * modify, copy, or redistribute it subject to the terms and conditions
6 * of the GNU General Public License version 2.
9 #include <linux/miscdevice.h>
10 #include <linux/lock_dlm_plock.h>
11 #include <linux/poll.h>
16 static spinlock_t ops_lock
;
17 static struct list_head send_list
;
18 static struct list_head recv_list
;
19 static wait_queue_head_t send_wq
;
20 static wait_queue_head_t recv_wq
;
23 struct list_head list
;
25 struct gdlm_plock_info info
;
37 static inline void set_version(struct gdlm_plock_info
*info
)
39 info
->version
[0] = GDLM_PLOCK_VERSION_MAJOR
;
40 info
->version
[1] = GDLM_PLOCK_VERSION_MINOR
;
41 info
->version
[2] = GDLM_PLOCK_VERSION_PATCH
;
44 static int check_version(struct gdlm_plock_info
*info
)
46 if ((GDLM_PLOCK_VERSION_MAJOR
!= info
->version
[0]) ||
47 (GDLM_PLOCK_VERSION_MINOR
< info
->version
[1])) {
48 log_error("plock device version mismatch: "
49 "kernel (%u.%u.%u), user (%u.%u.%u)",
50 GDLM_PLOCK_VERSION_MAJOR
,
51 GDLM_PLOCK_VERSION_MINOR
,
52 GDLM_PLOCK_VERSION_PATCH
,
61 static void send_op(struct plock_op
*op
)
63 set_version(&op
->info
);
64 INIT_LIST_HEAD(&op
->list
);
66 list_add_tail(&op
->list
, &send_list
);
67 spin_unlock(&ops_lock
);
71 int gdlm_plock(void *lockspace
, struct lm_lockname
*name
,
72 struct file
*file
, int cmd
, struct file_lock
*fl
)
74 struct gdlm_ls
*ls
= lockspace
;
76 struct plock_xop
*xop
;
79 xop
= kzalloc(sizeof(*xop
), GFP_KERNEL
);
84 op
->info
.optype
= GDLM_PLOCK_OP_LOCK
;
85 op
->info
.pid
= fl
->fl_pid
;
86 op
->info
.ex
= (fl
->fl_type
== F_WRLCK
);
87 op
->info
.wait
= IS_SETLKW(cmd
);
88 op
->info
.fsid
= ls
->id
;
89 op
->info
.number
= name
->ln_number
;
90 op
->info
.start
= fl
->fl_start
;
91 op
->info
.end
= fl
->fl_end
;
92 if (fl
->fl_lmops
&& fl
->fl_lmops
->fl_grant
) {
93 /* fl_owner is lockd which doesn't distinguish
94 processes on the nfs client */
95 op
->info
.owner
= (__u64
) fl
->fl_pid
;
96 xop
->callback
= fl
->fl_lmops
->fl_grant
;
97 locks_init_lock(&xop
->flc
);
98 locks_copy_lock(&xop
->flc
, fl
);
102 op
->info
.owner
= (__u64
)(long) fl
->fl_owner
;
103 xop
->callback
= NULL
;
108 if (xop
->callback
== NULL
)
109 wait_event(recv_wq
, (op
->done
!= 0));
113 spin_lock(&ops_lock
);
114 if (!list_empty(&op
->list
)) {
115 printk(KERN_INFO
"plock op on list\n");
118 spin_unlock(&ops_lock
);
123 if (posix_lock_file_wait(file
, fl
) < 0)
124 log_error("gdlm_plock: vfs lock error %x,%llx",
126 (unsigned long long)name
->ln_number
);
133 /* Returns failure iff a succesful lock operation should be canceled */
134 static int gdlm_plock_callback(struct plock_op
*op
)
137 struct file_lock
*fl
;
138 struct file_lock
*flc
;
139 int (*notify
)(void *, void *, int) = NULL
;
140 struct plock_xop
*xop
= (struct plock_xop
*)op
;
143 spin_lock(&ops_lock
);
144 if (!list_empty(&op
->list
)) {
145 printk(KERN_INFO
"plock op on list\n");
148 spin_unlock(&ops_lock
);
150 /* check if the following 2 are still valid or make a copy */
154 notify
= xop
->callback
;
157 notify(flc
, NULL
, op
->info
.rv
);
161 /* got fs lock; bookkeep locally as well: */
162 flc
->fl_flags
&= ~FL_SLEEP
;
163 if (posix_lock_file(file
, flc
, NULL
)) {
165 * This can only happen in the case of kmalloc() failure.
166 * The filesystem's own lock is the authoritative lock,
167 * so a failure to get the lock locally is not a disaster.
168 * As long as GFS cannot reliably cancel locks (especially
169 * in a low-memory situation), we're better off ignoring
170 * this failure than trying to recover.
172 log_error("gdlm_plock: vfs lock error file %p fl %p",
176 rv
= notify(flc
, NULL
, 0);
178 /* XXX: We need to cancel the fs lock here: */
179 printk("gfs2 lock granted after lock request failed;"
180 " dangling lock!\n");
189 int gdlm_punlock(void *lockspace
, struct lm_lockname
*name
,
190 struct file
*file
, struct file_lock
*fl
)
192 struct gdlm_ls
*ls
= lockspace
;
196 op
= kzalloc(sizeof(*op
), GFP_KERNEL
);
200 if (posix_lock_file_wait(file
, fl
) < 0)
201 log_error("gdlm_punlock: vfs unlock error %x,%llx",
202 name
->ln_type
, (unsigned long long)name
->ln_number
);
204 op
->info
.optype
= GDLM_PLOCK_OP_UNLOCK
;
205 op
->info
.pid
= fl
->fl_pid
;
206 op
->info
.fsid
= ls
->id
;
207 op
->info
.number
= name
->ln_number
;
208 op
->info
.start
= fl
->fl_start
;
209 op
->info
.end
= fl
->fl_end
;
210 if (fl
->fl_lmops
&& fl
->fl_lmops
->fl_grant
)
211 op
->info
.owner
= (__u64
) fl
->fl_pid
;
213 op
->info
.owner
= (__u64
)(long) fl
->fl_owner
;
216 wait_event(recv_wq
, (op
->done
!= 0));
218 spin_lock(&ops_lock
);
219 if (!list_empty(&op
->list
)) {
220 printk(KERN_INFO
"punlock op on list\n");
223 spin_unlock(&ops_lock
);
234 int gdlm_plock_get(void *lockspace
, struct lm_lockname
*name
,
235 struct file
*file
, struct file_lock
*fl
)
237 struct gdlm_ls
*ls
= lockspace
;
241 op
= kzalloc(sizeof(*op
), GFP_KERNEL
);
245 op
->info
.optype
= GDLM_PLOCK_OP_GET
;
246 op
->info
.pid
= fl
->fl_pid
;
247 op
->info
.ex
= (fl
->fl_type
== F_WRLCK
);
248 op
->info
.fsid
= ls
->id
;
249 op
->info
.number
= name
->ln_number
;
250 op
->info
.start
= fl
->fl_start
;
251 op
->info
.end
= fl
->fl_end
;
252 if (fl
->fl_lmops
&& fl
->fl_lmops
->fl_grant
)
253 op
->info
.owner
= (__u64
) fl
->fl_pid
;
255 op
->info
.owner
= (__u64
)(long) fl
->fl_owner
;
258 wait_event(recv_wq
, (op
->done
!= 0));
260 spin_lock(&ops_lock
);
261 if (!list_empty(&op
->list
)) {
262 printk(KERN_INFO
"plock_get op on list\n");
265 spin_unlock(&ops_lock
);
267 /* info.rv from userspace is 1 for conflict, 0 for no-conflict,
268 -ENOENT if there are no locks on the file */
272 fl
->fl_type
= F_UNLCK
;
276 fl
->fl_type
= (op
->info
.ex
) ? F_WRLCK
: F_RDLCK
;
277 fl
->fl_pid
= op
->info
.pid
;
278 fl
->fl_start
= op
->info
.start
;
279 fl
->fl_end
= op
->info
.end
;
287 /* a read copies out one plock request from the send list */
288 static ssize_t
dev_read(struct file
*file
, char __user
*u
, size_t count
,
291 struct gdlm_plock_info info
;
292 struct plock_op
*op
= NULL
;
294 if (count
< sizeof(info
))
297 spin_lock(&ops_lock
);
298 if (!list_empty(&send_list
)) {
299 op
= list_entry(send_list
.next
, struct plock_op
, list
);
300 list_move(&op
->list
, &recv_list
);
301 memcpy(&info
, &op
->info
, sizeof(info
));
303 spin_unlock(&ops_lock
);
308 if (copy_to_user(u
, &info
, sizeof(info
)))
313 /* a write copies in one plock result that should match a plock_op
315 static ssize_t
dev_write(struct file
*file
, const char __user
*u
, size_t count
,
318 struct gdlm_plock_info info
;
322 if (count
!= sizeof(info
))
325 if (copy_from_user(&info
, u
, sizeof(info
)))
328 if (check_version(&info
))
331 spin_lock(&ops_lock
);
332 list_for_each_entry(op
, &recv_list
, list
) {
333 if (op
->info
.fsid
== info
.fsid
&& op
->info
.number
== info
.number
&&
334 op
->info
.owner
== info
.owner
) {
335 list_del_init(&op
->list
);
338 memcpy(&op
->info
, &info
, sizeof(info
));
342 spin_unlock(&ops_lock
);
345 struct plock_xop
*xop
;
346 xop
= (struct plock_xop
*)op
;
348 count
= gdlm_plock_callback(op
);
352 printk(KERN_INFO
"gdlm dev_write no op %x %llx\n", info
.fsid
,
353 (unsigned long long)info
.number
);
357 static unsigned int dev_poll(struct file
*file
, poll_table
*wait
)
359 unsigned int mask
= 0;
361 poll_wait(file
, &send_wq
, wait
);
363 spin_lock(&ops_lock
);
364 if (!list_empty(&send_list
))
365 mask
= POLLIN
| POLLRDNORM
;
366 spin_unlock(&ops_lock
);
371 static const struct file_operations dev_fops
= {
378 static struct miscdevice plock_dev_misc
= {
379 .minor
= MISC_DYNAMIC_MINOR
,
380 .name
= GDLM_PLOCK_MISC_NAME
,
384 int gdlm_plock_init(void)
388 spin_lock_init(&ops_lock
);
389 INIT_LIST_HEAD(&send_list
);
390 INIT_LIST_HEAD(&recv_list
);
391 init_waitqueue_head(&send_wq
);
392 init_waitqueue_head(&recv_wq
);
394 rv
= misc_register(&plock_dev_misc
);
396 printk(KERN_INFO
"gdlm_plock_init: misc_register failed %d",
401 void gdlm_plock_exit(void)
403 if (misc_deregister(&plock_dev_misc
) < 0)
404 printk(KERN_INFO
"gdlm_plock_exit: misc_deregister failed");