Skip to content

Commit

Permalink
Revert changes to convert to ->poll_mask() and aio IOCB_CMD_POLL
Browse files Browse the repository at this point in the history
The poll() changes were not well thought out, and completely
unexplained.  They also caused a huge performance regression, because
"->poll()" was no longer a trivial file operation that just called down
to the underlying file operations, but instead did at least two indirect
calls.

Indirect calls are sadly slow now with the Spectre mitigation, but the
performance problem could at least be largely mitigated by changing the
"->get_poll_head()" operation to just have a per-file-descriptor pointer
to the poll head instead.  That gets rid of one of the new indirections.

But that doesn't fix the new complexity that is completely unwarranted
for the regular case.  The (undocumented) reason for the poll() changes
was some alleged AIO poll race fixing, but we don't make the common case
slower and more complex for some uncommon special case, so this all
really needs way more explanations and most likely a fundamental
redesign.

[ This revert is a revert of about 30 different commits, not reverted
  individually because that would just be unnecessarily messy  - Linus ]

Cc: Al Viro <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
torvalds committed Jun 28, 2018
1 parent f574943 commit a11e1d4
Show file tree
Hide file tree
Showing 80 changed files with 301 additions and 450 deletions.
7 changes: 1 addition & 6 deletions Documentation/filesystems/Locking
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,6 @@ prototypes:
int (*iterate) (struct file *, struct dir_context *);
int (*iterate_shared) (struct file *, struct dir_context *);
__poll_t (*poll) (struct file *, struct poll_table_struct *);
struct wait_queue_head * (*get_poll_head)(struct file *, __poll_t);
__poll_t (*poll_mask) (struct file *, __poll_t);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
Expand Down Expand Up @@ -473,7 +471,7 @@ prototypes:
};

locking rules:
All except for ->poll_mask may block.
All may block.

->llseek() locking has moved from llseek to the individual llseek
implementations. If your fs is not using generic_file_llseek, you
Expand Down Expand Up @@ -505,9 +503,6 @@ in sys_read() and friends.
the lease within the individual filesystem to record the result of the
operation

->poll_mask can be called with or without the waitqueue lock for the waitqueue
returned from ->get_poll_head.

--------------------------- dquot_operations -------------------------------
prototypes:
int (*write_dquot) (struct dquot *);
Expand Down
13 changes: 0 additions & 13 deletions Documentation/filesystems/vfs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -857,8 +857,6 @@ struct file_operations {
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
int (*iterate) (struct file *, struct dir_context *);
__poll_t (*poll) (struct file *, struct poll_table_struct *);
struct wait_queue_head * (*get_poll_head)(struct file *, __poll_t);
__poll_t (*poll_mask) (struct file *, __poll_t);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
Expand Down Expand Up @@ -903,17 +901,6 @@ otherwise noted.
activity on this file and (optionally) go to sleep until there
is activity. Called by the select(2) and poll(2) system calls

get_poll_head: Returns the struct wait_queue_head that callers can
wait on. Callers need to check the returned events using ->poll_mask
once woken. Can return NULL to indicate polling is not supported,
or any error code using the ERR_PTR convention to indicate that a
grave error occured and ->poll_mask shall not be called.

poll_mask: return the mask of EPOLL* values describing the file descriptor
state. Called either before going to sleep on the waitqueue returned by
get_poll_head, or after it has been woken. If ->get_poll_head and
->poll_mask are implemented ->poll does not need to be implement.

unlocked_ioctl: called by the ioctl(2) system call.

compat_ioctl: called by the ioctl(2) system call when 32 bit system calls
Expand Down
13 changes: 10 additions & 3 deletions crypto/af_alg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1060,12 +1060,19 @@ void af_alg_async_cb(struct crypto_async_request *_req, int err)
}
EXPORT_SYMBOL_GPL(af_alg_async_cb);

__poll_t af_alg_poll_mask(struct socket *sock, __poll_t events)
/**
* af_alg_poll - poll system call handler
*/
__poll_t af_alg_poll(struct file *file, struct socket *sock,
poll_table *wait)
{
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
struct af_alg_ctx *ctx = ask->private;
__poll_t mask = 0;
__poll_t mask;

sock_poll_wait(file, sk_sleep(sk), wait);
mask = 0;

if (!ctx->more || ctx->used)
mask |= EPOLLIN | EPOLLRDNORM;
Expand All @@ -1075,7 +1082,7 @@ __poll_t af_alg_poll_mask(struct socket *sock, __poll_t events)

return mask;
}
EXPORT_SYMBOL_GPL(af_alg_poll_mask);
EXPORT_SYMBOL_GPL(af_alg_poll);

