LCOV - code coverage report
Current view: top level - source4/ntvfs/common - opendb_tdb.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 290 348 83.3 %
Date: 2024-04-21 15:09:00 Functions: 22 22 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Andrew Tridgell 2004
       5             :    Copyright (C) Stefan Metzmacher 2008
       6             : 
       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.
      11             :    
      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.
      16             :    
      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/>.
      19             : */
      20             : 
      21             : /*
      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.
      25             : 
      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
      29             :   pair.
      30             : 
      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.
      35             : 
      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.
      39             : */
      40             : 
      41             : #include "includes.h"
      42             : #include "system/filesys.h"
      43             : #include "lib/dbwrap/dbwrap.h"
      44             : #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"
      51             : #include "ntvfs/sysdep/sys_lease.h"
      52             : 
      53             : struct odb_context {
      54             :         struct db_context *db;
      55             :         struct ntvfs_context *ntvfs_ctx;
      56             :         bool oplocks;
      57             :         struct sys_lease_context *lease_ctx;
      58             : };
      59             : 
      60             : /*
      61             :   an odb lock handle. You must obtain one of these using odb_lock() before doing
      62             :   any other operations. 
      63             : */
      64             : struct odb_lock {
      65             :         struct odb_context *odb;
      66             :         struct db_record *locked;
      67             : 
      68             :         struct opendb_file file;
      69             : 
      70             :         struct {
      71             :                 struct opendb_entry *e;
      72             :                 bool attrs_only;
      73             :         } can_open;
      74             : };
      75             : 
      76             : static NTSTATUS odb_oplock_break_send(struct imessaging_context *msg_ctx,
      77             :                                       struct opendb_entry *e,
      78             :                                       uint8_t level);
      79             : 
      80             : /*
      81             :   Open up the openfiles.tdb database. Close it down using
      82             :   talloc_free(). We need the imessaging_ctx to allow for pending open
      83             :   notifications.
      84             : */
      85        1328 : static struct odb_context *odb_tdb_init(TALLOC_CTX *mem_ctx, 
      86             :                                         struct ntvfs_context *ntvfs_ctx)
      87             : {
      88           0 :         struct odb_context *odb;
      89             : 
      90        1328 :         odb = talloc(mem_ctx, struct odb_context);
      91        1328 :         if (odb == NULL) {
      92           0 :                 return NULL;
      93             :         }
      94             : 
      95        1328 :         odb->db = cluster_db_tmp_open(odb, ntvfs_ctx->lp_ctx,
      96             :                                       "openfiles", TDB_DEFAULT);
      97        1328 :         if (odb->db == NULL) {
      98           0 :                 talloc_free(odb);
      99           0 :                 return NULL;
     100             :         }
     101             : 
     102        1328 :         odb->ntvfs_ctx = ntvfs_ctx;
     103             : 
     104        1328 :         odb->oplocks = share_bool_option(ntvfs_ctx->config, SHARE_OPLOCKS, SHARE_OPLOCKS_DEFAULT);
     105             : 
     106        1328 :         odb->lease_ctx = sys_lease_context_create(ntvfs_ctx->config, odb,
     107             :                                                   ntvfs_ctx->event_ctx,
     108             :                                                   ntvfs_ctx->msg_ctx,
     109             :                                                   odb_oplock_break_send);
     110             : 
     111        1328 :         return odb;
     112             : }
     113             : 
     114             : static NTSTATUS odb_pull_record(struct odb_lock *lck, struct opendb_file *file);
     115             : 
     116             : /*
     117             :   get a lock on a entry in the odb. This call returns a lock handle,
     118             :   which the caller should unlock using talloc_free().
     119             : */
     120      949443 : static struct odb_lock *odb_tdb_lock(TALLOC_CTX *mem_ctx,
     121             :                                      struct odb_context *odb, DATA_BLOB *file_key)
     122             : {
     123           0 :         struct odb_lock *lck;
     124           0 :         NTSTATUS status;
     125           0 :         TDB_DATA key;
     126             : 
     127      949443 :         lck = talloc(mem_ctx, struct odb_lock);
     128      949443 :         if (lck == NULL) {
     129           0 :                 return NULL;
     130             :         }
     131             : 
     132      949443 :         lck->odb = talloc_reference(lck, odb);
     133      949443 :         key.dptr = talloc_memdup(lck, file_key->data, file_key->length);
     134      949443 :         key.dsize = file_key->length;
     135      949443 :         if (key.dptr == NULL) {
     136           0 :                 talloc_free(lck);
     137           0 :                 return NULL;
     138             :         }
     139             : 
     140      949443 :         lck->locked = dbwrap_fetch_locked(odb->db, lck, key);
     141      949443 :         if (!lck->locked) {
     142           0 :                 talloc_free(lck);
     143           0 :                 return NULL;
     144             :         }
     145             : 
     146      949443 :         ZERO_STRUCT(lck->can_open);
     147             : 
     148      949443 :         status = odb_pull_record(lck, &lck->file);
     149      949443 :         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     150             :                 /* initialise a blank structure */
     151      655231 :                 ZERO_STRUCT(lck->file);
     152      294212 :         } else if (!NT_STATUS_IS_OK(status)) {
     153           0 :                 talloc_free(lck);
     154           0 :                 return NULL;
     155             :         }
     156             :         
     157      949443 :         return lck;
     158             : }
     159             : 
     160        2915 : static DATA_BLOB odb_tdb_get_key(TALLOC_CTX *mem_ctx, struct odb_lock *lck)
     161             : {
     162        2915 :         TDB_DATA key = dbwrap_record_get_key(lck->locked);
     163        2915 :         return data_blob_talloc(mem_ctx, key.dptr, key.dsize);
     164             : }
     165             : 
     166             : 
     167             : /*
     168             :   determine if two odb_entry structures conflict
     169             : 
     170             :   return NT_STATUS_OK on no conflict
     171             : */
     172       14160 : static NTSTATUS share_conflict(struct opendb_entry *e1,
     173             :                                uint32_t stream_id,
     174             :                                uint32_t share_access,
     175             :                                uint32_t access_mask)
     176             : {
     177             :         /* if either open involves no read.write or delete access then
     178             :            it can't conflict */
     179       14160 :         if (!(e1->access_mask & (SEC_FILE_WRITE_DATA |
     180             :                                  SEC_FILE_APPEND_DATA |
     181             :                                  SEC_FILE_READ_DATA |
     182             :                                  SEC_FILE_EXECUTE |
     183             :                                  SEC_STD_DELETE))) {
     184        8410 :                 return NT_STATUS_OK;
     185             :         }
     186        5750 :         if (!(access_mask & (SEC_FILE_WRITE_DATA |
     187             :                              SEC_FILE_APPEND_DATA |
     188             :                              SEC_FILE_READ_DATA |
     189             :                              SEC_FILE_EXECUTE |
     190             :                              SEC_STD_DELETE))) {
     191         527 :                 return NT_STATUS_OK;
     192             :         }
     193             : 
     194             :         /* data IO access masks. This is skipped if the two open handles
     195             :            are on different streams (as in that case the masks don't
     196             :            interact) */
     197        5223 :         if (e1->stream_id != stream_id) {
     198          36 :                 return NT_STATUS_OK;
     199             :         }
     200             : 
     201             : #define CHECK_MASK(am, right, sa, share) \
     202             :         if (((am) & (right)) && !((sa) & (share))) return NT_STATUS_SHARING_VIOLATION
     203             : 
     204        5187 :         CHECK_MASK(e1->access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
     205             :                    share_access, NTCREATEX_SHARE_ACCESS_WRITE);
     206        3838 :         CHECK_MASK(access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
     207             :                    e1->share_access, NTCREATEX_SHARE_ACCESS_WRITE);
     208             :         
     209        3096 :         CHECK_MASK(e1->access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
     210             :                    share_access, NTCREATEX_SHARE_ACCESS_READ);
     211        2605 :         CHECK_MASK(access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
     212             :                    e1->share_access, NTCREATEX_SHARE_ACCESS_READ);
     213             : 
     214        2325 :         CHECK_MASK(e1->access_mask, SEC_STD_DELETE,
     215             :                    share_access, NTCREATEX_SHARE_ACCESS_DELETE);
     216        2289 :         CHECK_MASK(access_mask, SEC_STD_DELETE,
     217             :                    e1->share_access, NTCREATEX_SHARE_ACCESS_DELETE);
     218             : #undef CHECK_MASK
     219        2281 :         return NT_STATUS_OK;
     220             : }
     221             : 
     222             : /*
     223             :   pull a record, translating from the db format to the opendb_file structure defined
     224             :   in opendb.idl
     225             : */
     226      949443 : static NTSTATUS odb_pull_record(struct odb_lock *lck, struct opendb_file *file)
     227             : {
     228           0 :         TDB_DATA dbuf;
     229           0 :         DATA_BLOB blob;
     230           0 :         enum ndr_err_code ndr_err;
     231             : 
     232      949443 :         dbuf = dbwrap_record_get_value(lck->locked);
     233      949443 :         if (!dbuf.dptr) {
     234      655231 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     235             :         }
     236             : 
     237      294212 :         blob.data = dbuf.dptr;
     238      294212 :         blob.length = dbuf.dsize;
     239             : 
     240      294212 :         ndr_err = ndr_pull_struct_blob(&blob, lck, file, (ndr_pull_flags_fn_t)ndr_pull_opendb_file);
     241      294212 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     242           0 :                 return ndr_map_error2ntstatus(ndr_err);
     243             :         }
     244             : 
     245      294212 :         return NT_STATUS_OK;
     246             : }
     247             : 
     248             : /*
     249             :   push a record, translating from the opendb_file structure defined in opendb.idl
     250             : */
     251      422213 : static NTSTATUS odb_push_record(struct odb_lock *lck, struct opendb_file *file)
     252             : {
     253           0 :         TDB_DATA dbuf;
     254           0 :         DATA_BLOB blob;
     255           0 :         enum ndr_err_code ndr_err;
     256           0 :         NTSTATUS status;
     257             : 
     258      422213 :         if (file->num_entries == 0) {
     259      197120 :                 return dbwrap_record_delete(lck->locked);
     260             :         }
     261             : 
     262      225093 :         ndr_err = ndr_push_struct_blob(&blob, lck, file, (ndr_push_flags_fn_t)ndr_push_opendb_file);
     263      225093 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     264           0 :                 return ndr_map_error2ntstatus(ndr_err);
     265             :         }
     266             : 
     267      225093 :         dbuf.dptr = blob.data;
     268      225093 :         dbuf.dsize = blob.length;
     269             :                 
     270      225093 :         status = dbwrap_record_store(lck->locked, dbuf, TDB_REPLACE);
     271      225093 :         data_blob_free(&blob);
     272      225093 :         return status;
     273             : }
     274             : 
     275             : /*
     276             :   send an oplock break to a client
     277             : */
     278         108 : static NTSTATUS odb_oplock_break_send(struct imessaging_context *msg_ctx,
     279             :                                       struct opendb_entry *e,
     280             :                                       uint8_t level)
     281             : {
     282           0 :         NTSTATUS status;
     283           0 :         struct opendb_oplock_break op_break;
     284           0 :         DATA_BLOB blob;
     285             : 
     286         108 :         ZERO_STRUCT(op_break);
     287             : 
     288             :         /* tell the server handling this open file about the need to send the client
     289             :            a break */
     290         108 :         op_break.file_handle    = e->file_handle;
     291         108 :         op_break.level          = level;
     292             : 
     293         108 :         blob = data_blob_const(&op_break, sizeof(op_break));
     294             : 
     295         108 :         status = imessaging_send(msg_ctx, e->server,
     296             :                                 MSG_NTVFS_OPLOCK_BREAK, &blob);
     297         108 :         NT_STATUS_NOT_OK_RETURN(status);
     298             : 
     299         108 :         return NT_STATUS_OK;
     300             : }
     301             : 
     302          94 : static bool access_attributes_only(uint32_t access_mask,
     303             :                                    uint32_t open_disposition,
     304             :                                    bool break_to_none)
     305             : {
     306          94 :         switch (open_disposition) {
     307          13 :         case NTCREATEX_DISP_SUPERSEDE:
     308             :         case NTCREATEX_DISP_OVERWRITE_IF:
     309             :         case NTCREATEX_DISP_OVERWRITE:
     310          13 :                 return false;
     311          81 :         default:
     312          81 :                 break;
     313             :         }
     314             : 
     315          81 :         if (break_to_none) {
     316           3 :                 return false;
     317             :         }
     318             : 
     319             : #define CHECK_MASK(m,g) ((m) && (((m) & ~(g))==0) && (((m) & (g)) != 0))
     320          78 :         return CHECK_MASK(access_mask,
     321             :                           SEC_STD_SYNCHRONIZE |
     322             :                           SEC_FILE_READ_ATTRIBUTE |
     323             :                           SEC_FILE_WRITE_ATTRIBUTE);
     324             : #undef CHECK_MASK
     325             : }
     326             : 
     327      242479 : static NTSTATUS odb_tdb_open_can_internal(struct odb_context *odb,
     328             :                                           const struct opendb_file *file,
     329             :                                           uint32_t stream_id, uint32_t share_access,
     330             :                                           uint32_t access_mask, bool delete_on_close,
     331             :                                           uint32_t open_disposition, bool break_to_none,
     332             :                                           bool *_attrs_only)
     333             : {
     334           0 :         NTSTATUS status;
     335           0 :         uint32_t i;
     336      242479 :         bool attrs_only = false;
     337             : 
     338             :         /* see if anyone has an oplock, which we need to break */
     339      256749 :         for (i=0;i<file->num_entries;i++) {
     340       14341 :                 if (file->entries[i].oplock_level == OPLOCK_BATCH) {
     341          71 :                         bool oplock_return = OPLOCK_BREAK_TO_LEVEL_II;
     342             :                         /* if this is an attribute only access
     343             :                          * it doesn't conflict with a BACTCH oplock
     344             :                          * but we'll not grant the oplock below
     345             :                          */
     346          71 :                         attrs_only = access_attributes_only(access_mask,
     347             :                                                             open_disposition,
     348             :                                                             break_to_none);
     349          71 :                         if (attrs_only) {
     350           8 :                                 break;
     351             :                         }
     352             :                         /* a batch oplock caches close calls, which
     353             :                            means the client application might have
     354             :                            already closed the file. We have to allow
     355             :                            this close to propagate by sending a oplock
     356             :                            break request and suspending this call
     357             :                            until the break is acknowledged or the file
     358             :                            is closed */
     359          63 :                         if (break_to_none ||
     360          61 :                             !file->entries[i].allow_level_II_oplock) {
     361           7 :                                 oplock_return = OPLOCK_BREAK_TO_NONE;
     362             :                         }
     363          63 :                         odb_oplock_break_send(odb->ntvfs_ctx->msg_ctx,
     364          63 :                                               &file->entries[i],
     365             :                                               oplock_return);
     366          63 :                         return NT_STATUS_OPLOCK_NOT_GRANTED;
     367             :                 }
     368             :         }
     369             : 
     370      242416 :         if (file->delete_on_close) {
     371             :                 /* while delete on close is set, no new opens are allowed */
     372          43 :                 return NT_STATUS_DELETE_PENDING;
     373             :         }
     374             : 
     375      242373 :         if (file->num_entries != 0 && delete_on_close) {
     376          44 :                 return NT_STATUS_SHARING_VIOLATION;
     377             :         }
     378             : 
     379             :         /* check for sharing violations */
     380      253583 :         for (i=0;i<file->num_entries;i++) {
     381       14160 :                 status = share_conflict(&file->entries[i], stream_id,
     382             :                                         share_access, access_mask);
     383       14160 :                 NT_STATUS_NOT_OK_RETURN(status);
     384             :         }
     385             : 
     386             :         /* we now know the open could succeed, but we need to check
     387             :            for any exclusive oplocks. We can't grant a second open
     388             :            till these are broken. Note that we check for batch oplocks
     389             :            before checking for sharing violations, and check for
     390             :            exclusive oplocks afterwards. */
     391      250650 :         for (i=0;i<file->num_entries;i++) {
     392       11250 :                 if (file->entries[i].oplock_level == OPLOCK_EXCLUSIVE) {
     393          23 :                         bool oplock_return = OPLOCK_BREAK_TO_LEVEL_II;
     394             :                         /* if this is an attribute only access
     395             :                          * it doesn't conflict with an EXCLUSIVE oplock
     396             :                          * but we'll not grant the oplock below
     397             :                          */
     398          23 :                         attrs_only = access_attributes_only(access_mask,
     399             :                                                             open_disposition,
     400             :                                                             break_to_none);
     401          23 :                         if (attrs_only) {
     402           3 :                                 break;
     403             :                         }
     404             :                         /*
     405             :                          * send an oplock break to the holder of the
     406             :                          * oplock and tell caller to retry later
     407             :                          */
     408          20 :                         if (break_to_none ||
     409          19 :                             !file->entries[i].allow_level_II_oplock) {
     410           1 :                                 oplock_return = OPLOCK_BREAK_TO_NONE;
     411             :                         }
     412          20 :                         odb_oplock_break_send(odb->ntvfs_ctx->msg_ctx,
     413          20 :                                               &file->entries[i],
     414             :                                               oplock_return);
     415          20 :                         return NT_STATUS_OPLOCK_NOT_GRANTED;
     416             :                 }
     417             :         }
     418             : 
     419      239403 :         if (_attrs_only) {
     420      239403 :                 *_attrs_only = attrs_only;
     421             :         }
     422      239403 :         return NT_STATUS_OK;
     423             : }
     424             : 
     425             : /*
     426             :   register an open file in the open files database.
     427             :   The share_access rules are implemented by odb_can_open()
     428             :   and it's needed to call odb_can_open() before
     429             :   odb_open_file() otherwise NT_STATUS_INTERNAL_ERROR is returned
     430             : 
     431             :   Note that the path is only used by the delete on close logic, not
     432             :   for comparing with other filenames
     433             : */
     434      203228 : static NTSTATUS odb_tdb_open_file(struct odb_lock *lck,
     435             :                                   void *file_handle, const char *path,
     436             :                                   int *fd, NTTIME open_write_time,
     437             :                                   bool allow_level_II_oplock,
     438             :                                   uint32_t oplock_level, uint32_t *oplock_granted)
     439             : {
     440      203228 :         struct odb_context *odb = lck->odb;
     441             : 
     442      203228 :         if (!lck->can_open.e) {
     443           0 :                 return NT_STATUS_INTERNAL_ERROR;
     444             :         }
     445             : 
     446      203228 :         if (odb->oplocks == false) {
     447           0 :                 oplock_level = OPLOCK_NONE;
     448             :         }
     449             : 
     450      203228 :         if (!oplock_granted) {
     451       17040 :                 oplock_level = OPLOCK_NONE;
     452             :         }
     453             : 
     454      203228 :         if (lck->file.path == NULL) {
     455      197120 :                 lck->file.path = talloc_strdup(lck, path);
     456      197120 :                 NT_STATUS_HAVE_NO_MEMORY(lck->file.path);
     457             :         }
     458             : 
     459      203228 :         if (lck->file.open_write_time == 0) {
     460      197120 :                 lck->file.open_write_time = open_write_time;
     461             :         }
     462             : 
     463             :         /*
     464             :           possibly grant an exclusive, batch or level2 oplock
     465             :         */
     466      203228 :         if (lck->can_open.attrs_only) {
     467           9 :                 oplock_level    = OPLOCK_NONE;
     468      203219 :         } else if (oplock_level == OPLOCK_EXCLUSIVE) {
     469          49 :                 if (lck->file.num_entries == 0) {
     470          31 :                         oplock_level    = OPLOCK_EXCLUSIVE;
     471          18 :                 } else if (allow_level_II_oplock) {
     472          18 :                         oplock_level    = OPLOCK_LEVEL_II;
     473             :                 } else {
     474           0 :                         oplock_level    = OPLOCK_NONE;
     475             :                 }
     476      203170 :         } else if (oplock_level == OPLOCK_BATCH) {
     477         117 :                 if (lck->file.num_entries == 0) {
     478          86 :                         oplock_level    = OPLOCK_BATCH;
     479          31 :                 } else if (allow_level_II_oplock) {
     480          29 :                         oplock_level    = OPLOCK_LEVEL_II;
     481             :                 } else {
     482           2 :                         oplock_level    = OPLOCK_NONE;
     483             :                 }
     484      203053 :         } else if (oplock_level == OPLOCK_LEVEL_II) {
     485           0 :                 oplock_level    = OPLOCK_LEVEL_II;
     486             :         } else {
     487      203053 :                 oplock_level    = OPLOCK_NONE;
     488             :         }
     489             : 
     490      203228 :         lck->can_open.e->file_handle              = file_handle;
     491      203228 :         lck->can_open.e->fd                       = fd;
     492      203228 :         lck->can_open.e->allow_level_II_oplock    = allow_level_II_oplock;
     493      203228 :         lck->can_open.e->oplock_level             = oplock_level;
     494             : 
     495      203228 :         if (odb->lease_ctx && fd) {
     496           0 :                 NTSTATUS status;
     497           0 :                 status = sys_lease_setup(odb->lease_ctx, lck->can_open.e);
     498           0 :                 NT_STATUS_NOT_OK_RETURN(status);
     499             :         }
     500             : 
     501      203228 :         if (oplock_granted) {
     502      186188 :                 if (lck->can_open.e->oplock_level == OPLOCK_EXCLUSIVE) {
     503          31 :                         *oplock_granted = EXCLUSIVE_OPLOCK_RETURN;
     504      186157 :                 } else if (lck->can_open.e->oplock_level == OPLOCK_BATCH) {
     505          86 :                         *oplock_granted = BATCH_OPLOCK_RETURN;
     506      186071 :                 } else if (lck->can_open.e->oplock_level == OPLOCK_LEVEL_II) {
     507          47 :                         *oplock_granted = LEVEL_II_OPLOCK_RETURN;
     508             :                 } else {
     509      186024 :                         *oplock_granted = NO_OPLOCK_RETURN;
     510             :                 }
     511             :         }
     512             : 
     513             :         /* it doesn't conflict, so add it to the end */
     514      203228 :         lck->file.entries = talloc_realloc(lck, lck->file.entries,
     515             :                                            struct opendb_entry,
     516             :                                            lck->file.num_entries+1);
     517      203228 :         NT_STATUS_HAVE_NO_MEMORY(lck->file.entries);
     518             : 
     519      203228 :         lck->file.entries[lck->file.num_entries] = *lck->can_open.e;
     520      203228 :         lck->file.num_entries++;
     521             : 
     522      203228 :         talloc_free(lck->can_open.e);
     523      203228 :         lck->can_open.e = NULL;
     524             : 
     525      203228 :         return odb_push_record(lck, &lck->file);
     526             : }
     527             : 
     528             : 
     529             : /*
     530             :   register a pending open file in the open files database
     531             : */
     532        2915 : static NTSTATUS odb_tdb_open_file_pending(struct odb_lock *lck, void *private_data)
     533             : {
     534        2915 :         struct odb_context *odb = lck->odb;
     535             : 
     536        2915 :         if (lck->file.path == NULL) {
     537           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     538             :         }
     539             : 
     540        2915 :         lck->file.pending = talloc_realloc(lck, lck->file.pending,
     541             :                                            struct opendb_pending,
     542             :                                            lck->file.num_pending+1);
     543        2915 :         NT_STATUS_HAVE_NO_MEMORY(lck->file.pending);
     544             : 
     545        2915 :         lck->file.pending[lck->file.num_pending].server = odb->ntvfs_ctx->server_id;
     546        2915 :         lck->file.pending[lck->file.num_pending].notify_ptr = private_data;
     547             : 
     548        2915 :         lck->file.num_pending++;
     549             : 
     550        2915 :         return odb_push_record(lck, &lck->file);
     551             : }
     552             : 
     553             : 
     554             : /*
     555             :   remove a opendb entry
     556             : */
     557      203228 : static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle,
     558             :                                    const char **_delete_path)
     559             : {
     560      203228 :         struct odb_context *odb = lck->odb;
     561      203228 :         const char *delete_path = NULL;
     562           0 :         int i;
     563             : 
     564      203228 :         if (lck->file.path == NULL) {
     565           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     566             :         }
     567             : 
     568             :         /* find the entry, and delete it */
     569      203624 :         for (i=0;i<lck->file.num_entries;i++) {
     570      203624 :                 if (file_handle == lck->file.entries[i].file_handle &&
     571      203228 :                     cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.entries[i].server)) {
     572      203228 :                         if (lck->file.entries[i].delete_on_close) {
     573       66085 :                                 lck->file.delete_on_close = true;
     574             :                         }
     575      203228 :                         if (odb->lease_ctx && lck->file.entries[i].fd) {
     576           0 :                                 NTSTATUS status;
     577           0 :                                 status = sys_lease_remove(odb->lease_ctx, &lck->file.entries[i]);
     578           0 :                                 NT_STATUS_NOT_OK_RETURN(status);
     579             :                         }
     580      203228 :                         if (i < lck->file.num_entries-1) {
     581        5892 :                                 memmove(lck->file.entries+i, lck->file.entries+i+1,
     582        5892 :                                         (lck->file.num_entries - (i+1)) *
     583             :                                         sizeof(struct opendb_entry));
     584             :                         }
     585      203228 :                         break;
     586             :                 }
     587             :         }
     588             : 
     589      203228 :         if (i == lck->file.num_entries) {
     590           0 :                 return NT_STATUS_UNSUCCESSFUL;
     591             :         }
     592             : 
     593             :         /* send any pending notifications, removing them once sent */
     594      203280 :         for (i=0;i<lck->file.num_pending;i++) {
     595          52 :                 imessaging_send_ptr(odb->ntvfs_ctx->msg_ctx,
     596          52 :                                    lck->file.pending[i].server,
     597             :                                    MSG_PVFS_RETRY_OPEN,
     598          52 :                                    lck->file.pending[i].notify_ptr);
     599             :         }
     600      203228 :         lck->file.num_pending = 0;
     601             : 
     602      203228 :         lck->file.num_entries--;
     603             : 
     604      203228 :         if (lck->file.num_entries == 0 && lck->file.delete_on_close) {
     605       66368 :                 delete_path = lck->file.path;
     606             :         }
     607             : 
     608      203228 :         if (_delete_path) {
     609      203228 :                 *_delete_path = delete_path;
     610             :         }
     611             : 
     612      203228 :         return odb_push_record(lck, &lck->file);
     613             : }
     614             : 
     615             : /*
     616             :   update the oplock level of the client
     617             : */
     618          86 : static NTSTATUS odb_tdb_update_oplock(struct odb_lock *lck, void *file_handle,
     619             :                                       uint32_t oplock_level)
     620             : {
     621          86 :         struct odb_context *odb = lck->odb;
     622           0 :         int i;
     623             : 
     624          86 :         if (lck->file.path == NULL) {
     625           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     626             :         }
     627             : 
     628             :         /* find the entry, and update it */
     629          90 :         for (i=0;i<lck->file.num_entries;i++) {
     630          90 :                 if (file_handle == lck->file.entries[i].file_handle &&
     631          86 :                     cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.entries[i].server)) {
     632          86 :                         lck->file.entries[i].oplock_level = oplock_level;
     633             : 
     634          86 :                         if (odb->lease_ctx && lck->file.entries[i].fd) {
     635           0 :                                 NTSTATUS status;
     636           0 :                                 status = sys_lease_update(odb->lease_ctx, &lck->file.entries[i]);
     637           0 :                                 NT_STATUS_NOT_OK_RETURN(status);
     638             :                         }
     639             : 
     640          86 :                         break;
     641             :                 }
     642             :         }
     643             : 
     644          86 :         if (i == lck->file.num_entries) {
     645           0 :                 return NT_STATUS_UNSUCCESSFUL;
     646             :         }
     647             : 
     648             :         /* send any pending notifications, removing them once sent */
     649         159 :         for (i=0;i<lck->file.num_pending;i++) {
     650          73 :                 imessaging_send_ptr(odb->ntvfs_ctx->msg_ctx,
     651          73 :                                    lck->file.pending[i].server,
     652             :                                    MSG_PVFS_RETRY_OPEN,
     653          73 :                                    lck->file.pending[i].notify_ptr);
     654             :         }
     655          86 :         lck->file.num_pending = 0;
     656             : 
     657          86 :         return odb_push_record(lck, &lck->file);
     658             : }
     659             : 
     660             : /*
     661             :   send oplocks breaks to none to all level2 holders
     662             : */
     663       31538 : static NTSTATUS odb_tdb_break_oplocks(struct odb_lock *lck)
     664             : {
     665       31538 :         struct odb_context *odb = lck->odb;
     666           0 :         int i;
     667       31538 :         bool modified = false;
     668             : 
     669             :         /* see if anyone has an oplock, which we need to break */
     670       66193 :         for (i=0;i<lck->file.num_entries;i++) {
     671       34655 :                 if (lck->file.entries[i].oplock_level == OPLOCK_LEVEL_II) {
     672             :                         /*
     673             :                          * there could be multiple level2 oplocks
     674             :                          * and we just send a break to none to all of them
     675             :                          * without waiting for a release
     676             :                          */
     677          25 :                         odb_oplock_break_send(odb->ntvfs_ctx->msg_ctx,
     678          25 :                                               &lck->file.entries[i],
     679             :                                               OPLOCK_BREAK_TO_NONE);
     680          25 :                         lck->file.entries[i].oplock_level = OPLOCK_NONE;
     681          25 :                         modified = true;
     682             :                 }
     683             :         }
     684             : 
     685       31538 :         if (modified) {
     686          19 :                 return odb_push_record(lck, &lck->file);
     687             :         }
     688       31519 :         return NT_STATUS_OK;
     689             : }
     690             : 
     691             : /*
     692             :   remove a pending opendb entry
     693             : */
     694        2831 : static NTSTATUS odb_tdb_remove_pending(struct odb_lock *lck, void *private_data)
     695             : {
     696        2831 :         struct odb_context *odb = lck->odb;
     697           0 :         int i;
     698             : 
     699        2831 :         if (lck->file.path == NULL) {
     700          41 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     701             :         }
     702             : 
     703             :         /* find the entry, and delete it */
     704        2790 :         for (i=0;i<lck->file.num_pending;i++) {
     705        2790 :                 if (private_data == lck->file.pending[i].notify_ptr &&
     706        2790 :                     cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.pending[i].server)) {
     707        2790 :                         if (i < lck->file.num_pending-1) {
     708           0 :                                 memmove(lck->file.pending+i, lck->file.pending+i+1,
     709           0 :                                         (lck->file.num_pending - (i+1)) *
     710             :                                         sizeof(struct opendb_pending));
     711             :                         }
     712        2790 :                         break;
     713             :                 }
     714             :         }
     715             : 
     716        2790 :         if (i == lck->file.num_pending) {
     717           0 :                 return NT_STATUS_UNSUCCESSFUL;
     718             :         }
     719             : 
     720        2790 :         lck->file.num_pending--;
     721             :         
     722        2790 :         return odb_push_record(lck, &lck->file);
     723             : }
     724             : 
     725             : 
     726             : /*
     727             :   rename the path in a open file
     728             : */
     729         112 : static NTSTATUS odb_tdb_rename(struct odb_lock *lck, const char *path)
     730             : {
     731         112 :         if (lck->file.path == NULL) {
     732             :                 /* not having the record at all is OK */
     733          79 :                 return NT_STATUS_OK;
     734             :         }
     735             : 
     736          33 :         lck->file.path = talloc_strdup(lck, path);
     737          33 :         NT_STATUS_HAVE_NO_MEMORY(lck->file.path);
     738             : 
     739          33 :         return odb_push_record(lck, &lck->file);
     740             : }
     741             : 
     742             : /*
     743             :   get the path of an open file
     744             : */
     745        8392 : static NTSTATUS odb_tdb_get_path(struct odb_lock *lck, const char **path)
     746             : {
     747        8392 :         *path = NULL;
     748             : 
     749             :         /* we don't ignore NT_STATUS_OBJECT_NAME_NOT_FOUND here */
     750        8392 :         if (lck->file.path == NULL) {
     751           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     752             :         }
     753             : 
     754        8392 :         *path = lck->file.path;
     755             : 
     756        8392 :         return NT_STATUS_OK;
     757             : }
     758             : 
     759             : /*
     760             :   update delete on close flag on an open file
     761             : */
     762         317 : static NTSTATUS odb_tdb_set_delete_on_close(struct odb_lock *lck, bool del_on_close)
     763             : {
     764         317 :         if (lck->file.path == NULL) {
     765           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     766             :         }
     767             : 
     768         317 :         lck->file.delete_on_close = del_on_close;
     769             : 
     770         317 :         return odb_push_record(lck, &lck->file);
     771             : }
     772             : 
     773             : /*
     774             :   update the write time on an open file
     775             : */
     776        9634 : static NTSTATUS odb_tdb_set_write_time(struct odb_lock *lck,
     777             :                                        NTTIME write_time, bool force)
     778             : {
     779        9634 :         if (lck->file.path == NULL) {
     780          37 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     781             :         }
     782             : 
     783        9597 :         if (lck->file.changed_write_time != 0 && !force) {
     784           0 :                 return NT_STATUS_OK;
     785             :         }
     786             : 
     787        9597 :         lck->file.changed_write_time = write_time;
     788             : 
     789        9597 :         return odb_push_record(lck, &lck->file);
     790             : }
     791             : 
     792             : /*
     793             :   return the current value of the delete_on_close bit, and how many
     794             :   people still have the file open
     795             : */
     796      460156 : static NTSTATUS odb_tdb_get_file_infos(struct odb_context *odb, DATA_BLOB *key,
     797             :                                        bool *del_on_close, NTTIME *write_time)
     798             : {
     799           0 :         struct odb_lock *lck;
     800             : 
     801      460156 :         if (del_on_close) {
     802       98093 :                 *del_on_close = false;
     803             :         }
     804      460156 :         if (write_time) {
     805      362063 :                 *write_time = 0;
     806             :         }
     807             : 
     808      460156 :         lck = odb_lock(odb, odb, key);
     809      460156 :         NT_STATUS_HAVE_NO_MEMORY(lck);
     810             : 
     811      460156 :         if (del_on_close) {
     812       98093 :                 *del_on_close = lck->file.delete_on_close;
     813             :         }
     814      460156 :         if (write_time) {
     815      362063 :                 if (lck->file.changed_write_time == 0) {
     816      356943 :                         *write_time = lck->file.open_write_time;
     817             :                 } else {
     818        5120 :                         *write_time = lck->file.changed_write_time;
     819             :                 }
     820             :         }
     821             : 
     822      460156 :         talloc_free(lck);
     823             : 
     824      460156 :         return NT_STATUS_OK;
     825             : }
     826             : 
     827             : 
     828             : /*
     829             :   determine if a file can be opened with the given share_access,
     830             :   create_options and access_mask
     831             : */
     832      242479 : static NTSTATUS odb_tdb_can_open(struct odb_lock *lck,
     833             :                                  uint32_t stream_id, uint32_t share_access,
     834             :                                  uint32_t access_mask, bool delete_on_close,
     835             :                                  uint32_t open_disposition, bool break_to_none)
     836             : {
     837      242479 :         struct odb_context *odb = lck->odb;
     838           0 :         NTSTATUS status;
     839             : 
     840      242479 :         status = odb_tdb_open_can_internal(odb, &lck->file, stream_id,
     841             :                                            share_access, access_mask,
     842             :                                            delete_on_close, open_disposition,
     843             :                                            break_to_none, &lck->can_open.attrs_only);
     844      242479 :         NT_STATUS_NOT_OK_RETURN(status);
     845             : 
     846      239403 :         lck->can_open.e      = talloc(lck, struct opendb_entry);
     847      239403 :         NT_STATUS_HAVE_NO_MEMORY(lck->can_open.e);
     848             : 
     849      239403 :         lck->can_open.e->server                   = odb->ntvfs_ctx->server_id;
     850      239403 :         lck->can_open.e->file_handle              = NULL;
     851      239403 :         lck->can_open.e->fd                       = NULL;
     852      239403 :         lck->can_open.e->stream_id                = stream_id;
     853      239403 :         lck->can_open.e->share_access             = share_access;
     854      239403 :         lck->can_open.e->access_mask              = access_mask;
     855      239403 :         lck->can_open.e->delete_on_close  = delete_on_close;
     856      239403 :         lck->can_open.e->allow_level_II_oplock    = false;
     857      239403 :         lck->can_open.e->oplock_level             = OPLOCK_NONE;
     858             : 
     859      239403 :         return NT_STATUS_OK;
     860             : }
     861             : 
     862             : 
     863             : static const struct opendb_ops opendb_tdb_ops = {
     864             :         .odb_init                = odb_tdb_init,
     865             :         .odb_lock                = odb_tdb_lock,
     866             :         .odb_get_key             = odb_tdb_get_key,
     867             :         .odb_open_file           = odb_tdb_open_file,
     868             :         .odb_open_file_pending   = odb_tdb_open_file_pending,
     869             :         .odb_close_file          = odb_tdb_close_file,
     870             :         .odb_remove_pending      = odb_tdb_remove_pending,
     871             :         .odb_rename              = odb_tdb_rename,
     872             :         .odb_get_path            = odb_tdb_get_path,
     873             :         .odb_set_delete_on_close = odb_tdb_set_delete_on_close,
     874             :         .odb_set_write_time      = odb_tdb_set_write_time,
     875             :         .odb_get_file_infos      = odb_tdb_get_file_infos,
     876             :         .odb_can_open            = odb_tdb_can_open,
     877             :         .odb_update_oplock       = odb_tdb_update_oplock,
     878             :         .odb_break_oplocks       = odb_tdb_break_oplocks
     879             : };
     880             : 
     881             : 
     882           4 : void odb_tdb_init_ops(void)
     883             : {
     884           4 :         sys_lease_init();
     885           4 :         odb_set_ops(&opendb_tdb_ops);
     886           4 : }

Generated by: LCOV version 1.14