Skip to content

Commit

Permalink
afs: Push the net ns pointer to more places
Browse files Browse the repository at this point in the history
Push the network namespace pointer to more places in AFS, including the
afs_server structure (which doesn't hold a ref on the netns).

In particular, afs_put_cell() now takes requires a net ns parameter so that
it can safely alter the netns after decrementing the cell usage count - the
cell will be deallocated by a background thread after being cached for a
period, which means that it's not safe to access it after reducing its
usage count.

Signed-off-by: David Howells <dhowells@redhat.com>
  • Loading branch information
David Howells committed Nov 13, 2017
1 parent 49566f6 commit 9ed900b
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 56 deletions.
14 changes: 7 additions & 7 deletions fs/afs/cell.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ int afs_cell_init(struct afs_net *net, char *rootcell)
old_root = net->ws_cell;
net->ws_cell = new_root;
write_unlock(&net->cells_lock);
afs_put_cell(old_root);
afs_put_cell(net, old_root);

_leave(" = 0");
return 0;
Expand Down Expand Up @@ -336,7 +336,7 @@ struct afs_cell *afs_get_cell_maybe(struct afs_cell *cell)
/*
* destroy a cell record
*/
void afs_put_cell(struct afs_cell *cell)
void afs_put_cell(struct afs_net *net, struct afs_cell *cell)
{
if (!cell)
return;
Expand All @@ -347,20 +347,20 @@ void afs_put_cell(struct afs_cell *cell)

/* to prevent a race, the decrement and the dequeue must be effectively
* atomic */
write_lock(&cell->net->cells_lock);
write_lock(&net->cells_lock);

if (likely(!atomic_dec_and_test(&cell->usage))) {
write_unlock(&cell->net->cells_lock);
write_unlock(&net->cells_lock);
_leave("");
return;
}

ASSERT(list_empty(&cell->servers));
ASSERT(list_empty(&cell->vl_list));

wake_up(&cell->net->cells_freeable_wq);
wake_up(&net->cells_freeable_wq);

write_unlock(&cell->net->cells_lock);
write_unlock(&net->cells_lock);

_leave(" [unused]");
}
Expand Down Expand Up @@ -424,7 +424,7 @@ void afs_cell_purge(struct afs_net *net)

_enter("");

afs_put_cell(net->ws_cell);
afs_put_cell(net, net->ws_cell);

down_write(&net->cells_sem);

Expand Down
2 changes: 1 addition & 1 deletion fs/afs/cmservice.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ static void afs_cm_destructor(struct afs_call *call)
afs_break_callbacks(call->server, call->count, call->request);
}

afs_put_server(call->server);
afs_put_server(call->net, call->server);
call->server = NULL;
kfree(call->buffer);
call->buffer = NULL;
Expand Down
12 changes: 6 additions & 6 deletions fs/afs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
vnode->update_cnt++;
spin_unlock(&vnode->lock);
afs_vnode_finalise_status_update(vnode, server);
afs_put_server(server);
afs_put_server(afs_i2net(dir), server);

