struct aio_open_private_data *prev, *next;
/* Inputs. */
int dir_fd;
+ bool opened_dir_fd;
int flags;
mode_t mode;
uint64_t mid;
bool in_progress;
- struct smb_filename *dname;
- struct smb_filename *fname;
+ struct smb_filename *fsp_name;
+ struct smb_filename *smb_fname;
connection_struct *conn;
struct smbXsrv_connection *xconn;
const struct security_unix_token *ux_tok;
* to the NULL context, so just free it so we
* don't leak memory.
*/
- DBG_NOTICE("aio open request for %s/%s abandoned in flight\n",
- opd->dname->base_name,
- opd->fname->base_name);
+ DBG_NOTICE("aio open request for %s abandoned in flight\n",
+ opd->fsp_name->base_name);
if (opd->ret_fd != -1) {
close(opd->ret_fd);
opd->ret_fd = -1;
}
DEBUG(10,("aio_open_handle_completion: mid %llu "
- "for file %s/%s completed\n",
+ "for file %s completed\n",
(unsigned long long)opd->mid,
- opd->dname->base_name,
- opd->fname->base_name));
+ opd->fsp_name->base_name));
opd->in_progress = false;
static void aio_open_do(struct aio_open_private_data *opd)
{
opd->ret_fd = openat(opd->dir_fd,
- opd->fname->base_name,
+ opd->smb_fname->base_name,
opd->flags,
opd->mode);
static void opd_free(struct aio_open_private_data *opd)
{
- if (opd->dir_fd != -1) {
+ if (opd->opened_dir_fd && opd->dir_fd != -1) {
close(opd->dir_fd);
}
DLIST_REMOVE(open_pd_list, opd);
Create and initialize a private data struct for async open.
***********************************************************************/
-static struct aio_open_private_data *create_private_open_data(TALLOC_CTX *ctx,
- const files_struct *fsp,
- int flags,
- mode_t mode)
+static struct aio_open_private_data *create_private_open_data(
+ TALLOC_CTX *ctx,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ const files_struct *fsp,
+ int flags,
+ mode_t mode)
{
struct aio_open_private_data *opd = talloc_zero(ctx,
struct aio_open_private_data);
- bool ok;
if (!opd) {
return NULL;
}
/*
- * Copy the parent directory name and the
- * relative path within it.
+ * Copy the full fsp_name and smb_fname which is the basename.
*/
- ok = parent_smb_fname(opd,
- fsp->fsp_name,
- &opd->dname,
- &opd->fname);
- if (!ok) {
+ opd->smb_fname = cp_smb_filename(opd, smb_fname);
+ if (opd->smb_fname == NULL) {
opd_free(opd);
return NULL;
}
+ opd->fsp_name = cp_smb_filename(opd, fsp->fsp_name);
+ if (opd->fsp_name == NULL) {
+ opd_free(opd);
+ return NULL;
+ }
+
+ if (fsp_get_pathref_fd(dirfsp) != AT_FDCWD) {
+ opd->dir_fd = fsp_get_pathref_fd(dirfsp);
+ } else {
#if defined(O_DIRECTORY)
- opd->dir_fd = open(opd->dname->base_name, O_RDONLY|O_DIRECTORY);
+ opd->dir_fd = open(".", O_RDONLY|O_DIRECTORY);
#else
- opd->dir_fd = open(opd->dname->base_name, O_RDONLY);
+ opd->dir_fd = open(".", O_RDONLY);
#endif
+ opd->opened_dir_fd = true;
+ }
if (opd->dir_fd == -1) {
opd_free(opd);
return NULL;
* down which kills the fsp that owns
* opd.
*/
- DBG_NOTICE("aio open request for %s/%s cancelled\n",
- opd->dname->base_name,
- opd->fname->base_name);
+ DBG_NOTICE("aio open request for %s cancelled\n",
+ opd->fsp_name->base_name);
opd->conn = NULL;
/* Don't let opd go away. */
return -1;
Setup an async open.
*****************************************************************/
-static int open_async(const struct smb_filename *smb_fname,
+static int open_async(const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
const files_struct *fsp,
int flags,
mode_t mode)
* opd is always safely freed in all codepath so no
* memory leaks.
*/
- opd = create_private_open_data(fsp->conn, fsp, flags, mode);
+ opd = create_private_open_data(fsp->conn,
+ dirfsp,
+ smb_fname,
+ fsp,
+ flags,
+ mode);
if (opd == NULL) {
DEBUG(10, ("open_async: Could not create private data.\n"));
return -1;
}
tevent_req_set_callback(subreq, aio_open_handle_completion, opd);
- DEBUG(5,("open_async: mid %llu created for file %s/%s\n",
+ DEBUG(5,("open_async: mid %llu created for file %s\n",
(unsigned long long)opd->mid,
- opd->dname->base_name,
- opd->fname->base_name));
+ opd->fsp_name->base_name));
/*
* Add a destructor to protect us from connection
if (opd->in_progress) {
DEBUG(0,("find_completed_open: mid %llu "
"still in progress for "
- "file %s/%s. PANIC !\n",
+ "file %s. PANIC !\n",
(unsigned long long)opd->mid,
- opd->dname->base_name,
- opd->fname->base_name));
+ opd->fsp_name->base_name));
/* Disaster ! This is an open timeout. Just panic. */
smb_panic("find_completed_open - in_progress\n");
/* notreached. */
opens to prevent any race conditions.
*****************************************************************/
-static int aio_pthread_open_fn(vfs_handle_struct *handle,
- struct smb_filename *smb_fname,
- files_struct *fsp,
- int flags,
- mode_t mode)
+static int aio_pthread_openat_fn(vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ struct files_struct *fsp,
+ const struct vfs_open_how *how)
{
int my_errno = 0;
int fd = -1;
bool aio_allow_open = lp_parm_bool(
SNUM(handle->conn), "aio_pthread", "aio open", false);
- if (smb_fname->stream_name) {
+ if (how->resolve != 0) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (is_named_stream(smb_fname)) {
/* Don't handle stream opens. */
errno = ENOENT;
return -1;
}
- if (!aio_allow_open) {
- /* aio opens turned off. */
- return open(smb_fname->base_name, flags, mode);
+ if (fsp->conn->sconn->pool == NULL) {
+ /*
+ * a threadpool is required for async support
+ */
+ aio_allow_open = false;
+ }
+
+ if (fsp->conn->sconn->client != NULL &&
+ fsp->conn->sconn->client->server_multi_channel_enabled) {
+ /*
+ * This module is not compatible with multi channel yet.
+ */
+ aio_allow_open = false;
}
- if (!(flags & O_CREAT)) {
+ if (fsp->fsp_flags.is_pathref) {
+ /* Use SMB_VFS_NEXT_OPENAT() to call openat() with O_PATH. */
+ aio_allow_open = false;
+ }
+
+ if (!(how->flags & O_CREAT)) {
/* Only creates matter. */
- return open(smb_fname->base_name, flags, mode);
+ aio_allow_open = false;
}
- if (!(flags & O_EXCL)) {
+ if (!(how->flags & O_EXCL)) {
/* Only creates with O_EXCL matter. */
- return open(smb_fname->base_name, flags, mode);
+ aio_allow_open = false;
+ }
+
+ if (!aio_allow_open) {
+ /* aio opens turned off. */
+ return SMB_VFS_NEXT_OPENAT(handle,
+ dirfsp,
+ smb_fname,
+ fsp,
+ how);
}
/*
}
/* Ok, it's a create exclusive call - pass it to a thread helper. */
- return open_async(smb_fname, fsp, flags, mode);
+ return open_async(dirfsp, smb_fname, fsp, how->flags, how->mode);
}
#endif
static struct vfs_fn_pointers vfs_aio_pthread_fns = {
#if defined(HAVE_OPENAT) && defined(HAVE_LINUX_THREAD_CREDENTIALS)
- .open_fn = aio_pthread_open_fn,
+ .openat_fn = aio_pthread_openat_fn,
#endif
};