Exemple #1
0
static int pcrypt_cpumask_change_notify(struct notifier_block *self,
					unsigned long val, void *data)
{
	struct padata_pcrypt *pcrypt;
	struct pcrypt_cpumask *new_mask, *old_mask;
	struct padata_cpumask *cpumask = (struct padata_cpumask *)data;

	if (!(val & PADATA_CPU_SERIAL))
		return 0;

	pcrypt = container_of(self, struct padata_pcrypt, nblock);
	new_mask = kmalloc(sizeof(*new_mask), GFP_KERNEL);
	if (!new_mask)
		return -ENOMEM;
	if (!alloc_cpumask_var(&new_mask->mask, GFP_KERNEL)) {
		kfree(new_mask);
		return -ENOMEM;
	}

	old_mask = pcrypt->cb_cpumask;

	cpumask_copy(new_mask->mask, cpumask->cbcpu);
	rcu_assign_pointer(pcrypt->cb_cpumask, new_mask);
	synchronize_rcu_bh();

	free_cpumask_var(old_mask->mask);
	kfree(old_mask);
	return 0;
}
Exemple #2
0
int flush_bytes_array(void)
{
	struct bytes *tmp, *old;

	rcu_read_lock_bh();
	if (!(rcu_dereference_bh(bytes_to_skip)->array)) {
		log_info("Byte array list is empty nothing to flush");
		rcu_read_unlock_bh();
		return 0;
	}
	rcu_read_unlock_bh();

	tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
	if (!tmp) {
		log_err("Could not allocate struct bytes.");
		return -ENOMEM;
	}

	old = bytes_to_skip;
	*tmp = *bytes_to_skip;

	/* Delete. */
	tmp->array = NULL;
	tmp->count = 0;

	rcu_assign_pointer(bytes_to_skip, tmp);
	synchronize_rcu_bh();

	if (old->array)
		kfree(old->array);

	kfree(old);
	return 0;
}
Exemple #3
0
/*
 * Test each non-SRCU synchronous grace-period wait API.  This is
 * useful just after a change in mode for these primitives, and
 * during early boot.
 */
void rcu_test_sync_prims(void)
{
	if (!IS_ENABLED(CONFIG_PROVE_RCU))
		return;
	synchronize_rcu();
	synchronize_rcu_bh();
	synchronize_sched();
	synchronize_rcu_expedited();
	synchronize_rcu_bh_expedited();
	synchronize_sched_expedited();
}
Exemple #4
0
static void vlan_dev_netpoll_cleanup(struct net_device *dev)
{
	struct vlan_dev_priv *info = vlan_dev_priv(dev);
	struct netpoll *netpoll = info->netpoll;

	if (!netpoll)
		return;

	info->netpoll = NULL;

        /* Wait for transmitting packets to finish before freeing. */
        synchronize_rcu_bh();

        __netpoll_cleanup(netpoll);
        kfree(netpoll);
}
Exemple #5
0
/**
 * Updates the configuration value of this module whose identifier is "type".
 *
 * @param type ID of the configuration value you want to edit.
 * @size length of "value" in bytes.
 * @value the new value you want the field to have.
 */
int filtering_set_config(enum filtering_type type, size_t size, void *value)
{
	struct filtering_config *tmp_config;
	struct filtering_config *old_config;
	__u8 value8;

	if (size != sizeof(__u8)) {
		log_debug("Expected a boolean, got %zu bytes.", size);
		return -EINVAL;
	}
	value8 = *((__u8 *) value);

	tmp_config = kmalloc(sizeof(*tmp_config), GFP_KERNEL);
	if (!tmp_config)
		return -ENOMEM;

	old_config = config;
	*tmp_config = *old_config;

	switch (type) {
	case DROP_BY_ADDR:
		tmp_config->drop_by_addr = value8;
		break;
	case DROP_ICMP6_INFO:
		tmp_config->drop_icmp6_info = value8;
		break;
	case DROP_EXTERNAL_TCP:
		tmp_config->drop_external_tcp = value8;
		break;
	default:
		log_err("Unknown config type for the 'filtering and updating' module: %u", type);
		kfree(tmp_config);
		return -EINVAL;
	}

	rcu_assign_pointer(config, tmp_config);
	synchronize_rcu_bh();
	kfree(old_config);

	return 0;
}
Exemple #6
0
static int vhost_net_release(struct inode *inode, struct file *f)
{
	struct vhost_net *n = f->private_data;
	struct socket *tx_sock;
	struct socket *rx_sock;

	vhost_net_stop(n, &tx_sock, &rx_sock);
	vhost_net_flush(n);
	vhost_dev_stop(&n->dev);
	vhost_dev_cleanup(&n->dev, false);
	vhost_net_vq_reset(n);
	if (tx_sock)
		sockfd_put(tx_sock);
	if (rx_sock)
		sockfd_put(rx_sock);
	/* Make sure no callbacks are outstanding */
	synchronize_rcu_bh();
	/* We do an extra flush before freeing memory,
	 * since jobs can re-queue themselves. */
	vhost_net_flush(n);
	kfree(n->dev.vqs);
	kvfree(n);
	return 0;
}
Exemple #7
0
int update_bytes_array(void *values, size_t size)
{
	struct bytes *tmp, *old;
	__u16 *list = values;
	unsigned int count = size / 2;
	unsigned int i, j;

	if (!values) {
		log_err("Values cannot be NULL");
		return -EINVAL;
	}

	if (count == 0) {
		log_err("The bytes list received from userspace is empty.");
		return -EINVAL;
	}
	if (size % 2 == 1) {
		log_err("Expected an array of 16-bit integers; got an uneven number of bytes.");
		return -EINVAL;
	}

	tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
	if (!tmp) {
		log_err("Could not allocate struct bytes.");
		return -ENOMEM;
	}

	old = bytes_to_skip;
	*tmp = *bytes_to_skip;

	/* Remove zeroes and duplicates. */
	for (i = 0, j = 1; j < count; j++) {
		if (list[j] == 0)
			break;
		if (list[i] != list[j]) {
			i++;
			list[i] = list[j];
		}
	}

	count = i + 1;
	size = count * sizeof(*list);

	/* Update. */
	tmp->array = kmalloc(size, GFP_KERNEL);
	if (!tmp->array) {
		log_err("Could not allocate the byte array list.");
		return -ENOMEM;
	}
	memcpy(tmp->array, list, size);
	tmp->count = count;

	rcu_assign_pointer(bytes_to_skip, tmp);
	synchronize_rcu_bh();

	if (old->array && tmp->array != old->array)
		kfree(old->array);

	kfree(old);
	return 0;
}