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);
508 remove a pending opendb entry
510 static NTSTATUS odb_tdb_remove_pending(struct odb_lock *lck, void *private)
512 struct odb_context *odb = lck->odb;
515 struct opendb_file file;
517 status = odb_pull_record(lck, &file);
518 NT_STATUS_NOT_OK_RETURN(status);
520 /* find the entry, and delete it */
521 for (i=0;i<file.num_pending;i++) {
522 if (private == file.pending[i].notify_ptr &&
523 cluster_id_equal(&odb->ntvfs_ctx->server_id, &file.pending[i].server)) {
524 if (i < file.num_pending-1) {
525 memmove(file.pending+i, file.pending+i+1,
526 (file.num_pending - (i+1)) *
527 sizeof(struct opendb_pending));
533 if (i == file.num_pending) {
534 return NT_STATUS_UNSUCCESSFUL;
539 return odb_push_record(lck, &file);
544 rename the path in a open file
546 static NTSTATUS odb_tdb_rename(struct odb_lock *lck, const char *path)
548 struct opendb_file file;
551 status = odb_pull_record(lck, &file);
552 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
553 /* not having the record at all is OK */
556 NT_STATUS_NOT_OK_RETURN(status);
559 return odb_push_record(lck, &file);
563 update delete on close flag on an open file
565 static NTSTATUS odb_tdb_set_delete_on_close(struct odb_lock *lck, bool del_on_close)
568 struct opendb_file file;
570 status = odb_pull_record(lck, &file);
571 NT_STATUS_NOT_OK_RETURN(status);
573 file.delete_on_close = del_on_close;
575 return odb_push_record(lck, &file);
579 return the current value of the delete_on_close bit, and how many
580 people still have the file open
582 static NTSTATUS odb_tdb_get_delete_on_close(struct odb_context *odb,
583 DATA_BLOB *key, bool *del_on_close,
584 int *open_count, char **path)
587 struct opendb_file file;
588 struct odb_lock *lck;
590 lck = odb_lock(odb, odb, key);
591 NT_STATUS_HAVE_NO_MEMORY(lck);
593 status = odb_pull_record(lck, &file);
594 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
596 (*del_on_close) = false;
599 if (!NT_STATUS_IS_OK(status)) {
604 (*del_on_close) = file.delete_on_close;
605 if (open_count != NULL) {
606 (*open_count) = file.num_entries;
609 *path = talloc_strdup(odb, file.path);
610 NT_STATUS_HAVE_NO_MEMORY(*path);
611 if (file.num_entries == 1 && file.entries[0].delete_on_close) {
612 (*del_on_close) = true;
623 determine if a file can be opened with the given share_access,
624 create_options and access_mask
626 static NTSTATUS odb_tdb_can_open(struct odb_lock *lck,
627 uint32_t share_access, uint32_t create_options,
628 uint32_t access_mask)
630 struct odb_context *odb = lck->odb;
632 struct opendb_file file;
633 struct opendb_entry e;
636 status = odb_pull_record(lck, &file);
637 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
640 NT_STATUS_NOT_OK_RETURN(status);
642 if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
643 file.num_entries != 0) {
644 return NT_STATUS_SHARING_VIOLATION;
647 if (file.delete_on_close) {
648 return NT_STATUS_DELETE_PENDING;
651 e.server = odb->ntvfs_ctx->server_id;
652 e.file_handle = NULL;
654 e.share_access = share_access;
655 e.access_mask = access_mask;
657 for (i=0;i<file.num_entries;i++) {
658 status = share_conflict(&file.entries[i], &e);
659 if (!NT_STATUS_IS_OK(status)) {
660 /* note that we discard the error code
661 here. We do this as unless we are actually
662 doing an open (which comes via a different
663 function), we need to return a sharing
665 return NT_STATUS_SHARING_VIOLATION;
673 static const struct opendb_ops opendb_tdb_ops = {
674 .odb_init = odb_tdb_init,
675 .odb_lock = odb_tdb_lock,
676 .odb_get_key = odb_tdb_get_key,
677 .odb_open_file = odb_tdb_open_file,
678 .odb_open_file_pending = odb_tdb_open_file_pending,
679 .odb_close_file = odb_tdb_close_file,
680 .odb_remove_pending = odb_tdb_remove_pending,
681 .odb_rename = odb_tdb_rename,
682 .odb_set_delete_on_close = odb_tdb_set_delete_on_close,
683 .odb_get_delete_on_close = odb_tdb_get_delete_on_close,
684 .odb_can_open = odb_tdb_can_open,
685 .odb_update_oplock = odb_tdb_update_oplock
689 void odb_tdb_init_ops(void)
691 odb_set_ops(&opendb_tdb_ops);