libndr: Avoid assigning duplicate versions to symbols
[amitay/samba.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         struct file_id_buf buf;
62
63         if (fsp->oplock_type == LEVEL_II_OPLOCK && use_kernel) {
64                 DEBUG(10, ("Refusing level2 oplock, kernel oplocks "
65                            "don't support them\n"));
66                 return NT_STATUS_NOT_SUPPORTED;
67         }
68
69         if ((fsp->oplock_type != NO_OPLOCK) &&
70             use_kernel &&
71             !koplocks->ops->set_oplock(koplocks, fsp, fsp->oplock_type))
72         {
73                 return map_nt_error_from_unix(errno);
74         }
75
76         fsp->sent_oplock_break = NO_BREAK_SENT;
77         if (fsp->oplock_type == LEVEL_II_OPLOCK) {
78                 sconn->oplocks.level_II_open++;
79         } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
80                 sconn->oplocks.exclusive_open++;
81         }
82
83         DBG_INFO("granted oplock on file %s, %s/%"PRIu64", "
84                  "tv_sec = %x, tv_usec = %x\n",
85                  fsp_str_dbg(fsp),
86                  file_id_str_buf(fsp->file_id, &buf),
87                  fsp->fh->gen_id,
88                  (int)fsp->open_time.tv_sec,
89                  (int)fsp->open_time.tv_usec);
90
91         return NT_STATUS_OK;
92 }
93
94 static void release_fsp_kernel_oplock(files_struct *fsp)
95 {
96         struct smbd_server_connection *sconn = fsp->conn->sconn;
97         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
98         bool use_kernel;
99
100         if (koplocks == NULL) {
101                 return;
102         }
103         use_kernel = lp_kernel_oplocks(SNUM(fsp->conn));
104         if (!use_kernel) {
105                 return;
106         }
107         if (fsp->oplock_type == NO_OPLOCK) {
108                 return;
109         }
110         if (fsp->oplock_type == LEASE_OPLOCK) {
111                 /*
112                  * For leases we don't touch kernel oplocks at all
113                  */
114                 return;
115         }
116
117         koplocks->ops->release_oplock(koplocks, fsp, NO_OPLOCK);
118 }
119
120 /****************************************************************************
121  Attempt to release an oplock on a file. Decrements oplock count.
122 ****************************************************************************/
123
124 static void release_file_oplock(files_struct *fsp)
125 {
126         struct smbd_server_connection *sconn = fsp->conn->sconn;
127
128         release_fsp_kernel_oplock(fsp);
129
130         if (fsp->oplock_type == LEVEL_II_OPLOCK) {
131                 sconn->oplocks.level_II_open--;
132         } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
133                 sconn->oplocks.exclusive_open--;
134         }
135
136         SMB_ASSERT(sconn->oplocks.exclusive_open>=0);
137         SMB_ASSERT(sconn->oplocks.level_II_open>=0);
138
139         fsp->oplock_type = NO_OPLOCK;
140         fsp->sent_oplock_break = NO_BREAK_SENT;
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         TALLOC_FREE(fsp->oplock_timeout);
170 }
171
172 uint32_t get_lease_type(struct share_mode_entry *e, struct file_id id)
173 {
174         struct GUID_txt_buf guid_strbuf;
175         struct file_id_buf file_id_strbuf;
176         NTSTATUS status;
177         uint32_t current_state;
178
179         if (e->op_type != LEASE_OPLOCK) {
180                 return map_oplock_to_lease_type(e->op_type);
181         }
182
183         status = leases_db_get(&e->client_guid,
184                                &e->lease_key,
185                                &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         if (NT_STATUS_IS_OK(status)) {
193                 return current_state;
194         }
195
196         if (share_entry_stale_pid(e)) {
197                 return 0;
198         }
199         DBG_ERR("leases_db_get for client_guid [%s] "
200                 "lease_key [%"PRIu64"/%"PRIu64"] "
201                 "file_id [%s] failed: %s\n",
202                 GUID_buf_string(&e->client_guid, &guid_strbuf),
203                 e->lease_key.data[0],
204                 e->lease_key.data[1],
205                 file_id_str_buf(id, &file_id_strbuf),
206                 nt_errstr(status));
207         smb_panic("leases_db_get() failed");
208 }
209
210 /****************************************************************************
211  Remove a file oplock. Copes with level II and exclusive.
212  Locks then unlocks the share mode lock. Client can decide to go directly
213  to none even if a "break-to-level II" was sent.
214 ****************************************************************************/
215
216 bool remove_oplock(files_struct *fsp)
217 {
218         bool ret;
219         struct share_mode_lock *lck;
220
221         DBG_DEBUG("remove_oplock called for %s\n", fsp_str_dbg(fsp));
222
223         /* Remove the oplock flag from the sharemode. */
224         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
225         if (lck == NULL) {
226                 DBG_ERR("failed to lock share entry for "
227                          "file %s\n", fsp_str_dbg(fsp));
228                 return false;
229         }
230
231         ret = remove_share_oplock(lck, fsp);
232         if (!ret) {
233                 struct file_id_buf buf;
234
235                 DBG_ERR("failed to remove share oplock for "
236                         "file %s, %s, %s\n",
237                         fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
238                         file_id_str_buf(fsp->file_id, &buf));
239         }
240         release_file_oplock(fsp);
241
242         TALLOC_FREE(lck);
243         return ret;
244 }
245
246 /*
247  * Deal with a reply when a break-to-level II was sent.
248  */
249 bool downgrade_oplock(files_struct *fsp)
250 {
251         bool ret;
252         struct share_mode_lock *lck;
253
254         DEBUG(10, ("downgrade_oplock called for %s\n",
255                    fsp_str_dbg(fsp)));
256
257         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
258         if (lck == NULL) {
259                 DEBUG(0,("downgrade_oplock: failed to lock share entry for "
260                          "file %s\n", fsp_str_dbg(fsp)));
261                 return False;
262         }
263         ret = downgrade_share_oplock(lck, fsp);
264         if (!ret) {
265                 struct file_id_buf idbuf;
266                 DBG_ERR("failed to downgrade share oplock "
267                         "for file %s, %s, file_id %s\n",
268                         fsp_str_dbg(fsp),
269                         fsp_fnum_dbg(fsp),
270                         file_id_str_buf(fsp->file_id, &idbuf));
271         }
272         downgrade_file_oplock(fsp);
273
274         TALLOC_FREE(lck);
275         return ret;
276 }
277
278 static void lease_timeout_handler(struct tevent_context *ctx,
279                                   struct tevent_timer *te,
280                                   struct timeval now,
281                                   void *private_data)
282 {
283         struct fsp_lease *lease =
284                 talloc_get_type_abort(private_data,
285                 struct fsp_lease);
286         struct files_struct *fsp;
287         struct share_mode_lock *lck;
288         uint16_t old_epoch = lease->lease.lease_epoch;
289
290         fsp = file_find_one_fsp_from_lease_key(lease->sconn,
291                                                &lease->lease.lease_key);
292         if (fsp == NULL) {
293                 /* race? */
294                 TALLOC_FREE(lease->timeout);
295                 return;
296         }
297
298         /*
299          * Paranoia check: There can only be one fsp_lease per lease
300          * key
301          */
302         SMB_ASSERT(fsp->lease == lease);
303
304         lck = get_existing_share_mode_lock(
305                         talloc_tos(), fsp->file_id);
306         if (lck == NULL) {
307                 /* race? */
308                 TALLOC_FREE(lease->timeout);
309                 return;
310         }
311
312         fsp_lease_update(fsp);
313
314         if (lease->lease.lease_epoch != old_epoch) {
315                 /*
316                  * If the epoch changed we need to wait for
317                  * the next timeout to happen.
318                  */
319                 DEBUG(10, ("lease break timeout race (epoch) for file %s - ignoring\n",
320                            fsp_str_dbg(fsp)));
321                 TALLOC_FREE(lck);
322                 return;
323         }
324
325         if (!(lease->lease.lease_flags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)) {
326                 /*
327                  * If the epoch changed we need to wait for
328                  * the next timeout to happen.
329                  */
330                 DEBUG(10, ("lease break timeout race (flags) for file %s - ignoring\n",
331                            fsp_str_dbg(fsp)));
332                 TALLOC_FREE(lck);
333                 return;
334         }
335
336         DEBUG(1, ("lease break timed out for file %s -- replying anyway\n",
337                   fsp_str_dbg(fsp)));
338         (void)downgrade_lease(lease->sconn->client,
339                         1,
340                         &fsp->file_id,
341                         &lease->lease.lease_key,
342                         SMB2_LEASE_NONE);
343
344         TALLOC_FREE(lck);
345 }
346
347 bool fsp_lease_update(struct files_struct *fsp)
348 {
349         const struct GUID *client_guid = fsp_client_guid(fsp);
350         struct fsp_lease *lease = fsp->lease;
351         uint32_t current_state;
352         bool breaking;
353         uint16_t lease_version, epoch;
354         NTSTATUS status;
355
356         status = leases_db_get(client_guid,
357                                &lease->lease.lease_key,
358                                &fsp->file_id,
359                                &current_state,
360                                &breaking,
361                                NULL, /* breaking_to_requested */
362                                NULL, /* breaking_to_required */
363                                &lease_version,
364                                &epoch);
365         if (!NT_STATUS_IS_OK(status)) {
366                 DBG_WARNING("Could not find lease entry: %s\n",
367                             nt_errstr(status));
368                 TALLOC_FREE(lease->timeout);
369                 lease->lease.lease_state = SMB2_LEASE_NONE;
370                 lease->lease.lease_epoch += 1;
371                 lease->lease.lease_flags = 0;
372                 return false;
373         }
374
375         DEBUG(10,("%s: refresh lease state\n", __func__));
376
377         /* Ensure we're in sync with current lease state. */
378         if (lease->lease.lease_epoch != epoch) {
379                 DEBUG(10,("%s: cancel outdated timeout\n", __func__));
380                 TALLOC_FREE(lease->timeout);
381         }
382         lease->lease.lease_epoch = epoch;
383         lease->lease.lease_state = current_state;
384
385         if (breaking) {
386                 lease->lease.lease_flags |= SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
387
388                 if (lease->timeout == NULL) {
389                         struct timeval t = timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0);
390
391                         DEBUG(10,("%s: setup timeout handler\n", __func__));
392
393                         lease->timeout = tevent_add_timer(lease->sconn->ev_ctx,
394                                                           lease, t,
395                                                           lease_timeout_handler,
396                                                           lease);
397                         if (lease->timeout == NULL) {
398                                 DEBUG(0, ("%s: Could not add lease timeout handler\n",
399                                           __func__));
400                         }
401                 }
402         } else {
403                 lease->lease.lease_flags &= ~SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
404                 TALLOC_FREE(lease->timeout);
405         }
406
407         return true;
408 }
409
410 struct downgrade_lease_additional_state {
411         struct tevent_immediate *im;
412         struct smbXsrv_client *client;
413         uint32_t break_flags;
414         struct smb2_lease_key lease_key;
415         uint32_t break_from;
416         uint32_t break_to;
417         uint16_t new_epoch;
418 };
419
420 static void downgrade_lease_additional_trigger(struct tevent_context *ev,
421                                                struct tevent_immediate *im,
422                                                void *private_data)
423 {
424         struct downgrade_lease_additional_state *state =
425                 talloc_get_type_abort(private_data,
426                 struct downgrade_lease_additional_state);
427         NTSTATUS status;
428
429         status = smbd_smb2_send_lease_break(state->client,
430                                             state->new_epoch,
431                                             state->break_flags,
432                                             &state->lease_key,
433                                             state->break_from,
434                                             state->break_to);
435         TALLOC_FREE(state);
436         if (!NT_STATUS_IS_OK(status)) {
437                 smbd_server_disconnect_client(state->client,
438                                               nt_errstr(status));
439                 return;
440         }
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 /****************************************************************************
706  Set up an oplock break message.
707 ****************************************************************************/
708
709 #define SMB1_BREAK_MESSAGE_LENGTH (smb_size + 8*2)
710
711 static void new_break_message_smb1(files_struct *fsp, int cmd,
712                                    char result[SMB1_BREAK_MESSAGE_LENGTH])
713 {
714         memset(result,'\0',smb_size);
715         srv_set_message(result,8,0,true);
716         SCVAL(result,smb_com,SMBlockingX);
717         SSVAL(result,smb_tid,fsp->conn->cnum);
718         SSVAL(result,smb_pid,0xFFFF);
719         SSVAL(result,smb_uid,0);
720         SSVAL(result,smb_mid,0xFFFF);
721         SCVAL(result,smb_vwv0,0xFF);
722         SSVAL(result,smb_vwv2,fsp->fnum);
723         SCVAL(result,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE);
724         SCVAL(result,smb_vwv3+1,cmd);
725 }
726
727 /****************************************************************************
728  Function to do the waiting before sending a local break.
729 ****************************************************************************/
730
731 static void wait_before_sending_break(void)
732 {
733         long wait_time = (long)lp_oplock_break_wait_time();
734
735         if (wait_time) {
736                 smb_msleep(wait_time);
737         }
738 }
739
740 /****************************************************************************
741  Ensure that we have a valid oplock.
742 ****************************************************************************/
743
744 static files_struct *initial_break_processing(
745         struct smbd_server_connection *sconn, struct file_id id,
746         unsigned long file_id)
747 {
748         files_struct *fsp = NULL;
749         struct file_id_buf idbuf;
750
751         DBG_NOTICE("called for %s/%u\n"
752                    "Current oplocks_open (exclusive = %d, levelII = %d)\n",
753                    file_id_str_buf(id, &idbuf),
754                    (int)file_id,
755                    sconn->oplocks.exclusive_open,
756                    sconn->oplocks.level_II_open);
757
758         /*
759          * We need to search the file open table for the
760          * entry containing this dev and inode, and ensure
761          * we have an oplock on it.
762          */
763
764         fsp = file_find_dif(sconn, id, file_id);
765
766         if(fsp == NULL) {
767                 /* The file could have been closed in the meantime - return success. */
768                 DBG_NOTICE("cannot find open file "
769                            "with file_id %s gen_id = %lu, allowing break to "
770                            "succeed.\n",
771                            file_id_str_buf(id, &idbuf),
772                            file_id);
773                 return NULL;
774         }
775
776         /* Ensure we have an oplock on the file */
777
778         /*
779          * There is a potential race condition in that an oplock could
780          * have been broken due to another udp request, and yet there are
781          * still oplock break messages being sent in the udp message
782          * queue for this file. So return true if we don't have an oplock,
783          * as we may have just freed it.
784          */
785
786         if(fsp->oplock_type == NO_OPLOCK) {
787                 DBG_NOTICE("file %s (file_id = %s gen_id = %"PRIu64") "
788                            "has no oplock. "
789                            "Allowing break to succeed regardless.\n",
790                            fsp_str_dbg(fsp),
791                            file_id_str_buf(id, &idbuf),
792                            fsp->fh->gen_id);
793                 return NULL;
794         }
795
796         return fsp;
797 }
798
799 static void oplock_timeout_handler(struct tevent_context *ctx,
800                                    struct tevent_timer *te,
801                                    struct timeval now,
802                                    void *private_data)
803 {
804         files_struct *fsp = (files_struct *)private_data;
805
806         SMB_ASSERT(fsp->sent_oplock_break != NO_BREAK_SENT);
807
808         /* Remove the timed event handler. */
809         TALLOC_FREE(fsp->oplock_timeout);
810         DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n",
811                   fsp_str_dbg(fsp)));
812         remove_oplock(fsp);
813 }
814
815 /*******************************************************************
816  Add a timeout handler waiting for the client reply.
817 *******************************************************************/
818
819 static void add_oplock_timeout_handler(files_struct *fsp)
820 {
821         if (fsp->oplock_timeout != NULL) {
822                 DEBUG(0, ("Logic problem -- have an oplock event hanging "
823                           "around\n"));
824         }
825
826         fsp->oplock_timeout =
827                 tevent_add_timer(fsp->conn->sconn->ev_ctx, fsp,
828                                  timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),
829                                  oplock_timeout_handler, fsp);
830
831         if (fsp->oplock_timeout == NULL) {
832                 DEBUG(0, ("Could not add oplock timeout handler\n"));
833         }
834 }
835
836 static void send_break_message_smb1(files_struct *fsp, int level)
837 {
838         struct smbXsrv_connection *xconn = NULL;
839         char break_msg[SMB1_BREAK_MESSAGE_LENGTH];
840
841         /*
842          * For SMB1 we only have one connection
843          */
844         xconn = fsp->conn->sconn->client->connections;
845
846         new_break_message_smb1(fsp, level, break_msg);
847
848         show_msg(break_msg);
849         if (!srv_send_smb(xconn,
850                         break_msg, false, 0,
851                         IS_CONN_ENCRYPTED(fsp->conn),
852                         NULL)) {
853                 exit_server_cleanly("send_break_message_smb1: "
854                         "srv_send_smb failed.");
855         }
856 }
857
858 /*******************************************************************
859  This handles the generic oplock break message from another smbd.
860 *******************************************************************/
861
862 static void process_oplock_break_message(struct messaging_context *msg_ctx,
863                                          void *private_data,
864                                          uint32_t msg_type,
865                                          struct server_id src,
866                                          DATA_BLOB *data)
867 {
868         struct oplock_break_message *msg = NULL;
869         enum ndr_err_code ndr_err;
870         files_struct *fsp;
871         bool use_kernel;
872         struct smbd_server_connection *sconn =
873                 talloc_get_type_abort(private_data,
874                 struct smbd_server_connection);
875         struct server_id self = messaging_server_id(sconn->msg_ctx);
876         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
877         uint16_t break_from;
878         uint16_t break_to;
879         bool break_needed = true;
880
881         msg = talloc(talloc_tos(), struct oplock_break_message);
882         if (msg == NULL) {
883                 DBG_WARNING("talloc failed\n");
884                 return;
885         }
886
887         ndr_err = ndr_pull_struct_blob_all(
888                 data,
889                 msg,
890                 msg,
891                 (ndr_pull_flags_fn_t)ndr_pull_oplock_break_message);
892         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
893                 DBG_DEBUG("ndr_pull_oplock_break_message failed: %s\n",
894                           ndr_errstr(ndr_err));
895                 TALLOC_FREE(msg);
896                 return;
897         }
898         if (DEBUGLEVEL >= 10) {
899                 struct server_id_buf buf;
900                 DBG_DEBUG("Got break message from %s\n",
901                           server_id_str_buf(src, &buf));
902                 NDR_PRINT_DEBUG(oplock_break_message, msg);
903         }
904
905         break_to = msg->break_to;
906         fsp = initial_break_processing(sconn, msg->id, msg->share_file_id);
907
908         TALLOC_FREE(msg);
909
910         if (fsp == NULL) {
911                 /* We hit a race here. Break messages are sent, and before we
912                  * get to process this message, we have closed the file. */
913                 DEBUG(3, ("Did not find fsp\n"));
914                 return;
915         }
916
917         break_from = fsp_lease_type(fsp);
918
919         if (fsp->oplock_type != LEASE_OPLOCK) {
920                 if (fsp->sent_oplock_break != NO_BREAK_SENT) {
921                         /*
922                          * Nothing to do anymore
923                          */
924                         DEBUG(10, ("fsp->sent_oplock_break = %d\n",
925                                    fsp->sent_oplock_break));
926                         return;
927                 }
928         }
929
930         if (!(global_client_caps & CAP_LEVEL_II_OPLOCKS)) {
931                 DEBUG(10, ("client_caps without level2 oplocks\n"));
932                 break_to &= ~SMB2_LEASE_READ;
933         }
934
935         use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
936                         (koplocks != NULL);
937         if (use_kernel) {
938                 DEBUG(10, ("Kernel oplocks don't allow level2\n"));
939                 break_to &= ~SMB2_LEASE_READ;
940         }
941
942         if (!lp_level2_oplocks(SNUM(fsp->conn))) {
943                 DEBUG(10, ("no level2 oplocks by config\n"));
944                 break_to &= ~SMB2_LEASE_READ;
945         }
946
947         if (fsp->oplock_type == LEASE_OPLOCK) {
948                 const struct GUID *client_guid = fsp_client_guid(fsp);
949                 struct share_mode_lock *lck;
950                 uint32_t current_state;
951                 uint32_t breaking_to_requested, breaking_to_required;
952                 bool breaking;
953                 uint16_t lease_version, epoch;
954                 NTSTATUS status;
955
956                 lck = get_existing_share_mode_lock(
957                         talloc_tos(), fsp->file_id);
958                 if (lck == NULL) {
959                         /*
960                          * We hit a race here. Break messages are sent, and
961                          * before we get to process this message, we have closed
962                          * the file.
963                          */
964                         DEBUG(3, ("Did not find share_mode\n"));
965                         return;
966                 }
967
968                 status = leases_db_get(client_guid,
969                                        &fsp->lease->lease.lease_key,
970                                        &fsp->file_id,
971                                        &current_state,
972                                        &breaking,
973                                        &breaking_to_requested,
974                                        &breaking_to_required,
975                                        &lease_version,
976                                        &epoch);
977                 if (!NT_STATUS_IS_OK(status)) {
978                         DBG_WARNING("leases_db_get returned %s\n",
979                                     nt_errstr(status));
980                         TALLOC_FREE(lck);
981                         return;
982                 }
983
984                 break_from = current_state;
985                 break_to &= current_state;
986
987                 if (breaking) {
988                         break_to &= breaking_to_required;
989                         if (breaking_to_required != break_to) {
990                                 /*
991                                  * Note we don't increment the epoch
992                                  * here, which might be a bug in
993                                  * Windows too...
994                                  */
995                                 breaking_to_required = break_to;
996                         }
997                         break_needed = false;
998                 } else if (current_state == break_to) {
999                         break_needed = false;
1000                 } else if (current_state == SMB2_LEASE_READ) {
1001                         current_state = SMB2_LEASE_NONE;
1002                         /* Need to increment the epoch */
1003                         epoch += 1;
1004                 } else {
1005                         breaking = true;
1006                         breaking_to_required = break_to;
1007                         breaking_to_requested = break_to;
1008                         /* Need to increment the epoch */
1009                         epoch += 1;
1010                 }
1011
1012                 {
1013                         NTSTATUS set_status;
1014
1015                         set_status = leases_db_set(
1016                                 client_guid,
1017                                 &fsp->lease->lease.lease_key,
1018                                 current_state,
1019                                 breaking,
1020                                 breaking_to_requested,
1021                                 breaking_to_required,
1022                                 lease_version,
1023                                 epoch);
1024
1025                         if (!NT_STATUS_IS_OK(set_status)) {
1026                                 DBG_DEBUG("leases_db_set failed: %s\n",
1027                                           nt_errstr(set_status));
1028                                 return;
1029                         }
1030                 }
1031
1032                 /* Ensure we're in sync with current lease state. */
1033                 fsp_lease_update(fsp);
1034
1035                 TALLOC_FREE(lck);
1036         }
1037
1038         if (!break_needed) {
1039                 DEBUG(10,("%s: skip break\n", __func__));
1040                 return;
1041         }
1042
1043         if (break_from == SMB2_LEASE_NONE) {
1044                 struct file_id_buf idbuf;
1045                 DBG_NOTICE("Already downgraded oplock to none on %s: %s\n",
1046                            file_id_str_buf(fsp->file_id, &idbuf),
1047                            fsp_str_dbg(fsp));
1048                 return;
1049         }
1050
1051         DEBUG(10, ("break_from=%u, break_to=%u\n",
1052                    (unsigned)break_from, (unsigned)break_to));
1053
1054         if (break_from == break_to) {
1055                 struct file_id_buf idbuf;
1056                 DBG_NOTICE("Already downgraded oplock to %u on %s: %s\n",
1057                            (unsigned)break_to,
1058                            file_id_str_buf(fsp->file_id, &idbuf),
1059                            fsp_str_dbg(fsp));
1060                 return;
1061         }
1062
1063         /* Need to wait before sending a break
1064            message if we sent ourselves this message. */
1065         if (server_id_equal(&self, &src)) {
1066                 wait_before_sending_break();
1067         }
1068
1069         if (sconn->using_smb2) {
1070                 send_break_message_smb2(fsp, break_from, break_to);
1071         } else {
1072                 send_break_message_smb1(fsp, (break_to & SMB2_LEASE_READ) ?
1073                                         OPLOCKLEVEL_II : OPLOCKLEVEL_NONE);
1074         }
1075
1076         if ((break_from == SMB2_LEASE_READ) &&
1077             (break_to == SMB2_LEASE_NONE)) {
1078                 /*
1079                  * This is an async break without a reply and thus no timeout
1080                  *
1081                  * leases are handled above.
1082                  */
1083                 if (fsp->oplock_type != LEASE_OPLOCK) {
1084                         remove_oplock(fsp);
1085                 }
1086                 return;
1087         }
1088         if (fsp->oplock_type == LEASE_OPLOCK) {
1089                 return;
1090         }
1091
1092         fsp->sent_oplock_break = (break_to & SMB2_LEASE_READ) ?
1093                 LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
1094
1095         add_oplock_timeout_handler(fsp);
1096 }
1097
1098 /*******************************************************************
1099  This handles the kernel oplock break message.
1100 *******************************************************************/
1101
1102 static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
1103                                         void *private_data,
1104                                         uint32_t msg_type,
1105                                         struct server_id src,
1106                                         DATA_BLOB *data)
1107 {
1108         struct file_id id;
1109         struct file_id_buf idbuf;
1110         unsigned long file_id;
1111         files_struct *fsp;
1112         struct smbd_server_connection *sconn =
1113                 talloc_get_type_abort(private_data,
1114                 struct smbd_server_connection);
1115         struct server_id_buf tmp;
1116
1117         if (data->data == NULL) {
1118                 DEBUG(0, ("Got NULL buffer\n"));
1119                 return;
1120         }
1121
1122         if (data->length != MSG_SMB_KERNEL_BREAK_SIZE) {
1123                 DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
1124                 return;
1125         }
1126
1127         /* Pull the data from the message. */
1128         pull_file_id_24((char *)data->data, &id);
1129         file_id = (unsigned long)IVAL(data->data, 24);
1130
1131         DBG_DEBUG("Got kernel oplock break message from pid %s: %s/%u\n",
1132                   server_id_str_buf(src, &tmp),
1133                   file_id_str_buf(id, &idbuf),
1134                   (unsigned int)file_id);
1135
1136         fsp = initial_break_processing(sconn, id, file_id);
1137
1138         if (fsp == NULL) {
1139                 DEBUG(3, ("Got a kernel oplock break message for a file "
1140                           "I don't know about\n"));
1141                 return;
1142         }
1143
1144         if (fsp->sent_oplock_break != NO_BREAK_SENT) {
1145                 /* This is ok, kernel oplocks come in completely async */
1146                 DEBUG(3, ("Got a kernel oplock request while waiting for a "
1147                           "break reply\n"));
1148                 return;
1149         }
1150
1151         if (sconn->using_smb2) {
1152                 send_break_message_smb2(fsp, 0, OPLOCKLEVEL_NONE);
1153         } else {
1154                 send_break_message_smb1(fsp, OPLOCKLEVEL_NONE);
1155         }
1156
1157         fsp->sent_oplock_break = BREAK_TO_NONE_SENT;
1158
1159         add_oplock_timeout_handler(fsp);
1160 }
1161
1162 static void send_break_to_none(struct messaging_context *msg_ctx,
1163                                const struct file_id *id,
1164                                const struct share_mode_entry *e)
1165 {
1166         NTSTATUS status;
1167         status = send_break_message(msg_ctx, id, e, OPLOCK_NONE);
1168         if (!NT_STATUS_IS_OK(status)) {
1169                 DBG_DEBUG("send_break_message failed: %s\n",
1170                           nt_errstr(status));
1171         }
1172 }
1173 struct break_to_none_state {
1174         struct smbd_server_connection *sconn;
1175         struct file_id id;
1176         struct smb2_lease_key lease_key;
1177         struct GUID client_guid;
1178         size_t num_broken;
1179 };
1180
1181 static bool do_break_lease_to_none(struct share_mode_entry *e,
1182                                    void *private_data)
1183 {
1184         struct break_to_none_state *state = private_data;
1185         uint32_t current_state = 0;
1186         bool our_own;
1187         NTSTATUS status;
1188
1189         DBG_DEBUG("lease_key=%"PRIu64"/%"PRIu64"\n",
1190                   e->lease_key.data[0],
1191                   e->lease_key.data[1]);
1192
1193         status = leases_db_get(&e->client_guid,
1194                                &e->lease_key,
1195                                &state->id,
1196                                &current_state,
1197                                NULL, /* breaking */
1198                                NULL, /* breaking_to_requested */
1199                                NULL, /* breaking_to_required */
1200                                NULL, /* lease_version */
1201                                NULL); /* epoch */
1202         if (!NT_STATUS_IS_OK(status)) {
1203                 DBG_WARNING("leases_db_get failed: %s\n",
1204                             nt_errstr(status));
1205                 return false;
1206         }
1207
1208         if ((current_state & SMB2_LEASE_READ) == 0) {
1209                 return false;
1210         }
1211
1212         our_own = smb2_lease_equal(&state->client_guid,
1213                                    &state->lease_key,
1214                                    &e->client_guid,
1215                                    &e->lease_key);
1216         if (our_own) {
1217                 DEBUG(10, ("Don't break our own lease\n"));
1218                 return false;
1219         }
1220
1221         DBG_DEBUG("Breaking %"PRIu64"/%"PRIu64" to none\n",
1222                   e->lease_key.data[0],
1223                   e->lease_key.data[1]);
1224
1225         send_break_to_none(state->sconn->msg_ctx, &state->id, e);
1226
1227         state->num_broken += 1;
1228
1229         return false;
1230 }
1231
1232 static bool do_break_oplock_to_none(struct share_mode_entry *e,
1233                                     bool *modified,
1234                                     void *private_data)
1235 {
1236         struct break_to_none_state *state = private_data;
1237
1238         if (e->op_type == LEASE_OPLOCK) {
1239                 /*
1240                  * Already being taken care of
1241                  */
1242                 return false;
1243         }
1244
1245         /*
1246          * As there could have been multiple writes waiting at the
1247          * lock_share_entry gate we may not be the first to
1248          * enter. Hence the state of the op_types in the share mode
1249          * entries may be partly NO_OPLOCK and partly LEVEL_II
1250          * oplock. It will do no harm to re-send break messages to
1251          * those smbd's that are still waiting their turn to remove
1252          * their LEVEL_II state, and also no harm to ignore existing
1253          * NO_OPLOCK states. JRA.
1254          */
1255
1256         DBG_DEBUG("e->op_type == %d\n", e->op_type);
1257
1258         if (e->op_type == NO_OPLOCK) {
1259                 return false;
1260         }
1261
1262         /* Paranoia .... */
1263         SMB_ASSERT(!EXCLUSIVE_OPLOCK_TYPE(e->op_type));
1264
1265         send_break_to_none(state->sconn->msg_ctx, &state->id, e);
1266         state->num_broken += 1;
1267
1268         return false;
1269 }
1270
1271 /****************************************************************************
1272  This function is called on any file modification or lock request. If a file
1273  is level 2 oplocked then it must tell all other level 2 holders to break to
1274  none.
1275 ****************************************************************************/
1276
1277 static void contend_level2_oplocks_begin_default(files_struct *fsp,
1278                                               enum level2_contention_type type)
1279 {
1280         struct break_to_none_state state = {
1281                 .sconn = fsp->conn->sconn, .id = fsp->file_id,
1282         };
1283         struct share_mode_lock *lck = NULL;
1284         struct share_mode_data *d = NULL;
1285         bool ok, has_read_lease;
1286
1287         /*
1288          * If this file is level II oplocked then we need
1289          * to grab the shared memory lock and inform all
1290          * other files with a level II lock that they need
1291          * to flush their read caches. We keep the lock over
1292          * the shared memory area whilst doing this.
1293          */
1294
1295         if (fsp_lease_type_is_exclusive(fsp)) {
1296                 /*
1297                  * There can't be any level2 oplocks, we're alone.
1298                  */
1299                 return;
1300         }
1301
1302         has_read_lease = file_has_read_lease(fsp);
1303         if (!has_read_lease) {
1304                 DEBUG(10, ("No read oplocks around\n"));
1305                 return;
1306         }
1307
1308         if (fsp->oplock_type == LEASE_OPLOCK) {
1309                 state.client_guid = *fsp_client_guid(fsp);
1310                 state.lease_key = fsp->lease->lease.lease_key;
1311                 DEBUG(10, ("Breaking through lease key %"PRIu64"/%"PRIu64"\n",
1312                            state.lease_key.data[0],
1313                            state.lease_key.data[1]));
1314         }
1315
1316         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1317         if (lck == NULL) {
1318                 struct file_id_buf idbuf;
1319                 DBG_WARNING("failed to lock share mode entry for file %s.\n",
1320                             file_id_str_buf(state.id, &idbuf));
1321                 return;
1322         }
1323         d = lck->data;
1324
1325         /*
1326          * Walk leases and oplocks separately: We have to send one break per
1327          * lease. If we have multiple share_mode_entry having a common lease,
1328          * we would break the lease twice if we don't walk the leases list
1329          * separately.
1330          */
1331
1332         ok = share_mode_forall_leases(lck, do_break_lease_to_none, &state);
1333         if (!ok) {
1334                 DBG_WARNING("share_mode_forall_leases failed\n");
1335         }
1336
1337         ok = share_mode_forall_entries(lck, do_break_oplock_to_none, &state);
1338         if (!ok) {
1339                 DBG_WARNING("share_mode_forall_entries failed\n");
1340         }
1341
1342         if (state.num_broken == 0) {
1343                 /*
1344                  * Lazy update here. It might be that the read lease
1345                  * has gone in the meantime.
1346                  */
1347                 d->flags &= ~SHARE_MODE_LEASE_READ;
1348                 d->modified = true;
1349         }
1350
1351         TALLOC_FREE(lck);
1352 }
1353
1354 void smbd_contend_level2_oplocks_begin(files_struct *fsp,
1355                                   enum level2_contention_type type)
1356 {
1357         contend_level2_oplocks_begin_default(fsp, type);
1358 }
1359
1360 void smbd_contend_level2_oplocks_end(files_struct *fsp,
1361                                 enum level2_contention_type type)
1362 {
1363         return;
1364 }
1365
1366 /****************************************************************************
1367  Linearize a share mode entry struct to an internal oplock break message.
1368 ****************************************************************************/
1369
1370 void share_mode_entry_to_message(char *msg, const struct file_id *id,
1371                                  const struct share_mode_entry *e)
1372 {
1373         SIVAL(msg,OP_BREAK_MSG_PID_OFFSET,(uint32_t)e->pid.pid);
1374         SBVAL(msg,OP_BREAK_MSG_MID_OFFSET,e->op_mid);
1375         SSVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET,e->op_type);
1376         SIVAL(msg,OP_BREAK_MSG_ACCESS_MASK_OFFSET,e->access_mask);
1377         SIVAL(msg,OP_BREAK_MSG_SHARE_ACCESS_OFFSET,e->share_access);
1378         SIVAL(msg,OP_BREAK_MSG_PRIV_OFFSET,e->private_options);
1379         SIVAL(msg,OP_BREAK_MSG_TIME_SEC_OFFSET,(uint32_t)e->time.tv_sec);
1380         SIVAL(msg,OP_BREAK_MSG_TIME_USEC_OFFSET,(uint32_t)e->time.tv_usec);
1381         /*
1382          * "id" used to be part of share_mode_entry, thus the strange
1383          * place to put this. Feel free to move somewhere else :-)
1384          */
1385         push_file_id_24(msg+OP_BREAK_MSG_DEV_OFFSET, id);
1386         SIVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET,e->share_file_id);
1387         SIVAL(msg,OP_BREAK_MSG_UID_OFFSET,e->uid);
1388         SSVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET,e->flags);
1389         SIVAL(msg,OP_BREAK_MSG_NAME_HASH_OFFSET,e->name_hash);
1390         SIVAL(msg,OP_BREAK_MSG_VNN_OFFSET,e->pid.vnn);
1391 }
1392
1393 /****************************************************************************
1394  De-linearize an internal oplock break message to a share mode entry struct.
1395 ****************************************************************************/
1396
1397 void message_to_share_mode_entry(struct file_id *id,
1398                                  struct share_mode_entry *e,
1399                                  const char *msg)
1400 {
1401         e->pid.pid = (pid_t)IVAL(msg,OP_BREAK_MSG_PID_OFFSET);
1402         e->op_mid = BVAL(msg,OP_BREAK_MSG_MID_OFFSET);
1403         e->op_type = SVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET);
1404         e->access_mask = IVAL(msg,OP_BREAK_MSG_ACCESS_MASK_OFFSET);
1405         e->share_access = IVAL(msg,OP_BREAK_MSG_SHARE_ACCESS_OFFSET);
1406         e->private_options = IVAL(msg,OP_BREAK_MSG_PRIV_OFFSET);
1407         e->time.tv_sec = (time_t)IVAL(msg,OP_BREAK_MSG_TIME_SEC_OFFSET);
1408         e->time.tv_usec = (int)IVAL(msg,OP_BREAK_MSG_TIME_USEC_OFFSET);
1409         /*
1410          * "id" used to be part of share_mode_entry, thus the strange
1411          * place to put this. Feel free to move somewhere else :-)
1412          */
1413         pull_file_id_24(msg+OP_BREAK_MSG_DEV_OFFSET, id);
1414         e->share_file_id = (unsigned long)IVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET);
1415         e->uid = (uint32_t)IVAL(msg,OP_BREAK_MSG_UID_OFFSET);
1416         e->flags = (uint16_t)SVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET);
1417         e->name_hash = IVAL(msg,OP_BREAK_MSG_NAME_HASH_OFFSET);
1418         e->pid.vnn = IVAL(msg,OP_BREAK_MSG_VNN_OFFSET);
1419 }
1420
1421 /****************************************************************************
1422  Setup oplocks for this process.
1423 ****************************************************************************/
1424
1425 bool init_oplocks(struct smbd_server_connection *sconn)
1426 {
1427         DEBUG(3,("init_oplocks: initializing messages.\n"));
1428
1429         messaging_register(sconn->msg_ctx, sconn, MSG_SMB_BREAK_REQUEST,
1430                            process_oplock_break_message);
1431         messaging_register(sconn->msg_ctx, sconn, MSG_SMB_KERNEL_BREAK,
1432                            process_kernel_oplock_break);
1433         return true;
1434 }
1435
1436 void init_kernel_oplocks(struct smbd_server_connection *sconn)
1437 {
1438         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
1439
1440         /* only initialize once */
1441         if (koplocks == NULL) {
1442 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1443                 koplocks = linux_init_kernel_oplocks(sconn);
1444 #endif
1445                 sconn->oplocks.kernel_ops = koplocks;
1446         }
1447 }