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:
parent
d9583b8708
commit
976b95d929
@ -136,6 +136,11 @@ devices {
|
||||
# in recovery situations.
|
||||
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.
|
||||
require_restorefile_with_uuid = 1
|
||||
}
|
||||
|
@ -560,6 +560,10 @@ static int _init_dev_cache(struct cmd_context *cmd)
|
||||
const struct config_node *cn;
|
||||
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))
|
||||
return_0;
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define DEFAULT_MD_COMPONENT_DETECTION 1
|
||||
#define DEFAULT_MD_CHUNK_ALIGNMENT 1
|
||||
#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
|
||||
#define DEFAULT_DISABLE_AFTER_ERROR_COUNT 0
|
||||
#define DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID 1
|
||||
#define DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION 1
|
||||
#define DEFAULT_DATA_ALIGNMENT_DETECTION 1
|
||||
@ -117,6 +118,8 @@
|
||||
# define DEFAULT_MAX_HISTORY 100
|
||||
#endif
|
||||
|
||||
#define DEFAULT_MAX_ERROR_COUNT NO_DEV_ERROR_COUNT_LIMIT
|
||||
|
||||
#define DEFAULT_REP_ALIGNED 1
|
||||
#define DEFAULT_REP_BUFFERED 1
|
||||
#define DEFAULT_REP_COLUMNS_AS_ROWS 0
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -382,6 +382,7 @@ static int _lock_vol(struct cmd_context *cmd, const char *resource,
|
||||
else
|
||||
lvmcache_lock_vgname(resource, (flags & LCK_TYPE_MASK)
|
||||
== LCK_READ);
|
||||
dev_reset_error_count(cmd);
|
||||
}
|
||||
|
||||
_update_vg_lock_count(resource, flags);
|
||||
|
@ -41,6 +41,7 @@ static int _error_message_produced = 0;
|
||||
static unsigned _is_static = 0;
|
||||
static int _udev_checking = 1;
|
||||
static char _sysfs_dir_path[PATH_MAX] = "";
|
||||
static int _dev_disable_after_error_count = DEFAULT_DISABLE_AFTER_ERROR_COUNT;
|
||||
|
||||
void init_verbose(int level)
|
||||
{
|
||||
@ -122,6 +123,11 @@ void init_udev_checking(int checking)
|
||||
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)
|
||||
{
|
||||
strncpy(_cmd_name, cmd, sizeof(_cmd_name));
|
||||
@ -236,3 +242,8 @@ const char *sysfs_dir_path()
|
||||
{
|
||||
return _sysfs_dir_path;
|
||||
}
|
||||
|
||||
int dev_disable_after_error_count(void)
|
||||
{
|
||||
return _dev_disable_after_error_count;
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ void init_ignore_suspended_devices(int ignore);
|
||||
void init_error_message_produced(int produced);
|
||||
void init_is_static(unsigned value);
|
||||
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_sysfs_dir_path(const char *path);
|
||||
@ -62,4 +63,7 @@ const char *sysfs_dir_path(void);
|
||||
#define DMEVENTD_MONITOR_IGNORE -1
|
||||
int dmeventd_monitor_mode(void);
|
||||
|
||||
#define NO_DEV_ERROR_COUNT_LIMIT 0
|
||||
int dev_disable_after_error_count(void);
|
||||
|
||||
#endif
|
||||
|
@ -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_offset_detection\fP (if enabled) or the pvcreate
|
||||
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
|
||||
\fBlog\fP \(em Default log settings
|
||||
.IP
|
||||
|
Loading…
Reference in New Issue
Block a user