/**
* af_alg_alloc_areq - allocate struct af_alg_async_req
Expand Down
4 changes: 2 additions & 2 deletions crypto/algif_aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ static struct proto_ops algif_aead_ops = {
.sendmsg = aead_sendmsg,
.sendpage = af_alg_sendpage,
.recvmsg = aead_recvmsg,
.poll_mask = af_alg_poll_mask,
.poll = af_alg_poll,
};

static int aead_check_key(struct socket *sock)
Expand Down Expand Up @@ -471,7 +471,7 @@ static struct proto_ops algif_aead_ops_nokey = {
.sendmsg = aead_sendmsg_nokey,
.sendpage = aead_sendpage_nokey,
.recvmsg = aead_recvmsg_nokey,
.poll_mask = af_alg_poll_mask,
.poll = af_alg_poll,
};

static void *aead_bind(const char *name, u32 type, u32 mask)
Expand Down
4 changes: 2 additions & 2 deletions crypto/algif_skcipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ static struct proto_ops algif_skcipher_ops = {
.sendmsg = skcipher_sendmsg,
.sendpage = af_alg_sendpage,
.recvmsg = skcipher_recvmsg,
.poll_mask = af_alg_poll_mask,
.poll = af_alg_poll,
};

static int skcipher_check_key(struct socket *sock)
Expand Down Expand Up @@ -302,7 +302,7 @@ static struct proto_ops algif_skcipher_ops_nokey = {
.sendmsg = skcipher_sendmsg_nokey,
.sendpage = skcipher_sendpage_nokey,
.recvmsg = skcipher_recvmsg_nokey,
.poll_mask = af_alg_poll_mask,
.poll = af_alg_poll,
};

static void *skcipher_bind(const char *name, u32 type, u32 mask)
Expand Down
29 changes: 13 additions & 16 deletions drivers/char/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,8 @@ static struct poolinfo {
/*
* Static global variables
*/
static DECLARE_WAIT_QUEUE_HEAD(random_wait);
static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
static struct fasync_struct *fasync;

static DEFINE_SPINLOCK(random_ready_list_lock);
Expand Down Expand Up @@ -721,8 +722,8 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)

/* should we wake readers? */
if (entropy_bits >= random_read_wakeup_bits &&
wq_has_sleeper(&random_wait)) {
wake_up_interruptible_poll(&random_wait, POLLIN);
wq_has_sleeper(&random_read_wait)) {
wake_up_interruptible(&random_read_wait);
kill_fasync(&fasync, SIGIO, POLL_IN);
}
/* If the input pool is getting full, send some
Expand Down Expand Up @@ -1396,7 +1397,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
trace_debit_entropy(r->name, 8 * ibytes);
if (ibytes &&
(r->entropy_count >> ENTROPY_SHIFT) < random_write_wakeup_bits) {
wake_up_interruptible_poll(&random_wait, POLLOUT);
wake_up_interruptible(&random_write_wait);
kill_fasync(&fasync, SIGIO, POLL_OUT);
}

Expand Down Expand Up @@ -1838,7 +1839,7 @@ _random_read(int nonblock, char __user *buf, size_t nbytes)
if (nonblock)
return -EAGAIN;

wait_event_interruptible(random_wait,
wait_event_interruptible(random_read_wait,
ENTROPY_BITS(&input_pool) >=
random_read_wakeup_bits);
if (signal_pending(current))
Expand Down Expand Up @@ -1875,17 +1876,14 @@ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
return ret;
}

static struct wait_queue_head *
random_get_poll_head(struct file *file, __poll_t events)
{
return &random_wait;
}

static __poll_t
random_poll_mask(struct file *file, __poll_t events)
random_poll(struct file *file, poll_table * wait)
{
__poll_t mask = 0;
__poll_t mask;

poll_wait(file, &random_read_wait, wait);
poll_wait(file, &random_write_wait, wait);
mask = 0;
if (ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits)
mask |= EPOLLIN | EPOLLRDNORM;
if (ENTROPY_BITS(&input_pool) < random_write_wakeup_bits)
Expand Down Expand Up @@ -1992,8 +1990,7 @@ static int random_fasync(int fd, struct file *filp, int on)
const struct file_operations random_fops = {
.read = random_read,
.write = random_write,
.get_poll_head = random_get_poll_head,
.poll_mask = random_poll_mask,
.poll = random_poll,
.unlocked_ioctl = random_ioctl,
.fasync = random_fasync,
.llseek = noop_llseek,
Expand Down Expand Up @@ -2326,7 +2323,7 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
* We'll be woken up again once below random_write_wakeup_thresh,
* or when the calling thread is about to terminate.
*/
wait_event_interruptible(random_wait, kthread_should_stop() ||
wait_event_interruptible(random_write_wait, kthread_should_stop() ||
ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
mix_pool_bytes(poolp, buffer, count);
credit_entropy_bits(poolp, entropy);
Expand Down
2 changes: 1 addition & 1 deletion drivers/isdn/mISDN/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ static const struct proto_ops data_sock_ops = {
.getname = data_sock_getname,
.sendmsg = mISDN_sock_sendmsg,
.recvmsg = mISDN_sock_recvmsg,
.poll_mask = datagram_poll_mask,
.poll = datagram_poll,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = data_sock_setsockopt,
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ppp/pppoe.c
Original file line number Diff line number Diff line change
Expand Up @@ -1107,7 +1107,7 @@ static const struct proto_ops pppoe_ops = {
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.getname = pppoe_getname,
.poll_mask = datagram_poll_mask,
.poll = datagram_poll,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt,
Expand Down
Loading

0 comments on commit a11e1d4

Please sign in to comment.