2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2004
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.
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.
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/>.
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.
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
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.
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.
41 #include "system/filesys.h"
42 #include "lib/tdb/include/tdb.h"
43 #include "messaging/messaging.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"
54 struct ntvfs_context *ntvfs_ctx;
59 an odb lock handle. You must obtain one of these using odb_lock() before doing
63 struct odb_context *odb;
68 Open up the openfiles.tdb database. Close it down using
69 talloc_free(). We need the messaging_ctx to allow for pending open
72 static struct odb_context *odb_tdb_init(TALLOC_CTX *mem_ctx,
73 struct ntvfs_context *ntvfs_ctx)
75 struct odb_context *odb;
77 odb = talloc(mem_ctx, struct odb_context);
82 odb->w = cluster_tdb_tmp_open(odb, "openfiles.tdb", TDB_DEFAULT);
88 odb->ntvfs_ctx = ntvfs_ctx;
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);
97 destroy a lock on the database
99 static int odb_lock_destructor(struct odb_lock *lck)
101 tdb_chainunlock(lck->odb->w->tdb, lck->key);
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().
109 static struct odb_lock *odb_tdb_lock(TALLOC_CTX *mem_ctx,
110 struct odb_context *odb, DATA_BLOB *file_key)
112 struct odb_lock *lck;
114 lck = talloc(mem_ctx, struct odb_lock);
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) {
127 if (tdb_chainlock(odb->w->tdb, lck->key) != 0) {
132 talloc_set_destructor(lck, odb_lock_destructor);
138 determine if two odb_entry structures conflict
140 return NT_STATUS_OK on no conflict
142 static NTSTATUS share_conflict(struct opendb_entry *e1, struct opendb_entry *e2)
144 /* if either open involves no read.write or delete access then
146 if (!(e1->access_mask & (SEC_FILE_WRITE_DATA |
147 SEC_FILE_APPEND_DATA |
153 if (!(e2->access_mask & (SEC_FILE_WRITE_DATA |
154 SEC_FILE_APPEND_DATA |
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
164 if (e1->stream_id != e2->stream_id) {
168 #define CHECK_MASK(am, right, sa, share) \
169 if (((am) & (right)) && !((sa) & (share))) return NT_STATUS_SHARING_VIOLATION
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);
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);
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);
190 pull a record, translating from the db format to the opendb_file structure defined
193 static NTSTATUS odb_pull_record(struct odb_lock *lck, struct opendb_file *file)
195 struct odb_context *odb = lck->odb;
198 enum ndr_err_code ndr_err;
200 dbuf = tdb_fetch(odb->w->tdb, lck->key);
201 if (dbuf.dptr == NULL) {
202 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
205 blob.data = dbuf.dptr;
206 blob.length = dbuf.dsize;
208 ndr_err = ndr_pull_struct_blob(&blob, lck, file, (ndr_pull_flags_fn_t)ndr_pull_opendb_file);
210 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
211 return ndr_map_error2ntstatus(ndr_err);
218 push a record, translating from the opendb_file structure defined in opendb.idl
220 static NTSTATUS odb_push_record(struct odb_lock *lck, struct opendb_file *file)
222 struct odb_context *odb = lck->odb;
225 enum ndr_err_code ndr_err;
228 if (file->num_entries == 0) {
229 ret = tdb_delete(odb->w->tdb, lck->key);
231 return NT_STATUS_INTERNAL_DB_CORRUPTION;
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);
241 dbuf.dptr = blob.data;
242 dbuf.dsize = blob.length;
244 ret = tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE);
245 data_blob_free(&blob);
247 return NT_STATUS_INTERNAL_DB_CORRUPTION;
254 send an oplock break to a client
256 static NTSTATUS odb_oplock_break_send(struct odb_context *odb, struct opendb_entry *e)
258 /* tell the server handling this open file about the need to send the client
260 return messaging_send_ptr(odb->ntvfs_ctx->msg_ctx, e->server,
261 MSG_NTVFS_OPLOCK_BREAK, e->file_handle);
265 register an open file in the open files database. This implements the share_access
268 Note that the path is only used by the delete on close logic, not
269 for comparing with other filenames
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,
275 uint32_t oplock_level, uint32_t *oplock_granted)
277 struct odb_context *odb = lck->odb;
278 struct opendb_entry e;
280 struct opendb_file file;
283 if (odb->oplocks == false) {
284 oplock_level = OPLOCK_NONE;
287 status = odb_pull_record(lck, &file);
288 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
289 /* initialise a blank structure */
293 NT_STATUS_NOT_OK_RETURN(status);
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;
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
315 odb_oplock_break_send(odb, &file.entries[i]);
316 return NT_STATUS_OPLOCK_NOT_GRANTED;
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;
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);
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;
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.
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;
354 (*oplock_granted) = OPLOCK_NONE;
356 e.oplock_level = (*oplock_granted);
359 /* it doesn't conflict, so add it to the end */
360 file.entries = talloc_realloc(lck, file.entries, struct opendb_entry,
362 NT_STATUS_HAVE_NO_MEMORY(file.entries);
364 file.entries[file.num_entries] = e;
367 return odb_push_record(lck, &file);
372 register a pending open file in the open files database
374 static NTSTATUS odb_tdb_open_file_pending(struct odb_lock *lck, void *private)
376 struct odb_context *odb = lck->odb;
377 struct opendb_file file;
380 status = odb_pull_record(lck, &file);
381 NT_STATUS_NOT_OK_RETURN(status);
383 file.pending = talloc_realloc(lck, file.pending, struct opendb_pending,
385 NT_STATUS_HAVE_NO_MEMORY(file.pending);
387 file.pending[file.num_pending].server = odb->ntvfs_ctx->server_id;
388 file.pending[file.num_pending].notify_ptr = private;
392 return odb_push_record(lck, &file);
397 remove a opendb entry
399 static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle)
401 struct odb_context *odb = lck->odb;
402 struct opendb_file file;
406 status = odb_pull_record(lck, &file);
407 NT_STATUS_NOT_OK_RETURN(status);
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;
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));
425 if (i == file.num_entries) {
426 return NT_STATUS_UNSUCCESSFUL;
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,
433 file.pending[i].notify_ptr);
435 file.num_pending = 0;
439 return odb_push_record(lck, &file);
444 remove a pending opendb entry
446 static NTSTATUS odb_tdb_remove_pending(struct odb_lock *lck, void *private)
448 struct odb_context *odb = lck->odb;
451 struct opendb_file file;
453 status = odb_pull_record(lck, &file);
454 NT_STATUS_NOT_OK_RETURN(status);
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));
469 if (i == file.num_pending) {
470 return NT_STATUS_UNSUCCESSFUL;
475 return odb_push_record(lck, &file);
480 rename the path in a open file
482 static NTSTATUS odb_tdb_rename(struct odb_lock *lck, const char *path)
484 struct opendb_file file;
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 */
492 NT_STATUS_NOT_OK_RETURN(status);
495 return odb_push_record(lck, &file);
499 update delete on close flag on an open file
501 static NTSTATUS odb_tdb_set_delete_on_close(struct odb_lock *lck, bool del_on_close)
504 struct opendb_file file;
506 status = odb_pull_record(lck, &file);
507 NT_STATUS_NOT_OK_RETURN(status);
509 file.delete_on_close = del_on_close;
511 return odb_push_record(lck, &file);
515 return the current value of the delete_on_close bit, and how many
516 people still have the file open
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)
523 struct opendb_file file;
524 struct odb_lock *lck;
526 lck = odb_lock(odb, odb, key);
527 NT_STATUS_HAVE_NO_MEMORY(lck);
529 status = odb_pull_record(lck, &file);
530 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
532 (*del_on_close) = false;
535 if (!NT_STATUS_IS_OK(status)) {
540 (*del_on_close) = file.delete_on_close;
541 if (open_count != NULL) {
542 (*open_count) = file.num_entries;
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;
559 determine if a file can be opened with the given share_access,
560 create_options and access_mask
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)
566 struct odb_context *odb = lck->odb;
568 struct opendb_file file;
569 struct opendb_entry e;
572 status = odb_pull_record(lck, &file);
573 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
576 NT_STATUS_NOT_OK_RETURN(status);
578 if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
579 file.num_entries != 0) {
580 return NT_STATUS_SHARING_VIOLATION;
583 if (file.delete_on_close) {
584 return NT_STATUS_DELETE_PENDING;
587 e.server = odb->ntvfs_ctx->server_id;
588 e.file_handle = NULL;
590 e.share_access = share_access;
591 e.access_mask = access_mask;
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
601 return NT_STATUS_SHARING_VIOLATION;
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
623 void odb_tdb_init_ops(void)
625 odb_set_ops(&opendb_tdb_ops);