summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/afs/afs.h9
-rw-r--r--fs/afs/callback.c24
-rw-r--r--fs/afs/cell.c130
-rw-r--r--fs/afs/cmservice.c26
-rw-r--r--fs/afs/flock.c39
-rw-r--r--fs/afs/fsclient.c56
-rw-r--r--fs/afs/internal.h163
-rw-r--r--fs/afs/main.c153
-rw-r--r--fs/afs/proc.c64
-rw-r--r--fs/afs/rxrpc.c132
-rw-r--r--fs/afs/server.c82
-rw-r--r--fs/afs/super.c45
-rw-r--r--fs/afs/vlclient.c10
-rw-r--r--fs/afs/vlocation.c151
-rw-r--r--fs/afs/volume.c10
-rw-r--r--include/uapi/linux/magic.h1
16 files changed, 603 insertions, 492 deletions
diff --git a/fs/afs/afs.h b/fs/afs/afs.h
index 3c462ff6db63..93053115bcfc 100644
--- a/fs/afs/afs.h
+++ b/fs/afs/afs.h
@@ -72,6 +72,15 @@ struct afs_callback {
#define AFSCBMAX 50 /* maximum callbacks transferred per bulk op */
+struct afs_uuid {
+ __be32 time_low; /* low part of timestamp */
+ __be16 time_mid; /* mid part of timestamp */
+ __be16 time_hi_and_version; /* high part of timestamp and version */
+ __u8 clock_seq_hi_and_reserved; /* clock seq hi and variant */
+ __u8 clock_seq_low; /* clock seq low */
+ __u8 node[6]; /* spatially unique node ID (MAC addr) */
+};
+
/*
* AFS volume information
*/
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index 25d404d22cae..d12dffb76b67 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -28,9 +28,7 @@ unsigned afs_vnode_update_timeout = 10;
CIRC_SPACE((server)->cb_break_head, (server)->cb_break_tail, \
ARRAY_SIZE((server)->cb_break))
-//static void afs_callback_updater(struct work_struct *);
-
-static struct workqueue_struct *afs_callback_update_worker;
+struct workqueue_struct *afs_callback_update_worker;
/*
* allow the fileserver to request callback state (re-)initialisation
@@ -343,7 +341,7 @@ void afs_dispatch_give_up_callbacks(struct work_struct *work)
* had callbacks entirely, and the server will call us later to break
* them
*/
- afs_fs_give_up_callbacks(server, true);
+ afs_fs_give_up_callbacks(server->cell->net, server, true);
}
/*
@@ -456,21 +454,3 @@ static void afs_callback_updater(struct work_struct *work)
afs_put_vnode(vl);
}
#endif
-
-/*
- * initialise the callback update process
- */
-int __init afs_callback_update_init(void)
-{
- afs_callback_update_worker = alloc_ordered_workqueue("kafs_callbackd",
- WQ_MEM_RECLAIM);
- return afs_callback_update_worker ? 0 : -ENOMEM;
-}
-
-/*
- * shut down the callback update process
- */
-void afs_callback_update_kill(void)
-{
- destroy_workqueue(afs_callback_update_worker);
-}
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index ca0a3cf93791..bd570fa539a0 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -18,20 +18,12 @@
#include <keys/rxrpc-type.h>
#include "internal.h"
-DECLARE_RWSEM(afs_proc_cells_sem);
-LIST_HEAD(afs_proc_cells);
-
-static LIST_HEAD(afs_cells);
-static DEFINE_RWLOCK(afs_cells_lock);
-static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */
-static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freeable_wq);
-static struct afs_cell *afs_cell_root;
-
/*
* allocate a cell record and fill in its name, VL server address list and
* allocate an anonymous key
*/
-static struct afs_cell *afs_cell_alloc(const char *name, unsigned namelen,
+static struct afs_cell *afs_cell_alloc(struct afs_net *net,
+ const char *name, unsigned namelen,
char *vllist)
{
struct afs_cell *cell;
@@ -62,6 +54,7 @@ static struct afs_cell *afs_cell_alloc(const char *name, unsigned namelen,
atomic_set(&cell->usage, 1);
INIT_LIST_HEAD(&cell->link);
+ cell->net = net;
rwlock_init(&cell->servers_lock);
INIT_LIST_HEAD(&cell->servers);
init_rwsem(&cell->vl_sem);
@@ -142,12 +135,14 @@ error:
/*
* afs_cell_crate() - create a cell record
+ * @net: The network namespace
* @name: is the name of the cell.
* @namsesz: is the strlen of the cell name.
* @vllist: is a colon separated list of IP addresses in "a.b.c.d" format.
* @retref: is T to return the cell reference when the cell exists.
*/
-struct afs_cell *afs_cell_create(const char *name, unsigned namesz,
+struct afs_cell *afs_cell_create(struct afs_net *net,
+ const char *name, unsigned namesz,
char *vllist, bool retref)
{
struct afs_cell *cell;
@@ -155,23 +150,23 @@ struct afs_cell *afs_cell_create(const char *name, unsigned namesz,
_enter("%*.*s,%s", namesz, namesz, name ?: "", vllist);
- down_write(&afs_cells_sem);
- read_lock(&afs_cells_lock);
- list_for_each_entry(cell, &afs_cells, link) {
+ down_write(&net->cells_sem);
+ read_lock(&net->cells_lock);
+ list_for_each_entry(cell, &net->cells, link) {
if (strncasecmp(cell->name, name, namesz) == 0)
goto duplicate_name;
}
- read_unlock(&afs_cells_lock);
+ read_unlock(&net->cells_lock);
- cell = afs_cell_alloc(name, namesz, vllist);
+ cell = afs_cell_alloc(net, name, namesz, vllist);
if (IS_ERR(cell)) {
_leave(" = %ld", PTR_ERR(cell));
- up_write(&afs_cells_sem);
+ up_write(&net->cells_sem);
return cell;
}
/* add a proc directory for this cell */
- ret = afs_proc_cell_setup(cell);
+ ret = afs_proc_cell_setup(net, cell);
if (ret < 0)
goto error;
@@ -183,20 +178,20 @@ struct afs_cell *afs_cell_create(const char *name, unsigned namesz,
#endif
/* add to the cell lists */
- write_lock(&afs_cells_lock);
- list_add_tail(&cell->link, &afs_cells);
- write_unlock(&afs_cells_lock);
+ write_lock(&net->cells_lock);
+ list_add_tail(&cell->link, &net->cells);
+ write_unlock(&net->cells_lock);
- down_write(&afs_proc_cells_sem);
- list_add_tail(&cell->proc_link, &afs_proc_cells);
- up_write(&afs_proc_cells_sem);
- up_write(&afs_cells_sem);
+ down_write(&net->proc_cells_sem);
+ list_add_tail(&cell->proc_link, &net->proc_cells);
+ up_write(&net->proc_cells_sem);
+ up_write(&net->cells_sem);
_leave(" = %p", cell);
return cell;
error:
- up_write(&afs_cells_sem);
+ up_write(&net->cells_sem);
key_put(cell->anonymous_key);
kfree(cell);
_leave(" = %d", ret);
@@ -206,8 +201,8 @@ duplicate_name:
if (retref && !IS_ERR(cell))
afs_get_cell(cell);
- read_unlock(&afs_cells_lock);
- up_write(&afs_cells_sem);
+ read_unlock(&net->cells_lock);
+ up_write(&net->cells_sem);
if (retref) {
_leave(" = %p", cell);
@@ -223,7 +218,7 @@ duplicate_name:
* - can be called with a module parameter string
* - can be called from a write to /proc/fs/afs/rootcell
*/
-int afs_cell_init(char *rootcell)
+int afs_cell_init(struct afs_net *net, char *rootcell)
{
struct afs_cell *old_root, *new_root;
char *cp;
@@ -245,17 +240,17 @@ int afs_cell_init(char *rootcell)
*cp++ = 0;
/* allocate a cell record for the root cell */
- new_root = afs_cell_create(rootcell, strlen(rootcell), cp, false);
+ new_root = afs_cell_create(net, rootcell, strlen(rootcell), cp, false);
if (IS_ERR(new_root)) {
_leave(" = %ld", PTR_ERR(new_root));
return PTR_ERR(new_root);
}
/* install the new cell */
- write_lock(&afs_cells_lock);
- old_root = afs_cell_root;
- afs_cell_root = new_root;
- write_unlock(&afs_cells_lock);
+ write_lock(&net->cells_lock);
+ old_root = net->ws_cell;
+ net->ws_cell = new_root;
+ write_unlock(&net->cells_lock);
afs_put_cell(old_root);
_leave(" = 0");
@@ -265,19 +260,20 @@ int afs_cell_init(char *rootcell)
/*
* lookup a cell record
*/
-struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz,
+struct afs_cell *afs_cell_lookup(struct afs_net *net,
+ const char *name, unsigned namesz,
bool dns_cell)
{
struct afs_cell *cell;
_enter("\"%*.*s\",", namesz, namesz, name ?: "");
- down_read(&afs_cells_sem);
- read_lock(&afs_cells_lock);
+ down_read(&net->cells_sem);
+ read_lock(&net->cells_lock);
if (name) {
/* if the cell was named, look for it in the cell record list */
- list_for_each_entry(cell, &afs_cells, link) {
+ list_for_each_entry(cell, &net->cells, link) {
if (strncmp(cell->name, name, namesz) == 0) {
afs_get_cell(cell);
goto found;
@@ -289,7 +285,7 @@ struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz,
found:
;
} else {
- cell = afs_cell_root;
+ cell = net->ws_cell;
if (!cell) {
/* this should not happen unless user tries to mount
* when root cell is not set. Return an impossibly
@@ -304,16 +300,16 @@ struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz,
}
- read_unlock(&afs_cells_lock);
- up_read(&afs_cells_sem);
+ read_unlock(&net->cells_lock);
+ up_read(&net->cells_sem);
_leave(" = %p", cell);
return cell;
create_cell:
- read_unlock(&afs_cells_lock);
- up_read(&afs_cells_sem);
+ read_unlock(&net->cells_lock);
+ up_read(&net->cells_sem);
- cell = afs_cell_create(name, namesz, NULL, true);
+ cell = afs_cell_create(net, name, namesz, NULL, true);
_leave(" = %p", cell);
return cell;
@@ -325,14 +321,14 @@ create_cell:
*/
struct afs_cell *afs_get_cell_maybe(struct afs_cell *cell)
{
- write_lock(&afs_cells_lock);
+ write_lock(&net->cells_lock);
if (cell && !list_empty(&cell->link))
afs_get_cell(cell);
else
cell = NULL;
- write_unlock(&afs_cells_lock);
+ write_unlock(&net->cells_lock);
return cell;
}
#endif /* 0 */
@@ -351,10 +347,10 @@ void afs_put_cell(struct afs_cell *cell)
/* to prevent a race, the decrement and the dequeue must be effectively
* atomic */
- write_lock(&afs_cells_lock);
+ write_lock(&cell->net->cells_lock);
if (likely(!atomic_dec_and_test(&cell->usage))) {
- write_unlock(&afs_cells_lock);
+ write_unlock(&cell->net->cells_lock);
_leave("");
return;
}
@@ -362,19 +358,19 @@ void afs_put_cell(struct afs_cell *cell)
ASSERT(list_empty(&cell->servers));
ASSERT(list_empty(&cell->vl_list));
- write_unlock(&afs_cells_lock);
+ wake_up(&cell->net->cells_freeable_wq);
- wake_up(&afs_cells_freeable_wq);
+ write_unlock(&cell->net->cells_lock);
_leave(" [unused]");
}
/*
* destroy a cell record
- * - must be called with the afs_cells_sem write-locked
+ * - must be called with the net->cells_sem write-locked
* - cell->link should have been broken by the caller
*/
-static void afs_cell_destroy(struct afs_cell *cell)
+static void afs_cell_destroy(struct afs_net *net, struct afs_cell *cell)
{
_enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name);
@@ -387,14 +383,14 @@ static void afs_cell_destroy(struct afs_cell *cell)
_debug("wait for cell %s", cell->name);
set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&afs_cells_freeable_wq, &myself);
+ add_wait_queue(&net->cells_freeable_wq, &myself);
while (atomic_read(&cell->usage) > 0) {
schedule();
set_current_state(TASK_UNINTERRUPTIBLE);
}
- remove_wait_queue(&afs_cells_freeable_wq, &myself);
+ remove_wait_queue(&net->cells_freeable_wq, &myself);
set_current_state(TASK_RUNNING);
}
@@ -403,11 +399,11 @@ static void afs_cell_destroy(struct afs_cell *cell)
ASSERT(list_empty(&cell->servers));
ASSERT(list_empty(&cell->vl_list));
- afs_proc_cell_remove(cell);
+ afs_proc_cell_remove(net, cell);
- down_write(&afs_proc_cells_sem);
+ down_write(&net->proc_cells_sem);
list_del_init(&cell->proc_link);
- up_write(&afs_proc_cells_sem);
+ up_write(&net->proc_cells_sem);
#ifdef CONFIG_AFS_FSCACHE
fscache_relinquish_cookie(cell->cache, 0);
@@ -422,39 +418,39 @@ static void afs_cell_destroy(struct afs_cell *cell)
* purge in-memory cell database on module unload or afs_init() failure
* - the timeout daemon is stopped before calling this
*/
-void afs_cell_purge(void)
+void afs_cell_purge(struct afs_net *net)
{
struct afs_cell *cell;
_enter("");
- afs_put_cell(afs_cell_root);
+ afs_put_cell(net->ws_cell);
- down_write(&afs_cells_sem);
+ down_write(&net->cells_sem);
- while (!list_empty(&afs_cells)) {
+ while (!list_empty(&net->cells)) {
cell = NULL;
/* remove the next cell from the front of the list */
- write_lock(&afs_cells_lock);
+ write_lock(&net->cells_lock);
- if (!list_empty(&afs_cells)) {
- cell = list_entry(afs_cells.next,
+ if (!list_empty(&net->cells)) {
+ cell = list_entry(net->cells.next,
struct afs_cell, link);
list_del_init(&cell->link);
}
- write_unlock(&afs_cells_lock);
+ write_unlock(&net->cells_lock);
if (cell) {
_debug("PURGING CELL %s (%d)",
cell->name, atomic_read(&cell->usage));
/* now the cell should be left with no references */
- afs_cell_destroy(cell);
+ afs_cell_destroy(net, cell);
}
}
- up_write(&afs_cells_sem);
+ up_write(&net->cells_sem);
_leave("");
}
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index 782d4d05a53b..30ce4be4165f 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -193,7 +193,7 @@ static int afs_deliver_cb_callback(struct afs_call *call)
switch (call->unmarshall) {
case 0:
- rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);
+ rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
call->offset = 0;
call->unmarshall++;
@@ -290,7 +290,7 @@ static int afs_deliver_cb_callback(struct afs_call *call)
/* we'll need the file server record as that tells us which set of
* vnodes to operate upon */
- server = afs_find_server(&srx);
+ server = afs_find_server(call->net, &srx);
if (!server)
return -ENOTCONN;
call->server = server;
@@ -324,7 +324,7 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
_enter("");
- rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);
+ rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
ret = afs_extract_data(call, NULL, 0, false);
if (ret < 0)
@@ -335,7 +335,7 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
/* we'll need the file server record as that tells us which set of
* vnodes to operate upon */
- server = afs_find_server(&srx);
+ server = afs_find_server(call->net, &srx);
if (!server)
return -ENOTCONN;
call->server = server;
@@ -357,7 +357,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
_enter("");
- rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);
+ rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
_enter("{%u}", call->unmarshall);
@@ -407,7 +407,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
/* we'll need the file server record as that tells us which set of
* vnodes to operate upon */
- server = afs_find_server(&srx);
+ server = afs_find_server(call->net, &srx);
if (!server)
return -ENOTCONN;
call->server = server;
@@ -461,7 +461,7 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work)
_enter("");
- if (memcmp(r, &afs_uuid, sizeof(afs_uuid)) == 0)
+ if (memcmp(r, &call->net->uuid, sizeof(call->net->uuid)) == 0)
reply.match = htonl(0);
else
reply.match = htonl(1);
@@ -568,13 +568,13 @@ static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
memset(&reply, 0, sizeof(reply));
reply.ia.nifs = htonl(nifs);
- reply.ia.uuid[0] = afs_uuid.time_low;
- reply.ia.uuid[1] = htonl(ntohs(afs_uuid.time_mid));
- reply.ia.uuid[2] = htonl(ntohs(afs_uuid.time_hi_and_version));
- reply.ia.uuid[3] = htonl((s8) afs_uuid.clock_seq_hi_and_reserved);
- reply.ia.uuid[4] = htonl((s8) afs_uuid.clock_seq_low);
+ reply.ia.uuid[0] = call->net->uuid.time_low;
+ reply.ia.uuid[1] = htonl(ntohs(call->net->uuid.time_mid));
+ reply.ia.uuid[2] = htonl(ntohs(call->net->uuid.time_hi_and_version));
+ reply.ia.uuid[3] = htonl((s8) call->net->uuid.clock_seq_hi_and_reserved);
+ reply.ia.uuid[4] = htonl((s8) call->net->uuid.clock_seq_low);
for (loop = 0; loop < 6; loop++)
- reply.ia.uuid[loop + 5] = htonl((s8) afs_uuid.node[loop]);
+ reply.ia.uuid[loop + 5] = htonl((s8) call->net->uuid.node[loop]);
if (ifs) {
for (loop = 0; loop < nifs; loop++) {
diff --git a/fs/afs/flock.c b/fs/afs/flock.c
index 3191dff2c156..559ac00af5f7 100644
--- a/fs/afs/flock.c
+++ b/fs/afs/flock.c
@@ -14,48 +14,17 @@
#define AFS_LOCK_GRANTED 0
#define AFS_LOCK_PENDING 1
+struct workqueue_struct *afs_lock_manager;
+
static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl);
static void afs_fl_release_private(struct file_lock *fl);
-static struct workqueue_struct *afs_lock_manager;
-static DEFINE_MUTEX(afs_lock_manager_mutex);
-
static const struct file_lock_operations afs_lock_ops = {
.fl_copy_lock = afs_fl_copy_lock,
.fl_release_private = afs_fl_release_private,
};
/*
- * initialise the lock manager thread if it isn't already running
- */
-static int afs_init_lock_manager(void)
-{
- int ret;
-
- ret = 0;
- if (!afs_lock_manager) {
- mutex_lock(&afs_lock_manager_mutex);
- if (!afs_lock_manager) {
- afs_lock_manager = alloc_workqueue("kafs_lockd",
- WQ_MEM_RECLAIM, 0);
- if (!afs_lock_manager)
- ret = -ENOMEM;
- }
- mutex_unlock(&afs_lock_manager_mutex);
- }
- return ret;
-}
-
-/*
- * destroy the lock manager thread if it's running
- */
-void __exit afs_kill_lock_manager(void)
-{
- if (afs_lock_manager)
- destroy_workqueue(afs_lock_manager);
-}
-
-/*
* if the callback is broken on this vnode, then the lock may now be available
*/
void afs_lock_may_be_available(struct afs_vnode *vnode)
@@ -264,10 +233,6 @@ static int afs_do_setlk(struct file *file, struct file_lock *fl)
if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
return -EINVAL;
- ret = afs_init_lock_manager();
- if (ret < 0)
- return ret;
-
fl->fl_ops = &afs_lock_ops;
INIT_LIST_HEAD(&fl->fl_u.afs.link);
fl->fl_u.afs.state = AFS_LOCK_PENDING;
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 19f76ae36982..ce6f0159e1d4 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -284,12 +284,13 @@ int afs_fs_fetch_file_status(struct afs_server *server,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
__be32 *bp;
_enter(",%x,{%x:%u},,",
key_serial(key), vnode->fid.vid, vnode->fid.vnode);
- call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
+ call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
if (!call)
return -ENOMEM;
@@ -490,11 +491,12 @@ static int afs_fs_fetch_data64(struct afs_server *server,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
__be32 *bp;
_enter("");
- call = afs_alloc_flat_call(&afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
+ call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
if (!call)
return -ENOMEM;
@@ -531,6 +533,7 @@ int afs_fs_fetch_data(struct afs_server *server,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
__be32 *bp;
if (upper_32_bits(req->pos) ||
@@ -540,7 +543,7 @@ int afs_fs_fetch_data(struct afs_server *server,
_enter("");
- call = afs_alloc_flat_call(&afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
+ call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
if (!call)
return -ENOMEM;
@@ -590,7 +593,8 @@ static const struct afs_call_type afs_RXFSGiveUpCallBacks = {
* give up a set of callbacks
* - the callbacks are held in the server->cb_break ring
*/
-int afs_fs_give_up_callbacks(struct afs_server *server,
+int afs_fs_give_up_callbacks(struct afs_net *net,
+ struct afs_server *server,
bool async)
{
struct afs_call *call;
@@ -610,7 +614,7 @@ int afs_fs_give_up_callbacks(struct afs_server *server,
_debug("break %zu callbacks", ncallbacks);
- call = afs_alloc_flat_call(&afs_RXFSGiveUpCallBacks,
+ call = afs_alloc_flat_call(net, &afs_RXFSGiveUpCallBacks,
12 + ncallbacks * 6 * 4, 0);
if (!call)
return -ENOMEM;
@@ -699,6 +703,7 @@ int afs_fs_create(struct afs_server *server,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
size_t namesz, reqsz, padsz;
__be32 *bp;
@@ -708,7 +713,7 @@ int afs_fs_create(struct afs_server *server,
padsz = (4 - (namesz & 3)) & 3;
reqsz = (5 * 4) + namesz + padsz + (6 * 4);
- call = afs_alloc_flat_call(&afs_RXFSCreateXXXX, reqsz,
+ call = afs_alloc_flat_call(net, &afs_RXFSCreateXXXX, reqsz,
(3 + 21 + 21 + 3 + 6) * 4);
if (!call)
return -ENOMEM;
@@ -789,6 +794,7 @@ int afs_fs_remove(struct afs_server *server,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
size_t namesz, reqsz, padsz;
__be32 *bp;
@@ -798,7 +804,7 @@ int afs_fs_remove(struct afs_server *server,
padsz = (4 - (namesz & 3)) & 3;
reqsz = (5 * 4) + namesz + padsz;
- call = afs_alloc_flat_call(&afs_RXFSRemoveXXXX, reqsz, (21 + 6) * 4);
+ call = afs_alloc_flat_call(net, &afs_RXFSRemoveXXXX, reqsz, (21 + 6) * 4);
if (!call)
return -ENOMEM;
@@ -870,6 +876,7 @@ int afs_fs_link(struct afs_server *server,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
size_t namesz, reqsz, padsz;
__be32 *bp;
@@ -879,7 +886,7 @@ int afs_fs_link(struct afs_server *server,
padsz = (4 - (namesz & 3)) & 3;
reqsz = (5 * 4) + namesz + padsz + (3 * 4);
- call = afs_alloc_flat_call(&afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
+ call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
if (!call)
return -ENOMEM;
@@ -958,6 +965,7 @@ int afs_fs_symlink(struct afs_server *server,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
size_t namesz, reqsz, padsz, c_namesz, c_padsz;
__be32 *bp;
@@ -971,7 +979,7 @@ int afs_fs_symlink(struct afs_server *server,
reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
- call = afs_alloc_flat_call(&afs_RXFSSymlink, reqsz,
+ call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
(3 + 21 + 21 + 6) * 4);
if (!call)
return -ENOMEM;
@@ -1062,6 +1070,7 @@ int afs_fs_rename(struct afs_server *server,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(orig_dvnode);
size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
__be32 *bp;
@@ -1078,7 +1087,7 @@ int afs_fs_rename(struct afs_server *server,
(3 * 4) +
4 + n_namesz + n_padsz;
- call = afs_alloc_flat_call(&afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
+ call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
if (!call)
return -ENOMEM;
@@ -1172,12 +1181,13 @@ static int afs_fs_store_data64(struct afs_server *server,
{
struct afs_vnode *vnode = wb->vnode;
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
__be32 *bp;
_enter(",%x,{%x:%u},,",
key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
- call = afs_alloc_flat_call(&afs_RXFSStoreData64,
+ call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
(4 + 6 + 3 * 2) * 4,
(21 + 6) * 4);
if (!call)
@@ -1230,6 +1240,7 @@ int afs_fs_store_data(struct afs_server *server, struct afs_writeback *wb,
{
struct afs_vnode *vnode = wb->vnode;
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
loff_t size, pos, i_size;
__be32 *bp;
@@ -1254,7 +1265,7 @@ int afs_fs_store_data(struct afs_server *server, struct afs_writeback *wb,
return afs_fs_store_data64(server, wb, first, last, offset, to,
size, pos, i_size, async);
- call = afs_alloc_flat_call(&afs_RXFSStoreData,
+ call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
(4 + 6 + 3) * 4,
(21 + 6) * 4);
if (!call)
@@ -1356,6 +1367,7 @@ static int afs_fs_setattr_size64(struct afs_server *server, struct key *key,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
__be32 *bp;
_enter(",%x,{%x:%u},,",
@@ -1363,7 +1375,7 @@ static int afs_fs_setattr_size64(struct afs_server *server, struct key *key,
ASSERT(attr->ia_valid & ATTR_SIZE);
- call = afs_alloc_flat_call(&afs_RXFSStoreData64_as_Status,
+ call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
(4 + 6 + 3 * 2) * 4,
(21 + 6) * 4);
if (!call)
@@ -1404,6 +1416,7 @@ static int afs_fs_setattr_size(struct afs_server *server, struct key *key,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
__be32 *bp;
_enter(",%x,{%x:%u},,",
@@ -1414,7 +1427,7 @@ static int afs_fs_setattr_size(struct afs_server *server, struct key *key,
return afs_fs_setattr_size64(server, key, vnode, attr,
async);
- call = afs_alloc_flat_call(&afs_RXFSStoreData_as_Status,
+ call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
(4 + 6 + 3) * 4,
(21 + 6) * 4);
if (!call)
@@ -1452,6 +1465,7 @@ int afs_fs_setattr(struct afs_server *server, struct key *key,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
__be32 *bp;
if (attr->ia_valid & ATTR_SIZE)
@@ -1461,7 +1475,7 @@ int afs_fs_setattr(struct afs_server *server, struct key *key,
_enter(",%x,{%x:%u},,",
key_serial(key), vnode->fid.vid, vnode->fid.vnode);
- call = afs_alloc_flat_call(&afs_RXFSStoreStatus,
+ call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
(4 + 6) * 4,
(21 + 6) * 4);
if (!call)
@@ -1687,6 +1701,7 @@ int afs_fs_get_volume_status(struct afs_server *server,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
__be32 *bp;
void *tmpbuf;
@@ -1696,7 +1711,7 @@ int afs_fs_get_volume_status(struct afs_server *server,
if (!tmpbuf)
return -ENOMEM;
- call = afs_alloc_flat_call(&afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
+ call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
if (!call) {
kfree(tmpbuf);
return -ENOMEM;
@@ -1779,11 +1794,12 @@ int afs_fs_set_lock(struct afs_server *server,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
__be32 *bp;
_enter("");
- call = afs_alloc_flat_call(&afs_RXFSSetLock, 5 * 4, 6 * 4);
+ call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
if (!call)
return -ENOMEM;
@@ -1812,11 +1828,12 @@ int afs_fs_extend_lock(struct afs_server *server,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
__be32 *bp;
_enter("");
- call = afs_alloc_flat_call(&afs_RXFSExtendLock, 4 * 4, 6 * 4);
+ call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
if (!call)
return -ENOMEM;
@@ -1844,11 +1861,12 @@ int afs_fs_release_lock(struct afs_server *server,
bool async)
{
struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
__be32 *bp;
_enter("");
- call = afs_alloc_flat_call(&afs_RXFSReleaseLock, 4 * 4, 6 * 4);
+ call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
if (!call)
return -ENOMEM;
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 3f03f7888302..53bd11d73469 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -21,6 +21,7 @@
#include <linux/fscache.h>
#include <linux/backing-dev.h>
#include <linux/uuid.h>
+#include <net/net_namespace.h>
#include <net/af_rxrpc.h>
#include "afs.h"
@@ -48,6 +49,7 @@ struct afs_mount_params {
afs_voltype_t type; /* type of volume requested */
int volnamesz; /* size of volume name */
const char *volname; /* name of volume to mount */
+ struct afs_net *net; /* Network namespace in effect */
struct afs_cell *cell; /* cell in which to find volume */
struct afs_volume *volume; /* volume record */
struct key *key; /* key to use for secure mounting */
@@ -62,6 +64,7 @@ enum afs_call_state {
AFS_CALL_AWAIT_ACK, /* awaiting final ACK of incoming call */
AFS_CALL_COMPLETE, /* Completed or failed */
};
+
/*
* a record of an in-progress RxRPC call
*/
@@ -72,6 +75,7 @@ struct afs_call {
struct work_struct work; /* actual work processor */
struct rxrpc_call *rxcall; /* RxRPC call handle */
struct key *key; /* security for this call */
+ struct afs_net *net; /* The network namespace */
struct afs_server *server; /* server affected by incoming CM call */
void *request; /* request data (first part) */
struct address_space *mapping; /* page set */
@@ -173,6 +177,7 @@ struct afs_writeback {
* - there's one superblock per volume
*/
struct afs_super_info {
+ struct afs_net *net; /* Network namespace */
struct afs_volume *volume; /* volume record */
char rwparent; /* T if parent is R/W AFS volume */
};
@@ -193,11 +198,61 @@ struct afs_cache_cell {
};
/*
+ * AFS network namespace record.
+ */
+struct afs_net {
+ struct afs_uuid uuid;
+ bool live; /* F if this namespace is being removed */
+
+ /* AF_RXRPC I/O stuff */
+ struct socket *socket;
+ struct afs_call *spare_incoming_call;
+ struct work_struct charge_preallocation_work;
+ struct mutex socket_mutex;
+ atomic_t nr_outstanding_calls;
+ atomic_t nr_superblocks;
+
+ /* Cell database */
+ struct list_head cells;
+ struct afs_cell *ws_cell;
+ rwlock_t cells_lock;
+ struct rw_semaphore cells_sem;
+ wait_queue_head_t cells_freeable_wq;
+
+ struct rw_semaphore proc_cells_sem;
+ struct list_head proc_cells;
+
+ /* Volume location database */
+ struct list_head vl_updates; /* VL records in need-update order */
+ struct list_head vl_graveyard; /* Inactive VL records */
+ struct delayed_work vl_reaper;
+ struct delayed_work vl_updater;
+ spinlock_t vl_updates_lock;
+ spinlock_t vl_graveyard_lock;
+
+ /* File locking renewal management */
+ struct mutex lock_manager_mutex;
+
+ /* Server database */
+ struct rb_root servers; /* Active servers */
+ rwlock_t servers_lock;
+ struct list_head server_graveyard; /* Inactive server LRU list */
+ spinlock_t server_graveyard_lock;
+ struct delayed_work server_reaper;
+
+ /* Misc */
+ struct proc_dir_entry *proc_afs; /* /proc/net/afs directory */
+};
+
+extern struct afs_net __afs_net;// Dummy AFS network namespace; TODO: replace with real netns
+
+/*
* AFS cell record
*/
struct afs_cell {
atomic_t usage;
struct list_head link; /* main cell list link */
+ struct afs_net *net; /* The network namespace */
struct key *anonymous_key; /* anonymous user key for this cell */
struct list_head proc_link; /* /proc cell list link */
#ifdef CONFIG_AFS_FSCACHE
@@ -411,15 +466,6 @@ struct afs_interface {
unsigned mtu; /* MTU of interface */
};
-struct afs_uuid {
- __be32 time_low; /* low part of timestamp */
- __be16 time_mid; /* mid part of timestamp */
- __be16 time_hi_and_version; /* high part of timestamp and version */
- __u8 clock_seq_hi_and_reserved; /* clock seq hi and variant */
- __u8 clock_seq_low; /* clock seq low */
- __u8 node[6]; /* spatially unique node ID (MAC addr) */
-};
-
/*****************************************************************************/
/*
* cache.c
@@ -440,6 +486,8 @@ extern struct fscache_cookie_def afs_vnode_cache_index_def;
/*
* callback.c
*/
+extern struct workqueue_struct *afs_callback_update_worker;
+
extern void afs_init_callback_state(struct afs_server *);
extern void afs_broken_callback_work(struct work_struct *);
extern void afs_break_callbacks(struct afs_server *, size_t,
@@ -448,22 +496,17 @@ extern void afs_discard_callback_on_delete(struct afs_vnode *);
extern void afs_give_up_callback(struct afs_vnode *);
extern void afs_dispatch_give_up_callbacks(struct work_struct *);
extern void afs_flush_callback_breaks(struct afs_server *);
-extern int __init afs_callback_update_init(void);
-extern void afs_callback_update_kill(void);
/*
* cell.c
*/
-extern struct rw_semaphore afs_proc_cells_sem;