1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

Limit repeated accesses to broken devices.

Signed-off-by: Takahiro Yasui <takahiro.yasui@hds.com>
Reviewed-by: Petr Rockai <prockai@redhat.com>
This commit is contained in:
Petr Rockai 2010-10-13 15:40:38 +00:00
parent d9583b8708
commit 976b95d929
11 changed files with 88 additions and 2 deletions

View File

@ -136,6 +136,11 @@ devices {
# in recovery situations. # in recovery situations.
ignore_suspended_devices = 0 ignore_suspended_devices = 0
# During each LVM operation any errors received from a device are counted.
# If this counter exceeds the number here, no further I/O is sent to the
# device.
disable_after_error_count = 0
# Allow use of pvcreate --uuid without requiring --restorefile. # Allow use of pvcreate --uuid without requiring --restorefile.
require_restorefile_with_uuid = 1 require_restorefile_with_uuid = 1
} }

View File

@ -560,6 +560,10 @@ static int _init_dev_cache(struct cmd_context *cmd)
const struct config_node *cn; const struct config_node *cn;
struct config_value *cv; struct config_value *cv;
init_dev_disable_after_error_count(
find_config_tree_int(cmd, "devices/disable_after_error_count",
DEFAULT_DISABLE_AFTER_ERROR_COUNT));
if (!dev_cache_init(cmd)) if (!dev_cache_init(cmd))
return_0; return_0;

View File

@ -33,6 +33,7 @@
#define DEFAULT_MD_COMPONENT_DETECTION 1 #define DEFAULT_MD_COMPONENT_DETECTION 1
#define DEFAULT_MD_CHUNK_ALIGNMENT 1 #define DEFAULT_MD_CHUNK_ALIGNMENT 1
#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1 #define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
#define DEFAULT_DISABLE_AFTER_ERROR_COUNT 0
#define DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID 1 #define DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID 1
#define DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION 1 #define DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION 1
#define DEFAULT_DATA_ALIGNMENT_DETECTION 1 #define DEFAULT_DATA_ALIGNMENT_DETECTION 1
@ -117,6 +118,8 @@
# define DEFAULT_MAX_HISTORY 100 # define DEFAULT_MAX_HISTORY 100
#endif #endif
#define DEFAULT_MAX_ERROR_COUNT NO_DEV_ERROR_COUNT_LIMIT
#define DEFAULT_REP_ALIGNED 1 #define DEFAULT_REP_ALIGNED 1
#define DEFAULT_REP_BUFFERED 1 #define DEFAULT_REP_BUFFERED 1
#define DEFAULT_REP_COLUMNS_AS_ROWS 0 #define DEFAULT_REP_COLUMNS_AS_ROWS 0

View File

