Revision d8ea6a91ad70ae0881d76446df27d3f58fd478c3 authored by Eric Dumazet on 21 September 2018, 22:27:49 UTC, committed by David S. Miller on 24 September 2018, 04:55:25 UTC
As diagnosed by Song Liu, ndo_poll_controller() can
be very dangerous on loaded hosts, since the cpu
calling ndo_poll_controller() might steal all NAPI
contexts (for all RX/TX queues of the NIC). This capture
can last for unlimited amount of time, since one
cpu is generally not able to drain all the queues under load.

bnx2x uses NAPI for TX completions, so we better let core
networking stack call the napi->poll() to avoid the capture.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ariel Elior <ariel.elior@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 9c29bcd
Raw File
procfs.c
// SPDX-License-Identifier: GPL-2.0
/*
 * Procfs support for lockd
 *
 * Copyright (c) 2014 Jeff Layton <jlayton@primarydata.com>
 */

#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/module.h>
#include <linux/nsproxy.h>
#include <net/net_namespace.h>

#include "netns.h"
#include "procfs.h"

/*
 * We only allow strings that start with 'Y', 'y', or '1'.
 */
static ssize_t
nlm_end_grace_write(struct file *file, const char __user *buf, size_t size,
		    loff_t *pos)
{
	char *data;
	struct lockd_net *ln = net_generic(current->nsproxy->net_ns,
					   lockd_net_id);

	if (size < 1)
		return -EINVAL;

	data = simple_transaction_get(file, buf, size);
	if (IS_ERR(data))
		return PTR_ERR(data);

	switch(data[0]) {
	case 'Y':
	case 'y':
	case '1':
		locks_end_grace(&ln->lockd_manager);
		break;
	default:
		return -EINVAL;
	}

	return size;
}

static ssize_t
nlm_end_grace_read(struct file *file, char __user *buf, size_t size,
		   loff_t *pos)
{
	struct lockd_net *ln = net_generic(current->nsproxy->net_ns,
					   lockd_net_id);
	char resp[3];

	resp[0] = list_empty(&ln->lockd_manager.list) ? 'Y' : 'N';
	resp[1] = '\n';
	resp[2] = '\0';

	return simple_read_from_buffer(buf, size, pos, resp, sizeof(resp));
}

static const struct file_operations lockd_end_grace_operations = {
	.write		= nlm_end_grace_write,
	.read		= nlm_end_grace_read,
	.llseek		= default_llseek,
	.release	= simple_transaction_release,
};

int __init
lockd_create_procfs(void)
{
	struct proc_dir_entry *entry;

	entry = proc_mkdir("fs/lockd", NULL);
	if (!entry)
		return -ENOMEM;
	entry = proc_create("nlm_end_grace", S_IRUGO|S_IWUSR, entry,
				 &lockd_end_grace_operations);
	if (!entry) {
		remove_proc_entry("fs/lockd", NULL);
		return -ENOMEM;
	}
	return 0;
}

void __exit
lockd_remove_procfs(void)
{
	remove_proc_entry("fs/lockd/nlm_end_grace", NULL);
	remove_proc_entry("fs/lockd", NULL);
}
back to top