mirror of
git://sourceware.org/git/lvm2.git
synced 2025-11-02 04:23:50 +03:00
Compare commits
3 Commits
v2_02_178
...
dev-dct-ne
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
812e851b07 | ||
|
|
28de418bc5 | ||
|
|
8b6b5d5355 |
69
configure
vendored
69
configure
vendored
@@ -704,7 +704,9 @@ FSADM
|
||||
ELDFLAGS
|
||||
DM_LIB_PATCHLEVEL
|
||||
DMEVENTD_PATH
|
||||
AIO_LIBS
|
||||
DL_LIBS
|
||||
AIO
|
||||
DEVMAPPER
|
||||
DEFAULT_USE_LVMLOCKD
|
||||
DEFAULT_USE_LVMPOLLD
|
||||
@@ -950,6 +952,7 @@ enable_profiling
|
||||
enable_testing
|
||||
enable_valgrind_pool
|
||||
enable_devmapper
|
||||
enable_aio
|
||||
enable_lvmetad
|
||||
enable_lvmpolld
|
||||
enable_lvmlockd_sanlock
|
||||
@@ -1688,6 +1691,7 @@ Optional Features:
|
||||
--enable-testing enable testing targets in the makefile
|
||||
--enable-valgrind-pool enable valgrind awareness of pools
|
||||
--disable-devmapper disable LVM2 device-mapper interaction
|
||||
--disable-aio disable async i/o
|
||||
--enable-lvmetad enable the LVM Metadata Daemon
|
||||
--enable-lvmpolld enable the LVM Polling Daemon
|
||||
--enable-lvmlockd-sanlock
|
||||
@@ -3175,6 +3179,7 @@ case "$host_os" in
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
LIB_SUFFIX=so
|
||||
DEVMAPPER=yes
|
||||
AIO=yes
|
||||
BUILD_LVMETAD=no
|
||||
BUILD_LVMPOLLD=no
|
||||
LOCKDSANLOCK=no
|
||||
@@ -3194,6 +3199,7 @@ case "$host_os" in
|
||||
CLDNOWHOLEARCHIVE=
|
||||
LIB_SUFFIX=dylib
|
||||
DEVMAPPER=yes
|
||||
AIO=no
|
||||
ODIRECT=no
|
||||
DM_IOCTLS=no
|
||||
SELINUX=no
|
||||
@@ -11816,6 +11822,67 @@ $as_echo "#define DEVMAPPER_SUPPORT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use aio" >&5
|
||||
$as_echo_n "checking whether to use aio... " >&6; }
|
||||
# Check whether --enable-aio was given.
|
||||
if test "${enable_aio+set}" = set; then :
|
||||
enableval=$enable_aio; AIO=$enableval
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $AIO" >&5
|
||||
$as_echo "$AIO" >&6; }
|
||||
|
||||
if test "$AIO" = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for io_setup in -laio" >&5
|
||||
$as_echo_n "checking for io_setup in -laio... " >&6; }
|
||||
if ${ac_cv_lib_aio_io_setup+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-laio $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char io_setup ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return io_setup ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_aio_io_setup=yes
|
||||
else
|
||||
ac_cv_lib_aio_io_setup=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_aio_io_setup" >&5
|
||||
$as_echo "$ac_cv_lib_aio_io_setup" >&6; }
|
||||
if test "x$ac_cv_lib_aio_io_setup" = xyes; then :
|
||||
|
||||
$as_echo "#define AIO_SUPPORT 1" >>confdefs.h
|
||||
|
||||
AIO_LIBS="-laio"
|
||||
AIO_SUPPORT=yes
|
||||
else
|
||||
AIO_LIBS=
|
||||
AIO_SUPPORT=no
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build LVMetaD" >&5
|
||||
$as_echo_n "checking whether to build LVMetaD... " >&6; }
|
||||
@@ -15763,6 +15830,8 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
22
configure.in
22
configure.in
@@ -39,6 +39,7 @@ case "$host_os" in
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
LIB_SUFFIX=so
|
||||
DEVMAPPER=yes
|
||||
AIO=yes
|
||||
BUILD_LVMETAD=no
|
||||
BUILD_LVMPOLLD=no
|
||||
LOCKDSANLOCK=no
|
||||
@@ -58,6 +59,7 @@ case "$host_os" in
|
||||
CLDNOWHOLEARCHIVE=
|
||||
LIB_SUFFIX=dylib
|
||||
DEVMAPPER=yes
|
||||
AIO=no
|
||||
ODIRECT=no
|
||||
DM_IOCTLS=no
|
||||
SELINUX=no
|
||||
@@ -1115,6 +1117,24 @@ if test "$DEVMAPPER" = yes; then
|
||||
AC_DEFINE([DEVMAPPER_SUPPORT], 1, [Define to 1 to enable LVM2 device-mapper interaction.])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable aio
|
||||
AC_MSG_CHECKING(whether to use aio)
|
||||
AC_ARG_ENABLE(aio,
|
||||
AC_HELP_STRING([--disable-aio],
|
||||
[disable async i/o]),
|
||||
AIO=$enableval)
|
||||
AC_MSG_RESULT($AIO)
|
||||
|
||||
if test "$AIO" = yes; then
|
||||
AC_CHECK_LIB(aio, io_setup,
|
||||
[AC_DEFINE([AIO_SUPPORT], 1, [Define to 1 if aio is available.])
|
||||
AIO_LIBS="-laio"
|
||||
AIO_SUPPORT=yes],
|
||||
[AIO_LIBS=
|
||||
AIO_SUPPORT=no ])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Build lvmetad
|
||||
AC_MSG_CHECKING(whether to build LVMetaD)
|
||||
@@ -2056,9 +2076,11 @@ AC_SUBST(DEFAULT_USE_LVMETAD)
|
||||
AC_SUBST(DEFAULT_USE_LVMPOLLD)
|
||||
AC_SUBST(DEFAULT_USE_LVMLOCKD)
|
||||
AC_SUBST(DEVMAPPER)
|
||||
AC_SUBST(AIO)
|
||||
AC_SUBST(DLM_CFLAGS)
|
||||
AC_SUBST(DLM_LIBS)
|
||||
AC_SUBST(DL_LIBS)
|
||||
AC_SUBST(AIO_LIBS)
|
||||
AC_SUBST(DMEVENTD_PATH)
|
||||
AC_SUBST(DM_LIB_PATCHLEVEL)
|
||||
AC_SUBST(ELDFLAGS)
|
||||
|
||||
@@ -77,6 +77,10 @@ include $(top_builddir)/make.tmpl
|
||||
LIBS += $(LVMINTERNAL_LIBS) -ldevmapper $(PTHREAD_LIBS)
|
||||
CFLAGS += -fno-strict-aliasing $(EXTRA_EXEC_CFLAGS)
|
||||
|
||||
ifeq ("@AIO@", "yes")
|
||||
LIBS += $(AIO_LIBS)
|
||||
endif
|
||||
|
||||
INSTALL_TARGETS = \
|
||||
install_clvmd
|
||||
|
||||
|
||||
@@ -542,6 +542,7 @@ static int _process_config(struct cmd_context *cmd)
|
||||
const struct dm_config_value *cv;
|
||||
int64_t pv_min_kb;
|
||||
int udev_disabled = 0;
|
||||
int scan_size;
|
||||
char sysfs_dir[PATH_MAX];
|
||||
|
||||
if (!_check_config(cmd))
|
||||
@@ -625,6 +626,29 @@ static int _process_config(struct cmd_context *cmd)
|
||||
cmd->default_settings.udev_sync = udev_disabled ? 0 :
|
||||
find_config_tree_bool(cmd, activation_udev_sync_CFG, NULL);
|
||||
|
||||
#ifdef AIO_SUPPORT
|
||||
cmd->use_aio = find_config_tree_bool(cmd, devices_scan_async_CFG, NULL);
|
||||
#else
|
||||
cmd->use_aio = 0;
|
||||
if (find_config_tree_bool(cmd, devices_scan_async_CFG, NULL))
|
||||
log_verbose("Ignoring scan_async, no async I/O support.");
|
||||
#endif
|
||||
scan_size = find_config_tree_int(cmd, devices_scan_size_CFG, NULL);
|
||||
|
||||
if (!scan_size || (scan_size < 0)) {
|
||||
log_warn("WARNING: Ignoring invalid metadata/scan_size %d, using default %u.",
|
||||
scan_size, DEFAULT_SCAN_SIZE_KB);
|
||||
scan_size = DEFAULT_SCAN_SIZE_KB;
|
||||
}
|
||||
|
||||
if (cmd->use_aio && (scan_size % 4)) {
|
||||
log_warn("WARNING: Ignoring invalid metadata/scan_size %d with scan_async, using default %u.",
|
||||
scan_size, DEFAULT_SCAN_SIZE_KB);
|
||||
scan_size = DEFAULT_SCAN_SIZE_KB;
|
||||
}
|
||||
|
||||
cmd->default_settings.scan_size_kb = scan_size;
|
||||
|
||||
/*
|
||||
* Set udev_fallback lazily on first use since it requires
|
||||
* checking DM driver version which is an extra ioctl!
|
||||
@@ -2226,6 +2250,9 @@ void destroy_toolcontext(struct cmd_context *cmd)
|
||||
!cmd->filter->dump(cmd->filter, 1))
|
||||
stack;
|
||||
|
||||
if (cmd->ac)
|
||||
dev_async_context_destroy(cmd->ac);
|
||||
|
||||
archive_exit(cmd);
|
||||
backup_exit(cmd);
|
||||
lvmcache_destroy(cmd, 0, 0);
|
||||
|
||||
@@ -40,6 +40,7 @@ struct config_info {
|
||||
int udev_sync;
|
||||
int udev_fallback;
|
||||
int cache_vgmetadata;
|
||||
int scan_size_kb;
|
||||
const char *msg_prefix;
|
||||
const char *fmt_name;
|
||||
uint64_t unit_factor;
|
||||
@@ -164,6 +165,7 @@ struct cmd_context {
|
||||
unsigned vg_notify:1;
|
||||
unsigned lv_notify:1;
|
||||
unsigned pv_notify:1;
|
||||
unsigned use_aio:1;
|
||||
|
||||
/*
|
||||
* Filtering.
|
||||
@@ -223,6 +225,7 @@ struct cmd_context {
|
||||
const char *time_format;
|
||||
unsigned rand_seed;
|
||||
struct dm_list unused_duplicate_devs; /* save preferences between lvmcache instances */
|
||||
struct dev_async_context *ac; /* for async i/o */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -457,6 +457,26 @@ cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_
|
||||
"Enabling this setting allows the VG to be used as usual even with\n"
|
||||
"uncertain devices.\n")
|
||||
|
||||
cfg(devices_scan_async_CFG, "scan_async", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SCAN_ASYNC, vsn(2, 2, 173), NULL, 0, NULL,
|
||||
"Use async I/O to read headers and metadata from disks in parallel.\n")
|
||||
|
||||
cfg(devices_scan_size_CFG, "scan_size", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SCAN_SIZE_KB, vsn(2, 2, 173), NULL, 0, NULL,
|
||||
"Number of KiB to read from each disk when scanning disks.\n"
|
||||
"The initial scan size is intended to cover all the headers\n"
|
||||
"and metadata that LVM places at the start of each disk so\n"
|
||||
"that a single read operation can retrieve them all.\n"
|
||||
"Any headers or metadata that lie beyond this size require\n"
|
||||
"an additional disk read.\n")
|
||||
|
||||
cfg(devices_async_events_CFG, "async_events", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_ASYNC_EVENTS, vsn(2, 2, 173), NULL, 0, NULL,
|
||||
"Max number of concurrent async reads when scanning disks.\n"
|
||||
"Up to this many disks can be read concurrently when scanning\n"
|
||||
"disks with async I/O. If there are more disks than this,\n"
|
||||
"they will be scanned serially with synchronous reads.\n"
|
||||
"Increasing this number to match a larger number of disks may\n"
|
||||
"improve performance, but will increase memory requirements.\n"
|
||||
"This setting is limitted by the system aio configuration.\n")
|
||||
|
||||
cfg_array(allocation_cling_tag_list_CFG, "cling_tag_list", allocation_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 77), NULL, 0, NULL,
|
||||
"Advise LVM which PVs to use when searching for new space.\n"
|
||||
"When searching for free space to extend an LV, the 'cling' allocation\n"
|
||||
|
||||
@@ -267,4 +267,9 @@
|
||||
#define DEFAULT_THIN_POOL_AUTOEXTEND_THRESHOLD 100
|
||||
#define DEFAULT_THIN_POOL_AUTOEXTEND_PERCENT 20
|
||||
|
||||
#define DEFAULT_ASYNC_EVENTS 100
|
||||
#define DEFAULT_SCAN_ASYNC 1
|
||||
#define DEFAULT_SCAN_SIZE_KB 128
|
||||
#define DEFAULT_ASYNC_EVENTS 100
|
||||
|
||||
#endif /* _LVM_DEFAULTS_H */
|
||||
|
||||
@@ -1081,6 +1081,8 @@ static void _full_scan(int dev_scan)
|
||||
if (_cache.has_scanned && !dev_scan)
|
||||
return;
|
||||
|
||||
log_debug_devs("Adding device paths to dev cache");
|
||||
|
||||
_insert_dirs(&_cache.dirs);
|
||||
|
||||
(void) dev_cache_index_devs();
|
||||
@@ -1090,6 +1092,8 @@ static void _full_scan(int dev_scan)
|
||||
|
||||
_cache.has_scanned = 1;
|
||||
init_full_scan_done(1);
|
||||
|
||||
log_debug_devs("Added %d device paths to dev cache", dm_hash_get_num_entries(_cache.names));
|
||||
}
|
||||
|
||||
int dev_cache_has_scanned(void)
|
||||
|
||||
@@ -827,3 +827,302 @@ int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
|
||||
|
||||
return (len == 0);
|
||||
}
|
||||
|
||||
#ifdef AIO_SUPPORT
|
||||
|
||||
/*
|
||||
* io_setup() wrapper:
|
||||
* async_event_count is the max number of concurrent async
|
||||
* i/os, i.e. the number of devices that can be read at once
|
||||
*
|
||||
* max_io_alloc_count: max number of aio structs to allocate,
|
||||
* each with a buf_len size buffer.
|
||||
*
|
||||
* max_buf_alloc_bytes: max number of bytes to use for buffers
|
||||
* attached to all aio structs; each aio struct gets a
|
||||
* buf_len size buffer.
|
||||
*
|
||||
* When only max_io_alloc_count is set, it is used directly.
|
||||
*
|
||||
* When only max_buf_alloc_bytes is set, the number of aio
|
||||
* structs is determined by this number divided by buf_len.
|
||||
*
|
||||
* When both are set, max_io_alloc_count is reduced, if needed,
|
||||
* to whatever value max_buf_alloc_bytes would allow.
|
||||
*
|
||||
* When both are zero, there is no limit on the number of aio
|
||||
* structs. If allocation fails for an aio struct or its buffer,
|
||||
* the code should revert to synchronous io.
|
||||
*/
|
||||
|
||||
struct dev_async_context *dev_async_context_setup(unsigned async_event_count,
|
||||
unsigned max_io_alloc_count,
|
||||
unsigned max_buf_alloc_bytes,
|
||||
int buf_len)
|
||||
{
|
||||
struct dev_async_context *ac;
|
||||
unsigned nr_events = DEFAULT_ASYNC_EVENTS;
|
||||
int count;
|
||||
int error;
|
||||
|
||||
if (async_event_count)
|
||||
nr_events = async_event_count;
|
||||
|
||||
if (!(ac = malloc(sizeof(struct dev_async_context))))
|
||||
return_0;
|
||||
|
||||
memset(ac, 0, sizeof(struct dev_async_context));
|
||||
|
||||
error = io_setup(nr_events, &ac->aio_ctx);
|
||||
|
||||
if (error < 0) {
|
||||
log_warn("WARNING: async io setup error %d with %u events.", error, nr_events);
|
||||
free(ac);
|
||||
return_0;
|
||||
}
|
||||
|
||||
|
||||
if (!max_io_alloc_count && !max_buf_alloc_bytes)
|
||||
count = 0;
|
||||
else if (!max_io_alloc_count && max_buf_alloc_bytes)
|
||||
count = max_buf_alloc_bytes / buf_len;
|
||||
else if (max_io_alloc_count && max_buf_alloc_bytes) {
|
||||
if (max_io_alloc_count * buf_len > max_buf_alloc_bytes)
|
||||
count = max_buf_alloc_bytes / buf_len;
|
||||
} else
|
||||
count = max_io_alloc_count;
|
||||
|
||||
ac->max_ios = count;
|
||||
return ac;
|
||||
}
|
||||
|
||||
void dev_async_context_destroy(struct dev_async_context *ac)
|
||||
{
|
||||
io_destroy(ac->aio_ctx);
|
||||
free(ac);
|
||||
}
|
||||
|
||||
static struct dev_async_io *_async_io_alloc(int buf_len)
|
||||
{
|
||||
struct dev_async_io *aio;
|
||||
char *buf;
|
||||
char **p_buf;
|
||||
|
||||
/*
|
||||
* mem pool doesn't seem to work for this, probably because
|
||||
* of the memalign that follows.
|
||||
*/
|
||||
if (!(aio = malloc(sizeof(struct dev_async_io))))
|
||||
return_0;
|
||||
|
||||
memset(aio, 0, sizeof(struct dev_async_io));
|
||||
|
||||
buf = NULL;
|
||||
p_buf = &buf;
|
||||
|
||||
if (posix_memalign((void *)p_buf, getpagesize(), buf_len)) {
|
||||
free(aio);
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
memset(buf, 0, buf_len);
|
||||
|
||||
aio->buf = buf;
|
||||
aio->buf_len = buf_len;
|
||||
return aio;
|
||||
}
|
||||
|
||||
static void _async_io_free(struct dev_async_io *aio)
|
||||
{
|
||||
if (aio->buf)
|
||||
free(aio->buf);
|
||||
free(aio);
|
||||
}
|
||||
|
||||
int dev_async_alloc_ios(struct dev_async_context *ac, int num, int buf_len, int *available)
|
||||
{
|
||||
struct dev_async_io *aio;
|
||||
int count;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* When no limit is used and no pre-alloc number is set,
|
||||
* then no ios are allocated up front, but the are
|
||||
* allocated as needed in get().
|
||||
*/
|
||||
if (!ac->max_ios && !num) {
|
||||
*available = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (num && !ac->max_ios)
|
||||
count = num;
|
||||
else if (!num && ac->max_ios)
|
||||
count = ac->max_ios;
|
||||
else if (num > ac->max_ios)
|
||||
count = ac->max_ios;
|
||||
else if (num < ac->max_ios)
|
||||
count = num;
|
||||
else
|
||||
count = ac->max_ios;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!(aio = _async_io_alloc(buf_len))) {
|
||||
ac->num_ios = i;
|
||||
*available = i;
|
||||
return 1;
|
||||
}
|
||||
dm_list_add(&ac->unused_ios, &aio->list);
|
||||
}
|
||||
|
||||
ac->num_ios = count;
|
||||
*available = count;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dev_async_free_ios(struct dev_async_context *ac)
|
||||
{
|
||||
struct dev_async_io *aio, *aio2;
|
||||
|
||||
dm_list_iterate_items_safe(aio, aio2, &ac->unused_ios) {
|
||||
dm_list_del(&aio->list);
|
||||
_async_io_free(aio);
|
||||
}
|
||||
}
|
||||
|
||||
struct dev_async_io *dev_async_io_get(struct dev_async_context *ac, int buf_len)
|
||||
{
|
||||
struct dev_async_io *aio;
|
||||
|
||||
if (!(aio = dm_list_item(dm_list_first(&ac->unused_ios), struct dev_async_io))) {
|
||||
/* alloc on demand if there is no max or we have used less than max */
|
||||
if (!ac->max_ios || (ac->num_ios < ac->max_ios))
|
||||
return _async_io_alloc(buf_len);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
dm_list_del(&aio->list);
|
||||
return aio;
|
||||
}
|
||||
|
||||
void dev_async_io_put(struct dev_async_context *ac, struct dev_async_io *aio)
|
||||
{
|
||||
/*
|
||||
* Some paths don't have cmd->ac available, so it's simpler for now
|
||||
* to just free the aio struct in those cases.
|
||||
*/
|
||||
if (!ac)
|
||||
_async_io_free(aio);
|
||||
else
|
||||
dm_list_add(&ac->unused_ios, &aio->list);
|
||||
}
|
||||
|
||||
/* io_submit() wrapper */
|
||||
|
||||
int dev_async_read_submit(struct dev_async_context *ac, struct dev_async_io *aio,
|
||||
struct device *dev, uint32_t len, uint64_t offset, int *nospace)
|
||||
{
|
||||
struct iocb *iocb = &aio->iocb;
|
||||
int error;
|
||||
|
||||
*nospace = 0;
|
||||
|
||||
if (len > aio->buf_len)
|
||||
return_0;
|
||||
|
||||
aio->len = len;
|
||||
|
||||
iocb->data = aio;
|
||||
iocb->aio_fildes = dev_fd(dev);
|
||||
iocb->aio_lio_opcode = IO_CMD_PREAD;
|
||||
iocb->u.c.buf = aio->buf;
|
||||
iocb->u.c.nbytes = len;
|
||||
iocb->u.c.offset = offset;
|
||||
|
||||
error = io_submit(ac->aio_ctx, 1, &iocb);
|
||||
if (error == -EAGAIN)
|
||||
*nospace = 1;
|
||||
if (error < 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* io_getevents() wrapper */
|
||||
|
||||
int dev_async_getevents(struct dev_async_context *ac, int wait_count, struct timespec *timeout)
|
||||
{
|
||||
int wait_nr;
|
||||
int rv;
|
||||
int i;
|
||||
|
||||
retry:
|
||||
memset(&ac->events, 0, sizeof(ac->events));
|
||||
|
||||
if (wait_count >= MAX_GET_EVENTS)
|
||||
wait_nr = MAX_GET_EVENTS;
|
||||
else
|
||||
wait_nr = wait_count;
|
||||
|
||||
rv = io_getevents(ac->aio_ctx, 1, wait_nr, (struct io_event *)&ac->events, timeout);
|
||||
|
||||
if (rv == -EINTR)
|
||||
goto retry;
|
||||
if (rv < 0)
|
||||
return 0;
|
||||
if (!rv)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < rv; i++) {
|
||||
struct iocb *iocb = ac->events[i].obj;
|
||||
struct dev_async_io *aio = iocb->data;
|
||||
aio->result = ac->events[i].res;
|
||||
aio->done = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else /* AIO_SUPPORT */
|
||||
|
||||
struct dev_async_context *dev_async_context_setup(unsigned async_event_count,
|
||||
unsigned max_io_alloc_count,
|
||||
unsigned max_buf_alloc_bytes,
|
||||
int buf_len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dev_async_context_destroy(struct dev_async_context *ac)
|
||||
{
|
||||
}
|
||||
|
||||
int dev_async_alloc_ios(struct dev_async_context *ac, int num, int buf_len, int *available)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dev_async_free_ios(struct dev_async_context *ac)
|
||||
{
|
||||
}
|
||||
|
||||
struct dev_async_io *dev_async_io_get(struct dev_async_context *ac)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dev_async_io_put(struct dev_async_context *ac, struct dev_async_io *aio)
|
||||
{
|
||||
}
|
||||
|
||||
int dev_async_read_submit(struct dev_async_context *ac, struct dev_async_io *aio,
|
||||
struct device *dev, uint32_t len, uint64_t offset, int *nospace)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dev_async_getevents(struct dev_async_context *ac, int wait_count, struct timespec *timeout)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* AIO_SUPPORT */
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "uuid.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <libaio.h>
|
||||
|
||||
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */
|
||||
#define DEV_REGULAR 0x00000002 /* Regular file? */
|
||||
@@ -90,6 +91,32 @@ struct device_area {
|
||||
uint64_t size; /* Bytes */
|
||||
};
|
||||
|
||||
/*
|
||||
* We'll collect the results of this many async reads
|
||||
* in one system call. It shouldn't matter much what
|
||||
* number is used here.
|
||||
*/
|
||||
#define MAX_GET_EVENTS 16
|
||||
|
||||
struct dev_async_context {
|
||||
io_context_t aio_ctx;
|
||||
struct io_event events[MAX_GET_EVENTS]; /* for processing completions */
|
||||
struct dm_list unused_ios; /* unused/available aio structcs */
|
||||
int num_ios; /* number of allocated aio structs */
|
||||
int max_ios; /* max number of aio structs to allocate */
|
||||
};
|
||||
|
||||
struct dev_async_io {
|
||||
struct dm_list list;
|
||||
struct iocb iocb;
|
||||
struct device *dev;
|
||||
char *buf;
|
||||
uint32_t buf_len; /* size of buf */
|
||||
uint32_t len; /* size of submitted io */
|
||||
int done;
|
||||
int result;
|
||||
};
|
||||
|
||||
/*
|
||||
* Support for external device info.
|
||||
*/
|
||||
@@ -144,4 +171,26 @@ void dev_destroy_file(struct device *dev);
|
||||
/* Return a valid device name from the alias list; NULL otherwise */
|
||||
const char *dev_name_confirmed(struct device *dev, int quiet);
|
||||
|
||||
struct dev_async_context *dev_async_context_setup(unsigned async_event_count,
|
||||
unsigned max_io_alloc_count,
|
||||
unsigned max_buf_alloc_bytes,
|
||||
int buf_len);
|
||||
void dev_async_context_destroy(struct dev_async_context *ac);
|
||||
|
||||
/* allocate aio structs (with buffers), up to the max specified during context setup */
|
||||
int dev_async_alloc_ios(struct dev_async_context *ac, int num, int buf_len, int *available);
|
||||
|
||||
/* free aio structs (and buffers) */
|
||||
void dev_async_free_ios(struct dev_async_context *ac);
|
||||
|
||||
/* get an available aio struct (with buffer) */
|
||||
struct dev_async_io *dev_async_io_get(struct dev_async_context *ac, int buf_len);
|
||||
|
||||
/* make an aio struct (with buffer) available for use (by another get) */
|
||||
void dev_async_io_put(struct dev_async_context *ac, struct dev_async_io *aio);
|
||||
|
||||
int dev_async_read_submit(struct dev_async_context *ac, struct dev_async_io *aio,
|
||||
struct device *dev, uint32_t len, uint64_t offset, int *nospace);
|
||||
int dev_async_getevents(struct dev_async_context *ac, int wait_count, struct timespec *timeout);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "uuid.h"
|
||||
#include "device.h"
|
||||
#include "toolcontext.h"
|
||||
|
||||
#define LABEL_ID "LABELONE"
|
||||
#define LABEL_SIZE SECTOR_SIZE /* Think very carefully before changing this */
|
||||
@@ -28,6 +29,17 @@ struct labeller;
|
||||
|
||||
void allow_reads_with_lvmetad(void);
|
||||
|
||||
struct label_read_data {
|
||||
struct dev_async_io *aio;
|
||||
char *buf; /* points to aio->buf */
|
||||
struct device *dev;
|
||||
struct dm_list list;
|
||||
int buf_len; /* same as aio->buf_len */
|
||||
int result; /* same as aio->result */
|
||||
int try_sync;
|
||||
int process_done;
|
||||
};
|
||||
|
||||
/* On disk - 32 bytes */
|
||||
struct label_header {
|
||||
int8_t id[8]; /* LABELONE */
|
||||
@@ -63,7 +75,7 @@ struct label_ops {
|
||||
* Read a label from a volume.
|
||||
*/
|
||||
int (*read) (struct labeller * l, struct device * dev,
|
||||
void *buf, struct label ** label);
|
||||
void *label_buf, struct label ** label);
|
||||
|
||||
/*
|
||||
* Additional consistency checks for the paranoid.
|
||||
@@ -99,11 +111,15 @@ int label_register_handler(struct labeller *handler);
|
||||
struct labeller *label_get_handler(const char *name);
|
||||
|
||||
int label_remove(struct device *dev);
|
||||
int label_read(struct device *dev, struct label **result,
|
||||
uint64_t scan_sector);
|
||||
int label_read(struct device *dev, struct label **label, uint64_t scan_sector);
|
||||
int label_write(struct device *dev, struct label *label);
|
||||
int label_verify(struct device *dev);
|
||||
struct label *label_create(struct labeller *labeller);
|
||||
void label_destroy(struct label *label);
|
||||
|
||||
int label_scan_force(struct cmd_context *cmd);
|
||||
int label_scan(struct cmd_context *cmd);
|
||||
int label_scan_devs(struct cmd_context *cmd, struct dm_list *devs);
|
||||
struct label_read_data *get_label_read_data(struct cmd_context *cmd, struct device *dev);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -45,6 +45,10 @@ include $(top_builddir)/make.tmpl
|
||||
LDFLAGS += -L$(top_builddir)/lib -L$(top_builddir)/daemons/dmeventd
|
||||
LIBS += $(LVMINTERNAL_LIBS) -ldevmapper
|
||||
|
||||
ifeq ("@AIO@", "yes")
|
||||
LIBS += $(AIO_LIBS)
|
||||
endif
|
||||
|
||||
.PHONY: install_dynamic install_static install_include install_pkgconfig
|
||||
|
||||
INSTALL_TYPE = install_dynamic
|
||||
|
||||
@@ -64,6 +64,7 @@ LDDEPS += @LDDEPS@
|
||||
LIB_SUFFIX = @LIB_SUFFIX@
|
||||
LVMINTERNAL_LIBS = -llvm-internal $(DMEVENT_LIBS) $(DAEMON_LIBS) $(SYSTEMD_LIBS) $(UDEV_LIBS) $(DL_LIBS) $(BLKID_LIBS)
|
||||
DL_LIBS = @DL_LIBS@
|
||||
AIO_LIBS = @AIO_LIBS@
|
||||
RT_LIBS = @RT_LIBS@
|
||||
M_LIBS = @M_LIBS@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
|
||||
@@ -31,6 +31,10 @@ endif
|
||||
LVMLIBS = @LVM2APP_LIB@ -ldevmapper
|
||||
endif
|
||||
|
||||
ifeq ("@AIO@", "yes")
|
||||
LVMLIBS += $(AIO_LIBS)
|
||||
endif
|
||||
|
||||
LVM_SCRIPTS = lvmdump.sh lvmconf.sh
|
||||
DM_SCRIPTS =
|
||||
|
||||
|
||||
@@ -109,6 +109,10 @@ ifeq ("@CMDLIB@", "yes")
|
||||
INSTALL_LVM_TARGETS += $(INSTALL_CMDLIB_TARGETS)
|
||||
endif
|
||||
|
||||
ifeq ("@AIO@", "yes")
|
||||
LVMLIBS += $(AIO_LIBS)
|
||||
endif
|
||||
|
||||
EXPORTED_HEADER = $(srcdir)/lvm2cmd.h
|
||||
EXPORTED_FN_PREFIX = lvm2
|
||||
|
||||
|
||||
Reference in New Issue
Block a user