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