The branch, master has been updated
       via  5ebb190 s3:locking: Change the data model for leases_db to cope 
with dynamic path renames.
       via  708f87b s3:locking: pass down servicepath to leases_db_add()
       via  b3b878e s3:locking: Add new utility function 
leases_db_copy_file_ids()
       via  5661198 s3:locking: prepare the data model for leases_db to cope 
with dynamic path renames.
       via  2cd9a5c s3:locking: pass servicename_new to leases_db_rename()
      from  4acf171 vfs: Add missing include for sys_pread() in cacheprime 
module.

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 5ebb1903858b4d1aadfa4e04644ec1b2b218b914
Author: Jeremy Allison <[email protected]>
Date:   Fri Dec 5 12:47:52 2014 -0800

    s3:locking: Change the data model for leases_db to cope with dynamic path 
renames.
    
    interface leases_db
    {
            typedef [public] struct {
                    GUID client_guid;
                    smb2_lease_key lease_key;
            } leases_db_key;
    
            typedef [public] struct {
                    file_id id;
                    [string,charset(UTF8)] char *servicepath;
                    [string,charset(UTF8)] char *base_name;
                    [string,charset(UTF8)] char *stream_name;
            } leases_db_file;
    
            typedef [public] struct {
                    uint32 num_files;
                    [size_is(num_files)] leases_db_file files[];
            } leases_db_value;
    }
    
    As designed by metze.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>
    
    Autobuild-User(master): Jeremy Allison <[email protected]>
    Autobuild-Date(master): Tue Dec  9 03:44:04 CET 2014 on sn-devel-104

commit 708f87b79dcdfc58e2219e90473160eb5a22ecb6
Author: Jeremy Allison <[email protected]>
Date:   Fri Dec 5 12:58:39 2014 -0800

    s3:locking: pass down servicepath to leases_db_add()
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit b3b878eea4ecdd13828fc8f912ad95904e8a6c5e
Author: Jeremy Allison <[email protected]>
Date:   Fri Dec 5 12:57:24 2014 -0800

    s3:locking: Add new utility function leases_db_copy_file_ids()
    
    Will be used by lease db parsers.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 5661198d718496201ea2a6bb75d043a8b255b578
Author: Jeremy Allison <[email protected]>
Date:   Fri Dec 5 12:47:52 2014 -0800

    s3:locking: prepare the data model for leases_db to cope with dynamic path 
renames.
    
    interface leases_db
    {
            typedef [public] struct {
                    GUID client_guid;
                    smb2_lease_key lease_key;
            } leases_db_key;
    
            typedef [public] struct {
                    file_id id;
                    [string,charset(UTF8)] char *servicepath;
                    [string,charset(UTF8)] char *base_name;
                    [string,charset(UTF8)] char *stream_name;
            } leases_db_file;
    
            typedef [public] struct {
                    uint32 num_files;
                    [size_is(num_files)] leases_db_file files[];
            } leases_db_value;
    }
    
    As designed by metze.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 2cd9a5c3209e947a6e63ad019da869790d01d0aa
Author: Jeremy Allison <[email protected]>
Date:   Fri Dec 5 12:56:03 2014 -0800

    s3:locking: pass servicename_new to leases_db_rename()
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

-----------------------------------------------------------------------

Summary of changes:
 source3/librpc/idl/leases_db.idl |  11 ++-
 source3/locking/leases_db.c      |  85 +++++++++++++++-------
 source3/locking/leases_db.h      |  13 ++--
 source3/locking/locking.c        |   1 +
 source3/smbd/open.c              | 151 +++++++++++++++++++++++++++++++--------
 source3/smbd/smb2_break.c        |  16 ++---
 6 files changed, 203 insertions(+), 74 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/librpc/idl/leases_db.idl b/source3/librpc/idl/leases_db.idl
index 2ab1591..d021875 100644
--- a/source3/librpc/idl/leases_db.idl
+++ b/source3/librpc/idl/leases_db.idl
@@ -15,9 +15,14 @@ interface leases_db
        } leases_db_key;
 
        typedef [public] struct {
-               uint32 num_file_ids;
-               [size_is(num_file_ids)] file_id ids[];
-               [string,charset(UTF8)] char *filename;
+               file_id id;
+               [string,charset(UTF8)] char *servicepath;
+               [string,charset(UTF8)] char *base_name;
                [string,charset(UTF8)] char *stream_name;
+       } leases_db_file;
+
+       typedef [public] struct {
+               uint32 num_files;
+               [size_is(num_files)] leases_db_file files[];
        } leases_db_value;
 }
