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(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;
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 status = ndr_pull_struct_blob(&blob, lck, file, (ndr_pull_flags_fn_t)ndr_pull_opendb_file);
216 push a record, translating from the opendb_file structure defined in opendb.idl
218 static NTSTATUS odb_push_record(struct odb_lock *lck, struct opendb_file *file)
220 struct odb_context *odb = lck->odb;
226 if (file->num_entries == 0) {
227 ret = tdb_delete(odb->w->tdb, lck->key);
229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
234 status = ndr_push_struct_blob(&blob, lck, file, (ndr_push_flags_fn_t)ndr_push_opendb_file);
235 NT_STATUS_NOT_OK_RETURN(status);
237 dbuf.dptr = blob.data;
238 dbuf.dsize = blob.length;
240 ret = tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE);
241 data_blob_free(&blob);
243 return NT_STATUS_INTERNAL_DB_CORRUPTION;
250 send an oplock break to a client
252 static NTSTATUS odb_oplock_break_send(struct odb_context *odb, struct opendb_entry *e)
254 /* tell the server handling this open file about the need to send the client
256 return messaging_send_ptr(odb->ntvfs_ctx->msg_ctx, e->server,
257 MSG_NTVFS_OPLOCK_BREAK, e->file_handle);
261 register an open file in the open files database. This implements the share_access
264 Note that the path is only used by the delete on close logic, not
265 for comparing with other filenames
267 static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
268 uint32_t stream_id, uint32_t share_access,
269 uint32_t access_mask, BOOL delete_on_close,
271 uint32_t oplock_level, uint32_t *oplock_granted)
273 struct odb_context *odb = lck->odb;
274 struct opendb_entry e;
276 struct opendb_file file;
279 if (odb->oplocks == False) {
280 oplock_level = OPLOCK_NONE;
283 status = odb_pull_record(lck, &file);
284 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
285 /* initialise a blank structure */
289 NT_STATUS_NOT_OK_RETURN(status);
292 /* see if it conflicts */
293 e.server = odb->ntvfs_ctx->server_id;
294 e.file_handle = file_handle;
295 e.stream_id = stream_id;
296 e.share_access = share_access;
297 e.access_mask = access_mask;
298 e.delete_on_close = delete_on_close;
299 e.oplock_level = OPLOCK_NONE;
301 /* see if anyone has an oplock, which we need to break */
302 for (i=0;i<file.num_entries;i++) {
303 if (file.entries[i].oplock_level == OPLOCK_BATCH) {
304 /* a batch oplock caches close calls, which
305 means the client application might have
306 already closed the file. We have to allow
307 this close to propogate by sending a oplock
308 break request and suspending this call
309 until the break is acknowledged or the file
311 odb_oplock_break_send(odb, &file.entries[i]);
312 return NT_STATUS_OPLOCK_NOT_GRANTED;
316 if (file.delete_on_close ||
317 (file.num_entries != 0 && delete_on_close)) {
318 /* while delete on close is set, no new opens are allowed */
319 return NT_STATUS_DELETE_PENDING;
322 /* check for sharing violations */
323 for (i=0;i<file.num_entries;i++) {
324 status = share_conflict(&file.entries[i], &e);
325 NT_STATUS_NOT_OK_RETURN(status);
328 /* we now know the open could succeed, but we need to check
329 for any exclusive oplocks. We can't grant a second open
330 till these are broken. Note that we check for batch oplocks
331 before checking for sharing violations, and check for
332 exclusive oplocks afterwards. */
333 for (i=0;i<file.num_entries;i++) {
334 if (file.entries[i].oplock_level == OPLOCK_EXCLUSIVE) {
335 odb_oplock_break_send(odb, &file.entries[i]);
336 return NT_STATUS_OPLOCK_NOT_GRANTED;
341 possibly grant an exclusive or batch oplock if this is the only client
342 with the file open. We don't yet grant levelII oplocks.
344 if (oplock_granted != NULL) {
345 if ((oplock_level == OPLOCK_BATCH ||
346 oplock_level == OPLOCK_EXCLUSIVE) &&
347 file.num_entries == 0) {
348 (*oplock_granted) = oplock_level;
350 (*oplock_granted) = OPLOCK_NONE;
352 e.oplock_level = (*oplock_granted);
355 /* it doesn't conflict, so add it to the end */
356 file.entries = talloc_realloc(lck, file.entries, struct opendb_entry,
358 NT_STATUS_HAVE_NO_MEMORY(file.entries);
360 file.entries[file.num_entries] = e;
363 return odb_push_record(lck, &file);
368 register a pending open file in the open files database
370 static NTSTATUS odb_tdb_open_file_pending(struct odb_lock *lck, void *private)
372 struct odb_context *odb = lck->odb;
373 struct opendb_file file;
376 status = odb_pull_record(lck, &file);
377 NT_STATUS_NOT_OK_RETURN(status);
379 file.pending = talloc_realloc(lck, file.pending, struct opendb_pending,
381 NT_STATUS_HAVE_NO_MEMORY(file.pending);
383 file.pending[file.num_pending].server = odb->ntvfs_ctx->server_id;
384 file.pending[file.num_pending].notify_ptr = private;
388 return odb_push_record(lck, &file);
393 remove a opendb entry
395 static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle)
397 struct odb_context *odb = lck->odb;
398 struct opendb_file file;
402 status = odb_pull_record(lck, &file);
403 NT_STATUS_NOT_OK_RETURN(status);
405 /* find the entry, and delete it */
406 for (i=0;i<file.num_entries;i++) {
407 if (file_handle == file.entries[i].file_handle &&
408 cluster_id_equal(&odb->ntvfs_ctx->server_id, &file.entries[i].server)) {
409 if (file.entries[i].delete_on_close) {
410 file.delete_on_close = True;
412 if (i < file.num_entries-1) {
413 memmove(file.entries+i, file.entries+i+1,
414 (file.num_entries - (i+1)) *
415 sizeof(struct opendb_entry));
421 if (i == file.num_entries) {
422 return NT_STATUS_UNSUCCESSFUL;
425 /* send any pending notifications, removing them once sent */
426 for (i=0;i<file.num_pending;i++) {
427 messaging_send_ptr(odb->ntvfs_ctx->msg_ctx, file.pending[i].server,
429 file.pending[i].notify_ptr);
431 file.num_pending = 0;
435 return odb_push_record(lck, &file);
440 remove a pending opendb entry
442 static NTSTATUS odb_tdb_remove_pending(struct odb_lock *lck, void *private)
444 struct odb_context *odb = lck->odb;
447 struct opendb_file file;
449 status = odb_pull_record(lck, &file);
450 NT_STATUS_NOT_OK_RETURN(status);
452 /* find the entry, and delete it */
453 for (i=0;i<file.num_pending;i++) {
454 if (private == file.pending[i].notify_ptr &&
455 cluster_id_equal(&odb->ntvfs_ctx->server_id, &file.pending[i].server)) {
456 if (i < file.num_pending-1) {
457 memmove(file.pending+i, file.pending+i+1,
458 (file.num_pending - (i+1)) *
459 sizeof(struct opendb_pending));
465 if (i == file.num_pending) {
466 return NT_STATUS_UNSUCCESSFUL;
471 return odb_push_record(lck, &file);
476 rename the path in a open file
478 static NTSTATUS odb_tdb_rename(struct odb_lock *lck, const char *path)
480 struct opendb_file file;
483 status = odb_pull_record(lck, &file);
484 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
485 /* not having the record at all is OK */
488 NT_STATUS_NOT_OK_RETURN(status);
491 return odb_push_record(lck, &file);
495 update delete on close flag on an open file
497 static NTSTATUS odb_tdb_set_delete_on_close(struct odb_lock *lck, BOOL del_on_close)
500 struct opendb_file file;
502 status = odb_pull_record(lck, &file);
503 NT_STATUS_NOT_OK_RETURN(status);
505 file.delete_on_close = del_on_close;
507 return odb_push_record(lck, &file);
511 return the current value of the delete_on_close bit, and how many
512 people still have the file open
514 static NTSTATUS odb_tdb_get_delete_on_close(struct odb_context *odb,
515 DATA_BLOB *key, BOOL *del_on_close,
516 int *open_count, char **path)
519 struct opendb_file file;
520 struct odb_lock *lck;
522 lck = odb_lock(odb, odb, key);
523 NT_STATUS_HAVE_NO_MEMORY(lck);
525 status = odb_pull_record(lck, &file);
526 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
528 (*del_on_close) = False;
531 if (!NT_STATUS_IS_OK(status)) {
536 (*del_on_close) = file.delete_on_close;
537 if (open_count != NULL) {
538 (*open_count) = file.num_entries;
541 *path = talloc_strdup(odb, file.path);
542 NT_STATUS_HAVE_NO_MEMORY(*path);
543 if (file.num_entries == 1 && file.entries[0].delete_on_close) {
544 (*del_on_close) = True;
555 determine if a file can be opened with the given share_access,
556 create_options and access_mask
558 static NTSTATUS odb_tdb_can_open(struct odb_lock *lck,
559 uint32_t share_access, uint32_t create_options,
560 uint32_t access_mask)
562 struct odb_context *odb = lck->odb;
564 struct opendb_file file;
565 struct opendb_entry e;
568 status = odb_pull_record(lck, &file);
569 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
572 NT_STATUS_NOT_OK_RETURN(status);
574 if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
575 file.num_entries != 0) {
576 return NT_STATUS_SHARING_VIOLATION;
579 if (file.delete_on_close) {
580 return NT_STATUS_DELETE_PENDING;
583 e.server = odb->ntvfs_ctx->server_id;
584 e.file_handle = NULL;
586 e.share_access = share_access;
587 e.access_mask = access_mask;
589 for (i=0;i<file.num_entries;i++) {
590 status = share_conflict(&file.entries[i], &e);
591 if (!NT_STATUS_IS_OK(status)) {
592 /* note that we discard the error code
593 here. We do this as unless we are actually
594 doing an open (which comes via a different
595 function), we need to return a sharing
597 return NT_STATUS_SHARING_VIOLATION;
605 static const struct opendb_ops opendb_tdb_ops = {
606 .odb_init = odb_tdb_init,
607 .odb_lock = odb_tdb_lock,
608 .odb_open_file = odb_tdb_open_file,
609 .odb_open_file_pending = odb_tdb_open_file_pending,
610 .odb_close_file = odb_tdb_close_file,
611 .odb_remove_pending = odb_tdb_remove_pending,
612 .odb_rename = odb_tdb_rename,
613 .odb_set_delete_on_close = odb_tdb_set_delete_on_close,
614 .odb_get_delete_on_close = odb_tdb_get_delete_on_close,
615 .odb_can_open = odb_tdb_can_open
619 void odb_tdb_init_ops(void)
621 odb_set_ops(&opendb_tdb_ops);