Merge commit 'release-4-0-0alpha2' into v4-0-test
[bbaumbach/samba-autobuild/.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 "tdb_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, ntvfs_ctx->lp_ctx, "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(ntvfs_ctx->lp_ctx, 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         enum ndr_err_code ndr_err;
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         ndr_err = ndr_pull_struct_blob(&blob, lck, file, (ndr_pull_flags_fn_t)ndr_pull_opendb_file);
209         free(dbuf.dptr);
210         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
211                 return ndr_map_error2ntstatus(ndr_err);
212         }
213
214         return NT_STATUS_OK;
215 }
216
217 /*
218   push a record, translating from the opendb_file structure defined in opendb.idl
219 */
220 static NTSTATUS odb_push_record(struct odb_lock *lck, struct opendb_file *file)
221 {
222         struct odb_context *odb = lck->odb;
223         TDB_DATA dbuf;
224         DATA_BLOB blob;
225         enum ndr_err_code ndr_err;
226         int ret;
227
228         if (file->num_entries == 0) {
229                 ret = tdb_delete(odb->w->tdb, lck->key);
230                 if (ret != 0) {
231                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
232                 }
233                 return NT_STATUS_OK;
234         }
235
236         ndr_err = ndr_push_struct_blob(&blob, lck, file, (ndr_push_flags_fn_t)ndr_push_opendb_file);
237         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
238                 return ndr_map_error2ntstatus(ndr_err);
239         }
240
241         dbuf.dptr = blob.data;
242         dbuf.dsize = blob.length;
243                 
244         ret = tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE);
245         data_blob_free(&blob);
246         if (ret != 0) {
247                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
248         }
249
250         return NT_STATUS_OK;
251 }
252
253 /*
254   send an oplock break to a client
255 */
256 static NTSTATUS odb_oplock_break_send(struct odb_context *odb, struct opendb_entry *e)
257 {
258         /* tell the server handling this open file about the need to send the client
259            a break */
260         return messaging_send_ptr(odb->ntvfs_ctx->msg_ctx, e->server, 
261                                   MSG_NTVFS_OPLOCK_BREAK, e->file_handle);
262 }
263
264 /*
265   register an open file in the open files database. This implements the share_access
266   rules
267
268   Note that the path is only used by the delete on close logic, not
269   for comparing with other filenames
270 */
271 static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
272                                   uint32_t stream_id, uint32_t share_access, 
273                                   uint32_t access_mask, bool delete_on_close,
274                                   const char *path, 
275                                   uint32_t oplock_level, uint32_t *oplock_granted)
276 {
277         struct odb_context *odb = lck->odb;
278         struct opendb_entry e;
279         int i;
280         struct opendb_file file;
281         NTSTATUS status;
282
283         if (odb->oplocks == false) {
284                 oplock_level = OPLOCK_NONE;
285         }
286
287         status = odb_pull_record(lck, &file);
288         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
289                 /* initialise a blank structure */
290                 ZERO_STRUCT(file);
291                 file.path = path;
292         } else {
293                 NT_STATUS_NOT_OK_RETURN(status);
294         }
295
296         /* see if it conflicts */
297         e.server          = odb->ntvfs_ctx->server_id;
298         e.file_handle     = file_handle;
299         e.stream_id       = stream_id;
300         e.share_access    = share_access;
301         e.access_mask     = access_mask;
302         e.delete_on_close = delete_on_close;
303         e.oplock_level    = OPLOCK_NONE;
304                 
305         /* see if anyone has an oplock, which we need to break */
306         for (i=0;i<file.num_entries;i++) {
307                 if (file.entries[i].oplock_level == OPLOCK_BATCH) {
308                         /* a batch oplock caches close calls, which
309                            means the client application might have
310                            already closed the file. We have to allow
311                            this close to propogate by sending a oplock
312                            break request and suspending this call
313                            until the break is acknowledged or the file
314                            is closed */
315                         odb_oplock_break_send(odb, &file.entries[i]);
316                         return NT_STATUS_OPLOCK_NOT_GRANTED;
317                 }
318         }
319
320         if (file.delete_on_close || 
321             (file.num_entries != 0 && delete_on_close)) {
322                 /* while delete on close is set, no new opens are allowed */
323                 return NT_STATUS_DELETE_PENDING;
324         }
325
326         /* check for sharing violations */
327         for (i=0;i<file.num_entries;i++) {
328                 status = share_conflict(&file.entries[i], &e);
329                 NT_STATUS_NOT_OK_RETURN(status);
330         }
331
332         /* we now know the open could succeed, but we need to check
333            for any exclusive oplocks. We can't grant a second open
334            till these are broken. Note that we check for batch oplocks
335            before checking for sharing violations, and check for
336            exclusive oplocks afterwards. */
337         for (i=0;i<file.num_entries;i++) {
338                 if (file.entries[i].oplock_level == OPLOCK_EXCLUSIVE) {
339                         odb_oplock_break_send(odb, &file.entries[i]);
340                         return NT_STATUS_OPLOCK_NOT_GRANTED;
341                 }
342         }
343
344         /*
345           possibly grant an exclusive or batch oplock if this is the only client
346           with the file open. We don't yet grant levelII oplocks.
347         */
348         if (oplock_granted != NULL) {
349                 if ((oplock_level == OPLOCK_BATCH ||
350                      oplock_level == OPLOCK_EXCLUSIVE) &&
351                     file.num_entries == 0) {
352                         (*oplock_granted) = oplock_level;
353                 } else {
354                         (*oplock_granted) = OPLOCK_NONE;
355                 }
356                 e.oplock_level = (*oplock_granted);
357         }
358
359         /* it doesn't conflict, so add it to the end */
360         file.entries = talloc_realloc(lck, file.entries, struct opendb_entry, 
361                                       file.num_entries+1);
362         NT_STATUS_HAVE_NO_MEMORY(file.entries);
363
364         file.entries[file.num_entries] = e;
365         file.num_entries++;
366
367         return odb_push_record(lck, &file);
368 }
369
370
371 /*
372   register a pending open file in the open files database
373 */
374 static NTSTATUS odb_tdb_open_file_pending(struct odb_lock *lck, void *private)
375 {
376         struct odb_context *odb = lck->odb;
377         struct opendb_file file;
378         NTSTATUS status;
379                 
380         status = odb_pull_record(lck, &file);
381         NT_STATUS_NOT_OK_RETURN(status);
382
383         file.pending = talloc_realloc(lck, file.pending, struct opendb_pending, 
384                                       file.num_pending+1);
385         NT_STATUS_HAVE_NO_MEMORY(file.pending);
386
387         file.pending[file.num_pending].server = odb->ntvfs_ctx->server_id;
388         file.pending[file.num_pending].notify_ptr = private;
389
390         file.num_pending++;
391
392         return odb_push_record(lck, &file);
393 }
394
395
396 /*
397   remove a opendb entry
398 */
399 static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle)
400 {
401         struct odb_context *odb = lck->odb;
402         struct opendb_file file;
403         int i;
404         NTSTATUS status;
405
406         status = odb_pull_record(lck, &file);
407         NT_STATUS_NOT_OK_RETURN(status);
408
409         /* find the entry, and delete it */
410         for (i=0;i<file.num_entries;i++) {
411                 if (file_handle == file.entries[i].file_handle &&
412                     cluster_id_equal(&odb->ntvfs_ctx->server_id, &file.entries[i].server)) {
413                         if (file.entries[i].delete_on_close) {
414                                 file.delete_on_close = true;
415                         }
416                         if (i < file.num_entries-1) {
417                                 memmove(file.entries+i, file.entries+i+1, 
418                                         (file.num_entries - (i+1)) * 
419                                         sizeof(struct opendb_entry));
420                         }
421                         break;
422                 }
423         }
424
425         if (i == file.num_entries) {
426                 return NT_STATUS_UNSUCCESSFUL;
427         }
428
429         /* send any pending notifications, removing them once sent */
430         for (i=0;i<file.num_pending;i++) {
431                 messaging_send_ptr(odb->ntvfs_ctx->msg_ctx, file.pending[i].server, 
432                                    MSG_PVFS_RETRY_OPEN, 
433                                    file.pending[i].notify_ptr);
434         }
435         file.num_pending = 0;
436
437         file.num_entries--;
438         
439         return odb_push_record(lck, &file);
440 }
441
442
443 /*
444   remove a pending opendb entry
445 */
446 static NTSTATUS odb_tdb_remove_pending(struct odb_lock *lck, void *private)
447 {
448         struct odb_context *odb = lck->odb;
449         int i;
450         NTSTATUS status;
451         struct opendb_file file;
452
453         status = odb_pull_record(lck, &file);
454         NT_STATUS_NOT_OK_RETURN(status);
455
456         /* find the entry, and delete it */
457         for (i=0;i<file.num_pending;i++) {
458                 if (private == file.pending[i].notify_ptr &&
459                     cluster_id_equal(&odb->ntvfs_ctx->server_id, &file.pending[i].server)) {
460                         if (i < file.num_pending-1) {
461                                 memmove(file.pending+i, file.pending+i+1, 
462                                         (file.num_pending - (i+1)) * 
463                                         sizeof(struct opendb_pending));
464                         }
465                         break;
466                 }
467         }
468
469         if (i == file.num_pending) {
470                 return NT_STATUS_UNSUCCESSFUL;
471         }
472
473         file.num_pending--;
474         
475         return odb_push_record(lck, &file);
476 }
477
478
479 /*
480   rename the path in a open file
481 */
482 static NTSTATUS odb_tdb_rename(struct odb_lock *lck, const char *path)
483 {
484         struct opendb_file file;
485         NTSTATUS status;
486
487         status = odb_pull_record(lck, &file);
488         if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
489                 /* not having the record at all is OK */
490                 return NT_STATUS_OK;
491         }
492         NT_STATUS_NOT_OK_RETURN(status);
493
494         file.path = path;
495         return odb_push_record(lck, &file);
496 }
497
498 /*
499   update delete on close flag on an open file
500 */
501 static NTSTATUS odb_tdb_set_delete_on_close(struct odb_lock *lck, bool del_on_close)
502 {
503         NTSTATUS status;
504         struct opendb_file file;
505
506         status = odb_pull_record(lck, &file);
507         NT_STATUS_NOT_OK_RETURN(status);
508
509         file.delete_on_close = del_on_close;
510
511         return odb_push_record(lck, &file);
512 }
513
514 /*
515   return the current value of the delete_on_close bit, and how many
516   people still have the file open
517 */
518 static NTSTATUS odb_tdb_get_delete_on_close(struct odb_context *odb, 
519                                             DATA_BLOB *key, bool *del_on_close, 
520                                             int *open_count, char **path)
521 {
522         NTSTATUS status;
523         struct opendb_file file;
524         struct odb_lock *lck;
525
526         lck = odb_lock(odb, odb, key);
527         NT_STATUS_HAVE_NO_MEMORY(lck);
528
529         status = odb_pull_record(lck, &file);
530         if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
531                 talloc_free(lck);
532                 (*del_on_close) = false;
533                 return NT_STATUS_OK;
534         }
535         if (!NT_STATUS_IS_OK(status)) {
536                 talloc_free(lck);
537                 return status;
538         }
539
540         (*del_on_close) = file.delete_on_close;
541         if (open_count != NULL) {
542                 (*open_count) = file.num_entries;
543         }
544         if (path != NULL) {
545                 *path = talloc_strdup(odb, file.path);
546                 NT_STATUS_HAVE_NO_MEMORY(*path);
547                 if (file.num_entries == 1 && file.entries[0].delete_on_close) {
548                         (*del_on_close) = true;
549                 }
550         }
551
552         talloc_free(lck);
553
554         return NT_STATUS_OK;
555 }
556
557
558 /*
559   determine if a file can be opened with the given share_access,
560   create_options and access_mask
561 */
562 static NTSTATUS odb_tdb_can_open(struct odb_lock *lck,
563                                  uint32_t share_access, uint32_t create_options, 
564                                  uint32_t access_mask)
565 {
566         struct odb_context *odb = lck->odb;
567         NTSTATUS status;
568         struct opendb_file file;
569         struct opendb_entry e;
570         int i;
571
572         status = odb_pull_record(lck, &file);
573         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
574                 return NT_STATUS_OK;
575         }
576         NT_STATUS_NOT_OK_RETURN(status);
577
578         if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && 
579             file.num_entries != 0) {
580                 return NT_STATUS_SHARING_VIOLATION;
581         }
582
583         if (file.delete_on_close) {
584                 return NT_STATUS_DELETE_PENDING;
585         }
586
587         e.server       = odb->ntvfs_ctx->server_id;
588         e.file_handle  = NULL;
589         e.stream_id    = 0;
590         e.share_access = share_access;
591         e.access_mask  = access_mask;
592                 
593         for (i=0;i<file.num_entries;i++) {
594                 status = share_conflict(&file.entries[i], &e);
595                 if (!NT_STATUS_IS_OK(status)) {
596                         /* note that we discard the error code
597                            here. We do this as unless we are actually
598                            doing an open (which comes via a different
599                            function), we need to return a sharing
600                            violation */
601                         return NT_STATUS_SHARING_VIOLATION;
602                 }
603         }
604
605         return NT_STATUS_OK;
606 }
607
608
609 static const struct opendb_ops opendb_tdb_ops = {
610         .odb_init                = odb_tdb_init,
611         .odb_lock                = odb_tdb_lock,
612         .odb_open_file           = odb_tdb_open_file,
613         .odb_open_file_pending   = odb_tdb_open_file_pending,
614         .odb_close_file          = odb_tdb_close_file,
615         .odb_remove_pending      = odb_tdb_remove_pending,
616         .odb_rename              = odb_tdb_rename,
617         .odb_set_delete_on_close = odb_tdb_set_delete_on_close,
618         .odb_get_delete_on_close = odb_tdb_get_delete_on_close,
619         .odb_can_open            = odb_tdb_can_open
620 };
621
622
623 void odb_tdb_init_ops(void)
624 {
625         odb_set_ops(&opendb_tdb_ops);
626 }