a555d3ae4fe2e53d618e70fb786c23950338e8db
[samba-bkup.git] / source3 / smbd / smb2_oplock.c
1 /* 
2    Unix SMB/CIFS implementation.
3    oplock processing
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 1998 - 2001
6    Copyright (C) Volker Lendecke 2005
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #define DBGC_CLASS DBGC_LOCKING
23 #include "includes.h"
24 #include "lib/util/server_id.h"
25 #include "locking/share_mode_lock.h"
26 #include "smbd/smbd.h"
27 #include "smbd/globals.h"
28 #include "messages.h"
29 #include "locking/leases_db.h"
30 #include "../librpc/gen_ndr/ndr_open_files.h"
31
32 /*
33  * helper function used by the kernel oplock backends to post the break message
34  */
35 void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp)
36 {
37         uint8_t msg[MSG_SMB_KERNEL_BREAK_SIZE];
38
39         /* Put the kernel break info into the message. */
40         push_file_id_24((char *)msg, &fsp->file_id);
41         SIVAL(msg, 24, fh_get_gen_id(fsp->fh));
42
43         /* Don't need to be root here as we're only ever
44            sending to ourselves. */
45
46         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
47                            MSG_SMB_KERNEL_BREAK,
48                            msg, MSG_SMB_KERNEL_BREAK_SIZE);
49 }
50
51 /****************************************************************************
52  Attempt to set an oplock on a file. Succeeds if kernel oplocks are
53  disabled (just sets flags).
54 ****************************************************************************/
55
56 NTSTATUS set_file_oplock(files_struct *fsp)
57 {
58         struct smbd_server_connection *sconn = fsp->conn->sconn;
59         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
60         bool use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
61                         (koplocks != NULL);
62         struct file_id_buf buf;
63
64         if (fsp->oplock_type == LEVEL_II_OPLOCK && use_kernel) {
65                 DEBUG(10, ("Refusing level2 oplock, kernel oplocks "
66                            "don't support them\n"));
67                 return NT_STATUS_NOT_SUPPORTED;
68         }
69
70         if ((fsp->oplock_type != NO_OPLOCK) &&
71             use_kernel &&
72             !koplocks->ops->set_oplock(koplocks, fsp, fsp->oplock_type))
73         {
74                 return map_nt_error_from_unix(errno);
75         }
76
77         fsp->sent_oplock_break = NO_BREAK_SENT;
78         if (fsp->oplock_type == LEVEL_II_OPLOCK) {
79                 sconn->oplocks.level_II_open++;
80         } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
81                 sconn->oplocks.exclusive_open++;
82         }
83
84         DBG_INFO("granted oplock on file %s, %s/%"PRIu64", "
85                  "tv_sec = %x, tv_usec = %x\n",
86                  fsp_str_dbg(fsp),
87                  file_id_str_buf(fsp->file_id, &buf),
88                  fh_get_gen_id(fsp->fh),
89                  (int)fsp->open_time.tv_sec,
90                  (int)fsp->open_time.tv_usec);
91
92         return NT_STATUS_OK;
93 }
94
95 static void release_fsp_kernel_oplock(files_struct *fsp)
96 {
97         struct smbd_server_connection *sconn = fsp->conn->sconn;
98         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
99         bool use_kernel;
100
101         if (koplocks == NULL) {
102                 return;
103         }
104         use_kernel = lp_kernel_oplocks(SNUM(fsp->conn));
105         if (!use_kernel) {
106                 return;
107         }
108         if (fsp->oplock_type == NO_OPLOCK) {
109                 return;
110         }
111         if (fsp->oplock_type == LEASE_OPLOCK) {
112                 /*
113                  * For leases we don't touch kernel oplocks at all
114                  */
115                 return;
116         }
117
118         koplocks->ops->release_oplock(koplocks, fsp, NO_OPLOCK);
119 }
120
121 /****************************************************************************
122  Attempt to release an oplock on a file. Decrements oplock count.
123 ****************************************************************************/
124
125 static void release_file_oplock(files_struct *fsp)
126 {
127         struct smbd_server_connection *sconn = fsp->conn->sconn;
128
129         release_fsp_kernel_oplock(fsp);
130
131         if (fsp->oplock_type == LEVEL_II_OPLOCK) {
132                 sconn->oplocks.level_II_open--;
133         } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
134                 sconn->oplocks.exclusive_open--;
135         }
136
137         SMB_ASSERT(sconn->oplocks.exclusive_open>=0);
138         SMB_ASSERT(sconn->oplocks.level_II_open>=0);
139
140         fsp->oplock_type = NO_OPLOCK;
141         fsp->sent_oplock_break = NO_BREAK_SENT;
142
143         TALLOC_FREE(fsp->oplock_timeout);
144 }
145
146 /****************************************************************************
147  Attempt to downgrade an oplock on a file. Doesn't decrement oplock count.
148 ****************************************************************************/
149
150 static void downgrade_file_oplock(files_struct *fsp)
151 {
152         struct smbd_server_connection *sconn = fsp->conn->sconn;
153         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
154         bool use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
155                         (koplocks != NULL);
156
157         if (!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
158                 DEBUG(0, ("trying to downgrade an already-downgraded oplock!\n"));
159                 return;
160         }
161
162         if (use_kernel) {
163                 koplocks->ops->release_oplock(koplocks, fsp, LEVEL_II_OPLOCK);
164         }
165         fsp->oplock_type = LEVEL_II_OPLOCK;
166         sconn->oplocks.exclusive_open--;
167         sconn->oplocks.level_II_open++;
168         fsp->sent_oplock_break = NO_BREAK_SENT;
169
170         TALLOC_FREE(fsp->oplock_timeout);
171 }
172
173 uint32_t get_lease_type(struct share_mode_entry *e, struct file_id id)
174 {
175         struct GUID_txt_buf guid_strbuf;
176         struct file_id_buf file_id_strbuf;
177         NTSTATUS status;
178         uint32_t current_state;
179
180         if (e->op_type != LEASE_OPLOCK) {
181                 return map_oplock_to_lease_type(e->op_type);
182         }
183
184         status = leases_db_get(&e->client_guid,
185                                &e->lease_key,
186                                &id,
187                                &current_state,
188                                NULL,    /* breaking */
189                                NULL,    /* breaking_to_requested */
190                                NULL,    /* breaking_to_required */
191                                NULL,    /* lease_version */
192                                NULL);   /* epoch */
193         if (NT_STATUS_IS_OK(status)) {
194                 return current_state;
195         }
196
197         if (share_entry_stale_pid(e)) {
198                 return 0;
199         }
200         DBG_ERR("leases_db_get for client_guid [%s] "
201                 "lease_key [%"PRIu64"/%"PRIu64"] "
202                 "file_id [%s] failed: %s\n",
203                 GUID_buf_string(&e->client_guid, &guid_strbuf),
204                 e->lease_key.data[0],
205                 e->lease_key.data[1],
206                 file_id_str_buf(id, &file_id_strbuf),
207                 nt_errstr(status));
208         smb_panic("leases_db_get() failed");
209 }
210
211 /****************************************************************************
212  Remove a file oplock. Copes with level II and exclusive.
213  Locks then unlocks the share mode lock. Client can decide to go directly
214  to none even if a "break-to-level II" was sent.
215 ****************************************************************************/
216
217 bool remove_oplock(files_struct *fsp)
218 {
219         bool ret;
220         struct share_mode_lock *lck;
221
222         DBG_DEBUG("remove_oplock called for %s\n", fsp_str_dbg(fsp));
223
224         /* Remove the oplock flag from the sharemode. */
225         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
226         if (lck == NULL) {
227                 DBG_ERR("failed to lock share entry for "
228                          "file %s\n", fsp_str_dbg(fsp));
229                 return false;
230         }
231
232         ret = remove_share_oplock(lck, fsp);
233         if (!ret) {
234                 struct file_id_buf buf;
235
236                 DBG_ERR("failed to remove share oplock for "
237                         "file %s, %s, %s\n",
238                         fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
239                         file_id_str_buf(fsp->file_id, &buf));
240         }
241         release_file_oplock(fsp);
242
243         TALLOC_FREE(lck);
244         return ret;
245 }
246
247 /*
248  * Deal with a reply when a break-to-level II was sent.
249  */
250 bool downgrade_oplock(files_struct *fsp)
251 {
252         bool ret;
253         struct share_mode_lock *lck;
254
255         DEBUG(10, ("downgrade_oplock called for %s\n",
256                    fsp_str_dbg(fsp)));
257
258         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
259         if (lck == NULL) {
260                 DEBUG(0,("downgrade_oplock: failed to lock share entry for "
261                          "file %s\n", fsp_str_dbg(fsp)));
262                 return False;
263         }
264         ret = downgrade_share_oplock(lck, fsp);
265         if (!ret) {
266                 struct file_id_buf idbuf;
267                 DBG_ERR("failed to downgrade share oplock "
268                         "for file %s, %s, file_id %s\n",
269                         fsp_str_dbg(fsp),
270                         fsp_fnum_dbg(fsp),
271                         file_id_str_buf(fsp->file_id, &idbuf));
272         }
273         downgrade_file_oplock(fsp);
274
275         TALLOC_FREE(lck);
276         return ret;
277 }
278
279 static void lease_timeout_handler(struct tevent_context *ctx,
280                                   struct tevent_timer *te,
281                                   struct timeval now,
282                                   void *private_data)
283 {
284         struct fsp_lease *lease =
285                 talloc_get_type_abort(private_data,
286                 struct fsp_lease);
287         struct files_struct *fsp;
288         struct share_mode_lock *lck;
289         uint16_t old_epoch = lease->lease.lease_epoch;
290
291         fsp = file_find_one_fsp_from_lease_key(lease->sconn,
292                                                &lease->lease.lease_key);
293         if (fsp == NULL) {
294                 /* race? */
295                 TALLOC_FREE(lease->timeout);
296                 return;
297         }
298
299         /*
300          * Paranoia check: There can only be one fsp_lease per lease
301          * key
302          */
303         SMB_ASSERT(fsp->lease == lease);
304
305         lck = get_existing_share_mode_lock(
306                         talloc_tos(), fsp->file_id);
307         if (lck == NULL) {
308                 /* race? */
309                 TALLOC_FREE(lease->timeout);
310                 return;
311         }
312
313         fsp_lease_update(fsp);
314
315         if (lease->lease.lease_epoch != old_epoch) {
316                 /*
317                  * If the epoch changed we need to wait for
318                  * the next timeout to happen.
319                  */
320                 DEBUG(10, ("lease break timeout race (epoch) for file %s - ignoring\n",
321                            fsp_str_dbg(fsp)));
322                 TALLOC_FREE(lck);
323                 return;
324         }
325
326         if (!(lease->lease.lease_flags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)) {
327                 /*
328                  * If the epoch changed we need to wait for
329                  * the next timeout to happen.
330                  */
331                 DEBUG(10, ("lease break timeout race (flags) for file %s - ignoring\n",
332                            fsp_str_dbg(fsp)));
333                 TALLOC_FREE(lck);
334                 return;
335         }
336
337         DEBUG(1, ("lease break timed out for file %s -- replying anyway\n",
338                   fsp_str_dbg(fsp)));
339         (void)downgrade_lease(lease->sconn->client,
340                         1,
341                         &fsp->file_id,
342                         &lease->lease.lease_key,
343                         SMB2_LEASE_NONE);
344
345         TALLOC_FREE(lck);
346 }
347
348 bool fsp_lease_update(struct files_struct *fsp)
349 {
350         const struct GUID *client_guid = fsp_client_guid(fsp);
351         struct fsp_lease *lease = fsp->lease;
352         uint32_t current_state;
353         bool breaking;
354         uint16_t lease_version, epoch;
355         NTSTATUS status;
356
357         status = leases_db_get(client_guid,
358                                &lease->lease.lease_key,
359                                &fsp->file_id,
360                                &current_state,
361                                &breaking,
362                                NULL, /* breaking_to_requested */
363                                NULL, /* breaking_to_required */
364                                &lease_version,
365                                &epoch);
366         if (!NT_STATUS_IS_OK(status)) {
367                 DBG_WARNING("Could not find lease entry: %s\n",
368                             nt_errstr(status));
369                 TALLOC_FREE(lease->timeout);
370                 lease->lease.lease_state = SMB2_LEASE_NONE;
371                 lease->lease.lease_epoch += 1;
372                 lease->lease.lease_flags = 0;
373                 return false;
374         }
375
376         DEBUG(10,("%s: refresh lease state\n", __func__));
377
378         /* Ensure we're in sync with current lease state. */
379         if (lease->lease.lease_epoch != epoch) {
380                 DEBUG(10,("%s: cancel outdated timeout\n", __func__));
381                 TALLOC_FREE(lease->timeout);
382         }
383         lease->lease.lease_epoch = epoch;
384         lease->lease.lease_state = current_state;
385
386         if (breaking) {
387                 lease->lease.lease_flags |= SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
388
389                 if (lease->timeout == NULL) {
390                         struct timeval t = timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0);
391
392                         DEBUG(10,("%s: setup timeout handler\n", __func__));
393
394                         lease->timeout = tevent_add_timer(lease->sconn->ev_ctx,
395                                                           lease, t,
396                                                           lease_timeout_handler,
397                                                           lease);
398                         if (lease->timeout == NULL) {
399                                 DEBUG(0, ("%s: Could not add lease timeout handler\n",
400                                           __func__));
401                         }
402                 }
403         } else {
404                 lease->lease.lease_flags &= ~SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
405                 TALLOC_FREE(lease->timeout);
406         }
407
408         return true;
409 }
410
411 struct downgrade_lease_additional_state {
412         struct tevent_immediate *im;
413         struct smbXsrv_client *client;
414         uint32_t break_flags;
415         struct smb2_lease_key lease_key;
416         uint32_t break_from;
417         uint32_t break_to;
418         uint16_t new_epoch;
419 };
420
421 static void downgrade_lease_additional_trigger(struct tevent_context *ev,
422                                                struct tevent_immediate *im,
423                                                void *private_data)
424 {
425         struct downgrade_lease_additional_state *state =
426                 talloc_get_type_abort(private_data,
427                 struct downgrade_lease_additional_state);
428         NTSTATUS status;
429
430         status = smbd_smb2_send_lease_break(state->client,
431                                             state->new_epoch,
432                                             state->break_flags,
433                                             &state->lease_key,
434                                             state->break_from,
435                                             state->break_to);
436         if (!NT_STATUS_IS_OK(status)) {
437                 smbd_server_disconnect_client(state->client,
438                                               nt_errstr(status));
439         }
440         TALLOC_FREE(state);
441 }
442
443 struct fsps_lease_update_state {
444         const struct file_id *id;
445         const struct smb2_lease_key *key;
446 };
447
448 static struct files_struct *fsps_lease_update_fn(
449         struct files_struct *fsp, void *private_data)
450 {
451         struct fsps_lease_update_state *state =
452                 (struct fsps_lease_update_state *)private_data;
453
454         if (fsp->oplock_type != LEASE_OPLOCK) {
455                 return NULL;
456         }
457         if (!smb2_lease_key_equal(&fsp->lease->lease.lease_key, state->key)) {
458                 return NULL;
459         }
460         if (!file_id_equal(&fsp->file_id, state->id)) {
461                 return NULL;
462         }
463
464         fsp_lease_update(fsp);
465
466         return NULL;
467 }
468
469 static void fsps_lease_update(struct smbd_server_connection *sconn,
470                               const struct file_id *id,
471                               const struct smb2_lease_key *key)
472 {
473         struct fsps_lease_update_state state = { .id = id, .key = key };
474         files_forall(sconn, fsps_lease_update_fn, &state);
475 }
476
477 NTSTATUS downgrade_lease(struct smbXsrv_client *client,
478                          uint32_t num_file_ids,
479                          const struct file_id *ids,
480                          const struct smb2_lease_key *key,
481                          uint32_t lease_state)
482 {
483         struct smbd_server_connection *sconn = client->sconn;
484         const struct GUID *client_guid = NULL;
485         struct share_mode_lock *lck;
486         const struct file_id id = ids[0];
487         uint32_t current_state, breaking_to_requested, breaking_to_required;
488         bool breaking;
489         uint16_t lease_version, epoch;
490         NTSTATUS status;
491         uint32_t i;
492         struct file_id_buf idbuf;
493
494         DBG_DEBUG("Downgrading %s to %"PRIu32"\n",
495                   file_id_str_buf(id, &idbuf),
496                   lease_state);
497
498         lck = get_existing_share_mode_lock(talloc_tos(), id);
499         if (lck == NULL) {
500                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
501         }
502
503         client_guid = &sconn->client->global->client_guid;
504
505         status = leases_db_get(client_guid,
506                                key,
507                                &id,
508                                &current_state,
509                                &breaking,
510                                &breaking_to_requested,
511                                &breaking_to_required,
512                                &lease_version,
513                                &epoch);
514         if (!NT_STATUS_IS_OK(status)) {
515                 DBG_WARNING("leases_db_get returned %s\n",
516                             nt_errstr(status));
517                 TALLOC_FREE(lck);
518                 return status;
519         }
520
521         if (!breaking) {
522                 DBG_WARNING("Attempt to break from %"PRIu32" to %"PRIu32" - "
523                             "but we're not in breaking state\n",
524                             current_state, lease_state);
525                 TALLOC_FREE(lck);
526                 return NT_STATUS_UNSUCCESSFUL;
527         }
528
529         /*
530          * Can't upgrade anything: breaking_to_requested (and current_state)
531          * must be a strict bitwise superset of new_lease_state
532          */
533         if ((lease_state & breaking_to_requested) != lease_state) {
534                 DBG_WARNING("Attempt to upgrade from %"PRIu32" to %"PRIu32" "
535                             "- expected %"PRIu32"\n",
536                             current_state, lease_state,
537                             breaking_to_requested);
538                 TALLOC_FREE(lck);
539                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
540         }
541
542         if (current_state != lease_state) {
543                 current_state = lease_state;
544         }
545
546         status = NT_STATUS_OK;
547
548         if ((lease_state & ~breaking_to_required) != 0) {
549                 struct downgrade_lease_additional_state *state;
550
551                 DBG_INFO("lease state %"PRIu32" not fully broken from "
552                          "%"PRIu32" to %"PRIu32"\n",
553                          lease_state,
554                          current_state,
555                          breaking_to_required);
556
557                 breaking_to_requested = breaking_to_required;
558
559                 if (current_state & (SMB2_LEASE_WRITE|SMB2_LEASE_HANDLE)) {
560                         /*
561                          * Here we break in steps, as windows does
562                          * see the breaking3 and v2_breaking3 tests.
563                          */
564                         breaking_to_requested |= SMB2_LEASE_READ;
565                 }
566
567                 state = talloc_zero(client,
568                                     struct downgrade_lease_additional_state);
569                 if (state == NULL) {
570                         TALLOC_FREE(lck);
571                         return NT_STATUS_NO_MEMORY;
572                 }
573
574                 state->im = tevent_create_immediate(state);
575                 if (state->im == NULL) {
576                         TALLOC_FREE(state);
577                         TALLOC_FREE(lck);
578                         return NT_STATUS_NO_MEMORY;
579                 }
580
581                 state->client = client;
582                 state->lease_key = *key;
583                 state->break_from = current_state;
584                 state->break_to = breaking_to_requested;
585                 if (lease_version > 1) {
586                         state->new_epoch = epoch;
587                 }
588
589                 if (current_state & (SMB2_LEASE_WRITE|SMB2_LEASE_HANDLE)) {
590                         state->break_flags =
591                                 SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED;
592                 } else {
593                         /*
594                          * This is an async break without
595                          * SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED
596                          *
597                          * we need to store NONE state in the
598                          * database.
599                          */
600                         current_state = 0;
601                         breaking_to_requested = 0;
602                         breaking_to_required = 0;
603                         breaking = false;
604
605                         {
606                                 NTSTATUS set_status;
607
608                                 set_status = leases_db_set(
609                                         &sconn->client->global->client_guid,
610                                         key,
611                                         current_state,
612                                         breaking,
613                                         breaking_to_requested,
614                                         breaking_to_required,
615                                         lease_version,
616                                         epoch);
617
618                                 if (!NT_STATUS_IS_OK(set_status)) {
619                                         DBG_DEBUG("leases_db_set failed: %s\n",
620                                                   nt_errstr(set_status));
621                                         return set_status;
622                                 }
623                         }
624                 }
625
626                 tevent_schedule_immediate(state->im,
627                                           client->raw_ev_ctx,
628                                           downgrade_lease_additional_trigger,
629                                           state);
630
631                 status = NT_STATUS_OPLOCK_BREAK_IN_PROGRESS;
632         } else {
633                 DBG_DEBUG("breaking from %"PRIu32" to %"PRIu32" - "
634                           "expected %"PRIu32"\n",
635                           current_state,
636                           lease_state,
637                           breaking_to_requested);
638
639                 breaking_to_requested = 0;
640                 breaking_to_required = 0;
641                 breaking = false;
642         }
643
644         {
645                 NTSTATUS set_status;
646
647                 set_status = leases_db_set(
648                         client_guid,
649                         key,
650                         current_state,
651                         breaking,
652                         breaking_to_requested,
653                         breaking_to_required,
654                         lease_version,
655                         epoch);
656
657                 if (!NT_STATUS_IS_OK(set_status)) {
658                         DBG_DEBUG("leases_db_set failed: %s\n",
659                                   nt_errstr(set_status));
660                         TALLOC_FREE(lck);
661                         return set_status;
662                 }
663         }
664
665         DBG_DEBUG("Downgrading %s to %"PRIu32" => %s\n",
666                   file_id_str_buf(id, &idbuf),
667                   lease_state,
668                   nt_errstr(status));
669
670         share_mode_wakeup_waiters(id);
671
672         fsps_lease_update(sconn, &id, key);
673
674         TALLOC_FREE(lck);
675
676         DBG_DEBUG("Downgrading %s to %"PRIu32" => %s\n",
677                   file_id_str_buf(id, &idbuf),
678                   lease_state,
679                   nt_errstr(status));
680
681         /*
682          * Dynamic share case. Ensure other opens are copies.
683          * This will only be breaking to NONE.
684          */
685
686         for (i = 1; i < num_file_ids; i++) {
687                 lck = get_existing_share_mode_lock(talloc_tos(), ids[i]);
688                 if (lck == NULL) {
689                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
690                 }
691
692                 fsps_lease_update(sconn, &ids[i], key);
693
694                 DBG_DEBUG("Downgrading %s to %"PRIu32" => %s\n",
695                           file_id_str_buf(ids[i], &idbuf),
696                           lease_state,
697                           nt_errstr(status));
698
699                 TALLOC_FREE(lck);
700         }
701
702         return status;
703 }
704
705 #define SMB1_BREAK_MESSAGE_LENGTH (smb_size + 8*2)
706
707 /****************************************************************************
708  Function to do the waiting before sending a local break.
709 ****************************************************************************/
710
711 static void wait_before_sending_break(void)
712 {
713         long wait_time = (long)lp_oplock_break_wait_time();
714
715         if (wait_time) {
716                 smb_msleep(wait_time);
717         }
718 }
719
720 /****************************************************************************
721  Ensure that we have a valid oplock.
722 ****************************************************************************/
723
724 static files_struct *initial_break_processing(
725         struct smbd_server_connection *sconn, struct file_id id,
726         unsigned long file_id)
727 {
728         files_struct *fsp = NULL;
729         struct file_id_buf idbuf;
730
731         DBG_NOTICE("called for %s/%u\n"
732                    "Current oplocks_open (exclusive = %d, levelII = %d)\n",
733                    file_id_str_buf(id, &idbuf),
734                    (int)file_id,
735                    sconn->oplocks.exclusive_open,
736                    sconn->oplocks.level_II_open);
737
738         /*
739          * We need to search the file open table for the
740          * entry containing this dev and inode, and ensure
741          * we have an oplock on it.
742          */
743
744         fsp = file_find_dif(sconn, id, file_id);
745
746         if(fsp == NULL) {
747                 /* The file could have been closed in the meantime - return success. */
748                 DBG_NOTICE("cannot find open file "
749                            "with file_id %s gen_id = %lu, allowing break to "
750                            "succeed.\n",
751                            file_id_str_buf(id, &idbuf),
752                            file_id);
753                 return NULL;
754         }
755
756         /* Ensure we have an oplock on the file */
757
758         /*
759          * There is a potential race condition in that an oplock could
760          * have been broken due to another udp request, and yet there are
761          * still oplock break messages being sent in the udp message
762          * queue for this file. So return true if we don't have an oplock,
763          * as we may have just freed it.
764          */
765
766         if(fsp->oplock_type == NO_OPLOCK) {
767                 DBG_NOTICE("file %s (file_id = %s gen_id = %"PRIu64") "
768                            "has no oplock. "
769                            "Allowing break to succeed regardless.\n",
770                            fsp_str_dbg(fsp),
771                            file_id_str_buf(id, &idbuf),
772                            fh_get_gen_id(fsp->fh));
773                 return NULL;
774         }
775
776         return fsp;
777 }
778
779 static void oplock_timeout_handler(struct tevent_context *ctx,
780                                    struct tevent_timer *te,
781                                    struct timeval now,
782                                    void *private_data)
783 {
784         files_struct *fsp = (files_struct *)private_data;
785
786         SMB_ASSERT(fsp->sent_oplock_break != NO_BREAK_SENT);
787
788         /* Remove the timed event handler. */
789         TALLOC_FREE(fsp->oplock_timeout);
790         DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n",
791                   fsp_str_dbg(fsp)));
792         remove_oplock(fsp);
793 }
794
795 /*******************************************************************
796  Add a timeout handler waiting for the client reply.
797 *******************************************************************/
798
799 static void add_oplock_timeout_handler(files_struct *fsp)
800 {
801         if (fsp->oplock_timeout != NULL) {
802                 DEBUG(0, ("Logic problem -- have an oplock event hanging "
803                           "around\n"));
804         }
805
806         fsp->oplock_timeout =
807                 tevent_add_timer(fsp->conn->sconn->ev_ctx, fsp,
808                                  timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),
809                                  oplock_timeout_handler, fsp);
810
811         if (fsp->oplock_timeout == NULL) {
812                 DEBUG(0, ("Could not add oplock timeout handler\n"));
813         }
814 }
815
816 /*******************************************************************
817  This handles the generic oplock break message from another smbd.
818 *******************************************************************/
819
820 static void process_oplock_break_message(struct messaging_context *msg_ctx,
821                                          void *private_data,
822                                          uint32_t msg_type,
823                                          struct server_id src,
824                                          DATA_BLOB *data)
825 {
826         struct oplock_break_message *msg = NULL;
827         enum ndr_err_code ndr_err;
828         files_struct *fsp;
829         bool use_kernel;
830         struct smbd_server_connection *sconn =
831                 talloc_get_type_abort(private_data,
832                 struct smbd_server_connection);
833         struct server_id self = messaging_server_id(sconn->msg_ctx);
834         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
835         uint16_t break_from;
836         uint16_t break_to;
837         bool break_needed = true;
838
839         msg = talloc(talloc_tos(), struct oplock_break_message);
840         if (msg == NULL) {
841                 DBG_WARNING("talloc failed\n");
842                 return;
843         }
844
845         ndr_err = ndr_pull_struct_blob_all(
846                 data,
847                 msg,
848                 msg,
849                 (ndr_pull_flags_fn_t)ndr_pull_oplock_break_message);
850         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
851                 DBG_DEBUG("ndr_pull_oplock_break_message failed: %s\n",
852                           ndr_errstr(ndr_err));
853                 TALLOC_FREE(msg);
854                 return;
855         }
856         if (DEBUGLEVEL >= 10) {
857                 struct server_id_buf buf;
858                 DBG_DEBUG("Got break message from %s\n",
859                           server_id_str_buf(src, &buf));
860                 NDR_PRINT_DEBUG(oplock_break_message, msg);
861         }
862
863         break_to = msg->break_to;
864         fsp = initial_break_processing(sconn, msg->id, msg->share_file_id);
865
866         TALLOC_FREE(msg);
867
868         if (fsp == NULL) {
869                 /* We hit a race here. Break messages are sent, and before we
870                  * get to process this message, we have closed the file. */
871                 DEBUG(3, ("Did not find fsp\n"));
872                 return;
873         }
874
875         break_from = fsp_lease_type(fsp);
876
877         if (fsp->oplock_type != LEASE_OPLOCK) {
878                 if (fsp->sent_oplock_break != NO_BREAK_SENT) {
879                         /*
880                          * Nothing to do anymore
881                          */
882                         DEBUG(10, ("fsp->sent_oplock_break = %d\n",
883                                    fsp->sent_oplock_break));
884                         return;
885                 }
886         }
887
888         if (!(global_client_caps & CAP_LEVEL_II_OPLOCKS)) {
889                 DEBUG(10, ("client_caps without level2 oplocks\n"));
890                 break_to &= ~SMB2_LEASE_READ;
891         }
892
893         use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
894                         (koplocks != NULL);
895         if (use_kernel) {
896                 DEBUG(10, ("Kernel oplocks don't allow level2\n"));
897                 break_to &= ~SMB2_LEASE_READ;
898         }
899
900         if (!lp_level2_oplocks(SNUM(fsp->conn))) {
901                 DEBUG(10, ("no level2 oplocks by config\n"));
902                 break_to &= ~SMB2_LEASE_READ;
903         }
904
905         if (fsp->oplock_type == LEASE_OPLOCK) {
906                 const struct GUID *client_guid = fsp_client_guid(fsp);
907                 struct share_mode_lock *lck;
908                 uint32_t current_state;
909                 uint32_t breaking_to_requested, breaking_to_required;
910                 bool breaking;
911                 uint16_t lease_version, epoch;
912                 NTSTATUS status;
913
914                 lck = get_existing_share_mode_lock(
915                         talloc_tos(), fsp->file_id);
916                 if (lck == NULL) {
917                         /*
918                          * We hit a race here. Break messages are sent, and
919                          * before we get to process this message, we have closed
920                          * the file.
921                          */
922                         DEBUG(3, ("Did not find share_mode\n"));
923                         return;
924                 }
925
926                 status = leases_db_get(client_guid,
927                                        &fsp->lease->lease.lease_key,
928                                        &fsp->file_id,
929                                        &current_state,
930                                        &breaking,
931                                        &breaking_to_requested,
932                                        &breaking_to_required,
933                                        &lease_version,
934                                        &epoch);
935                 if (!NT_STATUS_IS_OK(status)) {
936                         DBG_WARNING("leases_db_get returned %s\n",
937                                     nt_errstr(status));
938                         TALLOC_FREE(lck);
939                         return;
940                 }
941
942                 break_from = current_state;
943                 break_to &= current_state;
944
945                 if (breaking) {
946                         break_to &= breaking_to_required;
947                         if (breaking_to_required != break_to) {
948                                 /*
949                                  * Note we don't increment the epoch
950                                  * here, which might be a bug in
951                                  * Windows too...
952                                  */
953                                 breaking_to_required = break_to;
954                         }
955                         break_needed = false;
956                 } else if (current_state == break_to) {
957                         break_needed = false;
958                 } else if (current_state == SMB2_LEASE_READ) {
959                         current_state = SMB2_LEASE_NONE;
960                         /* Need to increment the epoch */
961                         epoch += 1;
962                 } else {
963                         breaking = true;
964                         breaking_to_required = break_to;
965                         breaking_to_requested = break_to;
966                         /* Need to increment the epoch */
967                         epoch += 1;
968                 }
969
970                 {
971                         NTSTATUS set_status;
972
973                         set_status = leases_db_set(
974                                 client_guid,
975                                 &fsp->lease->lease.lease_key,
976                                 current_state,
977                                 breaking,
978                                 breaking_to_requested,
979                                 breaking_to_required,
980                                 lease_version,
981                                 epoch);
982
983                         if (!NT_STATUS_IS_OK(set_status)) {
984                                 DBG_DEBUG("leases_db_set failed: %s\n",
985                                           nt_errstr(set_status));
986                                 return;
987                         }
988                 }
989
990                 /* Ensure we're in sync with current lease state. */
991                 fsp_lease_update(fsp);
992
993                 TALLOC_FREE(lck);
994         }
995
996         if (!break_needed) {
997                 DEBUG(10,("%s: skip break\n", __func__));
998                 return;
999         }
1000
1001         if (break_from == SMB2_LEASE_NONE) {
1002                 struct file_id_buf idbuf;
1003                 DBG_NOTICE("Already downgraded oplock to none on %s: %s\n",
1004                            file_id_str_buf(fsp->file_id, &idbuf),
1005                            fsp_str_dbg(fsp));
1006                 return;
1007         }
1008
1009         DEBUG(10, ("break_from=%u, break_to=%u\n",
1010                    (unsigned)break_from, (unsigned)break_to));
1011
1012         if (break_from == break_to) {
1013                 struct file_id_buf idbuf;
1014                 DBG_NOTICE("Already downgraded oplock to %u on %s: %s\n",
1015                            (unsigned)break_to,
1016                            file_id_str_buf(fsp->file_id, &idbuf),
1017                            fsp_str_dbg(fsp));
1018                 return;
1019         }
1020
1021         /* Need to wait before sending a break
1022            message if we sent ourselves this message. */
1023         if (server_id_equal(&self, &src)) {
1024                 wait_before_sending_break();
1025         }
1026
1027 #if defined(WITH_SMB1SERVER)
1028         if (sconn->using_smb2) {
1029 #endif
1030                 send_break_message_smb2(fsp, break_from, break_to);
1031 #if defined(WITH_SMB1SERVER)
1032         } else {
1033                 send_break_message_smb1(fsp, (break_to & SMB2_LEASE_READ) ?
1034                                         OPLOCKLEVEL_II : OPLOCKLEVEL_NONE);
1035         }
1036 #endif
1037
1038         if ((break_from == SMB2_LEASE_READ) &&
1039             (break_to == SMB2_LEASE_NONE)) {
1040                 /*
1041                  * This is an async break without a reply and thus no timeout
1042                  *
1043                  * leases are handled above.
1044                  */
1045                 if (fsp->oplock_type != LEASE_OPLOCK) {
1046                         remove_oplock(fsp);
1047                 }
1048                 return;
1049         }
1050         if (fsp->oplock_type == LEASE_OPLOCK) {
1051                 return;
1052         }
1053
1054         fsp->sent_oplock_break = (break_to & SMB2_LEASE_READ) ?
1055                 LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
1056
1057         add_oplock_timeout_handler(fsp);
1058 }
1059
1060 /*******************************************************************
1061  This handles the kernel oplock break message.
1062 *******************************************************************/
1063
1064 static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
1065                                         void *private_data,
1066                                         uint32_t msg_type,
1067                                         struct server_id src,
1068                                         DATA_BLOB *data)
1069 {
1070         struct file_id id;
1071         struct file_id_buf idbuf;
1072         unsigned long file_id;
1073         files_struct *fsp;
1074         struct smbd_server_connection *sconn =
1075                 talloc_get_type_abort(private_data,
1076                 struct smbd_server_connection);
1077         struct server_id_buf tmp;
1078
1079         if (data->data == NULL) {
1080                 DEBUG(0, ("Got NULL buffer\n"));
1081                 return;
1082         }
1083
1084         if (data->length != MSG_SMB_KERNEL_BREAK_SIZE) {
1085                 DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
1086                 return;
1087         }
1088
1089         /* Pull the data from the message. */
1090         pull_file_id_24((char *)data->data, &id);
1091         file_id = (unsigned long)IVAL(data->data, 24);
1092
1093         DBG_DEBUG("Got kernel oplock break message from pid %s: %s/%u\n",
1094                   server_id_str_buf(src, &tmp),
1095                   file_id_str_buf(id, &idbuf),
1096                   (unsigned int)file_id);
1097
1098         fsp = initial_break_processing(sconn, id, file_id);
1099
1100         if (fsp == NULL) {
1101                 DEBUG(3, ("Got a kernel oplock break message for a file "
1102                           "I don't know about\n"));
1103                 return;
1104         }
1105
1106         if (fsp->sent_oplock_break != NO_BREAK_SENT) {
1107                 /* This is ok, kernel oplocks come in completely async */
1108                 DEBUG(3, ("Got a kernel oplock request while waiting for a "
1109                           "break reply\n"));
1110                 return;
1111         }
1112
1113 #if defined(WITH_SMB1SERVER)
1114         if (sconn->using_smb2) {
1115 #endif
1116                 send_break_message_smb2(fsp, 0, OPLOCKLEVEL_NONE);
1117 #if defined(WITH_SMB1SERVER)
1118         } else {
1119                 send_break_message_smb1(fsp, OPLOCKLEVEL_NONE);
1120         }
1121 #endif
1122
1123         fsp->sent_oplock_break = BREAK_TO_NONE_SENT;
1124
1125         add_oplock_timeout_handler(fsp);
1126 }
1127
1128 static void send_break_to_none(struct messaging_context *msg_ctx,
1129                                const struct file_id *id,
1130                                const struct share_mode_entry *e)
1131 {
1132         NTSTATUS status;
1133         status = send_break_message(msg_ctx, id, e, OPLOCK_NONE);
1134         if (!NT_STATUS_IS_OK(status)) {
1135                 DBG_DEBUG("send_break_message failed: %s\n",
1136                           nt_errstr(status));
1137         }
1138 }
1139 struct break_to_none_state {
1140         struct smbd_server_connection *sconn;
1141         struct file_id id;
1142         struct smb2_lease_key lease_key;
1143         struct GUID client_guid;
1144         size_t num_broken;
1145 };
1146
1147 static bool do_break_lease_to_none(struct share_mode_entry *e,
1148                                    void *private_data)
1149 {
1150         struct break_to_none_state *state = private_data;
1151         uint32_t current_state = 0;
1152         bool our_own;
1153         NTSTATUS status;
1154
1155         DBG_DEBUG("lease_key=%"PRIu64"/%"PRIu64"\n",
1156                   e->lease_key.data[0],
1157                   e->lease_key.data[1]);
1158
1159         status = leases_db_get(&e->client_guid,
1160                                &e->lease_key,
1161                                &state->id,
1162                                &current_state,
1163                                NULL, /* breaking */
1164                                NULL, /* breaking_to_requested */
1165                                NULL, /* breaking_to_required */
1166                                NULL, /* lease_version */
1167                                NULL); /* epoch */
1168         if (!NT_STATUS_IS_OK(status)) {
1169                 DBG_WARNING("leases_db_get failed: %s\n",
1170                             nt_errstr(status));
1171                 return false;
1172         }
1173
1174         if ((current_state & SMB2_LEASE_READ) == 0) {
1175                 return false;
1176         }
1177
1178         our_own = smb2_lease_equal(&state->client_guid,
1179                                    &state->lease_key,
1180                                    &e->client_guid,
1181                                    &e->lease_key);
1182         if (our_own) {
1183                 DEBUG(10, ("Don't break our own lease\n"));
1184                 return false;
1185         }
1186
1187         DBG_DEBUG("Breaking %"PRIu64"/%"PRIu64" to none\n",
1188                   e->lease_key.data[0],
1189                   e->lease_key.data[1]);
1190
1191         send_break_to_none(state->sconn->msg_ctx, &state->id, e);
1192
1193         state->num_broken += 1;
1194
1195         return false;
1196 }
1197
1198 static bool do_break_oplock_to_none(struct share_mode_entry *e,
1199                                     bool *modified,
1200                                     void *private_data)
1201 {
1202         struct break_to_none_state *state = private_data;
1203
1204         if (e->op_type == LEASE_OPLOCK) {
1205                 /*
1206                  * Already being taken care of
1207                  */
1208                 return false;
1209         }
1210
1211         /*
1212          * As there could have been multiple writes waiting at the
1213          * lock_share_entry gate we may not be the first to
1214          * enter. Hence the state of the op_types in the share mode
1215          * entries may be partly NO_OPLOCK and partly LEVEL_II
1216          * oplock. It will do no harm to re-send break messages to
1217          * those smbd's that are still waiting their turn to remove
1218          * their LEVEL_II state, and also no harm to ignore existing
1219          * NO_OPLOCK states. JRA.
1220          */
1221
1222         DBG_DEBUG("e->op_type == %d\n", e->op_type);
1223
1224         if (e->op_type == NO_OPLOCK) {
1225                 return false;
1226         }
1227
1228         /* Paranoia .... */
1229         SMB_ASSERT(!EXCLUSIVE_OPLOCK_TYPE(e->op_type));
1230
1231         send_break_to_none(state->sconn->msg_ctx, &state->id, e);
1232         state->num_broken += 1;
1233
1234         return false;
1235 }
1236
1237 /****************************************************************************
1238  This function is called on any file modification or lock request. If a file
1239  is level 2 oplocked then it must tell all other level 2 holders to break to
1240  none.
1241 ****************************************************************************/
1242
1243 static void contend_level2_oplocks_begin_default(files_struct *fsp,
1244                                               enum level2_contention_type type)
1245 {
1246         struct break_to_none_state state = {
1247                 .sconn = fsp->conn->sconn, .id = fsp->file_id,
1248         };
1249         struct share_mode_lock *lck = NULL;
1250         bool ok, has_read_lease;
1251
1252         /*
1253          * If this file is level II oplocked then we need
1254          * to grab the shared memory lock and inform all
1255          * other files with a level II lock that they need
1256          * to flush their read caches. We keep the lock over
1257          * the shared memory area whilst doing this.
1258          */
1259
1260         if (fsp_lease_type_is_exclusive(fsp)) {
1261                 /*
1262                  * There can't be any level2 oplocks, we're alone.
1263                  */
1264                 return;
1265         }
1266
1267         has_read_lease = file_has_read_lease(fsp);
1268         if (!has_read_lease) {
1269                 DEBUG(10, ("No read oplocks around\n"));
1270                 return;
1271         }
1272
1273         if (fsp->oplock_type == LEASE_OPLOCK) {
1274                 state.client_guid = *fsp_client_guid(fsp);
1275                 state.lease_key = fsp->lease->lease.lease_key;
1276                 DEBUG(10, ("Breaking through lease key %"PRIu64"/%"PRIu64"\n",
1277                            state.lease_key.data[0],
1278                            state.lease_key.data[1]));
1279         }
1280
1281         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1282         if (lck == NULL) {
1283                 struct file_id_buf idbuf;
1284                 DBG_WARNING("failed to lock share mode entry for file %s.\n",
1285                             file_id_str_buf(state.id, &idbuf));
1286                 return;
1287         }
1288
1289         /*
1290          * Walk leases and oplocks separately: We have to send one break per
1291          * lease. If we have multiple share_mode_entry having a common lease,
1292          * we would break the lease twice if we don't walk the leases list
1293          * separately.
1294          */
1295
1296         ok = share_mode_forall_leases(lck, do_break_lease_to_none, &state);
1297         if (!ok) {
1298                 DBG_WARNING("share_mode_forall_leases failed\n");
1299         }
1300
1301         ok = share_mode_forall_entries(lck, do_break_oplock_to_none, &state);
1302         if (!ok) {
1303                 DBG_WARNING("share_mode_forall_entries failed\n");
1304         }
1305
1306         if (state.num_broken == 0) {
1307                 /*
1308                  * Lazy update here. It might be that the read lease
1309                  * has gone in the meantime.
1310                  */
1311                 uint32_t acc, sh, ls;
1312                 share_mode_flags_get(lck, &acc, &sh, &ls);
1313                 ls &= ~SMB2_LEASE_READ;
1314                 share_mode_flags_set(lck, acc, sh, ls, NULL);
1315         }
1316
1317         TALLOC_FREE(lck);
1318 }
1319
1320 void smbd_contend_level2_oplocks_begin(files_struct *fsp,
1321                                   enum level2_contention_type type)
1322 {
1323         contend_level2_oplocks_begin_default(fsp, type);
1324 }
1325
1326 void smbd_contend_level2_oplocks_end(files_struct *fsp,
1327                                 enum level2_contention_type type)
1328 {
1329         return;
1330 }
1331
1332 /****************************************************************************
1333  Linearize a share mode entry struct to an internal oplock break message.
1334 ****************************************************************************/
1335
1336 void share_mode_entry_to_message(char *msg, const struct file_id *id,
1337                                  const struct share_mode_entry *e)
1338 {
1339         SIVAL(msg,OP_BREAK_MSG_PID_OFFSET,(uint32_t)e->pid.pid);
1340         SBVAL(msg,OP_BREAK_MSG_MID_OFFSET,e->op_mid);
1341         SSVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET,e->op_type);
1342         SIVAL(msg,OP_BREAK_MSG_ACCESS_MASK_OFFSET,e->access_mask);
1343         SIVAL(msg,OP_BREAK_MSG_SHARE_ACCESS_OFFSET,e->share_access);
1344         SIVAL(msg,OP_BREAK_MSG_PRIV_OFFSET,e->private_options);
1345         SIVAL(msg,OP_BREAK_MSG_TIME_SEC_OFFSET,(uint32_t)e->time.tv_sec);
1346         SIVAL(msg,OP_BREAK_MSG_TIME_USEC_OFFSET,(uint32_t)e->time.tv_usec);
1347         /*
1348          * "id" used to be part of share_mode_entry, thus the strange
1349          * place to put this. Feel free to move somewhere else :-)
1350          */
1351         push_file_id_24(msg+OP_BREAK_MSG_DEV_OFFSET, id);
1352         SIVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET,e->share_file_id);
1353         SIVAL(msg,OP_BREAK_MSG_UID_OFFSET,e->uid);
1354         SSVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET,e->flags);
1355         SIVAL(msg,OP_BREAK_MSG_NAME_HASH_OFFSET,e->name_hash);
1356         SIVAL(msg,OP_BREAK_MSG_VNN_OFFSET,e->pid.vnn);
1357 }
1358
1359 /****************************************************************************
1360  De-linearize an internal oplock break message to a share mode entry struct.
1361 ****************************************************************************/
1362
1363 void message_to_share_mode_entry(struct file_id *id,
1364                                  struct share_mode_entry *e,
1365                                  const char *msg)
1366 {
1367         e->pid.pid = (pid_t)IVAL(msg,OP_BREAK_MSG_PID_OFFSET);
1368         e->op_mid = BVAL(msg,OP_BREAK_MSG_MID_OFFSET);
1369         e->op_type = SVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET);
1370         e->access_mask = IVAL(msg,OP_BREAK_MSG_ACCESS_MASK_OFFSET);
1371         e->share_access = IVAL(msg,OP_BREAK_MSG_SHARE_ACCESS_OFFSET);
1372         e->private_options = IVAL(msg,OP_BREAK_MSG_PRIV_OFFSET);
1373         e->time.tv_sec = (time_t)IVAL(msg,OP_BREAK_MSG_TIME_SEC_OFFSET);
1374         e->time.tv_usec = (int)IVAL(msg,OP_BREAK_MSG_TIME_USEC_OFFSET);
1375         /*
1376          * "id" used to be part of share_mode_entry, thus the strange
1377          * place to put this. Feel free to move somewhere else :-)
1378          */
1379         pull_file_id_24(msg+OP_BREAK_MSG_DEV_OFFSET, id);
1380         e->share_file_id = (unsigned long)IVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET);
1381         e->uid = (uint32_t)IVAL(msg,OP_BREAK_MSG_UID_OFFSET);
1382         e->flags = (uint16_t)SVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET);
1383         e->name_hash = IVAL(msg,OP_BREAK_MSG_NAME_HASH_OFFSET);
1384         e->pid.vnn = IVAL(msg,OP_BREAK_MSG_VNN_OFFSET);
1385 }
1386
1387 /****************************************************************************
1388  Setup oplocks for this process.
1389 ****************************************************************************/
1390
1391 bool init_oplocks(struct smbd_server_connection *sconn)
1392 {
1393         DEBUG(3,("init_oplocks: initializing messages.\n"));
1394
1395         messaging_register(sconn->msg_ctx, sconn, MSG_SMB_BREAK_REQUEST,
1396                            process_oplock_break_message);
1397         messaging_register(sconn->msg_ctx, sconn, MSG_SMB_KERNEL_BREAK,
1398                            process_kernel_oplock_break);
1399         return true;
1400 }
1401
1402 void init_kernel_oplocks(struct smbd_server_connection *sconn)
1403 {
1404         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
1405
1406         /* only initialize once */
1407         if (koplocks == NULL) {
1408 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1409                 koplocks = linux_init_kernel_oplocks(sconn);
1410 #endif
1411                 sconn->oplocks.kernel_ops = koplocks;
1412         }
1413 }