NFS: replace global bl_wq with per-net one

This queue is used for sleeping in kernel and it have to be per-net since we
don't want to wake any other waiters except in out network nemespace.
BTW, move wq to per-net data is easy. But some way to handle upcall timeouts
have to be provided. On message destroy in case of timeout, tasks, waiting for
message to be delivered, should be awakened. Thus, some data required to
located the right wait queue. Chosen solution replaces rpc_pipe_msg object with
new introduced bl_pipe_msg object, containing rpc_pipe_msg and proper wq.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Stanislav Kinsbursky
2012-03-11 18:20:31 +04:00
committed by Trond Myklebust
parent cb9c1c4a88
commit 5ffaf85541
5 changed files with 39 additions and 31 deletions

View File

@@ -91,16 +91,18 @@ ssize_t bl_pipe_downcall(struct file *filp, const char __user *src,
if (copy_from_user(&nn->bl_mount_reply, src, mlen) != 0)
return -EFAULT;
wake_up(&bl_wq);
wake_up(&nn->bl_wq);
return mlen;
}
void bl_pipe_destroy_msg(struct rpc_pipe_msg *msg)
{
struct bl_pipe_msg *bl_pipe_msg = container_of(msg, struct bl_pipe_msg, msg);
if (msg->errno >= 0)
return;
wake_up(&bl_wq);
wake_up(bl_pipe_msg->bl_wq);
}
/*
@@ -112,7 +114,8 @@ nfs4_blk_decode_device(struct nfs_server *server,
{
struct pnfs_block_dev *rv;
struct block_device *bd = NULL;
struct rpc_pipe_msg msg;
struct bl_pipe_msg bl_pipe_msg;
struct rpc_pipe_msg *msg = &bl_pipe_msg.msg;
struct bl_msg_hdr bl_msg = {
.type = BL_DEVICE_MOUNT,
.totallen = dev->mincount,
@@ -128,15 +131,16 @@ nfs4_blk_decode_device(struct nfs_server *server,
dprintk("%s: deviceid: %s, mincount: %d\n", __func__, dev->dev_id.data,
dev->mincount);
memset(&msg, 0, sizeof(msg));
msg.data = kzalloc(sizeof(bl_msg) + dev->mincount, GFP_NOFS);
if (!msg.data) {
bl_pipe_msg.bl_wq = &nn->bl_wq;
memset(msg, 0, sizeof(*msg));
msg->data = kzalloc(sizeof(bl_msg) + dev->mincount, GFP_NOFS);
if (!msg->data) {
rv = ERR_PTR(-ENOMEM);
goto out;
}
memcpy(msg.data, &bl_msg, sizeof(bl_msg));
dataptr = (uint8_t *) msg.data;
memcpy(msg->data, &bl_msg, sizeof(bl_msg));
dataptr = (uint8_t *) msg->data;
len = dev->mincount;
offset = sizeof(bl_msg);
for (i = 0; len > 0; i++) {
@@ -145,13 +149,13 @@ nfs4_blk_decode_device(struct nfs_server *server,
len -= PAGE_CACHE_SIZE;
offset += PAGE_CACHE_SIZE;
}
msg.len = sizeof(bl_msg) + dev->mincount;
msg->len = sizeof(bl_msg) + dev->mincount;
dprintk("%s CALLING USERSPACE DAEMON\n", __func__);
add_wait_queue(&bl_wq, &wq);
rc = rpc_queue_upcall(nn->bl_device_pipe, &msg);
add_wait_queue(&nn->bl_wq, &wq);
rc = rpc_queue_upcall(nn->bl_device_pipe, msg);
if (rc < 0) {
remove_wait_queue(&bl_wq, &wq);
remove_wait_queue(&nn->bl_wq, &wq);
rv = ERR_PTR(rc);
goto out;
}
@@ -159,7 +163,7 @@ nfs4_blk_decode_device(struct nfs_server *server,
set_current_state(TASK_UNINTERRUPTIBLE);
schedule();
__set_current_state(TASK_RUNNING);
remove_wait_queue(&bl_wq, &wq);
remove_wait_queue(&nn->bl_wq, &wq);
if (reply->status != BL_DEVICE_REQUEST_PROC) {
dprintk("%s failed to open device: %d\n",
@@ -191,7 +195,7 @@ nfs4_blk_decode_device(struct nfs_server *server,
bd->bd_block_size);
out:
kfree(msg.data);
kfree(msg->data);
return rv;
}