summaryrefslogtreecommitdiffstats
path: root/lib/device
diff options
context:
space:
mode:
authorPetr Rockai <prockai@redhat.com>2010-10-13 15:40:38 +0000
committerPetr Rockai <prockai@redhat.com>2010-10-13 15:40:38 +0000
commit976b95d9290ad0e9ef10bdd35fe3ed08270666b8 (patch)
tree83dc1847d51c0991b5b4bda20bbeea635ba451c9 /lib/device
parentd9583b8708a90d305989db813728a9873e70eb43 (diff)
downloadlvm2-976b95d9290ad0e9ef10bdd35fe3ed08270666b8.tar.gz
lvm2-976b95d9290ad0e9ef10bdd35fe3ed08270666b8.tar.xz
lvm2-976b95d9290ad0e9ef10bdd35fe3ed08270666b8.zip
Limit repeated accesses to broken devices.
Signed-off-by: Takahiro Yasui <takahiro.yasui@hds.com> Reviewed-by: Petr Rockai <prockai@redhat.com>
Diffstat (limited to 'lib/device')
-rw-r--r--lib/device/dev-cache.c19
-rw-r--r--lib/device/dev-cache.h2
-rw-r--r--lib/device/dev-io.c34
-rw-r--r--lib/device/device.h2
4 files changed, 55 insertions, 2 deletions
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index d43fcc02..ef93f4d6 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -104,6 +104,8 @@ struct device *dev_create_file(const char *filename, struct device *dev,
dev->dev = 0;
dev->fd = -1;
dev->open_count = 0;
+ dev->error_count = 0;
+ dev->max_error_count = NO_DEV_ERROR_COUNT_LIMIT;
dev->block_size = -1;
dev->read_ahead = -1;
memset(dev->pvid, 0, sizeof(dev->pvid));
@@ -125,6 +127,7 @@ static struct device *_dev_create(dev_t d)
dev->dev = d;
dev->fd = -1;
dev->open_count = 0;
+ dev->max_error_count = dev_disable_after_error_count();
dev->block_size = -1;
dev->read_ahead = -1;
dev->end = UINT64_C(0);
@@ -845,6 +848,22 @@ struct device *dev_iter_get(struct dev_iter *iter)
return NULL;
}
+void dev_reset_error_count(struct cmd_context *cmd)
+{
+ struct dev_iter *iter;
+ struct device *dev;
+
+ if (!(iter = dev_iter_create(cmd->filter, 0))) {
+ log_error("Resetting device error count failed");
+ return;
+ }
+
+ for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter))
+ dev->error_count = 0;
+
+ dev_iter_destroy(iter);
+}
+
int dev_fd(struct device *dev)
{
return dev->fd;
diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h
index 0ade053c..c1c86d6a 100644
--- a/lib/device/dev-cache.h
+++ b/lib/device/dev-cache.h
@@ -53,4 +53,6 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan);
void dev_iter_destroy(struct dev_iter *iter);
struct device *dev_iter_get(struct dev_iter *iter);
+void dev_reset_error_count(struct cmd_context *cmd);
+
#endif
diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c
index 1995bdea..eb80a894 100644
--- a/lib/device/dev-io.c
+++ b/lib/device/dev-io.c
@@ -603,18 +603,40 @@ void dev_close_all(void)
}
}
+static inline int _dev_is_valid(struct device *dev)
+{
+ return (dev->max_error_count == NO_DEV_ERROR_COUNT_LIMIT ||
+ dev->error_count < dev->max_error_count);
+}
+
+static void _dev_inc_error_count(struct device *dev)
+{
+ if (++dev->error_count == dev->max_error_count)
+ log_warn("WARNING: Error counts reached a limit of %d. "
+ "Device %s was disabled",
+ dev->max_error_count, dev_name(dev));
+}
+
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
{
struct device_area where;
+ int ret;
if (!dev->open_count)
return_0;
+ if (!_dev_is_valid(dev))
+ return 0;
+
where.dev = dev;
where.start = offset;
where.size = len;
- return _aligned_io(&where, buffer, 0);
+ ret = _aligned_io(&where, buffer, 0);
+ if (!ret)
+ _dev_inc_error_count(dev);
+
+ return ret;
}
/*
@@ -670,17 +692,25 @@ int dev_append(struct device *dev, size_t len, void *buffer)
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
{
struct device_area where;
+ int ret;
if (!dev->open_count)
return_0;
+ if (!_dev_is_valid(dev))
+ return 0;
+
where.dev = dev;
where.start = offset;
where.size = len;
dev->flags |= DEV_ACCESSED_W;
- return _aligned_io(&where, buffer, 1);
+ ret = _aligned_io(&where, buffer, 1);
+ if (!ret)
+ _dev_inc_error_count(dev);
+
+ return ret;
}
int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
diff --git a/lib/device/device.h b/lib/device/device.h
index 5a599508..694f503f 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -39,6 +39,8 @@ struct device {
/* private */
int fd;
int open_count;
+ int error_count;
+ int max_error_count;
int block_size;
int read_ahead;
uint32_t flags;