2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2004
5 Copyright (C) Stefan Metzmacher 2008
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 this is the open files database, tdb backend. It implements shared
23 storage of what files are open between server instances, and
24 implements the rules of shared access to files.
26 The caller needs to provide a file_key, which specifies what file
27 they are talking about. This needs to be a unique key across all
28 filesystems, and is usually implemented in terms of a device/inode
31 Before any operations can be performed the caller needs to establish
32 a lock on the record associated with file_key. That is done by
33 calling odb_lock(). The caller releases this lock by calling
34 talloc_free() on the returned handle.
36 All other operations on a record are done by passing the odb_lock()
37 handle back to this module. The handle contains internal
38 information about what file_key is being operated on.
42 #include "system/filesys.h"
43 #include "lib/tdb/include/tdb.h"
44 #include "messaging/messaging.h"
46 #include "lib/messaging/irpc.h"
47 #include "librpc/gen_ndr/ndr_opendb.h"
48 #include "ntvfs/ntvfs.h"
49 #include "ntvfs/common/ntvfs_common.h"
50 #include "cluster/cluster.h"
51 #include "param/param.h"
55 struct ntvfs_context *ntvfs_ctx;
60 an odb lock handle. You must obtain one of these using odb_lock() before doing
64 struct odb_context *odb;
69 Open up the openfiles.tdb database. Close it down using
70 talloc_free(). We need the messaging_ctx to allow for pending open
73 static struct odb_context *odb_tdb_init(TALLOC_CTX *mem_ctx,
74 struct ntvfs_context *ntvfs_ctx)
76 struct odb_context *odb;
78 odb = talloc(mem_ctx, struct odb_context);
83 odb->w = cluster_tdb_tmp_open(odb, ntvfs_ctx->lp_ctx, "openfiles.tdb", TDB_DEFAULT);
89 odb->ntvfs_ctx = ntvfs_ctx;
91 /* leave oplocks disabled by default until the code is working */
92 odb->oplocks = lp_parm_bool(ntvfs_ctx->lp_ctx, NULL, "opendb", "oplocks", false);
98 destroy a lock on the database
100 static int odb_lock_destructor(struct odb_lock *lck)
102 tdb_chainunlock(lck->odb->w->tdb, lck->key);
107 get a lock on a entry in the odb. This call returns a lock handle,
108 which the caller should unlock using talloc_free().
110 static struct odb_lock *odb_tdb_lock(TALLOC_CTX *mem_ctx,
111 struct odb_context *odb, DATA_BLOB *file_key)
113 struct odb_lock *lck;
115 lck = talloc(mem_ctx, struct odb_lock);
120 lck->odb = talloc_reference(lck, odb);
121 lck->key.dptr = talloc_memdup(lck, file_key->data, file_key->length);
122 lck->key.dsize = file_key->length;
123 if (lck->key.dptr == NULL) {
128 if (tdb_chainlock(odb->w->tdb, lck->key) != 0) {
133 talloc_set_destructor(lck, odb_lock_destructor);
138 static DATA_BLOB odb_tdb_get_key(TALLOC_CTX *mem_ctx, struct odb_lock *lck)
140 return data_blob_talloc(mem_ctx, lck->key.dptr, lck->key.dsize);
145 determine if two odb_entry structures conflict
147 return NT_STATUS_OK on no conflict
149 static NTSTATUS share_conflict(struct opendb_entry *e1, struct opendb_entry *e2)
151 /* if either open involves no read.write or delete access then
153 if (!(e1->access_mask & (SEC_FILE_WRITE_DATA |
154 SEC_FILE_APPEND_DATA |
160 if (!(e2->access_mask & (SEC_FILE_WRITE_DATA |
161 SEC_FILE_APPEND_DATA |
168 /* data IO access masks. This is skipped if the two open handles
169 are on different streams (as in that case the masks don't
171 if (e1->stream_id != e2->stream_id) {
175 #define CHECK_MASK(am, right, sa, share) \
176 if (((am) & (right)) && !((sa) & (share))) return NT_STATUS_SHARING_VIOLATION
178 CHECK_MASK(e1->access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
179 e2->share_access, NTCREATEX_SHARE_ACCESS_WRITE);
180 CHECK_MASK(e2->access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
181 e1->share_access, NTCREATEX_SHARE_ACCESS_WRITE);
183 CHECK_MASK(e1->access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
184 e2->share_access, NTCREATEX_SHARE_ACCESS_READ);
185 CHECK_MASK(e2->access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
186 e1->share_access, NTCREATEX_SHARE_ACCESS_READ);
188 CHECK_MASK(e1->access_mask, SEC_STD_DELETE,
189 e2->share_access, NTCREATEX_SHARE_ACCESS_DELETE);
190 CHECK_MASK(e2->access_mask, SEC_STD_DELETE,
191 e1->share_access, NTCREATEX_SHARE_ACCESS_DELETE);
197 pull a record, translating from the db format to the opendb_file structure defined
200 static NTSTATUS odb_pull_record(struct odb_lock *lck, struct opendb_file *file)
202 struct odb_context *odb = lck->odb;
205 enum ndr_err_code ndr_err;
207 dbuf = tdb_fetch(odb->w->tdb, lck->key);
208 if (dbuf.dptr == NULL) {
209 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
212 blob.data = dbuf.dptr;
213 blob.length = dbuf.dsize;
215 ndr_err = ndr_pull_struct_blob(&blob, lck, lp_iconv_convenience(lck->odb->ntvfs_ctx->lp_ctx), file, (ndr_pull_flags_fn_t)ndr_pull_opendb_file);
217 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
218 return ndr_map_error2ntstatus(ndr_err);
225 push a record, translating from the opendb_file structure defined in opendb.idl
227 static NTSTATUS odb_push_record(struct odb_lock *lck, struct opendb_file *file)
229 struct odb_context *odb = lck->odb;
232 enum ndr_err_code ndr_err;
235 if (file->num_entries == 0) {
236 ret = tdb_delete(odb->w->tdb, lck->key);
238 return NT_STATUS_INTERNAL_DB_CORRUPTION;
243 ndr_err = ndr_push_struct_blob(&blob, lck, lp_iconv_convenience(lck->odb->ntvfs_ctx->lp_ctx), file, (ndr_push_flags_fn_t)ndr_push_opendb_file);
244 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
245 return ndr_map_error2ntstatus(ndr_err);
248 dbuf.dptr = blob.data;
249 dbuf.dsize = blob.length;
251 ret = tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE);
252 data_blob_free(&blob);
254 return NT_STATUS_INTERNAL_DB_CORRUPTION;
261 send an oplock break to a client
263 static NTSTATUS odb_oplock_break_send(struct odb_context *odb,
264 struct opendb_entry *e,
268 struct opendb_oplock_break op_break;
271 ZERO_STRUCT(op_break);
273 /* tell the server handling this open file about the need to send the client
275 op_break.file_handle = e->file_handle;
276 op_break.level = level;
278 blob = data_blob_const(&op_break, sizeof(op_break));
280 status = messaging_send(odb->ntvfs_ctx->msg_ctx, e->server,
281 MSG_NTVFS_OPLOCK_BREAK, &blob);
282 NT_STATUS_NOT_OK_RETURN(status);
288 register an open file in the open files database. This implements the share_access
291 Note that the path is only used by the delete on close logic, not
292 for comparing with other filenames
294 static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
295 uint32_t stream_id, uint32_t share_access,
296 uint32_t access_mask, bool delete_on_close,
298 uint32_t oplock_level, uint32_t *oplock_granted)
300 struct odb_context *odb = lck->odb;
301 struct opendb_entry e;
303 struct opendb_file file;
306 if (odb->oplocks == false) {
307 oplock_level = OPLOCK_NONE;
310 status = odb_pull_record(lck, &file);
311 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
312 /* initialise a blank structure */
316 NT_STATUS_NOT_OK_RETURN(status);
319 /* see if it conflicts */
320 e.server = odb->ntvfs_ctx->server_id;
321 e.file_handle = file_handle;
322 e.stream_id = stream_id;
323 e.share_access = share_access;
324 e.access_mask = access_mask;
325 e.delete_on_close = delete_on_close;
326 e.oplock_level = OPLOCK_NONE;
328 /* see if anyone has an oplock, which we need to break */
329 for (i=0;i<file.num_entries;i++) {
330 if (file.entries[i].oplock_level == OPLOCK_BATCH) {
331 /* a batch oplock caches close calls, which
332 means the client application might have
333 already closed the file. We have to allow
334 this close to propogate by sending a oplock
335 break request and suspending this call
336 until the break is acknowledged or the file
338 odb_oplock_break_send(odb, &file.entries[i],
339 OPLOCK_BREAK_TO_LEVEL_II/*TODO*/);
340 return NT_STATUS_OPLOCK_NOT_GRANTED;
344 if (file.delete_on_close ||
345 (file.num_entries != 0 && delete_on_close)) {
346 /* while delete on close is set, no new opens are allowed */
347 return NT_STATUS_DELETE_PENDING;
350 /* check for sharing violations */
351 for (i=0;i<file.num_entries;i++) {
352 status = share_conflict(&file.entries[i], &e);
353 NT_STATUS_NOT_OK_RETURN(status);
356 /* we now know the open could succeed, but we need to check
357 for any exclusive oplocks. We can't grant a second open
358 till these are broken. Note that we check for batch oplocks
359 before checking for sharing violations, and check for
360 exclusive oplocks afterwards. */
361 for (i=0;i<file.num_entries;i++) {
362 if (file.entries[i].oplock_level == OPLOCK_EXCLUSIVE) {
363 odb_oplock_break_send(odb, &file.entries[i],
364 OPLOCK_BREAK_TO_NONE/*TODO*/);
365 return NT_STATUS_OPLOCK_NOT_GRANTED;
370 possibly grant an exclusive or batch oplock if this is the only client
371 with the file open. We don't yet grant levelII oplocks.
373 if (oplock_granted != NULL) {
374 if ((oplock_level == OPLOCK_BATCH ||
375 oplock_level == OPLOCK_EXCLUSIVE) &&
376 file.num_entries == 0) {
377 (*oplock_granted) = oplock_level;
379 (*oplock_granted) = OPLOCK_NONE;
381 e.oplock_level = (*oplock_granted);
384 /* it doesn't conflict, so add it to the end */
385 file.entries = talloc_realloc(lck, file.entries, struct opendb_entry,
387 NT_STATUS_HAVE_NO_MEMORY(file.entries);
389 file.entries[file.num_entries] = e;
392 return odb_push_record(lck, &file);
397 register a pending open file in the open files database
399 static NTSTATUS odb_tdb_open_file_pending(struct odb_lock *lck, void *private)
401 struct odb_context *odb = lck->odb;
402 struct opendb_file file;
405 status = odb_pull_record(lck, &file);
406 NT_STATUS_NOT_OK_RETURN(status);
408 file.pending = talloc_realloc(lck, file.pending, struct opendb_pending,
410 NT_STATUS_HAVE_NO_MEMORY(file.pending);
412 file.pending[file.num_pending].server = odb->ntvfs_ctx->server_id;
413 file.pending[file.num_pending].notify_ptr = private;
417 return odb_push_record(lck, &file);
422 remove a opendb entry
424 static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle)
426 struct odb_context *odb = lck->odb;
427 struct opendb_file file;
431 status = odb_pull_record(lck, &file);
432 NT_STATUS_NOT_OK_RETURN(status);
434 /* find the entry, and delete it */
435 for (i=0;i<file.num_entries;i++) {
436 if (file_handle == file.entries[i].file_handle &&
437 cluster_id_equal(&odb->ntvfs_ctx->server_id, &file.entries[i].server)) {
438 if (file.entries[i].delete_on_close) {
439 file.delete_on_close = true;
441 if (i < file.num_entries-1) {
442 memmove(file.entries+i, file.entries+i+1,
443 (file.num_entries - (i+1)) *
444 sizeof(struct opendb_entry));
450 if (i == file.num_entries) {
451 return NT_STATUS_UNSUCCESSFUL;
454 /* send any pending notifications, removing them once sent */
455 for (i=0;i<file.num_pending;i++) {
456 messaging_send_ptr(odb->ntvfs_ctx->msg_ctx, file.pending[i].server,
458 file.pending[i].notify_ptr);
460 file.num_pending = 0;
464 return odb_push_record(lck, &file);
468 update the oplock level of the client
470 static NTSTATUS odb_tdb_update_oplock(struct odb_lock *lck, void *file_handle,
471 uint32_t oplock_level)
473 struct odb_context *odb = lck->odb;
474 struct opendb_file file;
478 status = odb_pull_record(lck, &file);
479 NT_STATUS_NOT_OK_RETURN(status);
481 /* find the entry, and update it */
482 for (i=0;i<file.num_entries;i++) {
483 if (file_handle == file.entries[i].file_handle &&
484 cluster_id_equal(&odb->ntvfs_ctx->server_id, &file.entries[i].server)) {
485 file.entries[i].oplock_level = oplock_level;
490 if (i == file.num_entries) {
491 return NT_STATUS_UNSUCCESSFUL;
494 /* send any pending notifications, removing them once sent */
495 for (i=0;i<file.num_pending;i++) {
496 messaging_send_ptr(odb->ntvfs_ctx->msg_ctx,
497 file.pending[i].server,
499 file.pending[i].notify_ptr);
501 file.num_pending = 0;
503 return odb_push_record(lck, &file);
507 send oplocks breaks to none to all level2 holders
509 static NTSTATUS odb_tdb_break_oplocks(struct odb_lock *lck)
511 struct odb_context *odb = lck->odb;
513 struct opendb_file file;
515 bool modified = true;
517 status = odb_pull_record(lck, &file);
518 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
521 NT_STATUS_NOT_OK_RETURN(status);
523 /* see if anyone has an oplock, which we need to break */
524 for (i=0;i<file.num_entries;i++) {
525 if (file.entries[i].oplock_level == OPLOCK_LEVEL_II) {
527 * there could be multiple level2 oplocks
528 * and we just send a break to none to all of them
529 * without waiting for a release
531 odb_oplock_break_send(odb, &file.entries[i],
532 OPLOCK_BREAK_TO_NONE);
533 file.entries[i].oplock_level = OPLOCK_NONE;
539 return odb_push_record(lck, &file);
545 remove a pending opendb entry
547 static NTSTATUS odb_tdb_remove_pending(struct odb_lock *lck, void *private)
549 struct odb_context *odb = lck->odb;
552 struct opendb_file file;
554 status = odb_pull_record(lck, &file);
555 NT_STATUS_NOT_OK_RETURN(status);
557 /* find the entry, and delete it */
558 for (i=0;i<file.num_pending;i++) {
559 if (private == file.pending[i].notify_ptr &&
560 cluster_id_equal(&odb->ntvfs_ctx->server_id, &file.pending[i].server)) {
561 if (i < file.num_pending-1) {
562 memmove(file.pending+i, file.pending+i+1,
563 (file.num_pending - (i+1)) *
564 sizeof(struct opendb_pending));
570 if (i == file.num_pending) {
571 return NT_STATUS_UNSUCCESSFUL;
576 return odb_push_record(lck, &file);
581 rename the path in a open file
583 static NTSTATUS odb_tdb_rename(struct odb_lock *lck, const char *path)
585 struct opendb_file file;
588 status = odb_pull_record(lck, &file);
589 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
590 /* not having the record at all is OK */
593 NT_STATUS_NOT_OK_RETURN(status);
596 return odb_push_record(lck, &file);
600 update delete on close flag on an open file
602 static NTSTATUS odb_tdb_set_delete_on_close(struct odb_lock *lck, bool del_on_close)
605 struct opendb_file file;
607 status = odb_pull_record(lck, &file);
608 NT_STATUS_NOT_OK_RETURN(status);
610 file.delete_on_close = del_on_close;
612 return odb_push_record(lck, &file);
616 return the current value of the delete_on_close bit, and how many
617 people still have the file open
619 static NTSTATUS odb_tdb_get_delete_on_close(struct odb_context *odb,
620 DATA_BLOB *key, bool *del_on_close,
621 int *open_count, char **path)
624 struct opendb_file file;
625 struct odb_lock *lck;
627 lck = odb_lock(odb, odb, key);
628 NT_STATUS_HAVE_NO_MEMORY(lck);
630 status = odb_pull_record(lck, &file);
631 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
633 (*del_on_close) = false;
636 if (!NT_STATUS_IS_OK(status)) {
641 (*del_on_close) = file.delete_on_close;
642 if (open_count != NULL) {
643 (*open_count) = file.num_entries;
646 *path = talloc_strdup(odb, file.path);
647 NT_STATUS_HAVE_NO_MEMORY(*path);
648 if (file.num_entries == 1 && file.entries[0].delete_on_close) {
649 (*del_on_close) = true;
660 determine if a file can be opened with the given share_access,
661 create_options and access_mask
663 static NTSTATUS odb_tdb_can_open(struct odb_lock *lck,
664 uint32_t share_access, uint32_t create_options,
665 uint32_t access_mask)
667 struct odb_context *odb = lck->odb;
669 struct opendb_file file;
670 struct opendb_entry e;
673 status = odb_pull_record(lck, &file);
674 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
677 NT_STATUS_NOT_OK_RETURN(status);
679 if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
680 file.num_entries != 0) {
681 return NT_STATUS_SHARING_VIOLATION;
684 if (file.delete_on_close) {
685 return NT_STATUS_DELETE_PENDING;
688 e.server = odb->ntvfs_ctx->server_id;
689 e.file_handle = NULL;
691 e.share_access = share_access;
692 e.access_mask = access_mask;
694 for (i=0;i<file.num_entries;i++) {
695 status = share_conflict(&file.entries[i], &e);
696 if (!NT_STATUS_IS_OK(status)) {
697 /* note that we discard the error code
698 here. We do this as unless we are actually
699 doing an open (which comes via a different
700 function), we need to return a sharing
702 return NT_STATUS_SHARING_VIOLATION;
710 static const struct opendb_ops opendb_tdb_ops = {
711 .odb_init = odb_tdb_init,
712 .odb_lock = odb_tdb_lock,
713 .odb_get_key = odb_tdb_get_key,
714 .odb_open_file = odb_tdb_open_file,
715 .odb_open_file_pending = odb_tdb_open_file_pending,
716 .odb_close_file = odb_tdb_close_file,
717 .odb_remove_pending = odb_tdb_remove_pending,
718 .odb_rename = odb_tdb_rename,
719 .odb_set_delete_on_close = odb_tdb_set_delete_on_close,
720 .odb_get_delete_on_close = odb_tdb_get_delete_on_close,
721 .odb_can_open = odb_tdb_can_open,
722 .odb_update_oplock = odb_tdb_update_oplock,
723 .odb_break_oplocks = odb_tdb_break_oplocks
727 void odb_tdb_init_ops(void)
729 odb_set_ops(&opendb_tdb_ops);