MINOR: fd: implement an exclusive syscall bit to remove the ugly "log" lock
There is a function called fd_write_frag_line() that's essentially used by loggers and that is used to write an atomic message line over a file descriptor using writev(). However a lock is required around the writev() call to prevent messages from multiple threads from being interleaved. Till now a SPIN_TRYLOCK was used on a dedicated lock that was common to all FDs. This is quite not pretty as if there are multiple output pipes to collect logs, there will be quite some contention. Now that there are empty flags left in the FD state and that we can finally use atomic ops on them, let's add a flag to indicate the FD is locked for exclusive access by a syscall. At least the locking will now be on an FD basis and not the whole process, so we can remove the log_lock.
This commit is contained in:
parent
9063a660cc
commit
1673c4a883
@ -68,6 +68,7 @@ enum {
|
||||
#define FD_INITIALIZED_BIT 18 /* init phase was done (e.g. output pipe set non-blocking) */
|
||||
#define FD_ET_POSSIBLE_BIT 19 /* edge-triggered is possible on this FD */
|
||||
#define FD_EXPORTED_BIT 20 /* FD is exported and must not be closed */
|
||||
#define FD_EXCL_SYSCALL_BIT 21 /* a syscall claims exclusivity on this FD */
|
||||
|
||||
|
||||
/* and flag values */
|
||||
@ -107,6 +108,7 @@ enum {
|
||||
#define FD_INITIALIZED (1U << FD_INITIALIZED_BIT)
|
||||
#define FD_ET_POSSIBLE (1U << FD_ET_POSSIBLE_BIT)
|
||||
#define FD_EXPORTED (1U << FD_EXPORTED_BIT)
|
||||
#define FD_EXCL_SYSCALL (1U << FD_EXCL_SYSCALL_BIT)
|
||||
|
||||
/* This is the value used to mark a file descriptor as dead. This value is
|
||||
* negative, this is important so that tests on fd < 0 properly match. It
|
||||
|
5
src/fd.c
5
src/fd.c
@ -444,7 +444,6 @@ void updt_fd_polling(const int fd)
|
||||
}
|
||||
}
|
||||
|
||||
__decl_spinlock(log_lock);
|
||||
/* Tries to send <npfx> parts from <prefix> followed by <nmsg> parts from <msg>
|
||||
* optionally followed by a newline if <nl> is non-null, to file descriptor
|
||||
* <fd>. The message is sent atomically using writev(). It may be truncated to
|
||||
@ -503,7 +502,7 @@ ssize_t fd_write_frag_line(int fd, size_t maxlen, const struct ist pfx[], size_t
|
||||
* up.
|
||||
*/
|
||||
|
||||
while (HA_SPIN_TRYLOCK(OTHER_LOCK, &log_lock) != 0) {
|
||||
while (HA_ATOMIC_BTS(&fdtab[fd].state, FD_EXCL_SYSCALL_BIT)) {
|
||||
if (++attempts >= 200) {
|
||||
/* so that the caller knows the message couldn't be delivered */
|
||||
sent = -1;
|
||||
@ -519,7 +518,7 @@ ssize_t fd_write_frag_line(int fd, size_t maxlen, const struct ist pfx[], size_t
|
||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
sent = writev(fd, iovec, vec);
|
||||
HA_SPIN_UNLOCK(OTHER_LOCK, &log_lock);
|
||||
HA_ATOMIC_BTR(&fdtab[fd].state, FD_EXCL_SYSCALL_BIT);
|
||||
|
||||
leave:
|
||||
/* sent > 0 if the message was delivered */
|
||||
|
Loading…
x
Reference in New Issue
Block a user