@@ -25,6 +25,15 @@ struct plock_op {
25
25
struct gdlm_plock_info info ;
26
26
};
27
27
28
+ struct plock_xop {
29
+ struct plock_op xop ;
30
+ void * callback ;
31
+ void * fl ;
32
+ void * file ;
33
+ struct file_lock flc ;
34
+ };
35
+
36
+
28
37
static inline void set_version (struct gdlm_plock_info * info )
29
38
{
30
39
info -> version [0 ] = GDLM_PLOCK_VERSION_MAJOR ;
@@ -64,12 +73,14 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
64
73
{
65
74
struct gdlm_ls * ls = lockspace ;
66
75
struct plock_op * op ;
76
+ struct plock_xop * xop ;
67
77
int rv ;
68
78
69
- op = kzalloc (sizeof (* op ), GFP_KERNEL );
70
- if (!op )
79
+ xop = kzalloc (sizeof (* xop ), GFP_KERNEL );
80
+ if (!xop )
71
81
return - ENOMEM ;
72
82
83
+ op = & xop -> xop ;
73
84
op -> info .optype = GDLM_PLOCK_OP_LOCK ;
74
85
op -> info .pid = fl -> fl_pid ;
75
86
op -> info .ex = (fl -> fl_type == F_WRLCK );
@@ -79,9 +90,21 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
79
90
op -> info .start = fl -> fl_start ;
80
91
op -> info .end = fl -> fl_end ;
81
92
op -> info .owner = (__u64 )(long ) fl -> fl_owner ;
93
+ if (fl -> fl_lmops && fl -> fl_lmops -> fl_grant ) {
94
+ xop -> callback = fl -> fl_lmops -> fl_grant ;
95
+ locks_init_lock (& xop -> flc );
96
+ locks_copy_lock (& xop -> flc , fl );
97
+ xop -> fl = fl ;
98
+ xop -> file = file ;
99
+ } else
100
+ xop -> callback = NULL ;
82
101
83
102
send_op (op );
84
- wait_event (recv_wq , (op -> done != 0 ));
103
+
104
+ if (xop -> callback == NULL )
105
+ wait_event (recv_wq , (op -> done != 0 ));
106
+ else
107
+ return - EINPROGRESS ;
85
108
86
109
spin_lock (& ops_lock );
87
110
if (!list_empty (& op -> list )) {
@@ -99,7 +122,63 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
99
122
(unsigned long long )name -> ln_number );
100
123
}
101
124
102
- kfree (op );
125
+ kfree (xop );
126
+ return rv ;
127
+ }
128
+
129
+ /* Returns failure iff a succesful lock operation should be canceled */
130
+ static int gdlm_plock_callback (struct plock_op * op )
131
+ {
132
+ struct file * file ;
133
+ struct file_lock * fl ;
134
+ struct file_lock * flc ;
135
+ int (* notify )(void * , void * , int ) = NULL ;
136
+ struct plock_xop * xop = (struct plock_xop * )op ;
137
+ int rv = 0 ;
138
+
139
+ spin_lock (& ops_lock );
140
+ if (!list_empty (& op -> list )) {
141
+ printk (KERN_INFO "plock op on list\n" );
142
+ list_del (& op -> list );
143
+ }
144
+ spin_unlock (& ops_lock );
145
+
146
+ /* check if the following 2 are still valid or make a copy */
147
+ file = xop -> file ;
148
+ flc = & xop -> flc ;
149
+ fl = xop -> fl ;
150
+ notify = xop -> callback ;
151
+
152
+ if (op -> info .rv ) {
153
+ notify (flc , NULL , op -> info .rv );
154
+ goto out ;
155
+ }
156
+
157
+ /* got fs lock; bookkeep locally as well: */
158
+ flc -> fl_flags &= ~FL_SLEEP ;
159
+ if (posix_lock_file (file , flc , NULL )) {
160
+ /*
161
+ * This can only happen in the case of kmalloc() failure.
162
+ * The filesystem's own lock is the authoritative lock,
163
+ * so a failure to get the lock locally is not a disaster.
164
+ * As long as GFS cannot reliably cancel locks (especially
165
+ * in a low-memory situation), we're better off ignoring
166
+ * this failure than trying to recover.
167
+ */
168
+ log_error ("gdlm_plock: vfs lock error file %p fl %p" ,
169
+ file , fl );
170
+ }
171
+
172
+ rv = notify (flc , NULL , 0 );
173
+ if (rv ) {
174
+ /* XXX: We need to cancel the fs lock here: */
175
+ printk ("gfs2 lock granted after lock request failed;"
176
+ " dangling lock!\n" );
177
+ goto out ;
178
+ }
179
+
180
+ out :
181
+ kfree (xop );
103
182
return rv ;
104
183
}
105
184
@@ -138,6 +217,9 @@ int gdlm_punlock(void *lockspace, struct lm_lockname *name,
138
217
139
218
rv = op -> info .rv ;
140
219
220
+ if (rv == - ENOENT )
221
+ rv = 0 ;
222
+
141
223
kfree (op );
142
224
return rv ;
143
225
}
@@ -161,6 +243,7 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
161
243
op -> info .start = fl -> fl_start ;
162
244
op -> info .end = fl -> fl_end ;
163
245
246
+
164
247
send_op (op );
165
248
wait_event (recv_wq , (op -> done != 0 ));
166
249
@@ -173,9 +256,10 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
173
256
174
257
rv = op -> info .rv ;
175
258
176
- if (rv == 0 )
177
- fl -> fl_type = F_UNLCK ;
178
- else if (rv > 0 ) {
259
+ fl -> fl_type = F_UNLCK ;
260
+ if (rv == - ENOENT )
261
+ rv = 0 ;
262
+ else if (rv == 0 && op -> info .pid != fl -> fl_pid ) {
179
263
fl -> fl_type = (op -> info .ex ) ? F_WRLCK : F_RDLCK ;
180
264
fl -> fl_pid = op -> info .pid ;
181
265
fl -> fl_start = op -> info .start ;
@@ -243,9 +327,14 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
243
327
}
244
328
spin_unlock (& ops_lock );
245
329
246
- if (found )
247
- wake_up (& recv_wq );
248
- else
330
+ if (found ) {
331
+ struct plock_xop * xop ;
332
+ xop = (struct plock_xop * )op ;
333
+ if (xop -> callback )
334
+ count = gdlm_plock_callback (op );
335
+ else
336
+ wake_up (& recv_wq );
337
+ } else
249
338
printk (KERN_INFO "gdlm dev_write no op %x %llx\n" , info .fsid ,
250
339
(unsigned long long )info .number );
251
340
return count ;
0 commit comments