login
Header Space

 
 

how to check if a given block device is in use?

September 8, 2008 - 8:37am
Submitted by Anonymous on September 8, 2008 - 8:37am.
Linux

How can I check if a given block device is in use (i.e., mounted, used as swap, used as a software RAID device etc.)?

One could technicaly check /proc/swaps, /proc/mdstat, /etc/mtab, etc., but that's just checking in lots of places. And it doesn't cover everything (i.e. LVM, dm-crypt etc.).

Is there a generic way to check if a given block device is in use?

block device in use check

September 10, 2008 - 2:32am

I don't think general solution exists.

On a case by case basis, as sometimes these are hardware specific (esp when we are dealing with hardware):

all the different examples can be found in kernel source drivers/block (grep for register_blkdev() for all block devices), for example:

1. xen-blkfront.c - checking if still mounted:

static int blkif_release(struct inode *inode, struct file *filep)
{
struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
info->users--;
if (info->users == 0) {
/* Check whether we have been instructed to close. We will
have ignored this request initially, as the device was
still mounted. */
struct xenbus_device *dev = info->xbdev;
enum xenbus_state state = xenbus_read_driver_state(dev->otherend);

2. z2ram.c - bit testing:

static void
get_z2ram( void )
{
int i;

for ( i = 0; i < Z2RAM_SIZE / Z2RAM_CHUNKSIZE; i++ )
{
if ( test_bit( i, zorro_unused_z2ram ) )
{

3. sx8.c: CARM_RME and CARM_CME bit testing. And I don't know what is that. But the use of the device is halted till the status turned otherwise.

tmp = readl(mmio + CARM_HMUC);
if (tmp & CARM_CME) {
DPRINTK("CME bit present, waiting\n");
rc = carm_init_wait(mmio, CARM_CME, 1);
if (rc) {
DPRINTK("EXIT, carm_init_wait 1 failed\n");
return rc;
}
}
if (tmp & CARM_RME) {
DPRINTK("RME bit present, waiting\n");
rc = carm_init_wait(mmio, CARM_RME, 1);
if (rc) {
DPRINTK("EXIT, carm_init_wait 2 failed\n");
return rc;
}
}

tmp &= ~(CARM_RME | CARM_CME);
writel(tmp, mmio + CARM_HMUC);

So many possibility exists.

DRBD tests it quite well

September 10, 2008 - 5:05am
sileNT (not verified)

I see DRBD[1] tests it quite well if we want to use a device which is already used:

"Lower device is already claimed. This usually means it is mounted."

However, I don't fully understand how it is done when looking at the code.

[1] http://www.drbd.org

look for bd_claim

September 11, 2008 - 3:44am

AFAIK, Linux uses bd_claim to claim exclusive use of a block dev. I only know what some docs about evms said, though... (evms has to hack around bd_claim, because it wants to have multiple dm devices on the same real block dev, or something nasty.)

so check out bd_claim and see if you can use it.

but how to use it from userspace?

September 11, 2008 - 12:55pm
sileNT (not verified)

Grepping kernel sources for bd_claim indeed shows this is perhaps what I'm looking for.

But how to use it from userspace?

fs/block_dev.c:

int bd_claim(struct block_device *bdev, void *holder)
{
int res;
spin_lock(&bdev_lock);

/* first decide result */
if (bdev->bd_holder == holder)
res = 0; /* already a holder */
else if (bdev->bd_holder != NULL)
res = -EBUSY; /* held by someone else */
else if (bdev->bd_contains == bdev)
res = 0; /* is a whole device which isn't held */

else if (bdev->bd_contains->bd_holder == bd_claim)
res = 0; /* is a partition of a device that is being partitioned */
else if (bdev->bd_contains->bd_holder != NULL)
res = -EBUSY; /* is a partition of a held device */
else
res = 0; /* is a partition of an un-held device */

> But how to use it

September 13, 2008 - 1:25pm

> But how to use it [bd_claim] from userspace?

sorry, no idea. It doesn't export info to sysfs, does it?
Maybe if you're feeling ambitious you could add some sysfs code to bd_claim...

here is a solution

September 24, 2008 - 4:51pm
sileNT (not verified)

Here's a quick solution in Perl:

#!/usr/bin/perl

use Fcntl;

my $path = "/dev/sda3";

sysopen(FH, $path, O_RDWR|O_EXCL) or die $!;

locking block device buffer

September 27, 2008 - 3:16am

THank you for the hints and discussion. I think u all are right....bd_claim and O_EXCL is the answer.

First, when u open a device with O_EXCL flag, u lock the buffer as the API blkdev_open() shows:

static int blkdev_open(struct inode * inode, struct file * filp)
{
struct block_device *bdev;
int res;

/*
* Preserve backwards compatibility and allow large file access
* even if userspace doesn't ask for it explicitly. Some mkfs
* binary needs it. We might want to drop this workaround
* during an unstable branch.
*/
filp->f_flags |= O_LARGEFILE;

bdev = bd_acquire(inode);
if (bdev == NULL)
return -ENOMEM;

res = do_open(bdev, filp, 0);
if (res)
return res;

if (!(filp->f_flags & O_EXCL) )
return 0;

if (!(res = bd_claim(bdev, filp)))==================> buffer is locked, at the VFS level.
return 0;

blkdev_put(bdev);
return res;
}

Since it worked at the VFS level, it is the same for all the different filesystem like ext3 or ext4 etc.

There goes your userspace solution as well.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
speck-geostationary