diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2015-04-18 12:39:51 +0200 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2015-04-18 12:39:51 +0200 |
commit | 61875e1abd38a965c9f7dfca28068dd0a871961c (patch) | |
tree | 3919ed234b07c62755133579631e877b9850e8af /CREDITS | |
parent | f396c12ecfda1717e5f76d6b4ab11e4db232e60d (diff) |
kdbus: reduce scope of handle locking
A kdbus handle is used to create objects in the kdbus hierarchy. During
open(), we do not have enough information to know how to setup the object.
Therefore, we provide setup ioctls, which allow user-space to pass in
parameters and options how the to-be-created object should behave. Once
setup is done, we allow user-space to use ioctls to operate on that newly
created object.
It is important to notice:
1) Only one setup ioctl can ever be called on a handle. You cannot call
multiple, different setup ioctls on the same handle.
2) A setup ioctl can only be called once, if it succeeded. If it failed,
it must not modify the handle in any way. If it succeeded, no further
setup ioctl can be issued.
3) After a setup ioctl is done, the handle is constant and must not be
modified in any way.
So far, we used a write-lock around all setup ioctls, and a read-lock
around everything else. The handle setup-indicator (the type field) can
only be set under the write-lock. Whenever you access the handle under a
read-lock, you must verify it was set before, otherwise, you must bail out
as the handle was not initialized, yet.
This has the downside that we need a read-lock on all operations on the
handle. For performance reasons, we should avoid that. This patch turns
the rwlock into a mutex and removes the read-side lock from all paths. It
relies on the 3 behaviors described above.
With this patch, the mutex is only taken around setup ioctls. Furthermore,
the setup-indicator (the type field) is only ever set if the mutex is
held. The mutex guarantees that multiple setup ioctls cannot race, and
also, that only one setup ioctl will ever succeed. If a setup ioctl is
called after setup was already finished, we do not touch the handle at all
and immediately fail.
Furthermore, all other operations (non-setup operations) can only be
called once setup is done. Therefore, we must synchronize them with any
racing setup, otherwise, they might access the handle which is currently
modified by setup.
We protect from this race by setting the setup-indicator (the type field)
_last_, and issue a write-barrier before setting it. Once it is set, we
never modify the handle ever again; it is constant from now on until
file-release.
Hence, on the read-side we simply read the type field and issue a
read-barrier afterwards. _Iff_ the type field was not set, yet, we must
not access the handle in any way, but bail out immediately. Setup was not
done, yet. But if the type field was set, the read-barrier pairs with the
write-barrier during setup. All member fields of the handle object are
guaranteed to be accessible by us, as the type-field is always the last
field that is written.
With this in place, we reduce the locking-overhead of all non-setup ioctls
to a read-barrier, instead of a read-side lock. And in combination with
the follow-up that removes the active-refs from kdbus_handle_poll(), we're
now lock-free in ->poll and ->mmap callbacks.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Diffstat (limited to 'CREDITS')
0 files changed, 0 insertions, 0 deletions