The branch, master has been updated
       via  480516e3b85 vfs_fruit: make use of 
adouble_open_from_base_fsp(ADOUBLE_RSRC) in fruit_open_rsrc_adouble()
       via  0b8c6e736af vfs_fruit: add fruit_get_complete_fio() helper
       via  94799dc8e61 vfs_fruit: let fruit_open_rsrc_adouble() return errno = 
EISDIR
       via  d62c670c3dd s3:adouble: add adouble_open_from_base_fsp()
       via  c45a8d753d3 s3:adouble: allow ad_fget/ad_get_internal to be used 
with a backend fsp
       via  db743ab005b share_mode_lock: DEBUG/ASSERT recursion deadlock 
detection
       via  1052314dcd0 s3:adouble: rewrite ad_open_rsrc() as 
adouble_open_rsrc_fsp() using create_internal_fsp()
      from  ff16c74ee2b WHATSNEW: Start release notes for Samba 4.15.0pre1.

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


- Log -----------------------------------------------------------------
commit 480516e3b850035d188b8dab8490c63e0a7afe80
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Dec 8 16:29:10 2020 +0100

    vfs_fruit: make use of adouble_open_from_base_fsp(ADOUBLE_RSRC) in 
fruit_open_rsrc_adouble()
    
    The key is that we return a fake_fd to the caller and only open
    the '._' file in the background.
    
    The next vfs backend should only see the fsp from
    adouble_open_from_base_fsp, while the vfs backends above
    should only see the fake_fd.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Ralph Boehme <s...@samba.org>
    
    Autobuild-User(master): Ralph Böhme <s...@samba.org>
    Autobuild-Date(master): Thu Jan 21 14:47:53 UTC 2021 on sn-devel-184

commit 0b8c6e736afbec7ea1f69219c54a33031db3b8d9
Author: Stefan Metzmacher <me...@samba.org>
Date:   Thu Dec 10 13:11:06 2020 +0100

    vfs_fruit: add fruit_get_complete_fio() helper
    
    This will make it easier to hide some fsp extension later.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Ralph Boehme <s...@samba.org>

commit 94799dc8e61126f0bdd566e0d054424aebd9d477
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Dec 30 13:49:37 2020 +0100

    vfs_fruit: let fruit_open_rsrc_adouble() return errno = EISDIR
    
    That hopefully makes the check that ':AFP_Resource' can't
    be created on directories.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Ralph Boehme <s...@samba.org>

commit d62c670c3dd33eafc515ee92be177d1ddcb7b0a9
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Dec 23 11:58:08 2020 +0100

    s3:adouble: add adouble_open_from_base_fsp()
    
    For now we only support ADOUBLE_RSRC, but that might change in future.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Ralph Boehme <s...@samba.org>

commit c45a8d753d3a415d2a8038d1327276ecb972b036
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Dec 23 11:58:08 2020 +0100

    s3:adouble: allow ad_fget/ad_get_internal to be used with a backend fsp
    
    Up to now we only passed in stream fsp, but that will change shortly.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Ralph Boehme <s...@samba.org>

commit db743ab005bc7671d4fb0f5bea895c1097b707c5
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Dec 23 11:59:05 2020 +0100

    share_mode_lock: DEBUG/ASSERT recursion deadlock detection
    
    This situation should never happen!
    
    The known trigger is fixed with the change to adouble_open_rsrc_fsp()
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Ralph Boehme <s...@samba.org>

commit 1052314dcd05738f29d1ae85a5a4b8eaa4babe3d
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Dec 23 11:58:08 2020 +0100

    s3:adouble: rewrite ad_open_rsrc() as adouble_open_rsrc_fsp() using 
create_internal_fsp()
    
    "._" AppleDouble files are hidden by vfs_fruit by default, so there's no
    need to go through a full SMB_VFS_CREATE_FILE() for them.
    
    They don't need an smbXsrv_open_global.tdb entry nor a locking.tdb
    entry, so we just open them with fd_openat().
    
    This avoids a recursion deadlock in get_share_mode_lock() when closing
    the ':AFP_Resource' stream.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Ralph Boehme <s...@samba.org>

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

Summary of changes:
 source3/lib/adouble.c             | 146 ++++++++++++--------
 source3/lib/adouble.h             |   6 +
 source3/locking/share_mode_lock.c |  21 ++-
 source3/modules/vfs_fruit.c       | 284 ++++++++++++++++++++++++++------------
 4 files changed, 314 insertions(+), 143 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/lib/adouble.c b/source3/lib/adouble.c
