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; }
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; }
/* * 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(); }
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); }
/** * 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; }
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; }
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; }