2 * Copyright (c) 2006,2007 The Regents of the University of Michigan.
5 * Andy Adamson <andros@citi.umich.edu>
6 * Fred Isaman <iisaman@umich.edu>
8 * permission is granted to use, copy, create derivative works and
9 * redistribute this software and such derivative works for any purpose,
10 * so long as the name of the university of michigan is not used in
11 * any advertising or publicity pertaining to the use or distribution
12 * of this software without specific, written prior authorization. if
13 * the above copyright notice or any other identification of the
14 * university of michigan is included in any copy of any portion of
15 * this software, then the disclaimer below must also be included.
17 * this software is provided as is, without representation from the
18 * university of michigan as to its fitness for any purpose, and without
19 * warranty by the university of michigan of any kind, either express
20 * or implied, including without limitation the implied warranties of
21 * merchantability and fitness for a particular purpose. the regents
22 * of the university of michigan shall not be liable for any damages,
23 * including special, indirect, incidental, or consequential damages,
24 * with respect to any claim arising out or in connection with the use
25 * of the software, even if it has been or is hereafter advised of the
26 * possibility of such damages.
29 #include <linux/module.h>
30 #include <linux/genhd.h>
31 #include <linux/blkdev.h>
33 #include "blocklayout.h"
35 #define NFSDBG_FACILITY NFSDBG_PNFS_LD
38 nfs4_encode_simple(__be32
*p
, struct pnfs_block_volume
*b
)
42 *p
++ = cpu_to_be32(1);
43 *p
++ = cpu_to_be32(b
->type
);
44 *p
++ = cpu_to_be32(b
->simple
.nr_sigs
);
45 for (i
= 0; i
< b
->simple
.nr_sigs
; i
++) {
46 p
= xdr_encode_hyper(p
, b
->simple
.sigs
[i
].offset
);
47 p
= xdr_encode_opaque(p
, b
->simple
.sigs
[i
].sig
,
48 b
->simple
.sigs
[i
].sig_len
);
53 bl_resolve_deviceid(struct nfs_server
*server
, struct pnfs_block_volume
*b
,
56 struct net
*net
= server
->nfs_client
->cl_net
;
57 struct nfs_net
*nn
= net_generic(net
, nfs_net_id
);
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
);
66 dprintk("%s CREATING PIPEFS MESSAGE\n", __func__
);
68 mutex_lock(&nn
->bl_mutex
);
69 bl_pipe_msg
.bl_wq
= &nn
->bl_wq
;
71 b
->simple
.len
+= 4; /* single volume */
72 if (b
->simple
.len
> PAGE_SIZE
)
75 memset(msg
, 0, sizeof(*msg
));
76 msg
->len
= sizeof(*bl_msg
) + b
->simple
.len
;
77 msg
->data
= kzalloc(msg
->len
, gfp_mask
);
82 bl_msg
->type
= BL_DEVICE_MOUNT
,
83 bl_msg
->totallen
= b
->simple
.len
;
84 nfs4_encode_simple(msg
->data
+ sizeof(*bl_msg
), b
);
86 dprintk("%s CALLING USERSPACE DAEMON\n", __func__
);
87 add_wait_queue(&nn
->bl_wq
, &wq
);
88 rc
= rpc_queue_upcall(nn
->bl_device_pipe
, msg
);
90 remove_wait_queue(&nn
->bl_wq
, &wq
);
94 set_current_state(TASK_UNINTERRUPTIBLE
);
96 remove_wait_queue(&nn
->bl_wq
, &wq
);
98 if (reply
->status
!= BL_DEVICE_REQUEST_PROC
) {
99 printk(KERN_WARNING
"%s failed to decode device: %d\n",
100 __func__
, reply
->status
);
104 dev
= MKDEV(reply
->major
, reply
->minor
);
108 mutex_unlock(&nn
->bl_mutex
);
112 static ssize_t
bl_pipe_downcall(struct file
*filp
, const char __user
*src
,
115 struct nfs_net
*nn
= net_generic(file_inode(filp
)->i_sb
->s_fs_info
,
118 if (mlen
!= sizeof (struct bl_dev_msg
))
121 if (copy_from_user(&nn
->bl_mount_reply
, src
, mlen
) != 0)
129 static void bl_pipe_destroy_msg(struct rpc_pipe_msg
*msg
)
131 struct bl_pipe_msg
*bl_pipe_msg
=
132 container_of(msg
, struct bl_pipe_msg
, msg
);
136 wake_up(bl_pipe_msg
->bl_wq
);
139 static const struct rpc_pipe_ops bl_upcall_ops
= {
140 .upcall
= rpc_pipe_generic_upcall
,
141 .downcall
= bl_pipe_downcall
,
142 .destroy_msg
= bl_pipe_destroy_msg
,
145 static struct dentry
*nfs4blocklayout_register_sb(struct super_block
*sb
,
146 struct rpc_pipe
*pipe
)
148 struct dentry
*dir
, *dentry
;
150 dir
= rpc_d_lookup_sb(sb
, NFS_PIPE_DIRNAME
);
152 return ERR_PTR(-ENOENT
);
153 dentry
= rpc_mkpipe_dentry(dir
, "blocklayout", NULL
, pipe
);
158 static void nfs4blocklayout_unregister_sb(struct super_block
*sb
,
159 struct rpc_pipe
*pipe
)
162 rpc_unlink(pipe
->dentry
);
165 static int rpc_pipefs_event(struct notifier_block
*nb
, unsigned long event
,
168 struct super_block
*sb
= ptr
;
169 struct net
*net
= sb
->s_fs_info
;
170 struct nfs_net
*nn
= net_generic(net
, nfs_net_id
);
171 struct dentry
*dentry
;
174 if (!try_module_get(THIS_MODULE
))
177 if (nn
->bl_device_pipe
== NULL
) {
178 module_put(THIS_MODULE
);
183 case RPC_PIPEFS_MOUNT
:
184 dentry
= nfs4blocklayout_register_sb(sb
, nn
->bl_device_pipe
);
185 if (IS_ERR(dentry
)) {
186 ret
= PTR_ERR(dentry
);
189 nn
->bl_device_pipe
->dentry
= dentry
;
191 case RPC_PIPEFS_UMOUNT
:
192 if (nn
->bl_device_pipe
->dentry
)
193 nfs4blocklayout_unregister_sb(sb
, nn
->bl_device_pipe
);
199 module_put(THIS_MODULE
);
203 static struct notifier_block nfs4blocklayout_block
= {
204 .notifier_call
= rpc_pipefs_event
,
207 static struct dentry
*nfs4blocklayout_register_net(struct net
*net
,
208 struct rpc_pipe
*pipe
)
210 struct super_block
*pipefs_sb
;
211 struct dentry
*dentry
;
213 pipefs_sb
= rpc_get_sb_net(net
);
216 dentry
= nfs4blocklayout_register_sb(pipefs_sb
, pipe
);
221 static void nfs4blocklayout_unregister_net(struct net
*net
,
222 struct rpc_pipe
*pipe
)
224 struct super_block
*pipefs_sb
;
226 pipefs_sb
= rpc_get_sb_net(net
);
228 nfs4blocklayout_unregister_sb(pipefs_sb
, pipe
);
233 static int nfs4blocklayout_net_init(struct net
*net
)
235 struct nfs_net
*nn
= net_generic(net
, nfs_net_id
);
236 struct dentry
*dentry
;
238 mutex_init(&nn
->bl_mutex
);
239 init_waitqueue_head(&nn
->bl_wq
);
240 nn
->bl_device_pipe
= rpc_mkpipe_data(&bl_upcall_ops
, 0);
241 if (IS_ERR(nn
->bl_device_pipe
))
242 return PTR_ERR(nn
->bl_device_pipe
);
243 dentry
= nfs4blocklayout_register_net(net
, nn
->bl_device_pipe
);
244 if (IS_ERR(dentry
)) {
245 rpc_destroy_pipe_data(nn
->bl_device_pipe
);
246 return PTR_ERR(dentry
);
248 nn
->bl_device_pipe
->dentry
= dentry
;
252 static void nfs4blocklayout_net_exit(struct net
*net
)
254 struct nfs_net
*nn
= net_generic(net
, nfs_net_id
);
256 nfs4blocklayout_unregister_net(net
, nn
->bl_device_pipe
);
257 rpc_destroy_pipe_data(nn
->bl_device_pipe
);
258 nn
->bl_device_pipe
= NULL
;
261 static struct pernet_operations nfs4blocklayout_net_ops
= {
262 .init
= nfs4blocklayout_net_init
,
263 .exit
= nfs4blocklayout_net_exit
,
266 int __init
bl_init_pipefs(void)
270 ret
= rpc_pipefs_notifier_register(&nfs4blocklayout_block
);
273 ret
= register_pernet_subsys(&nfs4blocklayout_net_ops
);
275 goto out_unregister_notifier
;
278 out_unregister_notifier
:
279 rpc_pipefs_notifier_unregister(&nfs4blocklayout_block
);
284 void bl_cleanup_pipefs(void)
286 rpc_pipefs_notifier_unregister(&nfs4blocklayout_block
);
287 unregister_pernet_subsys(&nfs4blocklayout_net_ops
);