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