diff options
Diffstat (limited to 'fs/nfs/blocklayout/blocklayoutdm.c')
| -rw-r--r-- | fs/nfs/blocklayout/blocklayoutdm.c | 108 | 
1 files changed, 108 insertions, 0 deletions
diff --git a/fs/nfs/blocklayout/blocklayoutdm.c b/fs/nfs/blocklayout/blocklayoutdm.c new file mode 100644 index 00000000000..8999cfddd86 --- /dev/null +++ b/fs/nfs/blocklayout/blocklayoutdm.c @@ -0,0 +1,108 @@ +/* + *  linux/fs/nfs/blocklayout/blocklayoutdm.c + * + *  Module for the NFSv4.1 pNFS block layout driver. + * + *  Copyright (c) 2007 The Regents of the University of Michigan. + *  All rights reserved. + * + *  Fred Isaman <iisaman@umich.edu> + *  Andy Adamson <andros@citi.umich.edu> + * + * permission is granted to use, copy, create derivative works and + * redistribute this software and such derivative works for any purpose, + * so long as the name of the university of michigan is not used in + * any advertising or publicity pertaining to the use or distribution + * of this software without specific, written prior authorization.  if + * the above copyright notice or any other identification of the + * university of michigan is included in any copy of any portion of + * this software, then the disclaimer below must also be included. + * + * this software is provided as is, without representation from the + * university of michigan as to its fitness for any purpose, and without + * warranty by the university of michigan of any kind, either express + * or implied, including without limitation the implied warranties of + * merchantability and fitness for a particular purpose.  the regents + * of the university of michigan shall not be liable for any damages, + * including special, indirect, incidental, or consequential damages, + * with respect to any claim arising out or in connection with the use + * of the software, even if it has been or is hereafter advised of the + * possibility of such damages. + */ + +#include <linux/genhd.h> /* gendisk - used in a dprintk*/ +#include <linux/sched.h> +#include <linux/hash.h> + +#include "blocklayout.h" + +#define NFSDBG_FACILITY         NFSDBG_PNFS_LD + +static void dev_remove(struct net *net, dev_t dev) +{ +	struct bl_pipe_msg bl_pipe_msg; +	struct rpc_pipe_msg *msg = &bl_pipe_msg.msg; +	struct bl_dev_msg bl_umount_request; +	struct bl_msg_hdr bl_msg = { +		.type = BL_DEVICE_UMOUNT, +		.totallen = sizeof(bl_umount_request), +	}; +	uint8_t *dataptr; +	DECLARE_WAITQUEUE(wq, current); +	struct nfs_net *nn = net_generic(net, nfs_net_id); + +	dprintk("Entering %s\n", __func__); + +	bl_pipe_msg.bl_wq = &nn->bl_wq; +	memset(msg, 0, sizeof(*msg)); +	msg->len = sizeof(bl_msg) + bl_msg.totallen; +	msg->data = kzalloc(msg->len, GFP_NOFS); +	if (!msg->data) +		goto out; + +	memset(&bl_umount_request, 0, sizeof(bl_umount_request)); +	bl_umount_request.major = MAJOR(dev); +	bl_umount_request.minor = MINOR(dev); + +	memcpy(msg->data, &bl_msg, sizeof(bl_msg)); +	dataptr = (uint8_t *) msg->data; +	memcpy(&dataptr[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request)); + +	add_wait_queue(&nn->bl_wq, &wq); +	if (rpc_queue_upcall(nn->bl_device_pipe, msg) < 0) { +		remove_wait_queue(&nn->bl_wq, &wq); +		goto out; +	} + +	set_current_state(TASK_UNINTERRUPTIBLE); +	schedule(); +	__set_current_state(TASK_RUNNING); +	remove_wait_queue(&nn->bl_wq, &wq); + +out: +	kfree(msg->data); +} + +/* + * Release meta device + */ +static void nfs4_blk_metadev_release(struct pnfs_block_dev *bdev) +{ +	dprintk("%s Releasing\n", __func__); +	nfs4_blkdev_put(bdev->bm_mdev); +	dev_remove(bdev->net, bdev->bm_mdev->bd_dev); +} + +void bl_free_block_dev(struct pnfs_block_dev *bdev) +{ +	if (bdev) { +		if (bdev->bm_mdev) { +			dprintk("%s Removing DM device: %d:%d\n", +				__func__, +				MAJOR(bdev->bm_mdev->bd_dev), +				MINOR(bdev->bm_mdev->bd_dev)); +			nfs4_blk_metadev_release(bdev); +		} +		kfree(bdev); +	} +}  | 
