projects
/
platform
/
adaptation
/
renesas_rcar
/
renesas_kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
dm: allow remove to be deferred
[platform/adaptation/renesas_rcar/renesas_kernel.git]
/
drivers
/
md
/
dm-ioctl.c
diff --git
a/drivers/md/dm-ioctl.c
b/drivers/md/dm-ioctl.c
index
afe0814
..
5152142
100644
(file)
--- a/
drivers/md/dm-ioctl.c
+++ b/
drivers/md/dm-ioctl.c
@@
-57,7
+57,7
@@
struct vers_iter {
static struct list_head _name_buckets[NUM_BUCKETS];
static struct list_head _uuid_buckets[NUM_BUCKETS];
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.
/*
* Guards access to both hash tables.
@@
-86,7
+86,7
@@
static int dm_hash_init(void)
static void dm_hash_exit(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(struct hash_cell *hc)
return table;
}
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;
{
int i, dev_skipped;
struct hash_cell *hc;
@@
-293,7
+293,8
@@
retry:
md = hc->md;
dm_get(md);
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;
dm_put(md);
dev_skipped++;
continue;
@@
-450,6
+451,11
@@
static struct mapped_device *dm_hash_rename(struct dm_ioctl *param,
return md;
}
return md;
}
+void dm_deferred_remove(void)
+{
+ dm_hash_remove_all(true, false, true);
+}
+
/*-----------------------------------------------------------------
* Implementation of the ioctl commands
*---------------------------------------------------------------*/
/*-----------------------------------------------------------------
* Implementation of the ioctl commands
*---------------------------------------------------------------*/
@@
-461,7
+467,7
@@
typedef int (*ioctl_fn)(struct dm_ioctl *param, size_t param_size);
static int remove_all(struct dm_ioctl *param, size_t param_size)
{
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;
}
param->data_size = 0;
return 0;
}
@@
-683,6
+689,9
@@
static void __dev_status(struct mapped_device *md, struct dm_ioctl *param)
if (dm_suspended_md(md))
param->flags |= DM_SUSPEND_FLAG;
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));
/*
param->dev = huge_encode_dev(disk_devt(disk));
/*
@@
-832,8
+841,13
@@
static int dev_remove(struct dm_ioctl *param, size_t param_size)
/*
* Ensure the device is not open and nothing further can open it.
*/
/*
* 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) {
+ 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);
DMDEBUG_LIMIT("unable to remove open device %s", hc->name);
up_write(&_hash_lock);
dm_put(md);
@@
-848,6
+862,8
@@
static int dev_remove(struct dm_ioctl *param, size_t param_size)
dm_table_destroy(t);
}
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;
if (!dm_kobject_uevent(md, KOBJ_REMOVE, param->event_nr))
param->flags |= DM_UEVENT_GENERATED_FLAG;
@@
-1469,6
+1485,14
@@
static int message_for_md(struct mapped_device *md, unsigned argc, char **argv,
if (**argv != '@')
return 2; /* no '@' prefix, deliver to target */
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;
r = dm_stats_message(md, argc, argv, result, maxlen);
if (r < 2)
return r;