hc
2024-05-11 645e752c5a84baeb21015cdc85fc05b7d16312c8
kernel/fs/dlm/plock.c
....@@ -1,9 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
3
- *
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.
74 */
85
96 #include <linux/fs.h>
....@@ -22,20 +19,20 @@
2219 static wait_queue_head_t send_wq;
2320 static wait_queue_head_t recv_wq;
2421
22
+struct plock_async_data {
23
+ void *fl;
24
+ void *file;
25
+ struct file_lock flc;
26
+ int (*callback)(struct file_lock *fl, int result);
27
+};
28
+
2529 struct plock_op {
2630 struct list_head list;
2731 int done;
2832 struct dlm_plock_info info;
33
+ /* if set indicates async handling */
34
+ struct plock_async_data *data;
2935 };
30
-
31
-struct plock_xop {
32
- struct plock_op xop;
33
- int (*callback)(struct file_lock *fl, int result);
34
- void *fl;
35
- void *file;
36
- struct file_lock flc;
37
-};
38
-
3936
4037 static inline void set_version(struct dlm_plock_info *info)
4138 {
....@@ -61,6 +58,12 @@
6158 return 0;
6259 }
6360
61
+static void dlm_release_plock_op(struct plock_op *op)
62
+{
63
+ kfree(op->data);
64
+ kfree(op);
65
+}
66
+
6467 static void send_op(struct plock_op *op)
6568 {
6669 set_version(&op->info);
....@@ -77,8 +80,7 @@
7780 abandoned waiter. So, we have to insert the unlock-close when the
7881 lock call is interrupted. */
7982
80
-static void do_unlock_close(struct dlm_ls *ls, u64 number,
81
- struct file *file, struct file_lock *fl)
83
+static void do_unlock_close(const struct dlm_plock_info *info)
8284 {
8385 struct plock_op *op;
8486
....@@ -87,15 +89,12 @@
8789 return;
8890
8991 op->info.optype = DLM_PLOCK_OP_UNLOCK;
90
- op->info.pid = fl->fl_pid;
91
- op->info.fsid = ls->ls_global_id;
92
- op->info.number = number;
92
+ op->info.pid = info->pid;
93
+ op->info.fsid = info->fsid;
94
+ op->info.number = info->number;
9395 op->info.start = 0;
9496 op->info.end = OFFSET_MAX;
95
- if (fl->fl_lmops && fl->fl_lmops->lm_grant)
96
- op->info.owner = (__u64) fl->fl_pid;
97
- else
98
- op->info.owner = (__u64)(long) fl->fl_owner;
97
+ op->info.owner = info->owner;
9998
10099 op->info.flags |= DLM_PLOCK_FL_CLOSE;
101100 send_op(op);
....@@ -104,22 +103,21 @@
104103 int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
105104 int cmd, struct file_lock *fl)
106105 {
106
+ struct plock_async_data *op_data;
107107 struct dlm_ls *ls;
108108 struct plock_op *op;
109
- struct plock_xop *xop;
110109 int rv;
111110
112111 ls = dlm_find_lockspace_local(lockspace);
113112 if (!ls)
114113 return -EINVAL;
115114
116
- xop = kzalloc(sizeof(*xop), GFP_NOFS);
117
- if (!xop) {
115
+ op = kzalloc(sizeof(*op), GFP_NOFS);
116
+ if (!op) {
118117 rv = -ENOMEM;
119118 goto out;
120119 }
121120
122
- op = &xop->xop;
123121 op->info.optype = DLM_PLOCK_OP_LOCK;
124122 op->info.pid = fl->fl_pid;
125123 op->info.ex = (fl->fl_type == F_WRLCK);
....@@ -128,36 +126,45 @@
128126 op->info.number = number;
129127 op->info.start = fl->fl_start;
130128 op->info.end = fl->fl_end;
129
+ /* async handling */
131130 if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
131
+ op_data = kzalloc(sizeof(*op_data), GFP_NOFS);
132
+ if (!op_data) {
133
+ dlm_release_plock_op(op);
134
+ rv = -ENOMEM;
135
+ goto out;
136
+ }
137
+
132138 /* fl_owner is lockd which doesn't distinguish
133139 processes on the nfs client */
134140 op->info.owner = (__u64) fl->fl_pid;
135
- xop->callback = fl->fl_lmops->lm_grant;
136
- locks_init_lock(&xop->flc);
137
- locks_copy_lock(&xop->flc, fl);
138
- xop->fl = fl;
139
- xop->file = file;
141
+ op_data->callback = fl->fl_lmops->lm_grant;
142
+ locks_init_lock(&op_data->flc);
143
+ locks_copy_lock(&op_data->flc, fl);
144
+ op_data->fl = fl;
145
+ op_data->file = file;
146
+
147
+ op->data = op_data;
148
+
149
+ send_op(op);
150
+ rv = FILE_LOCK_DEFERRED;
151
+ goto out;
140152 } else {
141153 op->info.owner = (__u64)(long) fl->fl_owner;
142
- xop->callback = NULL;
143154 }
144155
145156 send_op(op);
146157
147
- if (xop->callback == NULL) {
148
- rv = wait_event_interruptible(recv_wq, (op->done != 0));
149
- if (rv == -ERESTARTSYS) {
150
- log_debug(ls, "dlm_posix_lock: wait killed %llx",
151
- (unsigned long long)number);
152
- spin_lock(&ops_lock);
153
- list_del(&op->list);
154
- spin_unlock(&ops_lock);
155
- kfree(xop);
156
- do_unlock_close(ls, number, file, fl);
157
- goto out;
158
- }
159
- } else {
160
- rv = FILE_LOCK_DEFERRED;
158
+ rv = wait_event_killable(recv_wq, (op->done != 0));
159
+ if (rv == -ERESTARTSYS) {
160
+ spin_lock(&ops_lock);
161
+ list_del(&op->list);
162
+ spin_unlock(&ops_lock);
163
+ log_debug(ls, "%s: wait interrupted %x %llx pid %d",
164
+ __func__, ls->ls_global_id,
165
+ (unsigned long long)number, op->info.pid);
166
+ dlm_release_plock_op(op);
167
+ do_unlock_close(&op->info);
161168 goto out;
162169 }
163170
....@@ -177,7 +184,7 @@
177184 (unsigned long long)number);
178185 }
179186
180
- kfree(xop);
187
+ dlm_release_plock_op(op);
181188 out:
182189 dlm_put_lockspace(ls);
183190 return rv;
....@@ -187,11 +194,11 @@
187194 /* Returns failure iff a successful lock operation should be canceled */
188195 static int dlm_plock_callback(struct plock_op *op)
189196 {
197
+ struct plock_async_data *op_data = op->data;
190198 struct file *file;
191199 struct file_lock *fl;
192200 struct file_lock *flc;
193201 int (*notify)(struct file_lock *fl, int result) = NULL;
194
- struct plock_xop *xop = (struct plock_xop *)op;
195202 int rv = 0;
196203
197204 spin_lock(&ops_lock);
....@@ -203,10 +210,10 @@
203210 spin_unlock(&ops_lock);
204211
205212 /* check if the following 2 are still valid or make a copy */
206
- file = xop->file;
207
- flc = &xop->flc;
208
- fl = xop->fl;
209
- notify = xop->callback;
213
+ file = op_data->file;
214
+ flc = &op_data->flc;
215
+ fl = op_data->fl;
216
+ notify = op_data->callback;
210217
211218 if (op->info.rv) {
212219 notify(fl, op->info.rv);
....@@ -237,7 +244,7 @@
237244 }
238245
239246 out:
240
- kfree(xop);
247
+ dlm_release_plock_op(op);
241248 return rv;
242249 }
243250
....@@ -307,7 +314,7 @@
307314 rv = 0;
308315
309316 out_free:
310
- kfree(op);
317
+ dlm_release_plock_op(op);
311318 out:
312319 dlm_put_lockspace(ls);
313320 fl->fl_flags = fl_flags;
....@@ -367,13 +374,15 @@
367374 locks_init_lock(fl);
368375 fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
369376 fl->fl_flags = FL_POSIX;
370
- fl->fl_pid = -op->info.pid;
377
+ fl->fl_pid = op->info.pid;
378
+ if (op->info.nodeid != dlm_our_nodeid())
379
+ fl->fl_pid = -fl->fl_pid;
371380 fl->fl_start = op->info.start;
372381 fl->fl_end = op->info.end;
373382 rv = 0;
374383 }
375384
376
- kfree(op);
385
+ dlm_release_plock_op(op);
377386 out:
378387 dlm_put_lockspace(ls);
379388 return rv;
....@@ -396,7 +405,7 @@
396405 if (op->info.flags & DLM_PLOCK_FL_CLOSE)
397406 list_del(&op->list);
398407 else
399
- list_move(&op->list, &recv_list);
408
+ list_move_tail(&op->list, &recv_list);
400409 memcpy(&info, &op->info, sizeof(info));
401410 }
402411 spin_unlock(&ops_lock);
....@@ -409,7 +418,7 @@
409418 (the process did not make an unlock call). */
410419
411420 if (op->info.flags & DLM_PLOCK_FL_CLOSE)
412
- kfree(op);
421
+ dlm_release_plock_op(op);
413422
414423 if (copy_to_user(u, &info, sizeof(info)))
415424 return -EFAULT;
....@@ -421,9 +430,9 @@
421430 static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
422431 loff_t *ppos)
423432 {
433
+ struct plock_op *op = NULL, *iter;
424434 struct dlm_plock_info info;
425
- struct plock_op *op;
426
- int found = 0, do_callback = 0;
435
+ int do_callback = 0;
427436
428437 if (count != sizeof(info))
429438 return -EINVAL;
....@@ -434,32 +443,63 @@
434443 if (check_version(&info))
435444 return -EINVAL;
436445
446
+ /*
447
+ * The results for waiting ops (SETLKW) can be returned in any
448
+ * order, so match all fields to find the op. The results for
449
+ * non-waiting ops are returned in the order that they were sent
450
+ * to userspace, so match the result with the first non-waiting op.
451
+ */
437452 spin_lock(&ops_lock);
438
- list_for_each_entry(op, &recv_list, list) {
439
- if (op->info.fsid == info.fsid &&
440
- op->info.number == info.number &&
441
- op->info.owner == info.owner) {
442
- struct plock_xop *xop = (struct plock_xop *)op;
443
- list_del_init(&op->list);
444
- memcpy(&op->info, &info, sizeof(info));
445
- if (xop->callback)
446
- do_callback = 1;
447
- else
448
- op->done = 1;
449
- found = 1;
450
- break;
453
+ if (info.wait) {
454
+ list_for_each_entry(iter, &recv_list, list) {
455
+ if (iter->info.fsid == info.fsid &&
456
+ iter->info.number == info.number &&
457
+ iter->info.owner == info.owner &&
458
+ iter->info.pid == info.pid &&
459
+ iter->info.start == info.start &&
460
+ iter->info.end == info.end &&
461
+ iter->info.ex == info.ex &&
462
+ iter->info.wait) {
463
+ op = iter;
464
+ break;
465
+ }
451466 }
467
+ } else {
468
+ list_for_each_entry(iter, &recv_list, list) {
469
+ if (!iter->info.wait &&
470
+ iter->info.fsid == info.fsid) {
471
+ op = iter;
472
+ break;
473
+ }
474
+ }
475
+ }
476
+
477
+ if (op) {
478
+ /* Sanity check that op and info match. */
479
+ if (info.wait)
480
+ WARN_ON(op->info.optype != DLM_PLOCK_OP_LOCK);
481
+ else
482
+ WARN_ON(op->info.number != info.number ||
483
+ op->info.owner != info.owner ||
484
+ op->info.optype != info.optype);
485
+
486
+ list_del_init(&op->list);
487
+ memcpy(&op->info, &info, sizeof(info));
488
+ if (op->data)
489
+ do_callback = 1;
490
+ else
491
+ op->done = 1;
452492 }
453493 spin_unlock(&ops_lock);
454494
455
- if (found) {
495
+ if (op) {
456496 if (do_callback)
457497 dlm_plock_callback(op);
458498 else
459499 wake_up(&recv_wq);
460500 } else
461
- log_print("dev_write no op %x %llx", info.fsid,
462
- (unsigned long long)info.number);
501
+ log_print("%s: no op %x %llx", __func__,
502
+ info.fsid, (unsigned long long)info.number);
463503 return count;
464504 }
465505