The branch, v4-22-test has been updated
via bf440caab97 vfs_ceph_new: Do not resolve by inode number
via d26177dcaeb vfs_ceph_new: Handle absolute path in vfs_ceph_ll_walk
via 8b38092890d vfs_ceph_new: Remove unused code in cephmount_mount_fs()
via 4e9eb916024 vfs_ceph_new: Remove redundant re-intialization to NULL
via 6ca80fb612b vfs_ceph_new: use libcephfs nonblocking API for
async-io ops
via f8f85cf8533 s3:utils: Remove call of ads_startup() from
net_ads_keytab_create()
via 83c60df6e8d s3:libads: Make sure that REALM is always added to
keytab principals
via 3849e7abe6d lib:krb5_wrap: Add smb_krb5_parse_name_flags()
from 0e864939620 VERSION: Bump version up to Samba 4.22.1...
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-22-test
- Log -----------------------------------------------------------------
commit bf440caab97778ae6ce312d4905585abe277884c
Author: Anoop C S <[email protected]>
Date: Tue Feb 25 17:40:13 2025 +0530
vfs_ceph_new: Do not resolve by inode number
CephFS snapshots within snap directory shares the same inode number from
its parent. Until unless we resolve by name we may incorrectly point at
an inode which is not a snapshot directory. Therefore to be functionally
correct we avoid resolving by inode number but proper name.
For example:
path (ino = 3)
|
--- dir (ino = 4)
|
--- .snap (ino = 3)
|
--- snap1 (ino = 3)
|
--- dir (ino = 4)
In this case an attempt to resolve 'snap1' by inode number 3 results in
pointing at 'path' which is not the desired outcome.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15818
Signed-off-by: Anoop C S <[email protected]>
Reviewed-by: Guenther Deschner <[email protected]>
Autobuild-User(master): Günther Deschner <[email protected]>
Autobuild-Date(master): Fri Mar 7 18:20:47 UTC 2025 on atb-devel-224
(cherry picked from commit a96f0542c8317a7dd0470b32350de6893fd98723)
Autobuild-User(v4-22-test): Jule Anger <[email protected]>
Autobuild-Date(v4-22-test): Thu Mar 13 17:06:25 UTC 2025 on atb-devel-224
commit d26177dcaeb757e01a480ebd7a7a9dd7528ddbad
Author: Anoop C S <[email protected]>
Date: Mon Feb 24 14:00:56 2025 +0530
vfs_ceph_new: Handle absolute path in vfs_ceph_ll_walk
It can very well be the case that the incoming path is absolute in
nature which breaks the assumption inside vfs_ceph_ll_walk that it
is within the current working directory. Instead perform a check to
see whether the path includes current working directory path in its
components and accordingly trim it to make it relative in nature.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15818
Signed-off-by: Anoop C S <[email protected]>
Reviewed-by: Guenther Deschner <[email protected]>
(cherry picked from commit 9341d7fb466c95ea5aa0643049ce2a1f4183b9d0)
commit 8b38092890dc18183ed3190e6731f4a21d341d9e
Author: Anoop C S <[email protected]>
Date: Mon Feb 24 12:09:06 2025 +0530
vfs_ceph_new: Remove unused code in cephmount_mount_fs()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15818
Signed-off-by: Anoop C S <[email protected]>
Reviewed-by: Guenther Deschner <[email protected]>
(cherry picked from commit ee1c3e1db9a2d12ba6d9dd24faccf0020b1daf0d)
commit 4e9eb916024a61fdebb3aedd10e972ac957cc8c1
Author: Anoop C S <[email protected]>
Date: Mon Feb 24 11:54:45 2025 +0530
vfs_ceph_new: Remove redundant re-intialization to NULL
TALLOC_FREE() by default re-initializes the pointer to NULL after
corresponding memory is freed.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15818
Signed-off-by: Anoop C S <[email protected]>
Reviewed-by: Guenther Deschner <[email protected]>
(cherry picked from commit c5ddd94a08503a52914ce351ebf1083178e8c8bc)
commit 6ca80fb612b461c21897ee5e868395da381276dc
Author: Shachar Sharon <[email protected]>
Date: Tue Oct 1 12:09:40 2024 +0300
vfs_ceph_new: use libcephfs nonblocking API for async-io ops
Use libcephfs non-blocking API (ceph_ll_nonblocking_readv_writev[1]) in
combination with smb VFS async hooks ({pread,pwrite,fsync}_send/_recv).
Fills libcephfs' struct ceph_ll_io_info with single iovec and
submit/complete the operation asynchronously on libcephfs side, with
corresponding tevent schedule-immediate upon completion on smbd side.
Control nonblocking/normal I/O mode via config parameter. The common
parts of async I/O (with/without HAVE_CEPH_ASYNCIO) are united.
Specifically, use same struct vfs_ceph_aio_state and common code via
helper function for all async I/O hooks. When HAVE_CEPH_ASYNCIO
is True _and_ config option 'asyncio = yes' use libcephfs asynchronous
I/O API. Otherwise, fake async operation using normal blocking APIs.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15810
[1]
https://github.com/ceph/ceph/commit/b4e39f3eccd6734f1ed13c700c136e3aef1777f8
Signed-off-by: Shachar Sharon <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
Reviewed-by: Guenther Deschner <[email protected]>
Autobuild-User(master): Günther Deschner <[email protected]>
Autobuild-Date(master): Tue Mar 4 16:53:21 UTC 2025 on atb-devel-224
(cherry picked from commit 4ae9224138449fe7b8dd1e8ce8141aedd014efc4)
commit f8f85cf8533824e0c3fae7e4cac363c692f249c5
Author: Pavel Filipenský <[email protected]>
Date: Thu Mar 6 15:24:05 2025 +0100
s3:utils: Remove call of ads_startup() from net_ads_keytab_create()
Calling ads_startup() is not needed in net_ads_keytab_create. Keytab
creation code in sync_pw2keytabs() decides if it needs to talk to DC or
not and connects to AD accordingly.
Fixing this, makes the bug below easier to reproduce using
'net ads keytab create'.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15727
Signed-off-by: Pavel Filipenský <[email protected]>
Reviewed-by: Andreas Schneider <[email protected]>
Autobuild-User(master): Pavel Filipensky <[email protected]>
Autobuild-Date(master): Mon Mar 10 11:09:29 UTC 2025 on atb-devel-224
(cherry picked from commit 5cadaf91bc96cd2a8e0f6bcbd8a212e86b714180)
commit 83c60df6e8dd604c4954e1b444b8d2332dbff62b
Author: Pavel Filipenský <[email protected]>
Date: Fri Mar 7 10:32:40 2025 +0100
s3:libads: Make sure that REALM is always added to keytab principals
The code responsible for adding SPNs to keytab should always set the
REALM part. Current code is not adding it for e.g. SPNs synced from AD.
If REALM is missing, krb5_parse_name() will succeed (and add the REALM)
only if the krb5.conf contains libdefaults section with
default_realm set and will fail otherwise. E.g.:
[libdefaults]
default_realm = SOMETESTDOMAIN1.MY.COM
When calling 'net ads join' we get the following error if SPN is missing
REALM and krb5.conf does not provide the default_realm:
pw2kt_process_add_info: Failed to parse principal:
RestrictedKrbHost/$MACHINE_NAME
Failed to join domain: failed to create kerberos keytab
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15727
Pair-Programmed-With: Noel Power <[email protected]>
Signed-off-by: Pavel Filipenský <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Alexander Bokovoy <[email protected]>
Autobuild-User(master): Pavel Filipensky <[email protected]>
Autobuild-Date(master): Sun Mar 9 00:25:08 UTC 2025 on atb-devel-224
(cherry picked from commit c72554260c950d0ef7652955a59f0f68a026f4f2)
commit 3849e7abe6d7b1724ae6ab285e25c22086525d3f
Author: Pavel Filipenský <[email protected]>
Date: Thu Mar 6 23:20:53 2025 +0100
lib:krb5_wrap: Add smb_krb5_parse_name_flags()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15727
Signed-off-by: Pavel Filipenský <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Alexander Bokovoy <[email protected]>
(cherry picked from commit cf34645050df64d6b8c4fa45394c3feebe691e79)
-----------------------------------------------------------------------
Summary of changes:
lib/krb5_wrap/krb5_samba.c | 39 ++-
lib/krb5_wrap/krb5_samba.h | 5 +
source3/libads/kerberos_keytab.c | 19 +-
source3/modules/vfs_ceph_new.c | 577 ++++++++++++++++++++++++++-------------
source3/utils/net_ads.c | 11 -
source3/wscript | 4 +
6 files changed, 451 insertions(+), 204 deletions(-)
Changeset truncated at 500 lines:
diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c
index 451616c79e5..0a4a7ea986f 100644
--- a/lib/krb5_wrap/krb5_samba.c
+++ b/lib/krb5_wrap/krb5_samba.c
@@ -836,6 +836,29 @@ krb5_error_code smb_krb5_get_allowed_etypes(krb5_context
context,
krb5_error_code smb_krb5_parse_name(krb5_context context,
const char *name,
krb5_principal *principal)
+{
+ return smb_krb5_parse_name_flags(context, name, 0, principal);
+}
+
+/**
+ * @brief Convert a string principal name to a Kerberos principal.
+ *
+ * @param[in] context The library context
+ *
+ * @param[in] name The principal as a unix charset string.
+ *
+ * @param[in] flags Flags for krb5_parse_name_flags()
+ *
+ * @param[out] principal The newly allocated principal.
+ *
+ * Use krb5_free_principal() to free a principal when it is no longer needed.
+ *
+ * @return 0 on success, a Kerberos error code otherwise.
+ */
+krb5_error_code smb_krb5_parse_name_flags(krb5_context context,
+ const char *name,
+ int flags,
+ krb5_principal *principal)
{
krb5_error_code ret;
char *utf8_name;
@@ -843,17 +866,19 @@ krb5_error_code smb_krb5_parse_name(krb5_context context,
TALLOC_CTX *frame = talloc_stackframe();
if (!push_utf8_talloc(frame, &utf8_name, name, &converted_size)) {
- talloc_free(frame);
+ TALLOC_FREE(frame);
return ENOMEM;
}
+ TALLOC_FREE(frame);
- ret = krb5_parse_name(context, utf8_name, principal);
- if (ret == KRB5_PARSE_MALFORMED) {
- ret = krb5_parse_name_flags(context, utf8_name,
- KRB5_PRINCIPAL_PARSE_ENTERPRISE,
- principal);
+ ret = krb5_parse_name_flags(context, utf8_name, flags, principal);
+ if (ret != KRB5_PARSE_MALFORMED) {
+ return ret;
}
- TALLOC_FREE(frame);
+
+ flags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE;
+ ret = krb5_parse_name_flags(context, utf8_name, flags, principal);
+
return ret;
}
diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h
index 173307f7c88..a562359e121 100644
--- a/lib/krb5_wrap/krb5_samba.h
+++ b/lib/krb5_wrap/krb5_samba.h
@@ -186,6 +186,11 @@ krb5_error_code smb_krb5_parse_name(krb5_context context,
const char *name, /* in unix charset */
krb5_principal *principal);
+krb5_error_code smb_krb5_parse_name_flags(krb5_context context,
+ const char *name, /* unix charset */
+ int flags,
+ krb5_principal *principal);
+
krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx,
krb5_context context,
krb5_const_principal principal,
diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
index 5913db299ad..49a892e5a55 100644
--- a/source3/libads/kerberos_keytab.c
+++ b/source3/libads/kerberos_keytab.c
@@ -364,12 +364,29 @@ static krb5_error_code pw2kt_process_add_info(struct
pw2kt_keytab_state *state2,
krb5_principal princ = NULL;
krb5_principal *a = NULL;
size_t len;
+ const char *realm = NULL;
- ret = smb_krb5_parse_name(state2->context, princs, &princ);
+ ret = smb_krb5_parse_name_flags(state2->context,
+ princs,
+ KRB5_PRINCIPAL_PARSE_NO_DEF_REALM,
+ &princ);
if (ret != 0) {
DBG_ERR("Failed to parse principal: %s\n", princs);
return ret;
}
+ /* Add realm part if missing (e.g. SPNs synced from DC) */
+ realm = smb_krb5_principal_get_realm(state2, state2->context, princ);
+ if (realm == NULL || *realm == 0) {
+ ret = smb_krb5_principal_set_realm(state2->context,
+ princ,
+ lp_realm());
+ if (ret != 0) {
+ DBG_ERR("Failed to add realm to principal: %s\n",
+ princs);
+ return ret;
+ }
+ }
+
len = talloc_array_length(state2->princ_array);
a = talloc_realloc(state2,
state2->princ_array,
diff --git a/source3/modules/vfs_ceph_new.c b/source3/modules/vfs_ceph_new.c
index cae8317b1c8..05c2a72d57f 100644
--- a/source3/modules/vfs_ceph_new.c
+++ b/source3/modules/vfs_ceph_new.c
@@ -102,6 +102,9 @@ static const struct enum_list enum_vfs_cephfs_proxy_vals[]
= {
#define CEPH_FN(_name) typeof(_name) *_name ## _fn
struct vfs_ceph_config {
+#if HAVE_CEPH_ASYNCIO
+ struct tevent_threaded_context *tctx;
+#endif
const char *conf_file;
const char *user_id;
const char *fsname;
@@ -110,7 +113,6 @@ struct vfs_ceph_config {
enum vfs_cephfs_proxy_mode proxy;
void *libhandle;
- CEPH_FN(ceph_ll_lookup_inode);
CEPH_FN(ceph_ll_walk);
CEPH_FN(ceph_ll_getattr);
CEPH_FN(ceph_ll_setattr);
@@ -157,6 +159,9 @@ struct vfs_ceph_config {
CEPH_FN(ceph_version);
CEPH_FN(ceph_rewinddir);
CEPH_FN(ceph_readdir_r);
+#if HAVE_CEPH_ASYNCIO
+ CEPH_FN(ceph_ll_nonblocking_readv_writev);
+#endif
};
/*
@@ -274,7 +279,6 @@ static struct ceph_mount_info *cephmount_mount_fs(
struct vfs_ceph_config *config)
{
int ret;
- char buf[256];
struct ceph_mount_info *mnt = NULL;
/* if config_file and/or user_id are NULL, ceph will use defaults */
@@ -294,12 +298,6 @@ static struct ceph_mount_info *cephmount_mount_fs(
goto out;
}
- DBG_DEBUG("[CEPH] calling ceph_conf_get: option='%s'\n", "log_file");
- ret = config->ceph_conf_get_fn(mnt, "log_file", buf, sizeof(buf));
- if (ret < 0) {
- goto out;
- }
-
/* libcephfs disables POSIX ACL support by default, enable it... */
ret = cephmount_update_conf(config,
mnt,
@@ -396,7 +394,6 @@ static bool vfs_cephfs_load_lib(struct vfs_ceph_config
*config)
break;
}
- CHECK_CEPH_FN(libhandle, ceph_ll_lookup_inode);
CHECK_CEPH_FN(libhandle, ceph_ll_walk);
CHECK_CEPH_FN(libhandle, ceph_ll_getattr);
CHECK_CEPH_FN(libhandle, ceph_ll_setattr);
@@ -443,6 +440,9 @@ static bool vfs_cephfs_load_lib(struct vfs_ceph_config
*config)
CHECK_CEPH_FN(libhandle, ceph_version);
CHECK_CEPH_FN(libhandle, ceph_rewinddir);
CHECK_CEPH_FN(libhandle, ceph_readdir_r);
+#if HAVE_CEPH_ASYNCIO
+ CHECK_CEPH_FN(libhandle, ceph_ll_nonblocking_readv_writev);
+#endif
config->libhandle = libhandle;
@@ -698,10 +698,7 @@ static struct dirent *vfs_ceph_get_fh_dirent(struct
vfs_ceph_fh *cfh)
static void vfs_ceph_put_fh_dirent(struct vfs_ceph_fh *cfh)
{
- if (cfh->de != NULL) {
- TALLOC_FREE(cfh->de);
- cfh->de = NULL;
- }
+ TALLOC_FREE(cfh->de);
}
static int vfs_ceph_release_fh(struct vfs_ceph_fh *cfh)
@@ -798,21 +795,6 @@ static void vfs_ceph_assign_fh_fd(struct vfs_ceph_fh *cfh)
/* Ceph low-level wrappers */
-static int vfs_ceph_ll_lookup_inode(const struct vfs_handle_struct *handle,
- uint64_t inoval,
- Inode **pout)
-{
- struct inodeno_t ino = {.val = inoval};
- struct vfs_ceph_config *config = NULL;
-
- SMB_VFS_HANDLE_GET_DATA(handle, config, struct vfs_ceph_config,
- return -ENOMEM);
-
- DBG_DEBUG("[CEPH] ceph_ll_lookup_inode: ino=%" PRIu64 "\n", inoval);
-
- return config->ceph_ll_lookup_inode_fn(config->mount, ino, pout);
-}
-
static int vfs_ceph_ll_walk(const struct vfs_handle_struct *handle,
const char *name,
struct Inode **pin,
@@ -823,10 +805,31 @@ static int vfs_ceph_ll_walk(const struct
vfs_handle_struct *handle,
struct UserPerm *uperm = NULL;
int ret = -1;
struct vfs_ceph_config *config = NULL;
+ const char *cwd = NULL;
+ size_t cwdlen;
SMB_VFS_HANDLE_GET_DATA(handle, config, struct vfs_ceph_config,
return -ENOMEM);
+ cwd = config->ceph_getcwd_fn(config->mount);
+ cwdlen = strlen(cwd);
+
+ /*
+ * ceph_ll_walk() always operate on "name" relative to current working
+ * directory even if it starts with a '/' i.e, absolute path is never
+ * honoured. But why?? For now stick to the current behaviour and ensure
+ * that the "name" is always relative when it contains current working
+ * directory path with an exception to "/".
+ */
+ if ((strcmp(cwd, "/") != 0) &&
+ (strncmp(name, cwd, cwdlen) == 0)) {
+ if (name[cwdlen] == '/') {
+ name += cwdlen + 1;
+ } else if (name[cwdlen] == '\0') {
+ name = ".";
+ }
+ }
+
DBG_DEBUG("[CEPH] ceph_ll_walk: name=%s\n", name);
uperm = vfs_ceph_userperm_new(config, handle->conn);
@@ -1795,76 +1798,56 @@ static int vfs_ceph_ll_fremovexattr(const struct
vfs_handle_struct *handle,
cfh->uperm);
}
+#if HAVE_CEPH_ASYNCIO
+static int64_t vfs_ceph_ll_nonblocking_readv_writev(
+ const struct vfs_handle_struct *handle,
+ const struct vfs_ceph_fh *cfh,
+ struct ceph_ll_io_info *io_info)
+{
+ struct vfs_ceph_config *config = NULL;
+
+ SMB_VFS_HANDLE_GET_DATA(handle,
+ config,
+ struct vfs_ceph_config,
+ return -EINVAL);
+
+ DBG_DEBUG("[CEPH] ceph_ll_nonblocking_readv_writev: ino=%" PRIu64
+ " fd=%d off=%jd\n",
+ cfh->iref.ino,
+ cfh->fd,
+ io_info->off);
+
+ return config->ceph_ll_nonblocking_readv_writev_fn(config->mount,
+ io_info);
+}
+#endif
+
/* Ceph Inode-refernce get/put wrappers */
static int vfs_ceph_iget(const struct vfs_handle_struct *handle,
- uint64_t ino,
const char *name,
unsigned int flags,
struct vfs_ceph_iref *iref)
{
struct Inode *inode = NULL;
int ret = -1;
+ struct ceph_statx stx = {.stx_ino = 0};
- if (ino > CEPH_INO_ROOT) {
- /* get-by-ino */
- ret = vfs_ceph_ll_lookup_inode(handle, ino, &inode);
- if (ret != 0) {
- return ret;
- }
- } else {
- /* get-by-path */
- struct ceph_statx stx = {.stx_ino = 0};
-
- ret = vfs_ceph_ll_walk(handle,
- name,
- &inode,
- &stx,
- CEPH_STATX_INO,
- flags);
- if (ret != 0) {
- return ret;
- }
- ino = stx.stx_ino;
+ ret = vfs_ceph_ll_walk(handle,
+ name,
+ &inode,
+ &stx,
+ CEPH_STATX_INO,
+ flags);
+ if (ret != 0) {
+ return ret;
}
iref->inode = inode;
- iref->ino = ino;
+ iref->ino = stx.stx_ino;
iref->owner = true;
DBG_DEBUG("[CEPH] iget: %s ino=%" PRIu64 "\n", name, iref->ino);
return 0;
}
-static int vfs_ceph_iget_by_fname(const struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- struct vfs_ceph_iref *iref)
-{
- const char *name = smb_fname->base_name;
- const char *cwd = NULL;
- int ret = -1;
- struct vfs_ceph_config *config = NULL;
-
- SMB_VFS_HANDLE_GET_DATA(handle, config, struct vfs_ceph_config,
- return -ENOMEM);
-
- cwd = config->ceph_getcwd_fn(config->mount);
- if (!strcmp(name, cwd)) {
- ret = vfs_ceph_iget(handle, 0, "./", 0, iref);
- } else {
- ret = vfs_ceph_iget(handle, 0, name, 0, iref);
- }
- return ret;
-}
-
-static int vfs_ceph_igetl(const struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- struct vfs_ceph_iref *iref)
-{
- return vfs_ceph_iget(handle,
- 0,
- smb_fname->base_name,
- AT_SYMLINK_NOFOLLOW,
- iref);
-}
-
static int vfs_ceph_igetd(struct vfs_handle_struct *handle,
const struct files_struct *dirfsp,
struct vfs_ceph_iref *iref)
@@ -1883,25 +1866,16 @@ static int vfs_ceph_igetd(struct vfs_handle_struct
*handle,
/* case-2: resolve by current work-dir */
if (fsp_get_pathref_fd(dirfsp) == AT_FDCWD) {
- return vfs_ceph_iget(handle, 0, ".", 0, iref);
+ return vfs_ceph_iget(handle, ".", 0, iref);
}
/* case-3: resolve by parent dir and name */
return vfs_ceph_iget(handle,
- dirfsp->file_id.inode,
dirfsp->fsp_name->base_name,
AT_SYMLINK_NOFOLLOW,
iref);
}
-static int vfs_ceph_igetf(struct vfs_handle_struct *handle,
- const struct files_struct *fsp,
- struct vfs_ceph_iref *iref)
-{
- return vfs_ceph_iget(
- handle, fsp->file_id.inode, fsp->fsp_name->base_name, 0, iref);
-}
-
static void vfs_ceph_iput(const struct vfs_handle_struct *handle,
struct vfs_ceph_iref *iref)
{
@@ -1966,7 +1940,7 @@ static int vfs_ceph_statvfs(struct vfs_handle_struct
*handle,
struct vfs_ceph_iref iref = {0};
int ret;
- ret = vfs_ceph_iget_by_fname(handle, smb_fname, &iref);
+ ret = vfs_ceph_iget(handle, smb_fname->base_name, 0, &iref);
if (ret != 0) {
goto out;
}
@@ -2272,17 +2246,28 @@ out:
}
struct vfs_ceph_aio_state {
+ struct vfs_ceph_config *config;
+ struct vfs_ceph_fh *cfh;
+#if HAVE_CEPH_ASYNCIO
+ struct tevent_req *req;
+ bool orphaned;
+ struct tevent_immediate *im;
+ void *data;
+ size_t len;
+ off_t off;
+ bool write;
+ bool fsync;
+
+ struct ceph_ll_io_info io_info;
+ struct iovec iov;
+#endif
struct timespec start_time;
struct timespec finish_time;
+ ssize_t result;
struct vfs_aio_state vfs_aio_state;
SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
};
-struct vfs_ceph_pread_state {
- ssize_t bytes_read;
- struct vfs_ceph_aio_state ceph_aio_state;
-};
-
static void vfs_ceph_aio_start(struct vfs_ceph_aio_state *state)
{
SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
@@ -2298,22 +2283,218 @@ static void vfs_ceph_aio_finish(struct
vfs_ceph_aio_state *state,
if (result < 0) {
state->vfs_aio_state.error = (int)result;
}
+
+ state->result = result;
SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
}
-/*
- * Fake up an async ceph read by calling the synchronous API.
- */
+#if HAVE_CEPH_ASYNCIO
+
+static void vfs_ceph_aio_done(struct tevent_context *ev,
+ struct tevent_immediate *im,
+ void *private_data);
+
+static int vfs_ceph_require_tctx(struct vfs_ceph_aio_state *state,
+ struct tevent_context *ev)
+{
+ struct vfs_ceph_config *config = state->config;
+
+ if (config->tctx != NULL) {
+ return 0;
+ }
+
+ config->tctx = tevent_threaded_context_create(config, ev);
+ if (config->tctx == NULL) {
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void vfs_ceph_aio_complete(struct ceph_ll_io_info *io_info)
+{
+ struct vfs_ceph_aio_state *state = io_info->priv;
+
+ if (state->orphaned) {
+ return;
+ }
+
+ DBG_DEBUG("[CEPH] aio_complete: ino=%" PRIu64
+ " fd=%d off=%jd len=%ju result=%jd\n",
+ state->cfh->iref.ino,
+ state->cfh->fd,
+ state->off,
+ state->len,
+ state->io_info.result);
+
+ tevent_threaded_schedule_immediate(state->config->tctx,
+ state->im,
+ vfs_ceph_aio_done,
+ state->req);
+}
+
+static void vfs_ceph_aio_cleanup(struct tevent_req *req,
+ enum tevent_req_state req_state)
+{
+ struct vfs_ceph_aio_state *state = tevent_req_data(
+ req, struct vfs_ceph_aio_state);
+
+ if (req_state == TEVENT_REQ_IN_PROGRESS) {
+ /*
+ * The job thread is still running, we need to protect the
+ * memory used by the job completion function.
+ */
+ (void)talloc_reparent(req, NULL, state);
+ state->orphaned = true;
--
Samba Shared Repository