diff options
author | Volker Lendecke <vl@samba.org> | 2020-02-20 14:13:35 +0100 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2020-02-25 22:24:54 +0000 |
commit | a95a8c7eaa46d5c8c485de714f0a97e307e49f7e (patch) | |
tree | 64b99dfca01ed53a6f1b56c4a4d01d6f7cb4f443 | |
parent | a33656c9df2cde3ff1cfc6b0427c7dfb2b140cae (diff) | |
download | samba-a95a8c7eaa46d5c8c485de714f0a97e307e49f7e.tar.gz |
smbd: Separate aio_pthread indicator from normal EINTR
According to Posix and the Linux open(2) manpage, the open-syscall can
return EINTR. If that happens, core smbd saw this as an indication
that aio_pthread's open function was doing its job. With a real EINTR
without aio_pthread this meant we ended up in a server_exit after 20
seconds, because there was nobody to do the retry.
EINTR is mapped to NT_STATUS_RETRY. Handle this by just retrying after
a second.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=14285
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Thu Feb 20 22:14:25 UTC 2020 on sn-devel-184
(cherry picked from commit aebe427b77b5315eb5d2b05b8c72824ca0389723)
Autobuild-User(v4-11-test): Karolin Seeger <kseeger@samba.org>
Autobuild-Date(v4-11-test): Tue Feb 25 22:24:54 UTC 2020 on sn-devel-184
-rw-r--r-- | selftest/knownfail.d/open_eintr | 1 | ||||
-rw-r--r-- | source3/modules/vfs_aio_pthread.c | 2 | ||||
-rw-r--r-- | source3/smbd/open.c | 38 |
3 files changed, 28 insertions, 13 deletions
diff --git a/selftest/knownfail.d/open_eintr b/selftest/knownfail.d/open_eintr deleted file mode 100644 index e5b42ed6bcd..00000000000 --- a/selftest/knownfail.d/open_eintr +++ /dev/null @@ -1 +0,0 @@ -samba3.blackbox.open-eintr.*\(simpleserver:local\) diff --git a/source3/modules/vfs_aio_pthread.c b/source3/modules/vfs_aio_pthread.c index 577180b6b01..5febdd3af32 100644 --- a/source3/modules/vfs_aio_pthread.c +++ b/source3/modules/vfs_aio_pthread.c @@ -318,7 +318,7 @@ static int open_async(const files_struct *fsp, opd->fname)); /* Cause the calling code to reschedule us. */ - errno = EINTR; /* Maps to NT_STATUS_RETRY. */ + errno = EINPROGRESS; /* Maps to NT_STATUS_MORE_PROCESSING_REQUIRED. */ return -1; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5524f80af20..871cc72053f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2960,6 +2960,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, SMB_STRUCT_STAT saved_stat = smb_fname->st; struct timespec old_write_time; struct file_id id; + bool setup_poll = false; if (conn->printer) { /* @@ -3290,8 +3291,14 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, open_access_mask, &new_file_created); if (NT_STATUS_EQUAL(fsp_open, NT_STATUS_NETWORK_BUSY)) { - bool delay; - + if (file_existed && S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) { + DEBUG(10, ("FIFO busy\n")); + return NT_STATUS_NETWORK_BUSY; + } + if (req == NULL) { + DEBUG(10, ("Internal open busy\n")); + return NT_STATUS_NETWORK_BUSY; + } /* * This handles the kernel oplock case: * @@ -3301,14 +3308,21 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, * "Samba locking.tdb oplocks" are handled below after acquiring * the sharemode lock with get_share_mode_lock(). */ - if (file_existed && S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) { - DEBUG(10, ("FIFO busy\n")); - return NT_STATUS_NETWORK_BUSY; - } - if (req == NULL) { - DEBUG(10, ("Internal open busy\n")); - return NT_STATUS_NETWORK_BUSY; - } + setup_poll = true; + } + + if (NT_STATUS_EQUAL(fsp_open, NT_STATUS_RETRY)) { + /* + * EINTR from the open(2) syscall. Just setup a retry + * in a bit. We can't use the sys_write() tight retry + * loop here, as we might have to actually deal with + * lease-break signals to avoid a deadlock. + */ + setup_poll = true; + } + + if (setup_poll) { + bool delay; /* * From here on we assume this is an oplock break triggered @@ -3359,7 +3373,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, } if (!NT_STATUS_IS_OK(fsp_open)) { - if (NT_STATUS_EQUAL(fsp_open, NT_STATUS_RETRY)) { + bool wait_for_aio = NT_STATUS_EQUAL( + fsp_open, NT_STATUS_MORE_PROCESSING_REQUIRED); + if (wait_for_aio) { schedule_async_open(request_time, req); } return fsp_open; |