dm-devel.redhat.com archive mirror
 help / color / mirror / Atom feed
* ANNOUNCE: remove device on close
@ 2013-09-16 19:41 Mikulas Patocka
  2013-09-16 19:45 ` Mike Snitzer
  0 siblings, 1 reply; 3+ messages in thread
From: Mikulas Patocka @ 2013-09-16 19:41 UTC (permalink / raw)
  To: Alasdair G. Kergon, dm-devel, lvm-devel

Hi

I placed the patches for deferred removal at 
http://people.redhat.com/mpatocka/patches/kernel/deferred-remove/

Use the command:
dmsetup remove --deferred <device_name>

If the device is closed, it is deleted as usual. If the device is open, it 
is flagged to be deleted on close. When the last process that keeps the 
device open closes it, the device is deleted.

The state of deferred-remove flag can be queried with dmstup info - there 
is "(DEFERRED REMOVE)" if the device is flagged to be deleted.

The request to delete a device can be cancelled with message:
dmsetup message <device_name> 0 @cancel_deferred_remove

Mikulas

--
lvm-devel mailing list
lvm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/lvm-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: ANNOUNCE: remove device on close
  2013-09-16 19:41 ANNOUNCE: remove device on close Mikulas Patocka
@ 2013-09-16 19:45 ` Mike Snitzer
  2013-09-16 20:34   ` [PATCH] " Mikulas Patocka
  0 siblings, 1 reply; 3+ messages in thread
From: Mike Snitzer @ 2013-09-16 19:45 UTC (permalink / raw)
  To: Mikulas Patocka; +Cc: dm-devel, lvm-devel

On Mon, Sep 16 2013 at  3:41pm -0400,
Mikulas Patocka <mpatocka@redhat.com> wrote:

> Hi
> 
> I placed the patches for deferred removal at 
> http://people.redhat.com/mpatocka/patches/kernel/deferred-remove/

Please post the kernel patch to dm-devel so it is easier for people to
review/comment.  It also enables the patch to be tracked via patchwork.

Thanks,
Mike

--
lvm-devel mailing list
lvm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/lvm-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH] remove device on close
  2013-09-16 19:45 ` Mike Snitzer