index dffc0d5b7be..e869965876d 100644
--- a/source3/lib/adouble.c
+++ b/source3/lib/adouble.c
@@ -2091,71 +2091,95 @@ exit:
        return ealen;
 }
 
-static int ad_open_rsrc(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
-                       int flags,
-                       mode_t mode,
-                       files_struct **_fsp)
+static NTSTATUS adouble_open_rsrc_fsp(const struct files_struct *dirfsp,
+                                     const struct smb_filename *smb_base_fname,
+                                     int in_flags,
+                                     mode_t mode,
+                                     struct files_struct **_ad_fsp)
 {
-       int ret;
+       int rc = 0;
+       struct adouble *ad = NULL;
        struct smb_filename *adp_smb_fname = NULL;
-       files_struct *fsp = NULL;
-       uint32_t access_mask;
-       uint32_t share_access;
-       uint32_t create_disposition;
+       struct files_struct *ad_fsp = NULL;
        NTSTATUS status;
+       int flags = in_flags;
 
-       ret = adouble_path(talloc_tos(), smb_fname, &adp_smb_fname);
-       if (ret != 0) {
-               return -1;
+       rc = adouble_path(talloc_tos(),
+                         smb_base_fname,
+                         &adp_smb_fname);
+       if (rc != 0) {
+               return NT_STATUS_NO_MEMORY;
        }
 
-       ret = SMB_VFS_STAT(handle->conn, adp_smb_fname);
-       if (ret != 0) {
-               TALLOC_FREE(adp_smb_fname);
-               return -1;
+       status = create_internal_fsp(dirfsp->conn,
+                                    adp_smb_fname,
+                                    &ad_fsp);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
-       access_mask = FILE_GENERIC_READ;
-       share_access = FILE_SHARE_READ | FILE_SHARE_WRITE;
-       create_disposition = FILE_OPEN;
-
-       if (flags & O_RDWR) {
-               access_mask |= FILE_GENERIC_WRITE;
-               share_access &= ~FILE_SHARE_WRITE;
+#ifdef O_PATH
+       flags &= ~(O_PATH);
+#endif
+       if (flags & (O_CREAT | O_TRUNC | O_WRONLY)) {
+               /* We always need read/write access for the metadata header too 
*/
+               flags &= ~(O_WRONLY);
+               flags |= O_RDWR;
        }
 
-       status = openat_pathref_fsp(handle->conn->cwd_fsp, adp_smb_fname);
+       status = fd_openat(dirfsp,
+                          adp_smb_fname,
+                          ad_fsp,
+                          flags,
+                          mode);
        if (!NT_STATUS_IS_OK(status)) {
-               return -1;
+               file_free(NULL, ad_fsp);
+               return status;
        }
 
-       status = SMB_VFS_CREATE_FILE(
-               handle->conn,                   /* conn */
-               NULL,                           /* req */
-               adp_smb_fname,
-               access_mask,
-               share_access,
-               create_disposition,
-               0,                              /* create_options */
-               0,                              /* file_attributes */
-               INTERNAL_OPEN_ONLY,             /* oplock_request */
-               NULL,                           /* lease */
-               0,                              /* allocation_size */
-               0,                              /* private_flags */
-               NULL,                           /* sd */
-               NULL,                           /* ea_list */
-               &fsp,
-               NULL,                           /* psbuf */
-               NULL, NULL);                    /* create context */
-       TALLOC_FREE(adp_smb_fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               DBG_ERR("SMB_VFS_CREATE_FILE failed\n");
-               return -1;
+       if (flags & (O_CREAT | O_TRUNC)) {
+               ad = ad_init(talloc_tos(), ADOUBLE_RSRC);
+               if (ad == NULL) {
+                       file_free(NULL, ad_fsp);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               rc = ad_fset(ad_fsp->conn->vfs_handles, ad, ad_fsp);
+               if (rc != 0) {
+                       file_free(NULL, ad_fsp);
+                       return NT_STATUS_IO_DEVICE_ERROR;
+               }
+               TALLOC_FREE(ad);
        }
 
-       *_fsp = fsp;
-       return 0;
+       *_ad_fsp = ad_fsp;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS adouble_open_from_base_fsp(const struct files_struct *dirfsp,
+                                   struct files_struct *base_fsp,
+                                   adouble_type_t type,
+                                   int flags,
+                                   mode_t mode,
+                                   struct files_struct **_ad_fsp)
+{
+       *_ad_fsp = NULL;
+
+       SMB_ASSERT(base_fsp != NULL);
+       SMB_ASSERT(base_fsp->base_fsp == NULL);
+
+       switch (type) {
+       case ADOUBLE_META:
+               return NT_STATUS_INTERNAL_ERROR;
+       case ADOUBLE_RSRC:
+               return adouble_open_rsrc_fsp(dirfsp,
+                                            base_fsp->fsp_name,
+                                            flags,
+                                            mode,
+                                            _ad_fsp);
+       }
+
+       return NT_STATUS_INTERNAL_ERROR;
 }
 
 /*
@@ -2170,7 +2194,7 @@ static int ad_open(vfs_handle_struct *handle,
                   int flags,
                   mode_t mode)
 {
-       int ret;
+       NTSTATUS status;
 
        DBG_DEBUG("Path [%s] type [%s]\n", smb_fname->base_name,
                  ad->ad_type == ADOUBLE_META ? "meta" : "rsrc");
@@ -2185,8 +2209,13 @@ static int ad_open(vfs_handle_struct *handle,
                return 0;
        }
 
-       ret = ad_open_rsrc(handle, smb_fname, flags, mode, &ad->ad_fsp);
-       if (ret != 0) {
+       status = adouble_open_rsrc_fsp(handle->conn->cwd_fsp,
+                                      smb_fname,
+                                      flags,
+                                      mode,
+                                      &ad->ad_fsp);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
                return -1;
        }
        ad->ad_opened = true;
@@ -2291,11 +2320,14 @@ static int adouble_destructor(struct adouble *ad)
 
        SMB_ASSERT(ad->ad_fsp != NULL);
 
-       status = close_file(NULL, ad->ad_fsp, NORMAL_CLOSE);
+       status = fd_close(ad->ad_fsp);
        if (!NT_STATUS_IS_OK(status)) {
                DBG_ERR("Closing [%s] failed: %s\n",
                        fsp_str_dbg(ad->ad_fsp), nt_errstr(status));
        }
+       file_free(NULL, ad->ad_fsp);
+       ad->ad_fsp = NULL;
+       ad->ad_opened = false;
 
        return 0;
 }
@@ -2434,7 +2466,11 @@ static struct adouble *ad_get_internal(TALLOC_CTX *ctx,
        int mode;
 
        if (fsp != NULL) {
-               smb_fname = fsp->base_fsp->fsp_name;
+               if (fsp->base_fsp != NULL) {
+                       smb_fname = fsp->base_fsp->fsp_name;
+               } else {
+                       smb_fname = fsp->fsp_name;
+               }
        }
 
        DEBUG(10, ("ad_get(%s) called for %s\n",
diff --git a/source3/lib/adouble.h b/source3/lib/adouble.h
index 90a825c502e..a5761281670 100644
--- a/source3/lib/adouble.h
+++ b/source3/lib/adouble.h
@@ -164,6 +164,12 @@ bool ad_unconvert(TALLOC_CTX *mem_ctx,
                  struct smb_filename *smb_fname,
                  bool *converted);
 struct adouble *ad_init(TALLOC_CTX *ctx, adouble_type_t type);
+NTSTATUS adouble_open_from_base_fsp(const struct files_struct *dirfsp,
+                                   struct files_struct *base_fsp,
+                                   adouble_type_t type,
+                                   int flags,
+                                   mode_t mode,
+                                   struct files_struct **_ad_fsp);
 struct adouble *ad_get(TALLOC_CTX *ctx,
                       vfs_handle_struct *handle,
                       const struct smb_filename *smb_fname,
diff --git a/source3/locking/share_mode_lock.c 
b/source3/locking/share_mode_lock.c
index 80c04fdeda0..e8bb3e58e1f 100644
--- a/source3/locking/share_mode_lock.c
+++ b/source3/locking/share_mode_lock.c
@@ -880,8 +880,15 @@ struct share_mode_lock *get_share_mode_lock(
 
        if (static_share_mode_data != NULL) {
                if (!file_id_equal(&static_share_mode_data->id, &id)) {
-                       DEBUG(1, ("Can not lock two share modes "
-                                 "simultaneously\n"));
+                       struct file_id_buf existing;
+                       struct file_id_buf requested;
+
+                       DBG_ERR("Can not lock two share modes "
+                               "simultaneously: existing %s requested %s\n",
+                               file_id_str_buf(static_share_mode_data->id, 
&existing),
+                               file_id_str_buf(id, &requested));
+
+                       smb_panic(__location__);
                        goto fail;
                }
                goto done;
@@ -904,6 +911,7 @@ struct share_mode_lock *get_share_mode_lock(
        cmp = tdb_data_cmp(share_mode_lock_key, key);
        if (cmp != 0) {
                DBG_WARNING("Can not lock two share modes simultaneously\n");
+               smb_panic(__location__);
                goto fail;
        }
 
@@ -929,6 +937,15 @@ done:
 
        talloc_set_destructor(lck, share_mode_lock_destructor);
 
+       if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
+               struct file_id_buf returned;
+
+               DBG_DEBUG("Returning %s (data_refcount=%zu key_refcount=%zu)\n",
+                         file_id_str_buf(id, &returned),
+                         static_share_mode_data_refcount,
+                         share_mode_lock_key_refcount);
+       }
+
        return lck;
 fail:
        TALLOC_FREE(lck);
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index b25aebfa9ac..f5b5f91a012 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -172,9 +172,17 @@ static const struct enum_list fruit_encoding[] = {
 };
 
 struct fio {
+       vfs_handle_struct *handle;
+       files_struct *fsp; /* backlink to itself */
+
        /* tcon config handle */
        struct fruit_config_data *config;
 
+       /* Backend fsp for AppleDouble file, can be NULL */
+       files_struct *ad_fsp;
+       /* link from adouble_open_from_base_fsp() to fio */
+       struct fio *real_fio;
+
        /* Denote stream type, meta or rsrc */
        adouble_type_t type;
 
@@ -194,6 +202,27 @@ struct fio {
  * Helper functions
  *****************************************************************************/
 
+static struct fio *fruit_get_complete_fio(vfs_handle_struct *handle,
+                                         files_struct *fsp)
+{
+       struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+
+       if (fio == NULL) {
+               return NULL;
+       }
+
+       if (fio->real_fio != NULL) {
+               /*
+                * This is an fsp from adouble_open_from_base_fsp()
+                * we should just pass this to the next
+                * module.
+                */
+               return NULL;
+       }
+
+       return fio;
+}
+
 /**
  * Initialize config struct from our smb.conf config parameters
  **/
@@ -1313,6 +1342,32 @@ static int fruit_connect(vfs_handle_struct *handle,
        return rc;
 }
 
+static void fio_ref_destroy_fn(void *p_data)
+{
+       struct fio *ref_fio = (struct fio *)p_data;
+       if (ref_fio->real_fio != NULL) {
+               SMB_ASSERT(ref_fio->real_fio->ad_fsp == ref_fio->fsp);
+               ref_fio->real_fio->ad_fsp = NULL;
+               ref_fio->real_fio = NULL;
+       }
+}
+
+static void fio_close_ad_fsp(struct fio *fio)
+{
+       if (fio->ad_fsp != NULL) {
+               fd_close(fio->ad_fsp);
+               file_free(NULL, fio->ad_fsp);
+               /* fio_ref_destroy_fn() should have cleared this */
+               SMB_ASSERT(fio->ad_fsp == NULL);
+       }
+}
+
+static void fio_destroy_fn(void *p_data)
+{
+       struct fio *fio = (struct fio *)p_data;
+       fio_close_ad_fsp(fio);
+}
+
 static int fruit_open_meta_stream(vfs_handle_struct *handle,
                                  const struct files_struct *dirfsp,
                                  const struct smb_filename *smb_fname,
@@ -1330,7 +1385,9 @@ static int fruit_open_meta_stream(vfs_handle_struct 
*handle,
        SMB_VFS_HANDLE_GET_DATA(handle, config,
                                struct fruit_config_data, return -1);
 
-       fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL);
+       fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, fio_destroy_fn);
+       fio->handle = handle;
+       fio->fsp = fsp;
        fio->type = ADOUBLE_META;
        fio->config = config;
 
@@ -1397,7 +1454,9 @@ static int fruit_open_meta_netatalk(vfs_handle_struct 
*handle,
        SMB_VFS_HANDLE_GET_DATA(handle, config,
                                struct fruit_config_data, return -1);
 
-       fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL);
+       fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, fio_destroy_fn);
+       fio->handle = handle;
+       fio->fsp = fsp;
        fio->type = ADOUBLE_META;
        fio->config = config;
        fio->fake_fd = true;
@@ -1449,10 +1508,12 @@ static int fruit_open_rsrc_adouble(vfs_handle_struct 
*handle,
                                   mode_t mode)
 {
        int rc = 0;
-       struct adouble *ad = NULL;
-       struct smb_filename *smb_fname_base = NULL;
        struct fruit_config_data *config = NULL;
-       int hostfd = -1;
+       struct files_struct *ad_fsp = NULL;
+       struct fio *fio = NULL;
+       struct fio *ref_fio = NULL;
+       NTSTATUS status;
+       int fd = -1;
 
        SMB_VFS_HANDLE_GET_DATA(handle, config,
                                struct fruit_config_data, return -1);
@@ -1461,68 +1522,82 @@ static int fruit_open_rsrc_adouble(vfs_handle_struct 
*handle,
            S_ISDIR(fsp->base_fsp->fsp_name->st.st_ex_mode))
        {
                /* sorry, but directories don't habe a resource fork */
+               errno = EISDIR;
                rc = -1;
                goto exit;
        }
 
-       rc = adouble_path(talloc_tos(), smb_fname, &smb_fname_base);
-       if (rc != 0) {
+       /*
+        * We return a fake_fd to the vfs modules above,
+        * while we open an internal backend fsp for the
+        * '._' file for the next vfs modules.
+        *
+        * Note that adouble_open_from_base_fsp() recurses
+        * into fruit_openat(), but it'll just pass to
+        * the next module as just opens a flat file on
+        * disk.
+        */
+
+       fd = vfs_fake_fd();
+       if (fd == -1) {
+               rc = fd;
                goto exit;
        }
 
-       /* We always need read/write access for the metadata header too */
-       flags &= ~(O_RDONLY | O_WRONLY);
-       flags |= O_RDWR;
-
-       hostfd = SMB_VFS_NEXT_OPENAT(handle,
-                                    dirfsp,
-                                    smb_fname_base,
-                                    fsp,
-                                    flags,
-                                    mode);
-       if (hostfd == -1) {
+       status = adouble_open_from_base_fsp(dirfsp,
+                                           fsp->base_fsp,
+                                           ADOUBLE_RSRC,
+                                           flags,
+                                           mode,
+                                           &ad_fsp);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
                rc = -1;
                goto exit;
        }
 
-       if (flags & (O_CREAT | O_TRUNC)) {
-               ad = ad_init(fsp, ADOUBLE_RSRC);
-               if (ad == NULL) {
-                       rc = -1;
-                       goto exit;
-               }
-
-               fsp_set_fd(fsp, hostfd);
+       /*
+        * Now we need to glue both handles together,
+        * so that they automatically detach each other
+        * on close.
+        */
+       fio = fruit_get_complete_fio(handle, fsp);
 
-               rc = ad_fset(handle, ad, fsp);
-               fsp_set_fd(fsp, -1);
-               if (rc != 0) {
-                       rc = -1;
-                       goto exit;
-               }
-               TALLOC_FREE(ad);
+       ref_fio = VFS_ADD_FSP_EXTENSION(handle, ad_fsp,
+                                       struct fio,
+                                       fio_ref_destroy_fn);
+       if (ref_fio == NULL) {
+               int saved_errno = errno;
+               fd_close(ad_fsp);
+               file_free(NULL, ad_fsp);
+               ad_fsp = NULL;
+               errno = saved_errno;
+               rc = -1;
+               goto exit;
        }
 
-exit:
+       SMB_ASSERT(ref_fio->fsp == NULL);
+       ref_fio->handle = handle;
+       ref_fio->fsp = ad_fsp;
+       ref_fio->type = ADOUBLE_RSRC;
+       ref_fio->config = config;
+       ref_fio->real_fio = fio;
+       SMB_ASSERT(fio->ad_fsp == NULL);
+       fio->ad_fsp = ad_fsp;
+       fio->fake_fd = true;
 
-       TALLOC_FREE(smb_fname_base);
+exit:
 
-       DEBUG(10, ("fruit_open resource fork: rc=%d, fd=%d\n", rc, hostfd));
+       DEBUG(10, ("fruit_open resource fork: rc=%d\n", rc));
        if (rc != 0) {
                int saved_errno = errno;
-               if (hostfd >= 0) {
-                       /*
-                        * BUGBUGBUG -- we would need to call
-                        * fd_close_posix here, but we don't have a
-                        * full fsp yet
-                        */
-                       fsp_set_fd(fsp, hostfd);
-                       SMB_VFS_CLOSE(fsp);


-- 
Samba Shared Repository

Reply via email to