2011-07-30 20:52:43 -04:00
/*
* 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 ( dev_t dev )
{
struct rpc_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 ) ;
dprintk ( " Entering %s \n " , __func__ ) ;
memset ( & msg , 0 , sizeof ( msg ) ) ;
msg . data = kzalloc ( 1 + sizeof ( bl_umount_request ) , 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 ) ) ;
msg . len = sizeof ( bl_msg ) + bl_msg . totallen ;
add_wait_queue ( & bl_wq , & wq ) ;
2011-12-26 15:44:06 +03:00
if ( rpc_queue_upcall ( bl_device_pipe , & msg ) < 0 ) {
2011-07-30 20:52:43 -04:00
remove_wait_queue ( & bl_wq , & wq ) ;
goto out ;
}
set_current_state ( TASK_UNINTERRUPTIBLE ) ;
schedule ( ) ;
__set_current_state ( TASK_RUNNING ) ;
remove_wait_queue ( & bl_wq , & wq ) ;
out :
kfree ( msg . data ) ;
}
/*
* Release meta device
*/
static void nfs4_blk_metadev_release ( struct pnfs_block_dev * bdev )
{
int rv ;
dprintk ( " %s Releasing \n " , __func__ ) ;
rv = nfs4_blkdev_put ( bdev - > bm_mdev ) ;
if ( rv )
printk ( KERN_ERR " %s nfs4_blkdev_put returns %d \n " ,
__func__ , rv ) ;
dev_remove ( 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 ) ;
}
}