@ 2013-09-16 20:34   ` Mikulas Patocka
  0 siblings, 0 replies; 3+ messages in thread
From: Mikulas Patocka @ 2013-09-16 20:34 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: dm-devel, lvm-devel



On Mon, 16 Sep 2013, Mike Snitzer wrote:

> On Mon, Sep 16 2013 at  3:41pm -0400,
> Mikulas Patocka <mpatocka@redhat.com> wrote:
> 
> > Hi
> > 
> > I placed the patches for deferred removal at 
> > http://people.redhat.com/mpatocka/patches/kernel/deferred-remove/
> 
> Please post the kernel patch to dm-devel so it is easier for people to
> review/comment.  It also enables the patch to be tracked via patchwork.
> 
> Thanks,
> Mike

Here it is.

Mikulas

---

dm: deferred remove

This patch introduces the functionality of deferred remove - if a device
mapper device is open, it is scheduled to be deleted on close.

The deferred remove functionality is enabled by setting the flag
DM_DEFERRED_REMOVE in the ioctl structure on DM_DEV_REMOVE or
DM_REMOVE_ALL ioctl.

On return from DM_DEV_REMOVE, the flag DM_DEFERRED_REMOVE indicates if the
device was removed immediatelly or flagged to be removed on close - if the
flag is clear, the device was removed.

On return from DM_DEV_STATUS and other ioctls, the flag DM_DEFERRED_REMOVE
is set if the device is scheduled to be removed on close.

A device that is scheduled to be delete can be revived using the message
"@cancel_deferred_remove". This message clear the DMF_DEFERRED_REMOVE so
that the device won't be deleted on close.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
 drivers/md/dm-ioctl.c         |   35 +++++++++++++++++++++++++-----
 drivers/md/dm.c               |   48 +++++++++++++++++++++++++++++++++++++-----
 drivers/md/dm.h               |   13 ++++++++++-
 include/uapi/linux/dm-ioctl.h |   14 ++++++++++++
 4 files changed, 98 insertions(+), 12 deletions(-)

Index: linux-3.11.1-fast/include/uapi/linux/dm-ioctl.h
===================================================================
--- linux-3.11.1-fast.orig/include/uapi/linux/dm-ioctl.h	2013-09-16 21:15:10.000000000 +0200
+++ linux-3.11.1-fast/include/uapi/linux/dm-ioctl.h	2013-09-16 21:15:26.000000000 +0200
@@ -341,4 +341,18 @@ enum {
  */
 #define DM_DATA_OUT_FLAG		(1 << 16) /* Out */
 
+/*
+ * Remove the device when it is closed.
+ *
+ * This flag may be set on DM_DEV_REMOVE or DM_REMOVE_ALL to indicate that
+ * the device should be remove on close if it is open.
+ *
+ * On return from DM_DEV_REMOVE, this flag indicates that the device was not
+ * removed because it was open, but it is scheduled to be removed on close.
+ *
+ * When this flag is returned in DM_DEV_STATUS or other ioctls, it indicates
+ * that the device is scheduled to be removed on close.
+ */
+#define DM_DEFERRED_REMOVE		(1 << 17) /* In/Out */
+
 #endif				/* _LINUX_DM_IOCTL_H */
Index: linux-3.11.1-fast/drivers/md/dm-ioctl.c
===================================================================
--- linux-3.11.1-fast.orig/drivers/md/dm-ioctl.c	2013-09-16 21:15:11.000000000 +0200
+++ linux-3.11.1-fast/drivers/md/dm-ioctl.c	2013-09-16 21:15:26.000000000 +0200
@@ -57,7 +57,7 @@ struct vers_iter {
 static struct list_head _name_buckets[NUM_BUCKETS];
 static struct list_head _uuid_buckets[NUM_BUCKETS];
 
-static void dm_hash_remove_all(int keep_open_devices);
+static void dm_hash_remove_all(bool keep_open_devices, bool mark_deferred, bool only_deferred);
 
 /*
  * Guards access to both hash tables.
@@ -86,7 +86,7 @@ static int dm_hash_init(void)
 
 static void dm_hash_exit(void)
 {
-	dm_hash_remove_all(0);
+	dm_hash_remove_all(false, false, false);
 }
 
 /*-----------------------------------------------------------------
@@ -276,7 +276,7 @@ static struct dm_table *__hash_remove(st
 	return table;
 }
 
-static void dm_hash_remove_all(int keep_open_devices)
+static void dm_hash_remove_all(bool keep_open_devices, bool mark_deferred, bool only_deferred)
 {
 	int i, dev_skipped;
 	struct hash_cell *hc;
@@ -293,7 +293,7 @@ retry:
 			md = hc->md;
 			dm_get(md);
 
-			if (keep_open_devices && dm_lock_for_deletion(md)) {
+			if (keep_open_devices && dm_lock_for_deletion(md, mark_deferred, only_deferred)) {
 				dm_put(md);
 				dev_skipped++;
 				continue;
@@ -450,6 +450,11 @@ static struct mapped_device *dm_hash_ren
 	return md;
 }
 
+void dm_deferred_remove(void)
+{
+	dm_hash_remove_all(true, false, true);
+}
+
 /*-----------------------------------------------------------------
  * Implementation of the ioctl commands
  *---------------------------------------------------------------*/
@@ -461,7 +466,7 @@ typedef int (*ioctl_fn)(struct dm_ioctl 
 
 static int remove_all(struct dm_ioctl *param, size_t param_size)
 {
-	dm_hash_remove_all(1);
+	dm_hash_remove_all(true, !!(param->flags & DM_DEFERRED_REMOVE), false);
 	param->data_size = 0;
 	return 0;
 }
@@ -683,6 +688,9 @@ static void __dev_status(struct mapped_d
 	if (dm_suspended_md(md))
 		param->flags |= DM_SUSPEND_FLAG;
 
+	if (dm_test_deferred_remove_flag(md))
+		param->flags |= DM_DEFERRED_REMOVE;
+
 	param->dev = huge_encode_dev(disk_devt(disk));
 
 	/*
@@ -832,8 +840,13 @@ static int dev_remove(struct dm_ioctl *p
 	/*
 	 * Ensure the device is not open and nothing further can open it.
 	 */
-	r = dm_lock_for_deletion(md);
+	r = dm_lock_for_deletion(md, !!(param->flags & DM_DEFERRED_REMOVE), false);
 	if (r) {
+		if (r == -EBUSY && param->flags & DM_DEFERRED_REMOVE) {
+			up_write(&_hash_lock);
+			dm_put(md);
+			return 0;
+		}
 		DMDEBUG_LIMIT("unable to remove open device %s", hc->name);
 		up_write(&_hash_lock);
 		dm_put(md);
@@ -848,6 +861,8 @@ static int dev_remove(struct dm_ioctl *p
 		dm_table_destroy(t);
 	}
 
+	param->flags &= ~DM_DEFERRED_REMOVE;
+
 	if (!dm_kobject_uevent(md, KOBJ_REMOVE, param->event_nr))
 		param->flags |= DM_UEVENT_GENERATED_FLAG;
 
@@ -1469,6 +1484,14 @@ static int message_for_md(struct mapped_
 	if (**argv != '@')
 		return 2; /* no '@' prefix, deliver to target */
 
+	if (!strcasecmp(argv[0], "@cancel_deferred_remove")) {
+		if (argc != 1) {
+			DMERR("Invalid arguments for @cancel_deferred_remove");
+			return -EINVAL;
+		}
+		return dm_cancel_deferred_remove(md);
+	}
+
 	r = dm_stats_message(md, argc, argv, result, maxlen);
 	if (r < 2)
 		return r;
Index: linux-3.11.1-fast/drivers/md/dm.c
===================================================================
--- linux-3.11.1-fast.orig/drivers/md/dm.c	2013-09-16 21:15:11.000000000 +0200
+++ linux-3.11.1-fast/drivers/md/dm.c	2013-09-16 21:15:26.000000000 +0200
@@ -49,6 +49,11 @@ static unsigned int _major = 0;
 static DEFINE_IDR(_minor_idr);
 
 static DEFINE_SPINLOCK(_minor_lock);
+
+static void do_deferred_remove(struct work_struct *w);
+
+static DECLARE_WORK(deferred_remove_work, do_deferred_remove);
+
 /*
  * For bio-based dm.
  * One of these is allocated per bio.
@@ -116,6 +121,7 @@ EXPORT_SYMBOL_GPL(dm_get_rq_mapinfo);
 #define DMF_DELETING 4
 #define DMF_NOFLUSH_SUSPENDING 5
 #define DMF_MERGE_IS_OPTIONAL 6
+#define DMF_DEFERRED_REMOVE 7
 
 /*
  * A dummy definition to make RCU happy.
@@ -254,6 +260,8 @@ out_free_io_cache:
 
 static void local_exit(void)
 {
+	flush_scheduled_work();
+
 	kmem_cache_destroy(_rq_tio_cache);
 	kmem_cache_destroy(_io_cache);
 	unregister_blkdev(_major, _name);
@@ -359,7 +367,11 @@ static void dm_blk_close(struct gendisk 
 
 	spin_lock(&_minor_lock);
 
-	atomic_dec(&md->open_count);
+	if (atomic_dec_and_test(&md->open_count)) {
+		if (test_bit(DMF_DEFERRED_REMOVE, &md->flags)) {
+			schedule_work(&deferred_remove_work);
+		}
+	}
 	dm_put(md);
 
 	spin_unlock(&_minor_lock);
@@ -373,22 +385,43 @@ int dm_open_count(struct mapped_device *
 /*
  * Guarantees nothing is using the device before it's deleted.
  */
-int dm_lock_for_deletion(struct mapped_device *md)
+int dm_lock_for_deletion(struct mapped_device *md, bool mark_deferred, bool only_deferred)
 {
 	int r = 0;
 
 	spin_lock(&_minor_lock);
 
-	if (dm_open_count(md))
+	if (dm_open_count(md)) {
 		r = -EBUSY;
-	else
-		set_bit(DMF_DELETING, &md->flags);
+		if (mark_deferred)
+			set_bit(DMF_DEFERRED_REMOVE, &md->flags);
+	} else {
+		if (only_deferred && !test_bit(DMF_DEFERRED_REMOVE, &md->flags))
+			r = -EEXIST;
+		else
+			set_bit(DMF_DELETING, &md->flags);
+	}
 
 	spin_unlock(&_minor_lock);
 
 	return r;
 }
 
+int dm_cancel_deferred_remove(struct mapped_device *md)
+{
+	int r = 0;
+	spin_lock(&_minor_lock);
+	if (test_bit(DMF_DELETING, &md->flags)) r = -EBUSY;
+	else clear_bit(DMF_DEFERRED_REMOVE, &md->flags);
+	spin_unlock(&_minor_lock);
+	return r;
+}
+
+static void do_deferred_remove(struct work_struct *w)
+{
+	dm_deferred_remove();
+}
+
 sector_t dm_get_size(struct mapped_device *md)
 {
 	return get_capacity(md->disk);
@@ -2845,6 +2878,11 @@ int dm_suspended_md(struct mapped_device
 	return test_bit(DMF_SUSPENDED, &md->flags);
 }
 
+int dm_test_deferred_remove_flag(struct mapped_device *md)
+{
+	return test_bit(DMF_DEFERRED_REMOVE, &md->flags);
+}
+
 int dm_suspended(struct dm_target *ti)
 {
 	return dm_suspended_md(dm_table_get_md(ti->table));
Index: linux-3.11.1-fast/drivers/md/dm.h
===================================================================
--- linux-3.11.1-fast.orig/drivers/md/dm.h	2013-09-16 21:15:11.000000000 +0200
+++ linux-3.11.1-fast/drivers/md/dm.h	2013-09-16 21:15:26.000000000 +0200
@@ -118,6 +118,16 @@ int dm_deleting_md(struct mapped_device 
 int dm_suspended_md(struct mapped_device *md);
 
 /*
+ * Test if the device is scheduled for deferred remove.
+ */
+int dm_test_deferred_remove_flag(struct mapped_device *md);
+
+/*
+ * Try to remove devices marked for deferred removal.
+ */
+void dm_deferred_remove(void);
+
+/*
  * The device-mapper can be driven through one of two interfaces;
  * ioctl or filesystem, depending which patch you have applied.
  */
@@ -147,7 +157,8 @@ void dm_stripe_exit(void);
 void dm_destroy(struct mapped_device *md);
 void dm_destroy_immediate(struct mapped_device *md);
 int dm_open_count(struct mapped_device *md);
-int dm_lock_for_deletion(struct mapped_device *md);
+int dm_lock_for_deletion(struct mapped_device *md, bool mark_deferred, bool only_deferred);
+int dm_cancel_deferred_remove(struct mapped_device *md);
 int dm_request_based(struct mapped_device *md);
 sector_t dm_get_size(struct mapped_device *md);
 struct dm_stats *dm_get_stats(struct mapped_device *md);

--
lvm-devel mailing list
lvm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/lvm-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2013-09-16 20:34 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-16 19:41 ANNOUNCE: remove device on close Mikulas Patocka
2013-09-16 19:45 ` Mike Snitzer
2013-09-16 20:34   ` [PATCH] " Mikulas Patocka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).