aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/blocklayout/rpc_pipefs.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2014-09-10 20:37:27 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-09-12 13:33:50 -0400
commit5c83746a0cf2831d4b59f5cf99ef5fbf138564e4 (patch)
treefebe14fb7fea5b7716fc07a2996be4253f09a663 /fs/nfs/blocklayout/rpc_pipefs.c
parent871760ce97a9a544cfb1ae4589598b25b8570a25 (diff)
pnfs/blocklayout: in-kernel GETDEVICEINFO XDR parsing
This patches moves parsing of the GETDEVICEINFO XDR to kernel space, as well as the management of complex devices. The reason for that is we might have multiple outstanding complex devices after a NOTIFY_DEVICEID4_CHANGE, which device mapper or md can't handle as they claim devices exclusively. But as is turns out simple striping / concatenation is fairly trivial to implement anyway, so we make our life simpler by reducing the reliance on blkmapd. For now we still use blkmapd by feeding it synthetic SIMPLE device XDR to translate device signatures to device numbers, but in the long runs I have plans to eliminate it entirely. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/blocklayout/rpc_pipefs.c')
-rw-r--r--fs/nfs/blocklayout/rpc_pipefs.c141
1 files changed, 32 insertions, 109 deletions
diff --git a/fs/nfs/blocklayout/rpc_pipefs.c b/fs/nfs/blocklayout/rpc_pipefs.c
index bfb04861eb61..8d04bda2bd2e 100644
--- a/fs/nfs/blocklayout/rpc_pipefs.c
+++ b/fs/nfs/blocklayout/rpc_pipefs.c
@@ -34,94 +34,53 @@
34 34
35#define NFSDBG_FACILITY NFSDBG_PNFS_LD 35#define NFSDBG_FACILITY NFSDBG_PNFS_LD
36 36
37static void bl_dm_remove(struct net *net, dev_t dev) 37static void
38nfs4_encode_simple(__be32 *p, struct pnfs_block_volume *b)
38{ 39{
39 struct bl_pipe_msg bl_pipe_msg; 40 int i;
40 struct rpc_pipe_msg *msg = &bl_pipe_msg.msg; 41
41 struct bl_dev_msg bl_umount_request; 42 *p++ = cpu_to_be32(1);
42 struct bl_msg_hdr bl_msg = { 43 *p++ = cpu_to_be32(b->type);
43 .type = BL_DEVICE_UMOUNT, 44 *p++ = cpu_to_be32(b->simple.nr_sigs);
44 .totallen = sizeof(bl_umount_request), 45 for (i = 0; i < b->simple.nr_sigs; i++) {
45 }; 46 p = xdr_encode_hyper(p, b->simple.sigs[i].offset);
46 uint8_t *dataptr; 47 p = xdr_encode_opaque(p, b->simple.sigs[i].sig,
47 DECLARE_WAITQUEUE(wq, current); 48 b->simple.sigs[i].sig_len);
48 struct nfs_net *nn = net_generic(net, nfs_net_id);
49
50 dprintk("Entering %s\n", __func__);
51
52 bl_pipe_msg.bl_wq = &nn->bl_wq;
53 memset(msg, 0, sizeof(*msg));
54 msg->len = sizeof(bl_msg) + bl_msg.totallen;
55 msg->data = kzalloc(msg->len, GFP_NOFS);
56 if (!msg->data)
57 goto out;
58
59 memset(&bl_umount_request, 0, sizeof(bl_umount_request));
60 bl_umount_request.major = MAJOR(dev);
61 bl_umount_request.minor = MINOR(dev);
62
63 memcpy(msg->data, &bl_msg, sizeof(bl_msg));
64 dataptr = (uint8_t *) msg->data;
65 memcpy(&dataptr[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request));
66
67 add_wait_queue(&nn->bl_wq, &wq);
68 if (rpc_queue_upcall(nn->bl_device_pipe, msg) < 0) {
69 remove_wait_queue(&nn->bl_wq, &wq);
70 goto out;
71 } 49 }
72
73 set_current_state(TASK_UNINTERRUPTIBLE);
74 schedule();
75 __set_current_state(TASK_RUNNING);
76 remove_wait_queue(&nn->bl_wq, &wq);
77
78out:
79 kfree(msg->data);
80} 50}
81 51
82/* 52dev_t
83 * Decodes pnfs_block_deviceaddr4 which is XDR encoded in dev->dev_addr_buf. 53bl_resolve_deviceid(struct nfs_server *server, struct pnfs_block_volume *b,
84 */
85struct nfs4_deviceid_node *
86bl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *dev,
87 gfp_t gfp_mask) 54 gfp_t gfp_mask)
88{ 55{
89 struct pnfs_block_dev *rv;
90 struct block_device *bd;
91 struct bl_pipe_msg bl_pipe_msg;
92 struct rpc_pipe_msg *msg = &bl_pipe_msg.msg;
93 struct bl_msg_hdr bl_msg = {
94 .type = BL_DEVICE_MOUNT,
95 .totallen = dev->mincount,
96 };
97 uint8_t *dataptr;
98 DECLARE_WAITQUEUE(wq, current);
99 int offset, len, i, rc;
100 struct net *net = server->nfs_client->cl_net; 56 struct net *net = server->nfs_client->cl_net;
101 struct nfs_net *nn = net_generic(net, nfs_net_id); 57 struct nfs_net *nn = net_generic(net, nfs_net_id);
102 struct bl_dev_msg *reply = &nn->bl_mount_reply; 58 struct bl_dev_msg *reply = &nn->bl_mount_reply;
59 struct bl_pipe_msg bl_pipe_msg;
60 struct rpc_pipe_msg *msg = &bl_pipe_msg.msg;
61 struct bl_msg_hdr *bl_msg;
62 DECLARE_WAITQUEUE(wq, current);
63 dev_t dev = 0;
64 int rc;
103 65
104 dprintk("%s CREATING PIPEFS MESSAGE\n", __func__); 66 dprintk("%s CREATING PIPEFS MESSAGE\n", __func__);
105 dprintk("%s: deviceid: %s, mincount: %d\n", __func__, dev->dev_id.data,
106 dev->mincount);
107 67
108 bl_pipe_msg.bl_wq = &nn->bl_wq; 68 bl_pipe_msg.bl_wq = &nn->bl_wq;
69
70 b->simple.len += 4; /* single volume */
71 if (b->simple.len > PAGE_SIZE)
72 return -EIO;
73
109 memset(msg, 0, sizeof(*msg)); 74 memset(msg, 0, sizeof(*msg));
110 msg->data = kzalloc(sizeof(bl_msg) + dev->mincount, gfp_mask); 75 msg->len = sizeof(*bl_msg) + b->simple.len;
76 msg->data = kzalloc(msg->len, gfp_mask);
111 if (!msg->data) 77 if (!msg->data)
112 goto out; 78 goto out;
113 79
114 memcpy(msg->data, &bl_msg, sizeof(bl_msg)); 80 bl_msg = msg->data;
115 dataptr = (uint8_t *) msg->data; 81 bl_msg->type = BL_DEVICE_MOUNT,
116 len = dev->mincount; 82 bl_msg->totallen = b->simple.len;
117 offset = sizeof(bl_msg); 83 nfs4_encode_simple(msg->data + sizeof(*bl_msg), b);
118 for (i = 0; len > 0; i++) {
119 memcpy(&dataptr[offset], page_address(dev->pages[i]),
120 len < PAGE_CACHE_SIZE ? len : PAGE_CACHE_SIZE);
121 len -= PAGE_CACHE_SIZE;
122 offset += PAGE_CACHE_SIZE;
123 }
124 msg->len = sizeof(bl_msg) + dev->mincount;
125 84
126 dprintk("%s CALLING USERSPACE DAEMON\n", __func__); 85 dprintk("%s CALLING USERSPACE DAEMON\n", __func__);
127 add_wait_queue(&nn->bl_wq, &wq); 86 add_wait_queue(&nn->bl_wq, &wq);
@@ -142,46 +101,10 @@ bl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *dev,
142 goto out; 101 goto out;
143 } 102 }
144 103
145 bd = blkdev_get_by_dev(MKDEV(reply->major, reply->minor), 104 dev = MKDEV(reply->major, reply->minor);
146 FMODE_READ, NULL);
147 if (IS_ERR(bd)) {
148 printk(KERN_WARNING "%s failed to open device %d:%d (%ld)\n",
149 __func__, reply->major, reply->minor,
150 PTR_ERR(bd));
151 goto out;
152 }
153
154 rv = kzalloc(sizeof(*rv), gfp_mask);
155 if (!rv)
156 goto out;
157
158 nfs4_init_deviceid_node(&rv->d_node, server, &dev->dev_id);
159 rv->d_bdev = bd;
160
161 dprintk("%s Created device %s with bd_block_size %u\n",
162 __func__,
163 bd->bd_disk->disk_name,
164 bd->bd_block_size);
165
166 kfree(msg->data);
167 return &rv->d_node;
168
169out: 105out:
170 kfree(msg->data); 106 kfree(msg->data);
171 return NULL; 107 return dev;
172}
173
174void
175bl_free_deviceid_node(struct nfs4_deviceid_node *d)
176{
177 struct pnfs_block_dev *dev =
178 container_of(d, struct pnfs_block_dev, d_node);
179 struct net *net = d->nfs_client->cl_net;
180
181 blkdev_put(dev->d_bdev, FMODE_READ);
182 bl_dm_remove(net, dev->d_bdev->bd_dev);
183
184 kfree(dev);
185} 108}
186 109
187static ssize_t bl_pipe_downcall(struct file *filp, const char __user *src, 110static ssize_t bl_pipe_downcall(struct file *filp, const char __user *src,