Change to using TDB_INCOMPATIBLE_HASH (the jenkins hash) on all
[ira/wip.git] / source3 / locking / locking.c
index fba871c704e0cb5417e82bdd462524fed165e754..ed07d7a25a6be0c03e450c5d9059a27892068757 100644 (file)
@@ -36,6 +36,9 @@
 */
 
 #include "includes.h"
+#include "librpc/gen_ndr/messaging.h"
+#include "smbd/globals.h"
+#include "dbwrap.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_LOCKING
@@ -76,7 +79,7 @@ const char *lock_flav_name(enum brl_flavour lock_flav)
 ****************************************************************************/
 
 void init_strict_lock_struct(files_struct *fsp,
-                               uint32 smbpid,
+                               uint64_t smblctx,
                                br_off start,
                                br_off size,
                                enum brl_type lock_type,
@@ -84,9 +87,9 @@ void init_strict_lock_struct(files_struct *fsp,
 {
        SMB_ASSERT(lock_type == READ_LOCK || lock_type == WRITE_LOCK);
 
-       plock->context.smbpid = smbpid;
+       plock->context.smblctx = smblctx;
         plock->context.tid = fsp->conn->cnum;
-        plock->context.pid = procid_self();
+        plock->context.pid = sconn_server_id(fsp->conn->sconn);
         plock->start = start;
         plock->size = size;
         plock->fnum = fsp->fnum;
@@ -116,32 +119,34 @@ bool strict_lock_default(files_struct *fsp, struct lock_struct *plock)
                        DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp_str_dbg(fsp)));
                        ret = True;
                } else {
-                       struct byte_range_lock *br_lck = brl_get_locks_readonly(talloc_tos(), fsp);
+                       struct byte_range_lock *br_lck;
+
+                       br_lck = brl_get_locks_readonly(fsp);
                        if (!br_lck) {
                                return True;
                        }
                        ret = brl_locktest(br_lck,
-                                       plock->context.smbpid,
+                                       plock->context.smblctx,
                                        plock->context.pid,
                                        plock->start,
                                        plock->size,
                                        plock->lock_type,
                                        plock->lock_flav);
-                       TALLOC_FREE(br_lck);
                }
        } else {
-               struct byte_range_lock *br_lck = brl_get_locks_readonly(talloc_tos(), fsp);
+               struct byte_range_lock *br_lck;
+
+               br_lck = brl_get_locks_readonly(fsp);
                if (!br_lck) {
                        return True;
                }
                ret = brl_locktest(br_lck,
-                               plock->context.smbpid,
+                               plock->context.smblctx,
                                plock->context.pid,
                                plock->start,
                                plock->size,
                                plock->lock_type,
                                plock->lock_flav);
-               TALLOC_FREE(br_lck);
        }
 
        DEBUG(10,("strict_lock_default: flavour = %s brl start=%.0f "
@@ -163,14 +168,13 @@ void strict_unlock_default(files_struct *fsp, struct lock_struct *plock)
 ****************************************************************************/
 
 NTSTATUS query_lock(files_struct *fsp,
-                       uint32 *psmbpid,
+                       uint64_t *psmblctx,
                        uint64_t *pcount,
                        uint64_t *poffset,
                        enum brl_type *plock_type,
                        enum brl_flavour lock_flav)
 {
        struct byte_range_lock *br_lck = NULL;
-       NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
 
        if (!fsp->can_lock) {
                return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
@@ -180,21 +184,18 @@ NTSTATUS query_lock(files_struct *fsp,
                return NT_STATUS_OK;
        }
 
-       br_lck = brl_get_locks_readonly(talloc_tos(), fsp);
+       br_lck = brl_get_locks_readonly(fsp);
        if (!br_lck) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = brl_lockquery(br_lck,
-                       psmbpid,
-                       procid_self(),
+       return brl_lockquery(br_lck,
+                       psmblctx,
+                       sconn_server_id(fsp->conn->sconn),
                        poffset,
                        pcount,
                        plock_type,
                        lock_flav);
-
-       TALLOC_FREE(br_lck);
-       return status;
 }
 
 static void increment_current_lock_count(files_struct *fsp,
@@ -231,18 +232,24 @@ static void decrement_current_lock_count(files_struct *fsp,
 
 struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
                        files_struct *fsp,
-                       uint32 lock_pid,
+                       uint64_t smblctx,
                        uint64_t count,
                        uint64_t offset,
                        enum brl_type lock_type,
                        enum brl_flavour lock_flav,
                        bool blocking_lock,
                        NTSTATUS *perr,
-                       uint32 *plock_pid,
+                       uint64_t *psmblctx,
                        struct blocking_lock_record *blr)
 {
        struct byte_range_lock *br_lck = NULL;
 
+       /* silently return ok on print files as we don't do locking there */
+       if (fsp->print_file) {
+               *perr = NT_STATUS_OK;
+               return NULL;
+       }
+
        if (!fsp->can_lock) {
                *perr = fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
                return NULL;
@@ -269,14 +276,14 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
 
        *perr = brl_lock(msg_ctx,
                        br_lck,
-                       lock_pid,
-                       procid_self(),
+                       smblctx,
+                       sconn_server_id(fsp->conn->sconn),
                        offset,
-                       count, 
+                       count,
                        lock_type,
                        lock_flav,
                        blocking_lock,
-                       plock_pid,
+                       psmblctx,
                        blr);
 
        DEBUG(10, ("do_lock: returning status=%s\n", nt_errstr(*perr)));
@@ -291,7 +298,7 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
 
 NTSTATUS do_unlock(struct messaging_context *msg_ctx,
                        files_struct *fsp,
-                       uint32 lock_pid,
+                       uint64_t smblctx,
                        uint64_t count,
                        uint64_t offset,
                        enum brl_flavour lock_flav)
@@ -318,8 +325,8 @@ NTSTATUS do_unlock(struct messaging_context *msg_ctx,
 
        ok = brl_unlock(msg_ctx,
                        br_lck,
-                       lock_pid,
-                       procid_self(),
+                       smblctx,
+                       sconn_server_id(fsp->conn->sconn),
                        offset,
                        count,
                        lock_flav);
@@ -340,7 +347,7 @@ NTSTATUS do_unlock(struct messaging_context *msg_ctx,
 ****************************************************************************/
 
 NTSTATUS do_lock_cancel(files_struct *fsp,
-                       uint32 lock_pid,
+                       uint64 smblctx,
                        uint64_t count,
                        uint64_t offset,
                        enum brl_flavour lock_flav,
@@ -368,8 +375,8 @@ NTSTATUS do_lock_cancel(files_struct *fsp,
        }
 
        ok = brl_lock_cancel(br_lck,
-                       lock_pid,
-                       procid_self(),
+                       smblctx,
+                       sconn_server_id(fsp->conn->sconn),
                        offset,
                        count,
                        lock_flav,
@@ -391,7 +398,8 @@ NTSTATUS do_lock_cancel(files_struct *fsp,
 ****************************************************************************/
 
 void locking_close_file(struct messaging_context *msg_ctx,
-                       files_struct *fsp)
+                       files_struct *fsp,
+                       enum file_close_type close_type)
 {
        struct byte_range_lock *br_lck;
 
@@ -410,7 +418,7 @@ void locking_close_file(struct messaging_context *msg_ctx,
        br_lck = brl_get_locks(talloc_tos(),fsp);
 
        if (br_lck) {
-               cancel_pending_lock_requests_by_fid(fsp, br_lck);
+               cancel_pending_lock_requests_by_fid(fsp, br_lck, close_type);
                brl_close_fnum(msg_ctx, br_lck);
                TALLOC_FREE(br_lck);
        }
@@ -429,7 +437,7 @@ static bool locking_init_internal(bool read_only)
 
        lock_db = db_open(NULL, lock_path("locking.tdb"),
                          lp_open_files_db_hash_size(),
-                         TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST,
+                         TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
                          read_only?O_RDONLY:O_RDWR|O_CREAT, 0644);
 
        if (!lock_db) {
@@ -482,13 +490,14 @@ char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
 {
        return talloc_asprintf(ctx, "share_mode_entry[%d]: %s "
                 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
-                "access_mask = 0x%x, mid = 0x%x, type= 0x%x, gen_id = %lu, "
+                "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %lu, "
                 "uid = %u, flags = %u, file_id %s",
                 num,
                 e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "",
                 procid_str_static(&e->pid),
                 e->share_access, e->private_options,
-                e->access_mask, e->op_mid, e->op_type, e->share_file_id,
+                e->access_mask, (unsigned long long)e->op_mid,
+                e->op_type, e->share_file_id,
                 (unsigned int)e->uid, (unsigned int)e->flags,
                 file_id_string_tos(&e->id));
 }
@@ -545,9 +554,9 @@ static bool parse_share_modes(const TDB_DATA dbuf, struct share_mode_lock *lck)
        DEBUG(10, ("parse_share_modes: delete_on_close: %d, owrt: %s, "
                   "cwrt: %s, tok: %u, num_share_modes: %d\n",
                   lck->delete_on_close,
-                  timestring(debug_ctx(),
+                  timestring(talloc_tos(),
                              convert_timespec_to_time_t(lck->old_write_time)),
-                  timestring(debug_ctx(),
+                  timestring(talloc_tos(),
                              convert_timespec_to_time_t(
                                      lck->changed_write_time)),
                   (unsigned int)data.u.s.delete_token_size,
@@ -655,7 +664,7 @@ static bool parse_share_modes(const TDB_DATA dbuf, struct share_mode_lock *lck)
                }
                DEBUG(10,("parse_share_modes: %s\n",
                        str ? str : ""));
-               if (!process_exists(entry_p->pid)) {
+               if (!serverid_exists(&entry_p->pid)) {
                        DEBUG(10,("parse_share_modes: deleted %s\n",
                                str ? str : ""));
                        entry_p->op_type = UNUSED_SHARE_MODE_ENTRY;
@@ -719,9 +728,9 @@ static TDB_DATA unparse_share_modes(const struct share_mode_lock *lck)
 
        DEBUG(10,("unparse_share_modes: del: %d, owrt: %s cwrt: %s, tok: %u, "
                  "num: %d\n", data->u.s.delete_on_close,
-                 timestring(debug_ctx(),
+                 timestring(talloc_tos(),
                             convert_timespec_to_time_t(lck->old_write_time)),
-                 timestring(debug_ctx(),
+                 timestring(talloc_tos(),
                             convert_timespec_to_time_t(
                                     lck->changed_write_time)),
                  (unsigned int)data->u.s.delete_token_size,
@@ -782,9 +791,18 @@ static int share_mode_lock_destructor(struct share_mode_lock *lck)
 
                        status = lck->record->delete_rec(lck->record);
                        if (!NT_STATUS_IS_OK(status)) {
+                               char *errmsg;
+
                                DEBUG(0, ("delete_rec returned %s\n",
                                          nt_errstr(status)));
-                               smb_panic("could not delete share entry");
+
+                               if (asprintf(&errmsg, "could not delete share "
+                                            "entry: %s\n",
+                                            nt_errstr(status)) == -1) {
+                                       smb_panic("could not delete share"
+                                                 "entry");
+                               }
+                               smb_panic(errmsg);
                        }
                }
                goto done;
@@ -792,8 +810,15 @@ static int share_mode_lock_destructor(struct share_mode_lock *lck)
 
        status = lck->record->store(lck->record, data, TDB_REPLACE);
        if (!NT_STATUS_IS_OK(status)) {
+               char *errmsg;
+
                DEBUG(0, ("store returned %s\n", nt_errstr(status)));
-               smb_panic("could not store share mode entry");
+
+               if (asprintf(&errmsg, "could not store share mode entry: %s",
+                            nt_errstr(status)) == -1) {
+                       smb_panic("could not store share mode entry");
+               }
+               smb_panic(errmsg);
        }
 
  done:
@@ -1084,10 +1109,10 @@ bool is_unused_share_mode_entry(const struct share_mode_entry *e)
 
 static void fill_share_mode_entry(struct share_mode_entry *e,
                                  files_struct *fsp,
-                                 uid_t uid, uint16 mid, uint16 op_type)
+                                 uid_t uid, uint64_t mid, uint16 op_type)
 {
        ZERO_STRUCTP(e);
-       e->pid = procid_self();
+       e->pid = sconn_server_id(fsp->conn->sconn);
        e->share_access = fsp->share_access;
        e->private_options = fsp->fh->private_options;
        e->access_mask = fsp->access_mask;
@@ -1103,10 +1128,12 @@ static void fill_share_mode_entry(struct share_mode_entry *e,
 
 static void fill_deferred_open_entry(struct share_mode_entry *e,
                                     const struct timeval request_time,
-                                    struct file_id id, uint16 mid)
+                                    struct file_id id,
+                                    struct server_id pid,
+                                    uint64_t mid)
 {
        ZERO_STRUCTP(e);
-       e->pid = procid_self();
+       e->pid = pid;
        e->op_mid = mid;
        e->op_type = DEFERRED_OPEN_ENTRY;
        e->time.tv_sec = request_time.tv_sec;
@@ -1138,19 +1165,19 @@ static void add_share_mode_entry(struct share_mode_lock *lck,
 }
 
 void set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
-                   uid_t uid, uint16 mid, uint16 op_type)
+                   uid_t uid, uint64_t mid, uint16 op_type)
 {
        struct share_mode_entry entry;
        fill_share_mode_entry(&entry, fsp, uid, mid, op_type);
        add_share_mode_entry(lck, &entry);
 }
 
-void add_deferred_open(struct share_mode_lock *lck, uint16 mid,
+void add_deferred_open(struct share_mode_lock *lck, uint64_t mid,
                       struct timeval request_time,
-                      struct file_id id)
+                      struct server_id pid, struct file_id id)
 {
        struct share_mode_entry entry;
-       fill_deferred_open_entry(&entry, request_time, id, mid);
+       fill_deferred_open_entry(&entry, request_time, id, pid, mid);
        add_share_mode_entry(lck, &entry);
 }
 
@@ -1224,12 +1251,13 @@ bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
        return True;
 }
 
-void del_deferred_open_entry(struct share_mode_lock *lck, uint16 mid)
+void del_deferred_open_entry(struct share_mode_lock *lck, uint64_t mid,
+                            struct server_id pid)
 {
        struct share_mode_entry entry, *e;
 
        fill_deferred_open_entry(&entry, timeval_zero(),
-                                lck->id, mid);
+                                lck->id, pid, mid);
 
        e = find_share_mode_entry(lck, &entry);
        if (e == NULL) {
@@ -1293,18 +1321,11 @@ bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
 }
 
 /****************************************************************************
- Deal with the internal needs of setting the delete on close flag. Note that
- as the tdb locking is recursive, it is safe to call this from within 
- open_file_ntcreate. JRA.
+ Check if setting delete on close is allowed on this fsp.
 ****************************************************************************/
 
-NTSTATUS can_set_delete_on_close(files_struct *fsp, bool delete_on_close,
-                                uint32 dosmode)
+NTSTATUS can_set_delete_on_close(files_struct *fsp, uint32 dosmode)
 {
-       if (!delete_on_close) {
-               return NT_STATUS_OK;
-       }
-
        /*
         * Only allow delete on close for writable files.
         */
@@ -1420,7 +1441,6 @@ void set_delete_on_close_lck(struct share_mode_lock *lck, bool delete_on_close,
 
 bool set_delete_on_close(files_struct *fsp, bool delete_on_close, const UNIX_USER_TOKEN *tok)
 {
-       UNIX_USER_TOKEN *tok_copy = NULL;
        struct share_mode_lock *lck;
        
        DEBUG(10,("set_delete_on_close: %s delete on close flag for "
@@ -1434,24 +1454,18 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close, const UNIX_USE
                return False;
        }
 
-       if (fsp->conn->admin_user) {
-               tok_copy = copy_unix_token(lck, tok);
-               if (tok_copy == NULL) {
-                       TALLOC_FREE(lck);
-                       return false;
-               }
-               tok_copy->uid = (uid_t)0;
-               tok = tok_copy;
-       }
-
        set_delete_on_close_lck(lck, delete_on_close, tok);
 
        if (fsp->is_directory) {
                SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
-               send_stat_cache_delete_message(fsp->fsp_name->base_name);
+               send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
+                                              fsp->fsp_name->base_name);
        }
 
        TALLOC_FREE(lck);
+
+       fsp->delete_on_close = delete_on_close;
+
        return True;
 }
 
@@ -1460,7 +1474,7 @@ bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
        struct share_mode_lock *lck;
 
        DEBUG(5,("set_sticky_write_time: %s id=%s\n",
-                timestring(debug_ctx(),
+                timestring(talloc_tos(),
                            convert_timespec_to_time_t(write_time)),
                 file_id_string_tos(&fileid)));
 
@@ -1483,7 +1497,7 @@ bool set_write_time(struct file_id fileid, struct timespec write_time)
        struct share_mode_lock *lck;
 
        DEBUG(5,("set_write_time: %s id=%s\n",
-                timestring(debug_ctx(),
+                timestring(talloc_tos(),
                            convert_timespec_to_time_t(write_time)),
                 file_id_string_tos(&fileid)));