[DRBD-user] State change failed: Device is held open by someone

Satyajit Paul satyajit.paul at aricent.com
Fri Mar 8 12:37:23 CET 2013

Note: "permalinks" may not be as permanent as we would like,
direct links of old sources may well be a few messages off.


Hello,

When I wanted to change the state of DRBD from primary to secondary, sometimes I get the "Device is held open by someone" issue.
I looked into the code drbd_main.c (DRBD Release 8.0.11) and found that the error is set from the below code.

    else if( ns.role == Secondary && mdev->open_cnt )
        rv=SS_DeviceInUse;

I put debug logs and found that sometimes "open_cnt" variable is not equal to zero that results in the error. "open_cnt" variable is incremented and decremented from the function drbd_open() and drbd_close() respectively. In function drbd_open(), "open_cnt" variable is handled within locking/unlocking function to avoid race condition whereas in drbd_close(), no such locking/unlocking function is there to handle its critical section. Can we imagine any scenario that due to the absence of locking/unlocking function in the drbd_close() function, race condition is occurring that results in the wrong value of "open_cnt" variable.

Here is the code.

STATIC int drbd_close(struct inode *inode, struct file *file)
{
                        /* do not use *file (May be NULL, in case of a unmount :-) */
                        drbd_dev *mdev;

                        mdev = minor_to_mdev(MINOR(inode->i_rdev));
                        if(!mdev) return -ENODEV;

                        /*
                        printk(KERN_ERR DEVICE_NAME ": close(inode=%p,file=%p)"
                               "current=%p,minor=%d,wc=%d\n", inode, file, current, minor,
                               inode->i_writecount);
                        */

                         mdev->open_cnt--;

                        return 0;
}


STATIC int drbd_open(struct inode *inode, struct file *file)
{
                        drbd_dev *mdev;
                        unsigned long flags;
                        int rv=0;

                        mdev = minor_to_mdev(MINOR(inode->i_rdev));
                        if(!mdev) return -ENODEV;

                        spin_lock_irqsave(&mdev->req_lock,flags);
                        /* to have a stable mdev->state.role and no race with updating open_cnt */

                        if (mdev->state.role != Primary) {
                                                if (file->f_mode & FMODE_WRITE) {
                                                                        rv = -EROFS;
                                                } else if (!allow_oos) {
                                                                        rv = -EMEDIUMTYPE;
                                                }
                        }

                        if(!rv) mdev->open_cnt++;
                        spin_unlock_irqrestore(&mdev->req_lock,flags);

                        return rv;
}



Thanks in Advance.

Regards,
Satyajit Paul
Software Engineer
India





===============================================================================
Please refer to http://www.aricent.com/legal/email_disclaimer.html
for important disclosures regarding this electronic communication.
===============================================================================
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linbit.com/pipermail/drbd-user/attachments/20130308/f8369bbc/attachment.htm>


More information about the drbd-user mailing list