* [PATCH 1/2] add stripe end_io function and event trigger
@ 2007-12-04 17:36 Wood, Brian J
2007-12-05 17:57 ` Mike Anderson
0 siblings, 1 reply; 3+ messages in thread
From: Wood, Brian J @ 2007-12-04 17:36 UTC (permalink / raw)
To: device-mapper development, Alasdair G Kergon
From: Brian Wood <brian.j.wood@intel.com>
This patch adds the stripe_end_io function to process errors that might
occur after an IO operation. As part of this there are a number of
enhancements made to record and trigger events:
- New atomic variable in struct stripe to record the number of
errors each stripe volume has experienced (could be used later with
uevents to report back directly to userspace)
- New workqueue/work struct setup to process the trigger_event
function
- New trigger_event function to process failure events. This
will determine the exact stripe that cause the IO error, record the
error and call dm_table_event()
- With this change Alasdair requested that the version number be
incremented
Signed-off-by: Brian Wood <brian.j.wood@intel.com>
--- linux-2.6.24-rc3/drivers/md/dm-stripe.c 2007-11-16
21:16:36.000000000 -0800
+++ linux-2.6.24-rc3.mod/drivers/md/dm-stripe.c 2007-12-03
07:08:16.000000000 -0800
@@ -12,10 +12,14 @@
#include <linux/bio.h>
#include <linux/slab.h>
#include <linux/log2.h>
+#include <linux/namei.h>
#define DM_MSG_PREFIX "striped"
+#define IO_ERROR_COUNT 15
+#define DEV_STR_LEN 15
struct stripe {
+ atomic_t error_count;
struct dm_dev *dev;
sector_t physical_start;
};
@@ -30,9 +34,69 @@
uint32_t chunk_shift;
sector_t chunk_mask;
- struct stripe stripe[0];
+ /* Needed for handling events */
+ struct dm_target *ti;
+
+ /* Work struct used for triggering events*/
+ struct work_struct kstriped_ws;
+
+ struct stripe stripe[0];
};
+struct workqueue_struct *kstriped;
+
+/*
+ * An event is triggered whenever a drive
+ * drops out of a stripe volume.
+ */
+static void trigger_event(struct work_struct *work)
+{
+ int i, len;
+ char dev_path[DEV_STR_LEN];
+ struct stripe_c *sc = container_of(work, struct stripe_c,
kstriped_ws);
+ struct nameidata nd;
+ struct inode *inode;
+
+ /* Test to see which stripe drive triggered the event. */
+ for (i = 0; i < sc->stripes; i++) {
+ memset(dev_path, 0, DEV_STR_LEN);
+ memcpy(dev_path, "/dev/", len = strlen("/dev/"));
+ /* Copy name of the drive stored in the gendisk
structure
+ * (this is the same name as what is stored in the /proc
and /sysfs filesystems */
+ memcpy(dev_path+len,
sc->stripe[i].dev->bdev->bd_disk->disk_name,
+
strlen(sc->stripe[i].dev->bdev->bd_disk->disk_name));
+
+ /* Check to see if path can be used to fill nameidata
structure */
+ if (path_lookup(dev_path, LOOKUP_FOLLOW, &nd)) {
+ atomic_inc(&(sc->stripe[i].error_count));
+ goto out;
+ }
+
+ /* Next check to see if device has an inode entry
+ * (this is where it will likely find the disabled
device) */
+ inode = nd.dentry->d_inode;
+ if (!inode) {
+ atomic_inc(&(sc->stripe[i].error_count));
+ goto out;
+ }
+
+ /* Finally as a last check, see if the inode mode is set
+ * to be a block device, record error if not */
+ if (!S_ISBLK(inode->i_mode)) {
+ atomic_inc(&(sc->stripe[i].error_count));
+ }
+out:
+ /* We don't want to generate hundreds of work queue
calls
+ * when IO errors occur for a device, so we only queue
up the
+ * first IO_ERROR_COUNT for a given underlying hardware
device.
+ * After that point is reached we still record the
errors,
+ * but won't call dm_table_event() to report them. */
+ if(atomic_read(&(sc->stripe[i].error_count)) <
IO_ERROR_COUNT) {
+ dm_table_event(sc->ti->table);
+ }
+ }
+}
+
static inline struct stripe_c *alloc_context(unsigned int stripes)
{
size_t len;
@@ -63,6 +127,7 @@
return -ENXIO;
sc->stripe[stripe].physical_start = start;
+
return 0;
}
@@ -134,6 +199,12 @@
"failed";
return -ENOMEM;
}
+
+ /* Initialize the work_struct */
+ INIT_WORK(&sc->kstriped_ws, trigger_event);
+
+ /* Set pointer to dm target; used in trigger_event */
+ sc->ti = ti;
sc->stripes = stripes;
sc->stripe_width = width;
@@ -143,13 +214,12 @@
for (sc->chunk_shift = 0; chunk_size; sc->chunk_shift++)
chunk_size >>= 1;
sc->chunk_shift--;
-
+
/*
* Get the stripe destinations.
*/
for (i = 0; i < stripes; i++) {
argv += 2;
-
r = get_stripe(ti, sc, i, argv);
if (r < 0) {
ti->error = "Couldn't parse stripe destination";
@@ -158,9 +228,16 @@
kfree(sc);
return r;
}
+ /* Initialize error_count */
+ atomic_set(&(sc->stripe[i].error_count), 0);
}
ti->private = sc;
+
+ /* Trigger event to let dmeventd daemon know to
+ * check device status when stripe's DSO is registered*/
+ queue_work(kstriped, &sc->kstriped_ws);
+
return 0;
}
@@ -172,6 +249,7 @@
for (i = 0; i < sc->stripes; i++)
dm_put_device(ti, sc->stripe[i].dev);
+ flush_workqueue(kstriped);
kfree(sc);
}
@@ -213,13 +291,38 @@
return 0;
}
+static int stripe_end_io(struct dm_target *ti, struct bio *bio,
+ int error, union map_info *map_context)
+{
+ struct stripe_c *sc = (struct stripe_c *) ti->private;
+
+ if (!error)
+ return 0; /* I/O complete */
+
+ if ((error == -EWOULDBLOCK) && bio_rw_ahead(bio))
+ return error;
+
+ if (error == -EOPNOTSUPP)
+ return error;
+
+ /* Error not caught above, trigger event.
+ * For example, if member device gets
+ * disconnected this sets "error == -5" */
+ if (error < 0) {
+ queue_work(kstriped, &sc->kstriped_ws);
+ }
+
+ return error;
+}
+
static struct target_type stripe_target = {
.name = "striped",
- .version= {1, 0, 2},
+ .version= {1, 1, 2},
.module = THIS_MODULE,
.ctr = stripe_ctr,
.dtr = stripe_dtr,
.map = stripe_map,
+ .end_io = stripe_end_io,
.status = stripe_status,
};
@@ -230,7 +333,14 @@
r = dm_register_target(&stripe_target);
if (r < 0)
DMWARN("target registration failed");
-
+
+ kstriped = create_singlethread_workqueue("kstriped");
+ if (!kstriped) {
+ DMERR("failed to create workqueue kstriped");
+ dm_unregister_target(&stripe_target);
+ return -ENOMEM;
+ }
+
return r;
}
@@ -238,6 +348,8 @@
{
if (dm_unregister_target(&stripe_target))
DMWARN("target unregistration failed");
-
+
+ destroy_workqueue(kstriped);
+
return;
}
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 1/2] add stripe end_io function and event trigger
2007-12-04 17:36 [PATCH 1/2] add stripe end_io function and event trigger Wood, Brian J
@ 2007-12-05 17:57 ` Mike Anderson
2007-12-05 19:37 ` [PATCH 1/2] add stripe end_io function and eventtrigger Wood, Brian J
0 siblings, 1 reply; 3+ messages in thread
From: Mike Anderson @ 2007-12-05 17:57 UTC (permalink / raw)
To: device-mapper development; +Cc: Alasdair G Kergon
Wood, Brian J <brian.j.wood@intel.com> wrote:
> +static void trigger_event(struct work_struct *work)
> +{
> + int i, len;
> + char dev_path[DEV_STR_LEN];
> + struct stripe_c *sc = container_of(work, struct stripe_c,
> kstriped_ws);
It appears your mailer is breaking lines which leads to hand edits prior
to trying to apply the patch.
Your patch also appears to be adding extra whitespace. You want to run
checkpatch.pl prior to sending the patch out and correct all issues
listed.
> + /* Finally as a last check, see if the inode mode is set
>
> + * to be a block device, record error if not */
> + if (!S_ISBLK(inode->i_mode)) {
> + atomic_inc(&(sc->stripe[i].error_count));
> + }
Code comment style and extra bracing.
http://sources.redhat.com/lvm2/wiki/KernelPatchGuidelines
-andmike
--
Michael Anderson
andmike@linux.vnet.ibm.com
^ permalink raw reply [flat|nested] 3+ messages in thread
* RE: [PATCH 1/2] add stripe end_io function and eventtrigger
2007-12-05 17:57 ` Mike Anderson
@ 2007-12-05 19:37 ` Wood, Brian J
0 siblings, 0 replies; 3+ messages in thread
From: Wood, Brian J @ 2007-12-05 19:37 UTC (permalink / raw)
To: device-mapper development; +Cc: Alasdair G Kergon
Ah, ok. Thanks Mike I'll run that and repost. (Sorry for the error).
Brian Wood
Software Engineer
Intel Corp., Manageability & Platform Software Division
brian.j.wood@intel.com
>-----Original Message-----
>From: dm-devel-bounces@redhat.com [mailto:dm-devel-bounces@redhat.com]
On
>Behalf Of Mike Anderson
>Sent: Wednesday, December 05, 2007 9:57 AM
>To: device-mapper development
>Cc: Alasdair G Kergon
>Subject: Re: [dm-devel] [PATCH 1/2] add stripe end_io function and
>eventtrigger
>
>Wood, Brian J <brian.j.wood@intel.com> wrote:
>> +static void trigger_event(struct work_struct *work)
>> +{
>> + int i, len;
>> + char dev_path[DEV_STR_LEN];
>> + struct stripe_c *sc = container_of(work, struct stripe_c,
>> kstriped_ws);
>
>It appears your mailer is breaking lines which leads to hand edits
prior
>to trying to apply the patch.
>
>Your patch also appears to be adding extra whitespace. You want to run
>checkpatch.pl prior to sending the patch out and correct all issues
>listed.
>
>> + /* Finally as a last check, see if the inode mode is set
>>
>> + * to be a block device, record error if not */
>
>> + if (!S_ISBLK(inode->i_mode)) {
>> + atomic_inc(&(sc->stripe[i].error_count));
>> + }
>
>Code comment style and extra bracing.
>
>http://sources.redhat.com/lvm2/wiki/KernelPatchGuidelines
>
>
>-andmike
>--
>Michael Anderson
>andmike@linux.vnet.ibm.com
>
>--
>dm-devel mailing list
>dm-devel@redhat.com
>https://www.redhat.com/mailman/listinfo/dm-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2007-12-05 19:37 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-04 17:36 [PATCH 1/2] add stripe end_io function and event trigger Wood, Brian J
2007-12-05 17:57 ` Mike Anderson
2007-12-05 19:37 ` [PATCH 1/2] add stripe end_io function and eventtrigger Wood, Brian J
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.