hc
2024-05-11 645e752c5a84baeb21015cdc85fc05b7d16312c8
kernel/fs/dlm/plock.c
....@@ -19,20 +19,20 @@
1919 static wait_queue_head_t send_wq;
2020 static wait_queue_head_t recv_wq;
2121
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
+
2229 struct plock_op {
2330 struct list_head list;
2431 int done;
2532 struct dlm_plock_info info;
26
- int (*callback)(struct file_lock *fl, int result);
33
+ /* if set indicates async handling */
34
+ struct plock_async_data *data;
2735 };
28
-
29
-struct plock_xop {
30
- struct plock_op xop;
31
- void *fl;
32
- void *file;
33
- struct file_lock flc;
34
-};
35
-
3636
3737 static inline void set_version(struct dlm_plock_info *info)
3838 {
....@@ -58,6 +58,12 @@
5858 return 0;
5959 }
6060
61
+static void dlm_release_plock_op(struct plock_op *op)
62
+{
63
+ kfree(op->data);
64
+ kfree(op);
65
+}
66
+
6167 static void send_op(struct plock_op *op)
6268 {
6369 set_version(&op->info);
....@@ -74,8 +80,7 @@
7480 abandoned waiter. So, we have to insert the unlock-close when the
7581 lock call is interrupted. */
7682
77
-static void do_unlock_close(struct dlm_ls *ls, u64 number,
78
- struct file *file, struct file_lock *fl)
83
+static void do_unlock_close(const struct dlm_plock_info *info)
7984 {
8085 struct plock_op *op;
8186
....@@ -84,15 +89,12 @@
8489 return;
8590
8691 op->info.optype = DLM_PLOCK_OP_UNLOCK;
87
- op->info.pid = fl->fl_pid;
88
- op->info.fsid = ls->ls_global_id;
89
- op->info.number = number;
92
+ op->info.pid = info->pid;
93
+ op->info.fsid = info->fsid;
94
+ op->info.number = info->number;
9095 op->info.start = 0;
9196 op->info.end = OFFSET_MAX;
92
- if (fl->fl_lmops && fl->fl_lmops->lm_grant)
93
- op->info.owner = (__u64) fl->fl_pid;
94
- else
95
- op->info.owner = (__u64)(long) fl->fl_owner;
97
+ op->info.owner = info->owner;
9698
9799 op->info.flags |= DLM_PLOCK_FL_CLOSE;
98100 send_op(op);
....@@ -101,22 +103,21 @@
101103 int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
102104 int cmd, struct file_lock *fl)
103105 {
106
+ struct plock_async_data *op_data;
104107 struct dlm_ls *ls;
105108 struct plock_op *op;
106
- struct plock_xop *xop;
107109 int rv;
108110
109111 ls = dlm_find_lockspace_local(lockspace);
110112 if (!ls)
111113 return -EINVAL;
112114
113
- xop = kzalloc(sizeof(*xop), GFP_NOFS);
114
- if (!xop) {
115
+ op = kzalloc(sizeof(*op), GFP_NOFS);
116
+ if (!op) {
115117 rv = -ENOMEM;
116118 goto out;
117119 }
118120
119
- op = &xop->xop;
120121 op->info.optype = DLM_PLOCK_OP_LOCK;
121122 op->info.pid = fl->fl_pid;
122123 op->info.ex = (fl->fl_type == F_WRLCK);
....@@ -125,35 +126,45 @@
125126 op->info.number = number;
126127 op->info.start = fl->fl_start;
127128 op->info.end = fl->fl_end;
129
+ /* async handling */
128130 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
+
129138 /* fl_owner is lockd which doesn't distinguish
130139 processes on the nfs client */
131140 op->info.owner = (__u64) fl->fl_pid;
132
- op->callback = fl->fl_lmops->lm_grant;
133
- locks_init_lock(&xop->flc);
134
- locks_copy_lock(&xop->flc, fl);
135
- xop->fl = fl;
136
- 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;
137152 } else {
138153 op->info.owner = (__u64)(long) fl->fl_owner;
139154 }
140155
141156 send_op(op);
142157
143
- if (!op->callback) {
144
- rv = wait_event_interruptible(recv_wq, (op->done != 0));
145
- if (rv == -ERESTARTSYS) {
146
- log_debug(ls, "dlm_posix_lock: wait killed %llx",
147
- (unsigned long long)number);
148
- spin_lock(&ops_lock);
149
- list_del(&op->list);
150
- spin_unlock(&ops_lock);
151
- kfree(xop);
152
- do_unlock_close(ls, number, file, fl);
153
- goto out;
154
- }
155
- } else {
156
- 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);
157168 goto out;
158169 }
159170
....@@ -173,7 +184,7 @@
173184 (unsigned long long)number);
174185 }
175186
176
- kfree(xop);
187
+ dlm_release_plock_op(op);
177188 out:
178189 dlm_put_lockspace(ls);
179190 return rv;
....@@ -183,11 +194,11 @@
183194 /* Returns failure iff a successful lock operation should be canceled */
184195 static int dlm_plock_callback(struct plock_op *op)
185196 {
197
+ struct plock_async_data *op_data = op->data;
186198 struct file *file;
187199 struct file_lock *fl;
188200 struct file_lock *flc;
189201 int (*notify)(struct file_lock *fl, int result) = NULL;
190
- struct plock_xop *xop = (struct plock_xop *)op;
191202 int rv = 0;
192203
193204 spin_lock(&ops_lock);
....@@ -199,10 +210,10 @@
199210 spin_unlock(&ops_lock);
200211
201212 /* check if the following 2 are still valid or make a copy */
202
- file = xop->file;
203
- flc = &xop->flc;
204
- fl = xop->fl;
205
- notify = op->callback;
213
+ file = op_data->file;
214
+ flc = &op_data->flc;
215
+ fl = op_data->fl;
216
+ notify = op_data->callback;
206217
207218 if (op->info.rv) {
208219 notify(fl, op->info.rv);
....@@ -233,7 +244,7 @@
233244 }
234245
235246 out:
236
- kfree(xop);
247
+ dlm_release_plock_op(op);
237248 return rv;
238249 }
239250
....@@ -303,7 +314,7 @@
303314 rv = 0;
304315
305316 out_free:
306
- kfree(op);
317
+ dlm_release_plock_op(op);
307318 out:
308319 dlm_put_lockspace(ls);
309320 fl->fl_flags = fl_flags;
....@@ -363,13 +374,15 @@
363374 locks_init_lock(fl);
364375 fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
365376 fl->fl_flags = FL_POSIX;
366
- 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;
367380 fl->fl_start = op->info.start;
368381 fl->fl_end = op->info.end;
369382 rv = 0;
370383 }
371384
372
- kfree(op);
385
+ dlm_release_plock_op(op);
373386 out:
374387 dlm_put_lockspace(ls);
375388 return rv;
....@@ -392,7 +405,7 @@
392405 if (op->info.flags & DLM_PLOCK_FL_CLOSE)
393406 list_del(&op->list);
394407 else
395
- list_move(&op->list, &recv_list);
408
+ list_move_tail(&op->list, &recv_list);
396409 memcpy(&info, &op->info, sizeof(info));
397410 }
398411 spin_unlock(&ops_lock);
....@@ -405,7 +418,7 @@
405418 (the process did not make an unlock call). */
406419
407420 if (op->info.flags & DLM_PLOCK_FL_CLOSE)
408
- kfree(op);
421
+ dlm_release_plock_op(op);
409422
410423 if (copy_to_user(u, &info, sizeof(info)))
411424 return -EFAULT;
....@@ -417,9 +430,9 @@
417430 static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
418431 loff_t *ppos)
419432 {
433
+ struct plock_op *op = NULL, *iter;
420434 struct dlm_plock_info info;
421
- struct plock_op *op;
422
- int found = 0, do_callback = 0;
435
+ int do_callback = 0;
423436
424437 if (count != sizeof(info))
425438 return -EINVAL;
....@@ -430,31 +443,63 @@
430443 if (check_version(&info))
431444 return -EINVAL;
432445
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
+ */
433452 spin_lock(&ops_lock);
434
- list_for_each_entry(op, &recv_list, list) {
435
- if (op->info.fsid == info.fsid &&
436
- op->info.number == info.number &&
437
- op->info.owner == info.owner) {
438
- list_del_init(&op->list);
439
- memcpy(&op->info, &info, sizeof(info));
440
- if (op->callback)
441
- do_callback = 1;
442
- else
443
- op->done = 1;
444
- found = 1;
445
- 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
+ }
446466 }
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;
447492 }
448493 spin_unlock(&ops_lock);
449494
450
- if (found) {
495
+ if (op) {
451496 if (do_callback)
452497 dlm_plock_callback(op);
453498 else
454499 wake_up(&recv_wq);
455500 } else
456
- log_print("dev_write no op %x %llx", info.fsid,
457
- (unsigned long long)info.number);
501
+ log_print("%s: no op %x %llx", __func__,
502
+ info.fsid, (unsigned long long)info.number);
458503 return count;
459504 }
460505