In a few places, when creating a new vport we also need to allocate
some memory for configuration that can change. This data is protected
by RCU but we directly access the memory when initializing it. This
is fine, since the vport has not yet been published and we use the
apropriate memory barriers when doing so. However, it makes tools
like sparse unhappy and is also asymmetric since we use RCU to
dereference the pointers but not to assign them. This cleans that
up somewhat by initializing the memory first and then using RCU
to assign it, which makes everyone happy.
Found with sparse.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
{
struct vport *vport;
struct tnl_vport *tnl_vport;
{
struct vport *vport;
struct tnl_vport *tnl_vport;
+ struct tnl_mutable_config *mutable;
int initial_frag_id;
int err;
int initial_frag_id;
int err;
strcpy(tnl_vport->name, parms->name);
tnl_vport->tnl_ops = tnl_ops;
strcpy(tnl_vport->name, parms->name);
tnl_vport->tnl_ops = tnl_ops;
- tnl_vport->mutable = kzalloc(sizeof(struct tnl_mutable_config), GFP_KERNEL);
- if (!tnl_vport->mutable) {
+ mutable = kzalloc(sizeof(struct tnl_mutable_config), GFP_KERNEL);
+ if (!mutable) {
err = -ENOMEM;
goto error_free_vport;
}
err = -ENOMEM;
goto error_free_vport;
}
- vport_gen_rand_ether_addr(tnl_vport->mutable->eth_addr);
- tnl_vport->mutable->mtu = ETH_DATA_LEN;
+ vport_gen_rand_ether_addr(mutable->eth_addr);
+ mutable->mtu = ETH_DATA_LEN;
get_random_bytes(&initial_frag_id, sizeof(int));
atomic_set(&tnl_vport->frag_id, initial_frag_id);
get_random_bytes(&initial_frag_id, sizeof(int));
atomic_set(&tnl_vport->frag_id, initial_frag_id);
- err = set_config(parms->config, tnl_ops, NULL, tnl_vport->mutable);
+ err = set_config(parms->config, tnl_ops, NULL, mutable);
if (err)
goto error_free_mutable;
if (err)
goto error_free_mutable;
#ifdef NEED_CACHE_TIMEOUT
tnl_vport->cache_exp_interval = MAX_CACHE_EXP -
#ifdef NEED_CACHE_TIMEOUT
tnl_vport->cache_exp_interval = MAX_CACHE_EXP -
- (net_random() % (MAX_CACHE_EXP / 2));
+ (net_random() % (MAX_CACHE_EXP / 2));
+ rcu_assign_pointer(tnl_vport->mutable, mutable);
+
err = add_port(vport);
if (err)
goto error_free_mutable;
err = add_port(vport);
if (err)
goto error_free_mutable;
return vport;
error_free_mutable:
return vport;
error_free_mutable:
- kfree(tnl_vport->mutable);
error_free_vport:
vport_free(vport);
error:
error_free_vport:
vport_free(vport);
error:
struct vport *vport;
struct patch_vport *patch_vport;
const char *peer_name;
struct vport *vport;
struct patch_vport *patch_vport;
const char *peer_name;
+ struct device_config *devconf;
int err;
vport = vport_alloc(sizeof(struct patch_vport), &patch_vport_ops, parms);
int err;
vport = vport_alloc(sizeof(struct patch_vport), &patch_vport_ops, parms);
strcpy(patch_vport->name, parms->name);
strcpy(patch_vport->name, parms->name);
- patch_vport->devconf = kmalloc(sizeof(struct device_config), GFP_KERNEL);
- if (!patch_vport->devconf) {
+ devconf = kmalloc(sizeof(struct device_config), GFP_KERNEL);
+ if (!devconf) {
err = -ENOMEM;
goto error_free_vport;
}
err = -ENOMEM;
goto error_free_vport;
}
- err = set_config(vport, parms->config, patch_vport->devconf);
+ err = set_config(vport, parms->config, devconf);
if (err)
goto error_free_devconf;
if (err)
goto error_free_devconf;
- vport_gen_rand_ether_addr(patch_vport->devconf->eth_addr);
+ vport_gen_rand_ether_addr(devconf->eth_addr);
/* Make the default MTU fairly large so that it doesn't become the
* bottleneck on systems using jumbo frames. */
/* Make the default MTU fairly large so that it doesn't become the
* bottleneck on systems using jumbo frames. */
- patch_vport->devconf->mtu = 65535;
- peer_name = patch_vport->devconf->peer_name;
- hlist_add_head(&patch_vport->hash_node, hash_bucket(peer_name));
+ rcu_assign_pointer(patch_vport->devconf, devconf);
+ peer_name = devconf->peer_name;
+ hlist_add_head(&patch_vport->hash_node, hash_bucket(peer_name));
rcu_assign_pointer(patch_vport->peer, vport_locate(peer_name));
update_peers(patch_vport->name, vport);
return vport;
error_free_devconf:
rcu_assign_pointer(patch_vport->peer, vport_locate(peer_name));
update_peers(patch_vport->name, vport);
return vport;
error_free_devconf:
- kfree(patch_vport->devconf);
error_free_vport:
vport_free(vport);
error:
error_free_vport:
vport_free(vport);
error: