aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r--drivers/md/dm.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 952c49c3b9aa..6982f86db6dc 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -64,12 +64,14 @@ union map_info *dm_get_mapinfo(struct bio *bio)
64#define DMF_SUSPENDED 1 64#define DMF_SUSPENDED 1
65#define DMF_FROZEN 2 65#define DMF_FROZEN 2
66#define DMF_FREEING 3 66#define DMF_FREEING 3
67#define DMF_DELETING 4
67 68
68struct mapped_device { 69struct mapped_device {
69 struct rw_semaphore io_lock; 70 struct rw_semaphore io_lock;
70 struct semaphore suspend_lock; 71 struct semaphore suspend_lock;
71 rwlock_t map_lock; 72 rwlock_t map_lock;
72 atomic_t holders; 73 atomic_t holders;
74 atomic_t open_count;
73 75
74 unsigned long flags; 76 unsigned long flags;
75 77
@@ -228,12 +230,14 @@ static int dm_blk_open(struct inode *inode, struct file *file)
228 if (!md) 230 if (!md)
229 goto out; 231 goto out;
230 232
231 if (test_bit(DMF_FREEING, &md->flags)) { 233 if (test_bit(DMF_FREEING, &md->flags) ||
234 test_bit(DMF_DELETING, &md->flags)) {
232 md = NULL; 235 md = NULL;
233 goto out; 236 goto out;
234 } 237 }
235 238
236 dm_get(md); 239 dm_get(md);
240 atomic_inc(&md->open_count);
237 241
238out: 242out:
239 spin_unlock(&_minor_lock); 243 spin_unlock(&_minor_lock);
@@ -246,10 +250,35 @@ static int dm_blk_close(struct inode *inode, struct file *file)
246 struct mapped_device *md; 250 struct mapped_device *md;
247 251
248 md = inode->i_bdev->bd_disk->private_data; 252 md = inode->i_bdev->bd_disk->private_data;
253 atomic_dec(&md->open_count);
249 dm_put(md); 254 dm_put(md);
250 return 0; 255 return 0;
251} 256}
252 257
258int dm_open_count(struct mapped_device *md)
259{
260 return atomic_read(&md->open_count);
261}
262
263/*
264 * Guarantees nothing is using the device before it's deleted.
265 */
266int dm_lock_for_deletion(struct mapped_device *md)
267{
268 int r = 0;
269
270 spin_lock(&_minor_lock);
271
272 if (dm_open_count(md))
273 r = -EBUSY;
274 else
275 set_bit(DMF_DELETING, &md->flags);
276
277 spin_unlock(&_minor_lock);
278
279 return r;
280}
281
253static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) 282static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
254{ 283{
255 struct mapped_device *md = bdev->bd_disk->private_data; 284 struct mapped_device *md = bdev->bd_disk->private_data;
@@ -867,6 +896,7 @@ static struct mapped_device *alloc_dev(int minor)
867 init_MUTEX(&md->suspend_lock); 896 init_MUTEX(&md->suspend_lock);
868 rwlock_init(&md->map_lock); 897 rwlock_init(&md->map_lock);
869 atomic_set(&md->holders, 1); 898 atomic_set(&md->holders, 1);
899 atomic_set(&md->open_count, 0);
870 atomic_set(&md->event_nr, 0); 900 atomic_set(&md->event_nr, 0);
871 901
872 md->queue = blk_alloc_queue(GFP_KERNEL); 902 md->queue = blk_alloc_queue(GFP_KERNEL);