d_instantiate(dentry, inode);
if (d_unhashed(dentry)) {
Expand All @@ -783,7 +783,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
return 0;

iget_error:
afs_put_server(server);
afs_put_server(afs_i2net(dir), server);
mkdir_error:
key_put(key);
error:
Expand Down Expand Up @@ -948,7 +948,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
vnode->update_cnt++;
spin_unlock(&vnode->lock);
afs_vnode_finalise_status_update(vnode, server);
afs_put_server(server);
afs_put_server(afs_i2net(dir), server);

d_instantiate(dentry, inode);
if (d_unhashed(dentry)) {
Expand All @@ -960,7 +960,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
return 0;

iget_error:
afs_put_server(server);
afs_put_server(afs_i2net(dir), server);
create_error:
key_put(key);
error:
Expand Down Expand Up @@ -1060,7 +1060,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
vnode->update_cnt++;
spin_unlock(&vnode->lock);
afs_vnode_finalise_status_update(vnode, server);
afs_put_server(server);
afs_put_server(afs_i2net(dir), server);

d_instantiate(dentry, inode);
if (d_unhashed(dentry)) {
Expand All @@ -1072,7 +1072,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
return 0;

iget_error:
afs_put_server(server);
afs_put_server(afs_i2net(dir), server);
create_error:
key_put(key);
error:
Expand Down
2 changes: 1 addition & 1 deletion fs/afs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ void afs_evict_inode(struct inode *inode)
spin_lock(&vnode->server->fs_lock);
rb_erase(&vnode->server_rb, &vnode->server->fs_vnodes);
spin_unlock(&vnode->server->fs_lock);
afs_put_server(vnode->server);
afs_put_server(afs_i2net(inode), vnode->server);
vnode->server = NULL;
}

Expand Down
7 changes: 4 additions & 3 deletions fs/afs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ struct afs_server {
atomic_t usage;
time64_t time_of_death; /* time at which put reduced usage to 0 */
struct in_addr addr; /* server address */
struct afs_net *net; /* Network namespace in which the server resides */
struct afs_cell *cell; /* cell in which server resides */
struct list_head link; /* link in cell's server list */
struct list_head grave; /* link in master graveyard list */
Expand Down Expand Up @@ -513,7 +514,7 @@ extern int afs_cell_init(struct afs_net *, char *);
extern struct afs_cell *afs_cell_create(struct afs_net *, const char *, unsigned, char *, bool);
extern struct afs_cell *afs_cell_lookup(struct afs_net *, const char *, unsigned, bool);
extern struct afs_cell *afs_grab_cell(struct afs_cell *);
extern void afs_put_cell(struct afs_cell *);
extern void afs_put_cell(struct afs_net *, struct afs_cell *);
extern void __net_exit afs_cell_purge(struct afs_net *);

/*
Expand Down Expand Up @@ -713,7 +714,7 @@ extern struct afs_server *afs_lookup_server(struct afs_cell *,
const struct in_addr *);
extern struct afs_server *afs_find_server(struct afs_net *,
const struct sockaddr_rxrpc *);
extern void afs_put_server(struct afs_server *);
extern void afs_put_server(struct afs_net *, struct afs_server *);
extern void afs_reap_server(struct work_struct *);
extern void __net_exit afs_purge_servers(struct afs_net *);

Expand Down Expand Up @@ -802,7 +803,7 @@ static inline struct afs_volume *afs_get_volume(struct afs_volume *volume)
return volume;
}

extern void afs_put_volume(struct afs_net *, struct afs_volume *);
extern void afs_put_volume(struct afs_cell *, struct afs_volume *);
extern struct afs_volume *afs_volume_lookup(struct afs_mount_params *);
extern struct afs_server *afs_volume_pick_fileserver(struct afs_vnode *);
extern int afs_volume_release_fileserver(struct afs_vnode *,
Expand Down
2 changes: 1 addition & 1 deletion fs/afs/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
goto done;
}

afs_put_cell(cell);
afs_put_cell(net, cell);
printk("kAFS: Added new cell '%s'\n", name);
} else {
goto inval;
Expand Down
7 changes: 3 additions & 4 deletions fs/afs/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ static struct afs_server *afs_alloc_server(struct afs_cell *cell,
server = kzalloc(sizeof(struct afs_server), GFP_KERNEL);
if (server) {
atomic_set(&server->usage, 1);
server->net = cell->net;
server->cell = cell;

INIT_LIST_HEAD(&server->link);
Expand Down Expand Up @@ -245,10 +246,8 @@ static void afs_set_server_timer(struct afs_net *net, time64_t delay)
* destroy a server record
* - removes from the cell list
*/
void afs_put_server(struct afs_server *server)
void afs_put_server(struct afs_net *net, struct afs_server *server)
{
struct afs_net *net = server->cell->net;

if (!server)
return;

Expand Down Expand Up @@ -290,7 +289,7 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
ASSERTCMP(server->cb_break_head, ==, server->cb_break_tail);
ASSERTCMP(atomic_read(&server->cb_break_n), ==, 0);

afs_put_cell(server->cell);
afs_put_cell(server->net, server->cell);
kfree(server);
afs_dec_servers_outstanding(net);
}
Expand Down
12 changes: 6 additions & 6 deletions fs/afs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ static int afs_parse_options(struct afs_mount_params *params,
false);
if (IS_ERR(cell))
return PTR_ERR(cell);
afs_put_cell(params->cell);
afs_put_cell(params->net, params->cell);
params->cell = cell;
break;

Expand Down Expand Up @@ -314,7 +314,7 @@ static int afs_parse_device_name(struct afs_mount_params *params,
cellnamesz, cellnamesz, cellname ?: "");
return PTR_ERR(cell);
}
afs_put_cell(params->cell);
afs_put_cell(params->net, params->cell);
params->cell = cell;
}

Expand Down Expand Up @@ -409,8 +409,8 @@ static struct afs_super_info *afs_alloc_sbi(struct afs_mount_params *params)
static void afs_destroy_sbi(struct afs_super_info *as)
{
if (as) {
afs_put_volume(as->net, as->volume);
afs_put_cell(as->cell);
afs_put_volume(as->cell, as->volume);
afs_put_cell(as->net, as->cell);
afs_put_net(as->net);
kfree(as);
}
Expand Down Expand Up @@ -494,7 +494,7 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
as = NULL;
}

afs_put_cell(params.cell);
afs_put_cell(params.net, params.cell);
key_put(params.key);
_leave(" = 0 [%p]", sb);
return dget(sb->s_root);
Expand All @@ -504,7 +504,7 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
error_as:
afs_destroy_sbi(as);
error:
afs_put_cell(params.cell);
afs_put_cell(params.net, params.cell);
key_put(params.key);
_leave(" = %d", ret);
return ERR_PTR(ret);
Expand Down
6 changes: 3 additions & 3 deletions fs/afs/vlocation.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,14 +518,14 @@ void afs_put_vlocation(struct afs_net *net, struct afs_vlocation *vl)
/*
* destroy a dead volume location record
*/
static void afs_vlocation_destroy(struct afs_vlocation *vl)
static void afs_vlocation_destroy(struct afs_net *net, struct afs_vlocation *vl)
{
_enter("%p", vl);

#ifdef CONFIG_AFS_FSCACHE
fscache_relinquish_cookie(vl->cache, 0);
#endif
afs_put_cell(vl->cell);
afs_put_cell(net, vl->cell);
kfree(vl);
}

Expand Down Expand Up @@ -580,7 +580,7 @@ void afs_vlocation_reaper(struct work_struct *work)
while (!list_empty(&corpses)) {
vl = list_entry(corpses.next, struct afs_vlocation, grave);
list_del(&vl->grave);
afs_vlocation_destroy(vl);
afs_vlocation_destroy(net, vl);
}

_leave("");
Expand Down
28 changes: 14 additions & 14 deletions fs/afs/vnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static void afs_install_vnode(struct afs_vnode *vnode,

afs_get_server(server);
vnode->server = server;
afs_put_server(old_server);
afs_put_server(afs_v2net(vnode), old_server);

/* insert into the server's vnode tree in FID order */
spin_lock(&server->fs_lock);
Expand Down Expand Up @@ -196,7 +196,7 @@ static void afs_vnode_deleted_remotely(struct afs_vnode *vnode)
spin_unlock(&server->fs_lock);

vnode->server = NULL;
afs_put_server(server);
afs_put_server(afs_v2net(vnode), server);
} else {
ASSERT(!vnode->cb_promised);
}
Expand Down Expand Up @@ -225,7 +225,7 @@ void afs_vnode_finalise_status_update(struct afs_vnode *vnode,
spin_unlock(&vnode->lock);

wake_up_all(&vnode->update_waitq);
afs_put_server(oldserver);
afs_put_server(afs_v2net(vnode), oldserver);
_leave("");
}

Expand Down Expand Up @@ -368,7 +368,7 @@ int afs_vnode_fetch_status(struct afs_vnode *vnode,
if (auth_vnode)
afs_cache_permit(vnode, key, acl_order);
afs_vnode_finalise_status_update(vnode, server);
afs_put_server(server);
afs_put_server(afs_v2net(vnode), server);
} else {
_debug("failed [%d]", ret);
afs_vnode_status_update_failed(vnode, ret);
Expand Down Expand Up @@ -428,7 +428,7 @@ int afs_vnode_fetch_data(struct afs_vnode *vnode, struct key *key,
/* adjust the flags */
if (ret == 0) {
afs_vnode_finalise_status_update(vnode, server);
afs_put_server(server);
afs_put_server(afs_v2net(vnode), server);
} else {
afs_vnode_status_update_failed(vnode, ret);
}
Expand Down Expand Up @@ -540,7 +540,7 @@ int afs_vnode_remove(struct afs_vnode *vnode, struct key *key, const char *name,
/* adjust the flags */
if (ret == 0) {
afs_vnode_finalise_status_update(vnode, server);
afs_put_server(server);
afs_put_server(afs_v2net(vnode), server);
} else {
afs_vnode_status_update_failed(vnode, ret);
}
Expand Down Expand Up @@ -603,7 +603,7 @@ int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode,
if (ret == 0) {
afs_vnode_finalise_status_update(vnode, server);
afs_vnode_finalise_status_update(dvnode, server);
afs_put_server(server);
afs_put_server(afs_v2net(dvnode), server);
} else {
afs_vnode_status_update_failed(vnode, ret);
afs_vnode_status_update_failed(dvnode, ret);
Expand Down Expand Up @@ -738,7 +738,7 @@ int afs_vnode_rename(struct afs_vnode *orig_dvnode,
afs_vnode_finalise_status_update(orig_dvnode, server);
if (new_dvnode != orig_dvnode)
afs_vnode_finalise_status_update(new_dvnode, server);
afs_put_server(server);
afs_put_server(afs_v2net(orig_dvnode), server);
} else {
afs_vnode_status_update_failed(orig_dvnode, ret);
if (new_dvnode != orig_dvnode)
Expand Down Expand Up @@ -802,7 +802,7 @@ int afs_vnode_store_data(struct afs_writeback *wb, pgoff_t first, pgoff_t last,
/* adjust the flags */
if (ret == 0) {
afs_vnode_finalise_status_update(vnode, server);
afs_put_server(server);
afs_put_server(afs_v2net(vnode), server);
} else {
afs_vnode_status_update_failed(vnode, ret);
}
Expand Down Expand Up @@ -854,7 +854,7 @@ int afs_vnode_setattr(struct afs_vnode *vnode, struct key *key,
/* adjust the flags */
if (ret == 0) {
afs_vnode_finalise_status_update(vnode, server);
afs_put_server(server);
afs_put_server(afs_v2net(vnode), server);
} else {
afs_vnode_status_update_failed(vnode, ret);
}
Expand Down Expand Up @@ -900,7 +900,7 @@ int afs_vnode_get_volume_status(struct afs_vnode *vnode, struct key *key,

/* adjust the flags */
if (ret == 0)
afs_put_server(server);
afs_put_server(afs_v2net(vnode), server);

_leave(" = %d", ret);
return ret;
Expand Down Expand Up @@ -939,7 +939,7 @@ int afs_vnode_set_lock(struct afs_vnode *vnode, struct key *key,

/* adjust the flags */
if (ret == 0)
afs_put_server(server);
afs_put_server(afs_v2net(vnode), server);

_leave(" = %d", ret);
return ret;
Expand Down Expand Up @@ -977,7 +977,7 @@ int afs_vnode_extend_lock(struct afs_vnode *vnode, struct key *key)

/* adjust the flags */
if (ret == 0)
afs_put_server(server);
afs_put_server(afs_v2net(vnode), server);

_leave(" = %d", ret);
return ret;
Expand Down Expand Up @@ -1015,7 +1015,7 @@ int afs_vnode_release_lock(struct afs_vnode *vnode, struct key *key)

/* adjust the flags */
if (ret == 0)
afs_put_server(server);
afs_put_server(afs_v2net(vnode), server);

_leave(" = %d", ret);
return ret;
Expand Down
Loading

0 comments on commit 9ed900b

Please sign in to comment.