diff --git a/source3/locking/leases_db.c b/source3/locking/leases_db.c
index 7e000aa..0700ba9 100644
--- a/source3/locking/leases_db.c
+++ b/source3/locking/leases_db.c
@@ -85,7 +85,8 @@ static bool leases_db_key(TALLOC_CTX *mem_ctx,
 NTSTATUS leases_db_add(const struct GUID *client_guid,
                       const struct smb2_lease_key *lease_key,
                       const struct file_id *id,
-                      const char *filename,
+                      const char *servicepath,
+                      const char *base_name,
                       const char *stream_name)
 {
        TDB_DATA db_key, db_value;
@@ -94,6 +95,7 @@ NTSTATUS leases_db_add(const struct GUID *client_guid,
        NTSTATUS status;
        bool ok;
        struct leases_db_value new_value;
+       struct leases_db_file new_file;
        struct leases_db_value *value = NULL;
        enum ndr_err_code ndr_err;
 
@@ -139,31 +141,40 @@ NTSTATUS leases_db_add(const struct GUID *client_guid,
                }
 
                /* id must be unique. */
-               for (i = 0; i < value->num_file_ids; i++) {
-                       if (file_id_equal(id, &value->ids[i])) {
+               for (i = 0; i < value->num_files; i++) {
+                       if (file_id_equal(id, &value->files[i].id)) {
                                status = NT_STATUS_OBJECT_NAME_COLLISION;
                                goto out;
                        }
                }
 
-               value->ids = talloc_realloc(value, value->ids, struct file_id,
-                                       value->num_file_ids + 1);
-               if (value->ids == NULL) {
+               value->files = talloc_realloc(value, value->files,
+                                       struct leases_db_file,
+                                       value->num_files + 1);
+               if (value->files == NULL) {
                        status = NT_STATUS_NO_MEMORY;
                        goto out;
                }
-               value->ids[value->num_file_ids] = *id;
-               value->num_file_ids += 1;
+               value->files[value->num_files].id = *id;
+               value->files[value->num_files].servicepath = servicepath;
+               value->files[value->num_files].base_name = base_name;
+               value->files[value->num_files].stream_name = stream_name;
+               value->num_files += 1;
 
        } else {
                DEBUG(10, ("%s: new record\n", __func__));
 
-               new_value = (struct leases_db_value) {
-                       .num_file_ids = 1,
-                       .ids = discard_const_p(struct file_id, id),
-                       .filename = filename,
+               new_file = (struct leases_db_file) {
+                       .id = *id,
+                       .servicepath = servicepath,
+                       .base_name = base_name,
                        .stream_name = stream_name,
                };
+
+               new_value = (struct leases_db_value) {
+                       .num_files = 1,
+                       .files = &new_file,
+               };
                value = &new_value;
        }
 
@@ -252,21 +263,21 @@ NTSTATUS leases_db_del(const struct GUID *client_guid,
        }
 
        /* id must exist. */
-       for (i = 0; i < value->num_file_ids; i++) {
-               if (file_id_equal(id, &value->ids[i])) {
+       for (i = 0; i < value->num_files; i++) {
+               if (file_id_equal(id, &value->files[i].id)) {
                        break;
                }
        }
 
-       if (i == value->num_file_ids) {
+       if (i == value->num_files) {
                status = NT_STATUS_NOT_FOUND;
                goto out;
        }
 
-       value->ids[i] = value->ids[value->num_file_ids-1];
-       value->num_file_ids -= 1;
+       value->files[i] = value->files[value->num_files-1];
+       value->num_files -= 1;
 
-       if (value->num_file_ids == 0) {
+       if (value->num_files == 0) {
                DEBUG(10, ("%s: deleting record\n", __func__));
                status = dbwrap_record_delete(rec);
        } else {
@@ -303,9 +314,9 @@ NTSTATUS leases_db_del(const struct GUID *client_guid,
 }
 
 struct leases_db_fetch_state {
-       void (*parser)(uint32_t num_file_ids,
-                       struct file_id *ids, const char *filename,
-                       const char *stream_name, void *private_data);
+       void (*parser)(uint32_t num_files,
+                       const struct leases_db_file *files,
+                       void *private_data);
        void *private_data;
        NTSTATUS status;
 };
@@ -340,8 +351,8 @@ static void leases_db_parser(TDB_DATA key, TDB_DATA data, 
void *private_data)
                NDR_PRINT_DEBUG(leases_db_value, value);
        }
 
-       state->parser(value->num_file_ids,
-                       value->ids, value->filename, value->stream_name,
+       state->parser(value->num_files,
+                       value->files,
                        state->private_data);
 
        TALLOC_FREE(value);
@@ -350,10 +361,8 @@ static void leases_db_parser(TDB_DATA key, TDB_DATA data, 
void *private_data)
 
 NTSTATUS leases_db_parse(const struct GUID *client_guid,
                         const struct smb2_lease_key *lease_key,
-                        void (*parser)(uint32_t num_file_ids,
-                                       struct file_id *ids,
-                                       const char *filename,
-                                       const char *stream_name,
+                        void (*parser)(uint32_t num_files,
+                                       const struct leases_db_file *files,
                                        void *private_data),
                         void *private_data)
 {
@@ -389,6 +398,7 @@ NTSTATUS leases_db_parse(const struct GUID *client_guid,
 NTSTATUS leases_db_rename(const struct GUID *client_guid,
                       const struct smb2_lease_key *lease_key,
                       const struct file_id *id,
+                      const char *servicename_new,
                       const char *filename_new,
                       const char *stream_name_new)
 {
@@ -404,6 +414,27 @@ NTSTATUS leases_db_rename(const struct GUID *client_guid,
        return leases_db_add(client_guid,
                                lease_key,
                                id,
+                               servicename_new,
                                filename_new,
                                stream_name_new);
 }
+
+NTSTATUS leases_db_copy_file_ids(TALLOC_CTX *mem_ctx,
+                       uint32_t num_files,
+                       const struct leases_db_file *files,
+                       struct file_id **pp_ids)
+{
+       uint32_t i;
+       struct file_id *ids = talloc_array(mem_ctx,
+                               struct file_id,
+                               num_files);
+       if (ids == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i = 0; i < num_files; i++) {
+               ids[i] = files[i].id;
+       }
+       *pp_ids = ids;
+       return NT_STATUS_OK;
+}
diff --git a/source3/locking/leases_db.h b/source3/locking/leases_db.h
index 906a99b..383575a 100644
--- a/source3/locking/leases_db.h
+++ b/source3/locking/leases_db.h
@@ -24,11 +24,13 @@
 struct GUID;
 struct smb2_lease_key;
 struct file_id;
+struct leases_db_file;
 
 bool leases_db_init(bool read_only);
 NTSTATUS leases_db_add(const struct GUID *client_guid,
                       const struct smb2_lease_key *lease_key,
                       const struct file_id *id,
+                      const char *servicepath,
                       const char *filename,
                       const char *stream_name);
 NTSTATUS leases_db_del(const struct GUID *client_guid,
@@ -36,15 +38,18 @@ NTSTATUS leases_db_del(const struct GUID *client_guid,
                       const struct file_id *id);
 NTSTATUS leases_db_parse(const struct GUID *client_guid,
                         const struct smb2_lease_key *lease_key,
-                        void (*parser)(uint32_t num_file_ids,
-                                       struct file_id *ids,
-                                       const char *filename,
-                                       const char *stream_name,
+                        void (*parser)(uint32_t num_files,
+                                       const struct leases_db_file *files,
                                        void *private_data),
                         void *private_data);
 NTSTATUS leases_db_rename(const struct GUID *client_guid,
                        const struct smb2_lease_key *lease_key,
                        const struct file_id *id,
+                       const char *servicepath_new,
                        const char *filename_new,
                        const char *stream_name_new);
+NTSTATUS leases_db_copy_file_ids(TALLOC_CTX *mem_ctx,
+                       uint32_t num_files,
+                       const struct leases_db_file *files,
+                       struct file_id **pp_ids);
 #endif /* _LEASES_DB_H_ */
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index dd73f68..221d6ee 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -575,6 +575,7 @@ bool rename_share_filename(struct messaging_context 
*msg_ctx,
                status = leases_db_rename(&l->client_guid,
                                        &l->lease_key,
                                        &id,
+                                       d->servicepath,
                                        d->base_name,
                                        d->stream_name);
                if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 8f19a36..06770e0 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -36,6 +36,7 @@
 #include "messages.h"
 #include "source3/lib/dbwrap/dbwrap_watch.h"
 #include "locking/leases_db.h"
+#include "librpc/gen_ndr/ndr_leases_db.h"
 
 extern const struct generic_mapping file_generic_mapping;
 
@@ -1677,8 +1678,11 @@ static NTSTATUS grant_fsp_lease(struct files_struct *fsp,
                .epoch = fsp->lease->lease.lease_epoch,
        };
 
-       status = leases_db_add(client_guid, &lease->lease_key,
-                              &fsp->file_id, fsp->fsp_name->base_name,
+       status = leases_db_add(client_guid,
+                              &lease->lease_key,
+                              &fsp->file_id,
+                              fsp->conn->connectpath,
+                              fsp->fsp_name->base_name,
                               fsp->fsp_name->stream_name);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10, ("%s: leases_db_add failed: %s\n", __func__,
@@ -4124,8 +4128,10 @@ static NTSTATUS inherit_new_acl(files_struct *fsp)
  * used for a different file name.
  */
 
-struct lease_fname_match_state {
+struct lease_match_state {
        /* Input parameters. */
+       TALLOC_CTX *mem_ctx;
+       const char *servicepath;
        const struct smb_filename *fname;
        bool file_existed;
        struct file_id id;
@@ -4135,57 +4141,139 @@ struct lease_fname_match_state {
        NTSTATUS match_status;
 };
 
-static void lease_fname_match_parser(
-       uint32_t num_file_ids,
-       struct file_id *ids, const char *filename, const char *stream_name,
+/*************************************************************
+ File doesn't exist but this lease key+guid is already in use.
+
+ This is only allowable in the dynamic share case where the
+ service path must be different.
+
+ There is a small race condition here in the multi-connection
+ case where a client sends two create calls on different connections,
+ where the file doesn't exist and one smbd creates the leases_db
+ entry first, but this will get fixed by the multichannel cleanup
+ when all identical client_guids get handled by a single smbd.
+**************************************************************/
+
+static void lease_match_parser_new_file(
+       uint32_t num_files,
+       const struct leases_db_file *files,
+       struct lease_match_state *state)
+{
+       uint32_t i;
+
+       for (i = 0; i < num_files; i++) {
+               const struct leases_db_file *f = &files[i];
+               if (strequal(state->servicepath, f->servicepath)) {
+                       state->match_status = NT_STATUS_INVALID_PARAMETER;
+                       return;
+               }
+       }
+
+       /* Dynamic share case. Break leases on all other files. */
+       state->match_status = leases_db_copy_file_ids(state->mem_ctx,
+                                       num_files,
+                                       files,
+                                       &state->ids);
+       if (!NT_STATUS_IS_OK(state->match_status)) {
+               return;
+       }
+
+       state->num_file_ids = num_files;
+       state->match_status = NT_STATUS_OPLOCK_NOT_GRANTED;
+       return;
+}
+
+static void lease_match_parser(
+       uint32_t num_files,
+       const struct leases_db_file *files,
        void *private_data)
 {
-       struct lease_fname_match_state *state =
-               (struct lease_fname_match_state *)private_data;
+       struct lease_match_state *state =
+               (struct lease_match_state *)private_data;
+       uint32_t i;
 
-       if (!strequal(filename, state->fname->base_name) ||
-           !strequal(stream_name, state->fname->stream_name))
-       {
-               /* Names don't match lease key. */
-               state->match_status = NT_STATUS_INVALID_PARAMETER;
+       if (!state->file_existed) {
+               /*
+                * Deal with name mismatch or
+                * possible dynamic share case separately
+                * to make code clearer.
+                */
+               lease_match_parser_new_file(num_files,
+                                               files,
+                                               state);
                return;
        }
 
-       if (state->file_existed &&
-           num_file_ids == 1 &&
-           file_id_equal(&ids[0],&state->id))
-       {
-               /* Common case - non-dynamic share. We're ok.. */
-               state->match_status = NT_STATUS_OK;
+       /* File existed. */
+       state->match_status = NT_STATUS_OK;
+
+       for (i = 0; i < num_files; i++) {
+               const struct leases_db_file *f = &files[i];
+
+               /* Everything should be the same. */
+               if (!file_id_equal(&state->id, &f->id)) {
+                       /* This should catch all dynamic share cases. */
+                       state->match_status = NT_STATUS_OPLOCK_NOT_GRANTED;
+                       break;
+               }
+               if (!strequal(f->servicepath, state->servicepath)) {
+                       state->match_status = NT_STATUS_INVALID_PARAMETER;
+                       break;
+               }
+               if (!strequal(f->base_name, state->fname->base_name)) {
+                       state->match_status = NT_STATUS_INVALID_PARAMETER;
+                       break;
+               }
+               if (!strequal(f->stream_name, state->fname->stream_name)) {
+                       state->match_status = NT_STATUS_INVALID_PARAMETER;
+                       break;
+               }
+       }
+
+       if (NT_STATUS_IS_OK(state->match_status)) {
+               /*
+                * Common case - just opening another handle on a
+                * file on a non-dynamic share.
+                */
+               return;
+       }
+
+       if (NT_STATUS_EQUAL(state->match_status, NT_STATUS_INVALID_PARAMETER)) {
+               /* Mismatched path. Error back to client. */
                return;
        }
 
        /*
-        * More than one file id, or not equal, or new file
-        * being created and there's already an existing lease
-        * on this (client_guid, lease id) pair.
+        * File id mismatch. Dynamic share case NT_STATUS_OPLOCK_NOT_GRANTED.
         * Don't allow leases.
         */
 
-       state->match_status = NT_STATUS_OPLOCK_NOT_GRANTED;
-       state->num_file_ids = num_file_ids;
-       state->ids = talloc_memdup(talloc_tos(),
-                               ids,
-                               num_file_ids * sizeof(struct file_id));
-       if (state->ids == NULL) {
-               state->match_status = NT_STATUS_NO_MEMORY;
+       state->match_status = leases_db_copy_file_ids(state->mem_ctx,
+                                       num_files,
+                                       files,
+                                       &state->ids);
+       if (!NT_STATUS_IS_OK(state->match_status)) {
+               return;
        }
+
+       state->num_file_ids = num_files;
+       state->match_status = NT_STATUS_OPLOCK_NOT_GRANTED;
+       return;
 }
 
 static NTSTATUS lease_match(connection_struct *conn,
                            struct smb_request *req,
                            struct smb2_lease_key *lease_key,
+                           const char *servicepath,
                            const struct smb_filename *fname,
                            uint16_t *p_version,
                            uint16_t *p_epoch)
 {
        struct smbd_server_connection *sconn = req->sconn;
-       struct lease_fname_match_state state = {
+       TALLOC_CTX *tos = talloc_tos();
+       struct lease_match_state state = {
+               .mem_ctx = tos,
+               .servicepath = servicepath,
                .fname = fname,
                .match_status = NT_STATUS_OK
        };
@@ -4200,7 +4288,7 @@ static NTSTATUS lease_match(connection_struct *conn,
        }
 
        status = leases_db_parse(&sconn->client->connections->smb2.client.guid,
-                                lease_key, lease_fname_match_parser, &state);
+                                lease_key, lease_match_parser, &state);
        if (!NT_STATUS_IS_OK(status)) {
                /*
                 * Not found or error means okay: We can make the lease pass
@@ -4353,6 +4441,7 @@ static NTSTATUS create_file_unixpath(connection_struct 
*conn,
                status = lease_match(conn,
                                req,
                                &lease->lease_key,
+                               conn->connectpath,
                                smb_fname,
                                &version,
                                &epoch);
diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c
index 126bf78..5eab0a1 100644
--- a/source3/smbd/smb2_break.c
+++ b/source3/smbd/smb2_break.c
@@ -340,21 +340,19 @@ struct lease_lookup_state {
 };
 
 static void lease_parser(
-       uint32_t num_file_ids,
-       struct file_id *ids, const char *filename, const char *stream_name,
+       uint32_t num_files,
+       const struct leases_db_file *files,
        void *private_data)
 {
        struct lease_lookup_state *lls =
                (struct lease_lookup_state *)private_data;
 
        lls->status = NT_STATUS_OK;
-       lls->num_file_ids = num_file_ids;
-       lls->ids = talloc_memdup(lls->mem_ctx,
-                               ids,
-                               num_file_ids * sizeof(struct file_id));
-       if (lls->ids == NULL) {
-               lls->status = NT_STATUS_NO_MEMORY;
-       }
+       lls->num_file_ids = num_files;
+       lls->status = leases_db_copy_file_ids(lls->mem_ctx,
+                               num_files,


-- 
Samba Shared Repository

Reply via email to