7c6e9f48b3dca6c666f2c4c3ab362b2817297955
[jelmer/samba4-debian.git] / source / ntvfs / common / opendb_tdb.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Andrew Tridgell 2004
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /*
21   this is the open files database, tdb backend. It implements shared
22   storage of what files are open between server instances, and
23   implements the rules of shared access to files.
24
25   The caller needs to provide a file_key, which specifies what file
26   they are talking about. This needs to be a unique key across all
27   filesystems, and is usually implemented in terms of a device/inode
28   pair.
29
30   Before any operations can be performed the caller needs to establish
31   a lock on the record associated with file_key. That is done by
32   calling odb_lock(). The caller releases this lock by calling
33   talloc_free() on the returned handle.
34
35   All other operations on a record are done by passing the odb_lock()
36   handle back to this module. The handle contains internal
37   information about what file_key is being operated on.
38 */
39
40 #include "includes.h"
41 #include "system/filesys.h"
42 #include "lib/tdb/include/tdb.h"
43 #include "messaging/messaging.h"
44 #include "db_wrap.h"
45 #include "lib/messaging/irpc.h"
46 #include "librpc/gen_ndr/ndr_opendb.h"
47 #include "ntvfs/ntvfs.h"
48 #include "ntvfs/common/ntvfs_common.h"
49 #include "cluster/cluster.h"
50 #include "param/param.h"
51
52 struct odb_context {
53         struct tdb_wrap *w;
54         struct ntvfs_context *ntvfs_ctx;
55         BOOL oplocks;
56 };
57
58 /*
59   an odb lock handle. You must obtain one of these using odb_lock() before doing
60   any other operations. 
61 */
62 struct odb_lock {
63         struct odb_context *odb;
64         TDB_DATA key;
65 };
66
67 /*
68   Open up the openfiles.tdb database. Close it down using
69   talloc_free(). We need the messaging_ctx to allow for pending open
70   notifications.
71 */
72 static struct odb_context *odb_tdb_init(TALLOC_CTX *mem_ctx, 
73                                         struct ntvfs_context *ntvfs_ctx)
74 {
75         struct odb_context *odb;
76
77         odb = talloc(mem_ctx, struct odb_context);
78         if (odb == NULL) {
79                 return NULL;
80         }
81
82         odb->w = cluster_tdb_tmp_open(odb, "openfiles.tdb", TDB_DEFAULT);
83         if (odb->w == NULL) {
84                 talloc_free(odb);
85                 return NULL;
86         }
87
88         odb->ntvfs_ctx = ntvfs_ctx;
89
90         /* leave oplocks disabled by default until the code is working */
91         odb->oplocks = lp_parm_bool(NULL, "opendb", "oplocks", false);
92
93         return odb;
94 }
95
96 /*
97   destroy a lock on the database
98 */
99 static int odb_lock_destructor(struct odb_lock *lck)
100 {
101         tdb_chainunlock(lck->odb->w->tdb, lck->key);
102         return 0;
103 }
104
105 /*
106   get a lock on a entry in the odb. This call returns a lock handle,
107   which the caller should unlock using talloc_free().
108 */
109 static struct odb_lock *odb_tdb_lock(TALLOC_CTX *mem_ctx,
110                                      struct odb_context *odb, DATA_BLOB *file_key)
111 {
112         struct odb_lock *lck;
113
114         lck = talloc(mem_ctx, struct odb_lock);
115         if (lck == NULL) {
116                 return NULL;
117         }
118
119         lck->odb = talloc_reference(lck, odb);
120         lck->key.dptr = talloc_memdup(lck, file_key->data, file_key->length);
121         lck->key.dsize = file_key->length;
122         if (lck->key.dptr == NULL) {
123                 talloc_free(lck);
124                 return NULL;
125         }
126
127         if (tdb_chainlock(odb->w->tdb, lck->key) != 0) {
128                 talloc_free(lck);
129                 return NULL;
130         }
131
132         talloc_set_destructor(lck, odb_lock_destructor);
133         
134         return lck;
135 }
136
137 /*
138   determine if two odb_entry structures conflict
139
140   return NT_STATUS_OK on no conflict
141 */
142 static NTSTATUS share_conflict(struct opendb_entry *e1, struct opendb_entry *e2)
143 {
144         /* if either open involves no read.write or delete access then
145            it can't conflict */
146         if (!(e1->access_mask & (SEC_FILE_WRITE_DATA |
147                                  SEC_FILE_APPEND_DATA |
148                                  SEC_FILE_READ_DATA |
149                                  SEC_FILE_EXECUTE |
150                                  SEC_STD_DELETE))) {
151                 return NT_STATUS_OK;
152         }
153         if (!(e2->access_mask & (SEC_FILE_WRITE_DATA |
154                                  SEC_FILE_APPEND_DATA |
155                                  SEC_FILE_READ_DATA |
156                                  SEC_FILE_EXECUTE |
157                                  SEC_STD_DELETE))) {
158                 return NT_STATUS_OK;
159         }
160
161         /* data IO access masks. This is skipped if the two open handles
162            are on different streams (as in that case the masks don't
163            interact) */
164         if (e1->stream_id != e2->stream_id) {
165                 return NT_STATUS_OK;
166         }
167
168 #define CHECK_MASK(am, right, sa, share) \
169         if (((am) & (right)) && !((sa) & (share))) return NT_STATUS_SHARING_VIOLATION
170
171         CHECK_MASK(e1->access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
172                    e2->share_access, NTCREATEX_SHARE_ACCESS_WRITE);
173         CHECK_MASK(e2->access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
174                    e1->share_access, NTCREATEX_SHARE_ACCESS_WRITE);
175         
176         CHECK_MASK(e1->access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
177                    e2->share_access, NTCREATEX_SHARE_ACCESS_READ);
178         CHECK_MASK(e2->access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
179                    e1->share_access, NTCREATEX_SHARE_ACCESS_READ);
180
181         CHECK_MASK(e1->access_mask, SEC_STD_DELETE,
182                    e2->share_access, NTCREATEX_SHARE_ACCESS_DELETE);
183         CHECK_MASK(e2->access_mask, SEC_STD_DELETE,
184                    e1->share_access, NTCREATEX_SHARE_ACCESS_DELETE);
185
186         return NT_STATUS_OK;
187 }
188
189 /*
190   pull a record, translating from the db format to the opendb_file structure defined
191   in opendb.idl
192 */
193 static NTSTATUS odb_pull_record(struct odb_lock *lck, struct opendb_file *file)
194 {
195         struct odb_context *odb = lck->odb;
196         TDB_DATA dbuf;
197         DATA_BLOB blob;
198         NTSTATUS status;
199                 
200         dbuf = tdb_fetch(odb->w->tdb, lck->key);
201         if (dbuf.dptr == NULL) {
202                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
203         }
204
205         blob.data = dbuf.dptr;
206         blob.length = dbuf.dsize;
207
208         status = ndr_pull_struct_blob(&blob, lck, file, (ndr_pull_flags_fn_t)ndr_pull_opendb_file);
209
210         free(dbuf.dptr);
211
212         return status;
213 }
214
215 /*
216   push a record, translating from the opendb_file structure defined in opendb.idl
217 */
218 static NTSTATUS odb_push_record(struct odb_lock *lck, struct opendb_file *file)
219 {
220         struct odb_context *odb = lck->odb;
221         TDB_DATA dbuf;
222         DATA_BLOB blob;
223         NTSTATUS status;
224         int ret;
225
226         if (file->num_entries == 0) {
227                 ret = tdb_delete(odb->w->tdb, lck->key);
228                 if (ret != 0) {
229                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
230                 }
231                 return NT_STATUS_OK;
232         }
233
234         status = ndr_push_struct_blob(&blob, lck, file, (ndr_push_flags_fn_t)ndr_push_opendb_file);
235         NT_STATUS_NOT_OK_RETURN(status);
236
237         dbuf.dptr = blob.data;
238         dbuf.dsize = blob.length;
239                 
240         ret = tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE);
241         data_blob_free(&blob);
242         if (ret != 0) {
243                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
244         }
245
246         return NT_STATUS_OK;
247 }
248
249 /*
250   send an oplock break to a client
251 */
252 static NTSTATUS odb_oplock_break_send(struct odb_context *odb, struct opendb_entry *e)
253 {
254         /* tell the server handling this open file about the need to send the client
255            a break */
256         return messaging_send_ptr(odb->ntvfs_ctx->msg_ctx, e->server, 
257                                   MSG_NTVFS_OPLOCK_BREAK, e->file_handle);
258 }
259
260 /*
261   register an open file in the open files database. This implements the share_access
262   rules
263
264   Note that the path is only used by the delete on close logic, not
265   for comparing with other filenames
266 */
267 static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
268                                   uint32_t stream_id, uint32_t share_access, 
269                                   uint32_t access_mask, BOOL delete_on_close,
270                                   const char *path, 
271                                   uint32_t oplock_level, uint32_t *oplock_granted)
272 {
273         struct odb_context *odb = lck->odb;
274         struct opendb_entry e;
275         int i;
276         struct opendb_file file;
277         NTSTATUS status;
278
279         if (odb->oplocks == False) {
280                 oplock_level = OPLOCK_NONE;
281         }
282
283         status = odb_pull_record(lck, &file);
284         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
285                 /* initialise a blank structure */
286                 ZERO_STRUCT(file);
287                 file.path = path;
288         } else {
289                 NT_STATUS_NOT_OK_RETURN(status);
290         }
291
292         /* see if it conflicts */
293         e.server          = odb->ntvfs_ctx->server_id;
294         e.file_handle     = file_handle;
295         e.stream_id       = stream_id;
296         e.share_access    = share_access;
297         e.access_mask     = access_mask;
298         e.delete_on_close = delete_on_close;
299         e.oplock_level    = OPLOCK_NONE;
300                 
301         /* see if anyone has an oplock, which we need to break */
302         for (i=0;i<file.num_entries;i++) {
303                 if (file.entries[i].oplock_level == OPLOCK_BATCH) {
304                         /* a batch oplock caches close calls, which
305                            means the client application might have
306                            already closed the file. We have to allow
307                            this close to propogate by sending a oplock
308                            break request and suspending this call
309                            until the break is acknowledged or the file
310                            is closed */
311                         odb_oplock_break_send(odb, &file.entries[i]);
312                         return NT_STATUS_OPLOCK_NOT_GRANTED;
313                 }
314         }
315
316         if (file.delete_on_close || 
317             (file.num_entries != 0 && delete_on_close)) {
318                 /* while delete on close is set, no new opens are allowed */
319                 return NT_STATUS_DELETE_PENDING;
320         }
321
322         /* check for sharing violations */
323         for (i=0;i<file.num_entries;i++) {
324                 status = share_conflict(&file.entries[i], &e);
325                 NT_STATUS_NOT_OK_RETURN(status);
326         }
327
328         /* we now know the open could succeed, but we need to check
329            for any exclusive oplocks. We can't grant a second open
330            till these are broken. Note that we check for batch oplocks
331            before checking for sharing violations, and check for
332            exclusive oplocks afterwards. */
333         for (i=0;i<file.num_entries;i++) {
334                 if (file.entries[i].oplock_level == OPLOCK_EXCLUSIVE) {
335                         odb_oplock_break_send(odb, &file.entries[i]);
336                         return NT_STATUS_OPLOCK_NOT_GRANTED;
337                 }
338         }
339
340         /*
341           possibly grant an exclusive or batch oplock if this is the only client
342           with the file open. We don't yet grant levelII oplocks.
343         */
344         if (oplock_granted != NULL) {
345                 if ((oplock_level == OPLOCK_BATCH ||
346                      oplock_level == OPLOCK_EXCLUSIVE) &&
347                     file.num_entries == 0) {
348                         (*oplock_granted) = oplock_level;
349                 } else {
350                         (*oplock_granted) = OPLOCK_NONE;
351                 }
352                 e.oplock_level = (*oplock_granted);
353         }
354
355         /* it doesn't conflict, so add it to the end */
356         file.entries = talloc_realloc(lck, file.entries, struct opendb_entry, 
357                                       file.num_entries+1);
358         NT_STATUS_HAVE_NO_MEMORY(file.entries);
359
360         file.entries[file.num_entries] = e;
361         file.num_entries++;
362
363         return odb_push_record(lck, &file);
364 }
365
366
367 /*
368   register a pending open file in the open files database
369 */
370 static NTSTATUS odb_tdb_open_file_pending(struct odb_lock *lck, void *private)
371 {
372         struct odb_context *odb = lck->odb;
373         struct opendb_file file;
374         NTSTATUS status;
375                 
376         status = odb_pull_record(lck, &file);
377         NT_STATUS_NOT_OK_RETURN(status);
378
379         file.pending = talloc_realloc(lck, file.pending, struct opendb_pending, 
380                                       file.num_pending+1);
381         NT_STATUS_HAVE_NO_MEMORY(file.pending);
382
383         file.pending[file.num_pending].server = odb->ntvfs_ctx->server_id;
384         file.pending[file.num_pending].notify_ptr = private;
385
386         file.num_pending++;
387
388         return odb_push_record(lck, &file);
389 }
390
391
392 /*
393   remove a opendb entry
394 */
395 static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle)
396 {
397         struct odb_context *odb = lck->odb;
398         struct opendb_file file;
399         int i;
400         NTSTATUS status;
401
402         status = odb_pull_record(lck, &file);
403         NT_STATUS_NOT_OK_RETURN(status);
404
405         /* find the entry, and delete it */
406         for (i=0;i<file.num_entries;i++) {
407                 if (file_handle == file.entries[i].file_handle &&
408                     cluster_id_equal(&odb->ntvfs_ctx->server_id, &file.entries[i].server)) {
409                         if (file.entries[i].delete_on_close) {
410                                 file.delete_on_close = True;
411                         }
412                         if (i < file.num_entries-1) {
413                                 memmove(file.entries+i, file.entries+i+1, 
414                                         (file.num_entries - (i+1)) * 
415                                         sizeof(struct opendb_entry));
416                         }
417                         break;
418                 }
419         }
420
421         if (i == file.num_entries) {
422                 return NT_STATUS_UNSUCCESSFUL;
423         }
424
425         /* send any pending notifications, removing them once sent */
426         for (i=0;i<file.num_pending;i++) {
427                 messaging_send_ptr(odb->ntvfs_ctx->msg_ctx, file.pending[i].server, 
428                                    MSG_PVFS_RETRY_OPEN, 
429                                    file.pending[i].notify_ptr);
430         }
431         file.num_pending = 0;
432
433         file.num_entries--;
434         
435         return odb_push_record(lck, &file);
436 }
437
438
439 /*
440   remove a pending opendb entry
441 */
442 static NTSTATUS odb_tdb_remove_pending(struct odb_lock *lck, void *private)
443 {
444         struct odb_context *odb = lck->odb;
445         int i;
446         NTSTATUS status;
447         struct opendb_file file;
448
449         status = odb_pull_record(lck, &file);
450         NT_STATUS_NOT_OK_RETURN(status);
451
452         /* find the entry, and delete it */
453         for (i=0;i<file.num_pending;i++) {
454                 if (private == file.pending[i].notify_ptr &&
455                     cluster_id_equal(&odb->ntvfs_ctx->server_id, &file.pending[i].server)) {
456                         if (i < file.num_pending-1) {
457                                 memmove(file.pending+i, file.pending+i+1, 
458                                         (file.num_pending - (i+1)) * 
459                                         sizeof(struct opendb_pending));
460                         }
461                         break;
462                 }
463         }
464
465         if (i == file.num_pending) {
466                 return NT_STATUS_UNSUCCESSFUL;
467         }
468
469         file.num_pending--;
470         
471         return odb_push_record(lck, &file);
472 }
473
474
475 /*
476   rename the path in a open file
477 */
478 static NTSTATUS odb_tdb_rename(struct odb_lock *lck, const char *path)
479 {
480         struct opendb_file file;
481         NTSTATUS status;
482
483         status = odb_pull_record(lck, &file);
484         if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
485                 /* not having the record at all is OK */
486                 return NT_STATUS_OK;
487         }
488         NT_STATUS_NOT_OK_RETURN(status);
489
490         file.path = path;
491         return odb_push_record(lck, &file);
492 }
493
494 /*
495   update delete on close flag on an open file
496 */
497 static NTSTATUS odb_tdb_set_delete_on_close(struct odb_lock *lck, BOOL del_on_close)
498 {
499         NTSTATUS status;
500         struct opendb_file file;
501
502         status = odb_pull_record(lck, &file);
503         NT_STATUS_NOT_OK_RETURN(status);
504
505         file.delete_on_close = del_on_close;
506
507         return odb_push_record(lck, &file);
508 }
509
510 /*
511   return the current value of the delete_on_close bit, and how many
512   people still have the file open
513 */
514 static NTSTATUS odb_tdb_get_delete_on_close(struct odb_context *odb, 
515                                             DATA_BLOB *key, BOOL *del_on_close, 
516                                             int *open_count, char **path)
517 {
518         NTSTATUS status;
519         struct opendb_file file;
520         struct odb_lock *lck;
521
522         lck = odb_lock(odb, odb, key);
523         NT_STATUS_HAVE_NO_MEMORY(lck);
524
525         status = odb_pull_record(lck, &file);
526         if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
527                 talloc_free(lck);
528                 (*del_on_close) = False;
529                 return NT_STATUS_OK;
530         }
531         if (!NT_STATUS_IS_OK(status)) {
532                 talloc_free(lck);
533                 return status;
534         }
535
536         (*del_on_close) = file.delete_on_close;
537         if (open_count != NULL) {
538                 (*open_count) = file.num_entries;
539         }
540         if (path != NULL) {
541                 *path = talloc_strdup(odb, file.path);
542                 NT_STATUS_HAVE_NO_MEMORY(*path);
543                 if (file.num_entries == 1 && file.entries[0].delete_on_close) {
544                         (*del_on_close) = True;
545                 }
546         }
547
548         talloc_free(lck);
549
550         return NT_STATUS_OK;
551 }
552
553
554 /*
555   determine if a file can be opened with the given share_access,
556   create_options and access_mask
557 */
558 static NTSTATUS odb_tdb_can_open(struct odb_lock *lck,
559                                  uint32_t share_access, uint32_t create_options, 
560                                  uint32_t access_mask)
561 {
562         struct odb_context *odb = lck->odb;
563         NTSTATUS status;
564         struct opendb_file file;
565         struct opendb_entry e;
566         int i;
567
568         status = odb_pull_record(lck, &file);
569         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
570                 return NT_STATUS_OK;
571         }
572         NT_STATUS_NOT_OK_RETURN(status);
573
574         if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && 
575             file.num_entries != 0) {
576                 return NT_STATUS_SHARING_VIOLATION;
577         }
578
579         if (file.delete_on_close) {
580                 return NT_STATUS_DELETE_PENDING;
581         }
582
583         e.server       = odb->ntvfs_ctx->server_id;
584         e.file_handle  = NULL;
585         e.stream_id    = 0;
586         e.share_access = share_access;
587         e.access_mask  = access_mask;
588                 
589         for (i=0;i<file.num_entries;i++) {
590                 status = share_conflict(&file.entries[i], &e);
591                 if (!NT_STATUS_IS_OK(status)) {
592                         /* note that we discard the error code
593                            here. We do this as unless we are actually
594                            doing an open (which comes via a different
595                            function), we need to return a sharing
596                            violation */
597                         return NT_STATUS_SHARING_VIOLATION;
598                 }
599         }
600
601         return NT_STATUS_OK;
602 }
603
604
605 static const struct opendb_ops opendb_tdb_ops = {
606         .odb_init                = odb_tdb_init,
607         .odb_lock                = odb_tdb_lock,
608         .odb_open_file           = odb_tdb_open_file,
609         .odb_open_file_pending   = odb_tdb_open_file_pending,
610         .odb_close_file          = odb_tdb_close_file,
611         .odb_remove_pending      = odb_tdb_remove_pending,
612         .odb_rename              = odb_tdb_rename,
613         .odb_set_delete_on_close = odb_tdb_set_delete_on_close,
614         .odb_get_delete_on_close = odb_tdb_get_delete_on_close,
615         .odb_can_open            = odb_tdb_can_open
616 };
617
618
619 void odb_tdb_init_ops(void)
620 {
621         odb_set_ops(&opendb_tdb_ops);
622 }