@ -104,6 +104,8 @@ struct device *dev_create_file(const char *filename, struct device *dev,
dev->dev = 0; dev->dev = 0;
dev->fd = -1; dev->fd = -1;
dev->open_count = 0; dev->open_count = 0;
dev->error_count = 0;
dev->max_error_count = NO_DEV_ERROR_COUNT_LIMIT;
dev->block_size = -1; dev->block_size = -1;
dev->read_ahead = -1; dev->read_ahead = -1;
memset(dev->pvid, 0, sizeof(dev->pvid)); memset(dev->pvid, 0, sizeof(dev->pvid));
@ -125,6 +127,7 @@ static struct device *_dev_create(dev_t d)
dev->dev = d; dev->dev = d;
dev->fd = -1; dev->fd = -1;
dev->open_count = 0; dev->open_count = 0;
dev->max_error_count = dev_disable_after_error_count();
dev->block_size = -1; dev->block_size = -1;
dev->read_ahead = -1; dev->read_ahead = -1;
dev->end = UINT64_C(0); dev->end = UINT64_C(0);
@ -845,6 +848,22 @@ struct device *dev_iter_get(struct dev_iter *iter)
return NULL; 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) int dev_fd(struct device *dev)
{ {
return dev->fd; return dev->fd;

View File

@ -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); void dev_iter_destroy(struct dev_iter *iter);
struct device *dev_iter_get(struct dev_iter *iter); struct device *dev_iter_get(struct dev_iter *iter);
void dev_reset_error_count(struct cmd_context *cmd);
#endif #endif

View File

@ -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) int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
{ {
struct device_area where; struct device_area where;
int ret;
if (!dev->open_count) if (!dev->open_count)
return_0; return_0;
if (!_dev_is_valid(dev))
return 0;
where.dev = dev; where.dev = dev;
where.start = offset; where.start = offset;
where.size = len; 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) int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
{ {
struct device_area where; struct device_area where;
int ret;
if (!dev->open_count) if (!dev->open_count)
return_0; return_0;
if (!_dev_is_valid(dev))
return 0;
where.dev = dev; where.dev = dev;
where.start = offset; where.start = offset;
where.size = len; where.size = len;
dev->flags |= DEV_ACCESSED_W; 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) int dev_set(struct device *dev, uint64_t offset, size_t len, int value)

View File

@ -39,6 +39,8 @@ struct device {
/* private */ /* private */
int fd; int fd;
int open_count; int open_count;
int error_count;
int max_error_count;
int block_size; int block_size;
int read_ahead; int read_ahead;
uint32_t flags; uint32_t flags;

View File

@ -382,6 +382,7 @@ static int _lock_vol(struct cmd_context *cmd, const char *resource,
else else
lvmcache_lock_vgname(resource, (flags & LCK_TYPE_MASK) lvmcache_lock_vgname(resource, (flags & LCK_TYPE_MASK)
== LCK_READ); == LCK_READ);
dev_reset_error_count(cmd);
} }
_update_vg_lock_count(resource, flags); _update_vg_lock_count(resource, flags);

View File

@ -41,6 +41,7 @@ static int _error_message_produced = 0;
static unsigned _is_static = 0; static unsigned _is_static = 0;
static int _udev_checking = 1; static int _udev_checking = 1;
static char _sysfs_dir_path[PATH_MAX] = ""; static char _sysfs_dir_path[PATH_MAX] = "";
static int _dev_disable_after_error_count = DEFAULT_DISABLE_AFTER_ERROR_COUNT;
void init_verbose(int level) void init_verbose(int level)
{ {
@ -122,6 +123,11 @@ void init_udev_checking(int checking)
log_debug("LVM udev checking disabled"); log_debug("LVM udev checking disabled");
} }
void init_dev_disable_after_error_count(int value)
{
_dev_disable_after_error_count = value;
}
void set_cmd_name(const char *cmd) void set_cmd_name(const char *cmd)
{ {
strncpy(_cmd_name, cmd, sizeof(_cmd_name)); strncpy(_cmd_name, cmd, sizeof(_cmd_name));
@ -236,3 +242,8 @@ const char *sysfs_dir_path()
{ {
return _sysfs_dir_path; return _sysfs_dir_path;
} }
int dev_disable_after_error_count(void)
{
return _dev_disable_after_error_count;
}

View File

@ -37,6 +37,7 @@ void init_ignore_suspended_devices(int ignore);
void init_error_message_produced(int produced); void init_error_message_produced(int produced);
void init_is_static(unsigned value); void init_is_static(unsigned value);
void init_udev_checking(int checking); void init_udev_checking(int checking);
void init_dev_disable_after_error_count(int value);
void set_cmd_name(const char *cmd_name); void set_cmd_name(const char *cmd_name);
void set_sysfs_dir_path(const char *path); void set_sysfs_dir_path(const char *path);
@ -62,4 +63,7 @@ const char *sysfs_dir_path(void);
#define DMEVENTD_MONITOR_IGNORE -1 #define DMEVENTD_MONITOR_IGNORE -1
int dmeventd_monitor_mode(void); int dmeventd_monitor_mode(void);
#define NO_DEV_ERROR_COUNT_LIMIT 0
int dev_disable_after_error_count(void);
#endif #endif

View File

@ -165,6 +165,11 @@ use \fBpvs -o +pe_start\fP . It will be a multiple of the requested
\fBdata_alignment\fP plus the alignment_offset from \fBdata_alignment\fP plus the alignment_offset from
\fBdata_alignment_offset_detection\fP (if enabled) or the pvcreate \fBdata_alignment_offset_detection\fP (if enabled) or the pvcreate
commandline. commandline.
.IP
\fBdev_max_error_count\fP \(em Maximum number of error counts per device
before disabling devices. This option prevents a broken device from
being accessed repeatedly. If set to 0, no access control to devices is
done.
.TP .TP
\fBlog\fP \(em Default log settings \fBlog\fP \(em Default log settings
.IP .IP