Performance improvements
cover Performance improvements
Main target in this patchset is to again considerably speedup functinality of lvm tools.
1. PV_MIN_SIZE - updated init position for last patchset.
2. Fix and improve udev synchronization. (i.e. do not call fs_unlock after _lv_resume())
3. Hashing was consuming a lot of CPU - partly because of some small tables, partly becuase hash function for our data set was producing a lot of hash collisions.
4. Improves memory locking for multiple operation within one VG lock (i.e. activation of a lot of LVs from 1 VG).
Patch set also has few const pointer fixes, and man page updates. Allow 1 page difference between mlock munlock.
Few updates for test suite.
Minor extension for lvm2api - I've also noticed, few const in this API are wrong - we cannot pass const handler to routines, which are modifying them.
Zdenek Kabelac (24):
Add find_config_tree_int64 function
Replace PV_MIN_SIZE with function pv_min_size()
Test pv_min_size functionality
Move add_dev_node to DM_DEVICE_RESUME
Perf: Fix multiple operations on the same node
lv_info handle udev_sync
Remove open_count read from some lv_info calls
Perf: optimize _eat_space and _get_token
Align orphan strings
Perf: speed up hash tables
Perf: New HASH function
Perf: Increase hash sizes
Memory unlock allows 1 page difference
Critical section
Remove fs_unlock after failed suspend
Man pages reformating
Void* arithmetic replaced with char*
API change - support more const arg
Use cleaner const * pointer
Const fixing
Testing: remove -q from grep
Testing: Try to prioritize locking process
Extend lvm2api with lvm_lv_rename
Testing lvm_lv_rename
daemons/clvmd/clvmd.c | 4 +- daemons/clvmd/clvmd.h | 2 +- daemons/clvmd/lvm-functions.c | 12 +- doc/example.conf.in | 5 + lib/activate/activate.c | 36 ++++-- lib/activate/activate.h | 2 +- lib/activate/fs.c | 70 +++++++++++- lib/activate/fs.h | 1 + lib/cache/lvmcache.c | 14 +- lib/commands/toolcontext.c | 11 ++- lib/config/config.c | 42 ++++--- lib/config/config.h | 2 + lib/device/dev-cache.c | 2 +- lib/device/dev-io.c | 2 +- lib/filters/filter-persistent.c | 2 +- lib/filters/filter-regex.c | 2 +- lib/filters/filter.c | 2 +- lib/format1/format1.c | 10 +- lib/format1/import-export.c | 2 +- lib/format1/import-extents.c | 2 +- lib/format1/lvm1-label.c | 9 +- lib/format_pool/format_pool.c | 4 +- lib/format_text/export.c | 2 +- lib/format_text/format-text.c | 18 ++- lib/format_text/import_vsn1.c | 4 +- lib/format_text/text_label.c | 9 +- lib/locking/locking.c | 14 ++- lib/log/log.c | 8 +- lib/metadata/lv.h | 2 +- lib/metadata/lv_manip.c | 3 +- lib/metadata/metadata-exported.h | 9 +- lib/metadata/metadata.c | 45 ++++---- lib/metadata/metadata.h | 1 - lib/metadata/mirror.c | 20 ++-- lib/misc/lvm-globals.c | 12 ++ lib/misc/lvm-globals.h | 5 +- lib/mm/memlock.c | 72 +++++++++--- lib/mm/memlock.h | 6 +- lib/report/properties.c | 3 +- lib/report/report.c | 14 +-- libdm/datastruct/hash.c | 188 ++++++++++++++++++++++++++----- libdm/ioctl/libdm-iface.c | 8 +- libdm/libdevmapper.h | 8 +- libdm/libdm-common.c | 71 ++++++++++-- libdm/libdm-deptree.c | 4 +- libdm/libdm-report.c | 2 +- liblvm/lvm2app.h | 16 +++ liblvm/lvm_lv.c | 14 ++- liblvm/lvm_vg.c | 4 +- man/fsadm.8.in | 80 ++++++++------ man/lvreduce.8.in | 65 ++++++----- man/lvremove.8.in | 17 ++-- man/lvrename.8.in | 37 ++----- man/lvresize.8.in | 99 ++++++++-------- test/api/Makefile.in | 2 +- test/api/lvtest.c | 64 +++++++++++ test/api/lvtest.sh | 21 ++++ test/t-lock-blocking.sh | 10 +- test/t-mirror-names.sh | 2 +- test/t-mirror-vgreduce-removemissing.sh | 2 +- test/t-pv-min-size.sh | 31 +++++ test/t-pvcreate-operation.sh | 2 +- test/t-snapshot-merge.sh | 9 +- test/t-vgcreate-usage.sh | 2 +- test/t-vgextend-usage.sh | 2 +- tools/lvconvert.c | 2 +- tools/lvcreate.c | 2 +- tools/lvscan.c | 2 +- tools/pvresize.c | 6 +- tools/reporter.c | 4 +- tools/toollib.c | 10 +- tools/toollib.h | 4 +- tools/vgcfgrestore.c | 2 +- tools/vgcreate.c | 2 +- tools/vgextend.c | 4 +- tools/vgmerge.c | 2 +- tools/vgreduce.c | 2 +- tools/vgrename.c | 2 +- tools/vgsplit.c | 2 +- 79 files changed, 898 insertions(+), 393 deletions(-) create mode 100644 test/api/lvtest.c create mode 100644 test/api/lvtest.sh create mode 100755 test/t-pv-min-size.sh
--
1.7.3.5
PATCH 1/24 Add find_config_tree_int64 function
Add function for reading 64bit ints.
--- lib/config/config.c | 6 ++++++ lib/config/config.h | 2 ++ 2 files changed, 8 insertions(+), 0 deletions(-)
lib/config/config.c +6 -0
@@ -1049,6 +1049,12 @@ int find_config_tree_int(struct cmd_context *cmd, const char *path,return (int )_find_config_int64 (cmd->cft_override ? cmd->cft_override->root :NULL , cmd->cft->root, path, (int64_t ) fail); } +int64_t find_config_tree_int64 (struct cmd_context *cmd,const char *path,int64_t fail) +{ +return _find_config_int64 (cmd->cft_override ? cmd->cft_override->root :NULL , + cmd->cft->root, path, fail); +} +float find_config_tree_float (struct cmd_context *cmd,const char *path,float fail) {
lib/config/config.h +2 -0
@@ -95,6 +95,8 @@ const char *find_config_tree_str(struct cmd_context *cmd, const char *path, const char *fail);int find_config_tree_int (struct cmd_context *cmd,const char *path,int fail); +int64_t find_config_tree_int64 (struct cmd_context *cmd,const char *path, +int64_t fail);float find_config_tree_float (struct cmd_context *cmd,const char *path,float fail);
Signature · 1 line
1.7.3.5
PATCH 2/24 Replace PV_MIN_SIZE with function pv_min_size()
In reply to Zdenek KabelacAdd configurable option for defining minimal size of PV. pv_min_size() is added to lvm-globals and it's being initialized through _process_config.
Macro PV_MIN_SIZE is unused and removed.
New define DEFAULT_PV_MIN_SIZE_KB is added to lvm-global and unlike PV_MIN_SIZE it uses Kilobytes units.
Should help users with various slow devices attached to the system, which cannot be easily filtered out (like Fdd on /dev/sdX):
https://bugzilla.redhat.com/show_bug.cgi?id=644578
--- doc/example.conf.in | 5 +++++ lib/commands/toolcontext.c | 11 ++++++++++- lib/filters/filter.c | 2 +- lib/metadata/metadata-exported.h | 1 - lib/metadata/metadata.c | 6 +++--- lib/metadata/metadata.h | 1 - lib/misc/lvm-globals.c | 12 ++++++++++++ lib/misc/lvm-globals.h | 5 ++++- tools/pvresize.c | 6 +++--- 9 files changed, 38 insertions(+), 11 deletions(-)
doc/example.conf.in +5 -0
@@ -144,6 +144,11 @@ devices { # Allow use of pvcreate --uuid without requiring --restorefile. require_restorefile_with_uuid = 1 + + # Minimal size (in KB) of PV partion which will be consider to be able + # to hold PV. It allows to automatically skip too small partitions + # like FDD devices from scan. Any value smaller then 512 is ignored. + pv_min_size = 512 } # This section allows you to configure the way in which LVM selects
lib/commands/toolcontext.c +10 -1
@@ -205,6 +205,7 @@ static int _process_config(struct cmd_context *cmd)struct stat st;const struct config_node *cn;const struct config_value *cv; +int64_t pvmin;/* umask */ cmd->default_settings.umask = find_config_tree_int(cmd,
@@ -318,6 +319,15 @@ static int _process_config(struct cmd_context *cmd) cmd->metadata_read_only =find_config_tree_int (cmd,"global/metadata_read_only" ,DEFAULT_METADATA_READ_ONLY ); + pvmin =find_config_tree_int64 (cmd,"devices/pv_min_size" ,DEFAULT_PV_MIN_SIZE_KB ); +if (pvmin <DEFAULT_PV_MIN_SIZE_KB ) { +log_warn ("Ignoring too small pv_min_size = %" PRId64, pvmin); + pvmin =DEFAULT_PV_MIN_SIZE_KB ; +log_warn ("Falling back to default pv_min_size = %" PRId64, pvmin); + } +/* lvm internally works with device size in sectors */ +init_pv_min_size ((uint64_t )pvmin *1024 >>SECTOR_SHIFT ); +return 1 ; }
@@ -1113,7 +1123,6 @@ static void _init_globals(struct cmd_context *cmd) {init_full_scan_done (0 );init_mirror_in_sync (0 ); - }/* Entry point */
lib/filters/filter.c +1 -1
@@ -158,7 +158,7 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute__((un goto out; } -if (size <PV_MIN_SIZE ) { +if (size <pv_min_size ()) {log_debug ("%s: Skipping: Too small to hold a PV" , name); goto out; }
lib/metadata/metadata-exported.h +0 -1
@@ -33,7 +33,6 @@#define STRIPE_SIZE_MIN ( (unsigned) lvm_getpagesize() >> SECTOR_SHIFT)/* PAGESIZE in sectors */ #define STRIPE_SIZE_MAX ( 512L * 1024L >> SECTOR_SHIFT)/* 512 KB in sectors */ #define STRIPE_SIZE_LIMIT ((UINT_MAX >> 2) + 1) -#define PV_MIN_SIZE ( 512L * 1024L >> SECTOR_SHIFT)/* 512 KB in sectors */ #define MAX_RESTRICTED_LVS 255/* Used by FMT_RESTRICTED_LVIDS */ /* Layer suffix */
lib/metadata/metadata.c +3 -3
@@ -1626,9 +1626,9 @@ struct physical_volume *pv_create(const struct cmd_context *cmd, pv->size = size; } -if (pv->size <PV_MIN_SIZE ) { -log_error ("%s: Size must exceed minimum of %ld sectors." , -pv_dev_name (pv),PV_MIN_SIZE ); +if (pv->size <pv_min_size ()) { +log_error ("%s: Size must exceed minimum of %" PRIu64" sectors." , +pv_dev_name (pv),pv_min_size ()); goto bad; }
lib/metadata/metadata.h +0 -1
@@ -32,7 +32,6 @@//#define STRIPE_SIZE_MIN ( (unsigned) lvm_getpagesize() >> SECTOR_SHIFT) /* PAGESIZE in sectors */ //#define STRIPE_SIZE_MAX ( 512L * 1024L >> SECTOR_SHIFT) /* 512 KB in sectors */ //#define STRIPE_SIZE_LIMIT ((UINT_MAX >> 2) + 1) -//#define PV_MIN_SIZE ( 512L * 1024L >> SECTOR_SHIFT) /* 512 KB in sectors */ //#define MAX_RESTRICTED_LVS 255 /* Used by FMT_RESTRICTED_LVIDS */ #define MIRROR_LOG_OFFSET 2/* sectors */ #define VG_MEMPOOL_CHUNK 10240/* in bytes, hint only */
lib/misc/lvm-globals.c +12 -0
@@ -19,6 +19,7 @@#include "lvm-string.h" #include "lvm-file.h" #include "defaults.h" +#include "metadata-exported.h" #include <stdarg.h>
@@ -42,6 +43,7 @@ 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 ; +static uint64_t _pv_min_size = (DEFAULT_PV_MIN_SIZE_KB *1024L >>SECTOR_SHIFT );void init_verbose (int level) {
@@ -128,6 +130,11 @@ void init_dev_disable_after_error_count(int value) _dev_disable_after_error_count = value; } +void init_pv_min_size (uint64_t value) +{ + _pv_min_size = value; +} +void set_cmd_name (const char *cmd) {strncpy (_cmd_name, cmd,sizeof (_cmd_name));
@@ -247,3 +254,8 @@ int dev_disable_after_error_count(void) {return _dev_disable_after_error_count; } + +uint64_t pv_min_size (void ) +{ +return _pv_min_size; +}
lib/misc/lvm-globals.h +4 -1
@@ -1,6 +1,6 @@/* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. -* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +* Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. *
@@ -18,6 +18,7 @@#define VERBOSE_BASE_LEVEL _LOG_WARN#define SECURITY_LEVEL 0 +#define DEFAULT_PV_MIN_SIZE_KB 512/* 512 KB */ void init_verbose (int level);void init_test (int level);
@@ -38,6 +39,7 @@ 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 init_pv_min_size (uint64_t sectors);void set_cmd_name (const char *cmd_name);void set_sysfs_dir_path (const char *path);
@@ -59,6 +61,7 @@ const char *log_command_name(void);unsigned is_static (void );int udev_checking (void );const char *sysfs_dir_path (void ); +uint64_t pv_min_size (void );#define DMEVENTD_MONITOR_IGNORE -1int dmeventd_monitor_mode (void );
tools/pvresize.c +3 -3
@@ -111,9 +111,9 @@ static int _pv_resize_single(struct cmd_context *cmd, size = new_size; } -if (size <PV_MIN_SIZE ) { -log_error ("%s: Size must exceed minimum of %ld sectors." , - pv_name,PV_MIN_SIZE ); +if (size <pv_min_size ()) { +log_error ("%s: Size must exceed minimum of %" PRIu64" sectors." , + pv_name,pv_min_size ()); goto out; }
Signature · 1 line
1.7.3.5
PATCH 2/24 Replace PV_MIN_SIZE with function pv_min_size()
Quoted 4 lines · Zdenek Kabelac
Add configurable option for defining minimal size of PV.
pv_min_size()is added to lvm-globals and it's being initialized through_process_config.
Quoted 8 lines
Macro
PV_MIN_SIZEis unused and removed.New define
DEFAULT_PV_MIN_SIZE_KBis added to lvm-global and unlikePV_MIN_SIZEit uses Kilobytes units.Should help users with various slow devices attached to the system, which cannot be easily filtered out (like Fdd on
/dev/sdX):
https://bugzilla.redhat.com/show_bug.cgi?id=644578
I think you are mixing two distinct things here
- minimum PV size
- minimum device size which is considered for lvm metadata scan
I think that minimum PV size should remain fixed in code. The second is runtime variable, you can adjust it per user needs.
doc/example.conf.in devices { · line 151
Quoted 5 lines
doc/example.conf.in +5
-0+ + # Minimal size (in KB) of PV partion which will be consider to be able + # to hold PV. It allows to automatically skip too small partitions + # like FDD devices from scan. Any value smaller then 512 is ignored. + pv_min_size = 512
I thought we meant:
Minimal size of device, which will be scanned for LVM metadata.
IOW it should be filter, not limitation for PV creation.
(But maybe I just misunderstood what Alasdair wants here...)
Milan
PATCH 2/24 Replace PV_MIN_SIZE with function pv_min_size()
Dne 30.1.2011 21:01, Milan Broz napsal(a):
Quoted 29 lines · Zdenek Kabelac
Quoted 4 lines
Add configurable option for defining minimal size of PV.
pv_min_size()is added to lvm-globals and it's being initialized through_process_config.Quoted 8 lines
Macro
PV_MIN_SIZEis unused and removed.New define
DEFAULT_PV_MIN_SIZE_KBis added to lvm-global and unlikePV_MIN_SIZEit uses Kilobytes units.Should help users with various slow devices attached to the system, which cannot be easily filtered out (like Fdd on
/dev/sdX):
https://bugzilla.redhat.com/show_bug.cgi?id=644578I think you are mixing two distinct things here
- minimum PV size
- minimum device size which is considered for lvm metadata scanI think that minimum PV size should remain fixed in code. The second is runtime variable, you can adjust it per user needs.
doc/example.conf.in devices { · line 151
Quoted 5 lines
doc/example.conf.in +5
-0+ + # Minimal size (in KB) of PV partion which will be consider to be able + # to hold PV. It allows to automatically skip too small partitions + # like FDD devices from scan. Any value smaller then 512 is ignored. + pv_min_size = 512
Quoted 7 lines
I thought we meant:
Minimal size of device, which will be scanned for LVM metadata.IOW it should be filter, not limitation for PV creation.
(But maybe I just misunderstood what Alasdair wants here...)
Note: there is still hard coded 512KB value in the source code.
But what would be the point of creation of PV with smaller size then configured pv_min_size?
i.e. if you configure pv_min_size = 10MB - you cannot create smaller PV - as it would be invisible in your system - IMHO it could eventually lead to bigger confusion - you create small PV, which will be invisible for lvm tools...
If you want to create and see smaller PV - lvm.conf needs to be set to smaller value.
Zdenek
PATCH 2/24 Replace PV_MIN_SIZE with function pv_min_size()
Quoted 6 lines · Zdenek Kabelac
i.e. if you configure
pv_min_size= 10MB - you cannot create smaller PV - as it would be invisible in your system - IMHO it could eventually lead to bigger confusion - you create small PV, which will be invisible for lvm tools...If you want to create and see smaller PV - lvm.conf needs to be set to smaller value.
How it differs from filters line in principle?
If you want to see device, you have to set filer properly.
Of course it will prevent pv creation, because device is filtered out, but on another level.
Milan
PATCH 2/24 Replace PV_MIN_SIZE with function pv_min_size()
Dne 30.1.2011 21:22, Milan Broz napsal(a):
Quoted 9 lines · Zdenek Kabelac
Quoted 7 lines
i.e. if you configure
pv_min_size= 10MB - you cannot create smaller PV - as it would be invisible in your system - IMHO it could eventually lead to bigger confusion - you create small PV, which will be invisible for lvm tools...If you want to create and see smaller PV - lvm.conf needs to be set to smaller value.
Quoted 6 lines
How it differs from filters line in principle?
If you want to see device, you have to set filer properly.
Of course it will prevent pv creation, because device is filtered out, but on another level.
That's the purpose - to be a very simple and universal filter - to remove such devices out of any touch by any lvm scanning code (see RHBZ 644578).
You could create complicated lvm.conf per each host - to handle small local block devices (FDD or whatever you could be attached these days on USB and present itself as a small storage device /dev/sdX) and allow to support only larger drives by some smart regex patters unique to each host - or you could use this simple option to allow LVM only for devices which are i.e. 10GB in size minimum.
IMHO added new 'filter' config option would just add code like this:
if (dev_size < pv_min_size) goto err;
if (dev_size < configure_pv_min_size) goto err;
With the advantage to pvcreate or pvresize to get 'invisible' devic as it would be filtered out for any further usage.
Zdenek
PATCH 3/24 Test pv_min_size functionality
In reply to Zdenek Kabelac--- test/t-pv-min-size.sh | 31 +++++++++++++++++++++++++++++++ 1 files changed, 31 insertions(+), 0 deletions(-) create mode 100755 test/t-pv-min-size.sh
test/t-pv-min-size.sh new file +31 -0
@@ -0,0 +1,31 @@ +#!/bin/sh +# Copyright (C) 2011 Red Hat, Inc. All rights reserved. +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions +# of the GNU General Public License v.2. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +. lib/test + +# use small default size - 512KB +aux lvmconf 'devices/pv_min_size = 512' + +aux prepare_pvs 1 8 + +check pv_field $dev1 pv_name $dev1 + +# increase min size beyond created PV size 10MB +aux lvmconf 'devices/pv_min_size = 10240' + +# and test device is not visible +not check pv_field $dev1 pv_name $dev1 + +# set too low value errornous value +aux lvmconf 'devices/pv_min_size = -100' + +# check the incorrect value is printed +pvs $dev1 2>&1 | grep -- -100
Signature · 1 line
1.7.3.5
PATCH 4/24 Move add_dev_node to DM_DEVICE_RESUME
In reply to Zdenek KabelacThis patch came out from discussion with Petr. We need valid 'check_udev' for stacked ops processing.
Current code:
dmsetup create xxx --notable -> create node in /dev/mapper/xxx
(check_udev has incorrect 0 value)
**
New patched code creates node with:
dmsetup resume xxx
(As just at this moment udev is registering such device)
--- libdm/ioctl/libdm-iface.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
libdm/ioctl/libdm-iface.c +4 -4
@@ -2061,10 +2061,6 @@ repeat_ioctl:switch (dmt->type) {case DM_DEVICE_CREATE : -if (dmt->dev_name && *dmt->dev_name && !udev_only) -add_dev_node (dmt->dev_name,MAJOR (dmi->dev), -MINOR (dmi->dev), dmt->uid, dmt->gid, - dmt->mode, check_udev);break ;case DM_DEVICE_REMOVE :/* FIXME Kernel needs to fill in dmi->name */
@@ -2080,6 +2076,10 @@ repeat_ioctl:break ;case DM_DEVICE_RESUME : +if (dmt->dev_name && *dmt->dev_name && !udev_only) +add_dev_node (dmt->dev_name,MAJOR (dmi->dev), +MINOR (dmi->dev), dmt->uid, dmt->gid, + dmt->mode, check_udev);/* FIXME Kernel needs to fill in dmi->name */ set_dev_node_read_ahead (dmt->dev_name, dmt->read_ahead, dmt->read_ahead_flags);
Signature · 1 line
1.7.3.5
PATCH 4/24 Move add_dev_node to DM_DEVICE_RESUME
Quoted 1 line · Zdenek Kabelac
We need valid '
check_udev' for stacked ops processing.
This change would also remove this ugly part in _create_and_load_v4 fn (the "create with table"):
/* FIXME: Just for udev_check in dm_task_run. Can we avoid this? */ task->event_nr = dmt->event_nr & DM_UDEV_FLAGS_MASK; task->cookie_set = dmt->cookie_set;
I had to copy this artificially for the DM_DEVICE_CREATE task just to set the udev_check correctly in dm_task_run. Though, unfortunately, it does not work when we have the CREATE, LOAD and RESUME separated. So this fix is highly welcome!
Peter
PATCH 5/24 Perf: Fix multiple operations on the same node
In reply to Zdenek KabelacWith ability to stack many operations in one udev transaction - in same cases we are adding and removing same device at the same time.
This leads to a problem of checking stacked operations:
i.e. remove /dev/node1 followed by create /dev/node1
If the node creation is handled with udev - there is a problem as stacked operation gives warning about existing node1 and will try to remove it - while next operation needs to recreate it.
Current code removes all previous stacked operation if the fs op is FS_DEL - patch adds similar behavior for FS_ADD - it will try to remove any 'delete' operation if udev is in use.
For FS_RENAME operation it seems to be more complex. But as we are always stacking FS_READ_AHEAD after FS_ADD operation - should be safe to remove all previous operation on the node when udev is running.
Code does same checking for stacking libdm and liblvm operations.
As a very simple optimization counters were added for each stacked ops type to avoid unneeded list scans if some operation couldn't exist in the list.
WARNING:
Patch checks variable 'check_udev' flag so the previous patch is mandatory
--- lib/activate/fs.c | 61 ++++++++++++++++++++++++++++++++++++++++-- libdm/libdm-common.c | 71 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 121 insertions(+), 11 deletions(-)
lib/activate/fs.c +58 -3
@@ -257,7 +257,8 @@ static int _rm_link(const char *dev_dir, const char *vg_name,typedef enum {FS_ADD ,FS_DEL , -FS_RENAME +FS_RENAME , +NUM_FS_OPS }fs_op_t ; static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
@@ -283,12 +284,18 @@ static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,if (!_mk_link (dev_dir, vg_name, lv_name, dev, check_udev)) stack; +default :; }return 1 ; }static DM_LIST_INIT (_fs_ops); +/* +* Count number of stacked fs_op_t operations to allow to skip dm_list search. +* FIXME: handling of FS_RENAME +*/ +static int _c_fs_ops[NUM_FS_OPS ];struct fs_op_parms {struct dm_list list;
@@ -309,15 +316,63 @@ static void _store_str(char **pos, char **ptr, const char *str) *pos +=strlen (*ptr) +1 ; } +static int _other_fs_ops (fs_op_t type) +{ +int i; + +for (i =0 ; i <NUM_FS_OPS ; i++) +if (type != i && _c_fs_ops[i]) +return 1 ; +return 0 ; +} + +static void _del_fs_op (struct fs_op_parms *fsp) +{ + _c_fs_ops[fsp->type]--; +dm_list_del (&fsp->list); +dm_free (fsp); +} +static int _stack_fs_op (fs_op_t type,const char *dev_dir,const char *vg_name,const char *lv_name,const char *dev,const char *old_lv_name,int check_udev) { +struct dm_list *fsph, *fspht;struct fs_op_parms *fsp;size_t len =strlen (dev_dir) +strlen (vg_name) +strlen (lv_name) +strlen (dev) +strlen (old_lv_name) +5 ;char *pos; +if ((type ==FS_DEL ) &&_other_fs_ops (type)) + dm_list_iterate_safe(fsph, fspht, &_fs_ops) { + fsp = dm_list_item(fsph, struct fs_op_parms); +if (!strcmp (lv_name, fsp->lv_name) && + !strcmp (vg_name, fsp->vg_name)) { +_del_fs_op (fsp); +if (!_other_fs_ops (type)) +break ; + } + } + else if ((type == FS_ADD) && _c_fs_ops[FS_DEL] && check_udev && + dm_udev_get_sync_support() && dm_udev_get_checking()) + dm_list_iterate_safe(fsph, fspht, &_fs_ops) { + fsp = dm_list_item(fsph, struct fs_op_parms); +if ((fsp->type ==FS_DEL ) && + !strcmp (lv_name, fsp->lv_name) && + !strcmp (vg_name, fsp->vg_name)) { +_del_fs_op (fsp); +break ; + } + } + else if ((type == FS_RENAME) && check_udev && + dm_udev_get_sync_support() && dm_udev_get_checking()) + dm_list_iterate_safe(fsph, fspht, &_fs_ops) { + fsp = dm_list_item(fsph, struct fs_op_parms); +if (!strcmp (old_lv_name, fsp->lv_name) && + !strcmp (vg_name, fsp->vg_name)) +_del_fs_op (fsp); + } +if (!(fsp =dm_malloc (sizeof (*fsp) + len))) {log_error ("No space to stack fs operation" );return 0 ;
@@ -333,6 +388,7 @@ static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,_store_str (&pos, &fsp->dev, dev);_store_str (&pos, &fsp->old_lv_name, old_lv_name); + _c_fs_ops[type]++;dm_list_add (&_fs_ops, &fsp->list);return 1 ;
@@ -347,8 +403,7 @@ static void _pop_fs_ops(void) fsp = dm_list_item(fsph, struct fs_op_parms);_do_fs_op (fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name, fsp->dev, fsp->old_lv_name, fsp->check_udev); -dm_list_del (&fsp->list); -dm_free (fsp); +_del_fs_op (fsp); } }
libdm/libdm-common.c +63 -8
119 lines not on this page · raw message
Signature · 1 line
1.7.3.5
PATCH 5/24 Perf: Fix multiple operations on the same node
Dne 30.1.2011 13:57, Zdenek Kabelac napsal(a):
Quoted 6 lines
With ability to stack many operations in one udev transaction - in same cases we are adding and removing same device at the same time.
This leads to a problem of checking stacked operations:
i.e. remove/dev/node1followed by create/dev/node1
This patch a missing proper reaction when there is no locking at all.
Zdenek
PATCH 6/24 lv_info handle udev_sync
In reply to Zdenek KabelacIn case open_count is requested via lv_info - check if there are any udev operations in-progress - and wait for them before checking for lv_info
Remove fs_unlock after _lv_resume - as it's now handled via lv_info query.
Note: some those lv_info() which do not need open_count, needs to pass 0 for 'with_open_count' parameter.
NoteII: locking_is_clustered() is needed to detect in which context lv_info() is called as we cannot use sync_local_dev_names() when locking is not defined.
--- lib/activate/activate.c | 13 ++++++++++++- lib/activate/fs.c | 5 +++++ lib/activate/fs.h | 1 + 3 files changed, 18 insertions(+), 1 deletions(-)
lib/activate/activate.c +12 -1
@@ -460,6 +460,18 @@ int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, unsigned oif (!activation ())return 0 ; +/* +* If open_count info is requested and we have to be sure our own udev +* transactions are finished +* For non-clustered locking type we are only interested for non-delete operation +* in progress - as only those could lead to opened files +*/ +if (with_open_count) { +if (locking_is_clustered ()) +sync_local_dev_names (cmd);/* Wait to have udev in sync */ +else if (fs_has_non_delete_ops ()) +fs_unlock ();/* For non clustered - wait if there are non-delete ops */ + }if (!dev_manager_info (lv->vg->cmd->mem, lv, origin_only ?"real" :NULL , with_open_count, with_read_ahead, &dminfo, &info->read_ahead))
@@ -1112,7 +1124,6 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s, goto_out;memlock_dec (cmd); -fs_unlock ();if (!monitor_dev_for_events (cmd, lv, origin_only,1 )) stack;
lib/activate/fs.c +5 -0
@@ -477,3 +477,8 @@ void fs_set_cookie(uint32_t cookie) { _fs_cookie = cookie; } + +int fs_has_non_delete_ops (void ) +{ +return _other_fs_ops (FS_DEL ); +}
lib/activate/fs.h +1 -0
@@ -32,5 +32,6 @@ int fs_rename_lv(struct logical_volume *lv, const char *dev,/* void fs_unlock(void); moved to activate.h */ uint32_t fs_get_cookie (void );void fs_set_cookie (uint32_t cookie); +int fs_has_non_delete_ops (void );#endif
Signature · 1 line
1.7.3.5
PATCH 6/24 lv_info handle udev_sync
Quoted 3 lines · Zdenek Kabelac
NoteII:
locking_is_clustered()is needed to detect in which contextlv_info()is called as we cannot usesync_local_dev_names()when locking is not defined.
hmmmm. I probably confused you here:)
I don't think locking_is_clustered() can be used insinde clvmd (it is "locking implementation" itself).
Or you mean it that in clvmd should run fs_unlock() and in local code (lvm command) should run sync_local_dev_names(cmd) (with cluster locking)?
lib/activate/activate.c int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, unsigned o · line 474
Quoted 12 lines
lib/activate/activate.c +12
-0+/* +* If open_count info is requested and we have to be sure our own udev +* transactions are finished +* For non-clustered locking type we are only interested for non-delete operation +* in progress - as only those could lead to opened files +*/ +if (with_open_count) { +if (locking_is_clustered ()) +sync_local_dev_names (cmd);/* Wait to have udev in sync */ +else if (fs_has_non_delete_ops ()) +fs_unlock ();/* For non clustered - wait if there are non-delete ops */ + }
this is really ugly...
Milan
PATCH 6/24 lv_info handle udev_sync
Dne 30.1.2011 21:17, Milan Broz napsal(a):
Quoted 6 lines · Zdenek Kabelac
Quoted 4 lines
NoteII:
locking_is_clustered()is needed to detect in which contextlv_info()is called as we cannot usesync_local_dev_names()when locking is not defined.
Quoted 7 lines
hmmmm. I probably confused you here:)
I don't think
locking_is_clustered()can be used insinde clvmd (it is "locking implementation" itself).Or you mean it that in clvmd should run
fs_unlock()and in local code (lvm command) should runsync_local_dev_names(cmd)(with cluster locking)?
Yes - that's the intention
In clvmd - locking is not initilized - so sync_local_dev_names() cannot be used.
Quoted 15 lines
lib/activate/activate.c int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, unsigned o · line 474
Quoted 13 lines
lib/activate/activate.c +12
-0+/* +* If open_count info is requested and we have to be sure our own udev +* transactions are finished +* For non-clustered locking type we are only interested for non-delete operation +* in progress - as only those could lead to opened files +*/ +if (with_open_count) { +if (locking_is_clustered ()) +sync_local_dev_names (cmd);/* Wait to have udev in sync */ +else if (fs_has_non_delete_ops ()) +fs_unlock ();/* For non clustered - wait if there are non-delete ops */ + }this is really ugly...
Yes I know - plan for the future would be to hide this logic directly to sync_local_dev_names() - so only sync_local_dev_name() would stay there.
Zdenek
PATCH 7/24 Remove open_count read from some lv_info calls
In reply to Zdenek KabelacPLEASE CHECK ME!!!
It's not completely clear what could be the side effectlv_infoi() in these places does not read 'info.open_count' value - so it should not need to set this value - unless I'm missing some side-effect??
This change is needed to minimalize the amount of fs_unlock() calls.
As we need to make sure no udev operation is in progress when we check for open_count.
--- lib/activate/activate.c | 2 +- liblvm/lvm_lv.c | 4 ++-- tools/lvconvert.c | 2 +- tools/lvscan.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-)
lib/activate/activate.c +1 -1
@@ -1218,7 +1218,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s) r =_lv_deactivate (lv);memlock_dec (cmd); -if (!lv_info (cmd, lv,0 , &info,1 ,0 ) || info.exists) +if (!lv_info (cmd, lv,0 , &info,0 ,0 ) || info.exists) r =0 ; out:if (lv) {
liblvm/lvm_lv.c +2 -2
@@ -62,7 +62,7 @@ struct lvm_property_value lvm_lvseg_get_property(const lvseg_t lvseg,uint64_t lvm_lv_is_active (const lv_t lv) {struct lvinfo info; -if (lv_info (lv->vg->cmd, lv,0 , &info,1 ,0 ) && +if (lv_info (lv->vg->cmd, lv,0 , &info,0 ,0 ) && info.exists && info.live_table)return 1 ;return 0 ;
@@ -71,7 +71,7 @@ uint64_t lvm_lv_is_active(const lv_t lv)uint64_t lvm_lv_is_suspended (const lv_t lv) {struct lvinfo info; -if (lv_info (lv->vg->cmd, lv,0 , &info,1 ,0 ) && +if (lv_info (lv->vg->cmd, lv,0 , &info,0 ,0 ) && info.exists && info.suspended)return 1 ;return 0 ;
tools/lvconvert.c +1 -1
@@ -1637,7 +1637,7 @@ static int poll_logical_volume(struct cmd_context *cmd, struct logical_volume *l {struct lvinfo info; -if (!lv_info (cmd, lv,0 , &info,1 ,0 ) || !info.exists) { +if (!lv_info (cmd, lv,0 , &info,0 ,0 ) || !info.exists) {log_print ("Conversion starts after activation." );return ECMD_PROCESSED ; }
tools/lvscan.c +1 -1
@@ -28,7 +28,7 @@ static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv,if (!arg_count (cmd, all_ARG) && !lv_is_visible (lv))return ECMD_PROCESSED ; - inkernel =lv_info (cmd, lv,0 , &info,1 ,0 ) && info.exists; + inkernel =lv_info (cmd, lv,0 , &info,0 ,0 ) && info.exists;if (lv_is_origin (lv)) {dm_list_iterate_items_gen (snap_seg, &lv->snapshot_segs, origin_list) {
Signature · 1 line
1.7.3.5
PATCH 8/24 Perf: optimize _eat_space and _get_token
In reply to Zdenek KabelacMakes the code more readable and has a smaller number of memory accesses.
For _get_token() optimize number parsing. Check for '.' char only if it's not a digit. Move pointer incrementation into one place.
For _eat_space() check only p->te for '\0' in skipping of comment line. Avoid check for '\0' when we know it is space. Also master while loop doesn't need checking p->tb for '\0'. We just need to check p->tb isn't already at the end of buffer. This could give 'extra' loop cycle if we are already there - but safes memory access in every other case.
--- lib/config/config.c | 36 ++++++++++++++++++------------------ 1 files changed, 18 insertions(+), 18 deletions(-)
lib/config/config.c +18 -18
@@ -821,18 +821,20 @@ static void _get_token(struct parser *p, int tok_prev)case '+' :case '-' :if (values_allowed) { - te++; -while ((te != p->fe) && (*te)) { -if (*te =='.' ) { -if (p->t ==TOK_FLOAT ) -break ; - p->t =TOK_FLOAT ; - }else if (!isdigit ((int ) *te)) +while (++te != p->fe) { +if (!isdigit ((int ) *te)) { +if (*te =='.' ) { +if (p->t !=TOK_FLOAT ) { + p->t =TOK_FLOAT ; +continue ; + } + }break ; - te++; + } }break ; } +/* fall through */ default : p->t =TOK_IDENTIFIER ;
@@ -849,21 +851,19 @@ static void _get_token(struct parser *p, int tok_prev)static void _eat_space (struct parser *p) { -while ((p->tb != p->fe) && (*p->tb)) { +while (p->tb != p->fe) {if (*p->te =='#' )while ((p->te != p->fe) && (*p->te) && (*p->te !='\n' )) p->te++; -else if (isspace (*p->te)) { -while ((p->te != p->fe) && (*p->te) &&isspace (*p->te)) { -if (*p->te =='\n' ) - p->line++; - p->te++; - } - } +else if (!isspace (*p->te)) +break ; -else -return ; +while ((p->te != p->fe) &&isspace (*p->te)) { +if (*p->te =='\n' ) + p->line++; + p->te++; + } p->tb = p->te; }
Signature · 1 line
1.7.3.5
PATCH 9/24 Align orphan strings
In reply to Zdenek KabelacWhile checking for passed pointers to hash function - some buffers were not nicely aligned - and those were mainly 'static' strings.
So this code is a bit ugly but forces 8b alignment on these strings.
--- lib/format1/format1.c | 10 +++++++--- lib/format1/lvm1-label.c | 9 +++++++-- lib/format_pool/format_pool.c | 4 +++- lib/format_text/format-text.c | 16 ++++++++++++---- lib/format_text/text_label.c | 5 +++-- 5 files changed, 32 insertions(+), 12 deletions(-)
lib/format1/format1.c +7 -3
@@ -578,6 +578,10 @@ struct format_type *init_format(struct cmd_context *cmd); struct format_type *init_format(struct cmd_context *cmd) #endif { + static const char lvm1_orphan_vg_name[] __attribute__((aligned(8))) + = FMT_LVM1_ORPHAN_VG_NAME; + static const char lvm1_name[] __attribute__((aligned(8))) + = FMT_LVM1_NAME; struct format_type *fmt = dm_malloc(sizeof(*fmt)); if (!fmt)
@@ -585,9 +589,9 @@ struct format_type *init_format(struct cmd_context *cmd) fmt->cmd = cmd; fmt->ops = &_format1_ops; - fmt->name =FMT_LVM1_NAME ; + fmt->name = lvm1_name; fmt->alias =NULL ; - fmt->orphan_vg_name =FMT_LVM1_ORPHAN_VG_NAME ; + fmt->orphan_vg_name = lvm1_orphan_vg_name; fmt->features =FMT_RESTRICTED_LVIDS |FMT_ORPHAN_ALLOCATABLE |FMT_RESTRICTED_READAHEAD ; fmt->private =NULL ;
@@ -597,7 +601,7 @@ struct format_type *init_format(struct cmd_context *cmd)return NULL ; } -if (!(label_register_handler (FMT_LVM1_NAME , fmt->labeller))) { +if (!(label_register_handler (lvm1_name, fmt->labeller))) {log_error ("Couldn't register lvm1 label handler." );return NULL ; }
lib/format1/lvm1-label.c +7 -2
@@ -57,11 +57,16 @@ static int _lvm1_write(struct label *label __attribute__((unused)), void *buf __static int _lvm1_read (struct labeller *l,struct device *dev,void *buf,struct label **label) { + static const char orphan_vgid[] __attribute__((aligned(8))) + =FMT_LVM1_ORPHAN_VG_NAME ; + static const char orphan_vg_name[] __attribute__((aligned(8))) + = FMT_LVM1_ORPHAN_VG_NAME; +struct pv_disk *pvd = (struct pv_disk *) buf;struct vg_disk vgd;struct lvmcache_info *info; -const char *vgid =FMT_LVM1_ORPHAN_VG_NAME ; -const char *vgname =FMT_LVM1_ORPHAN_VG_NAME ; +const char *vgid = orphan_vgid; +const char *vgname = orphan_vg_name;unsigned exported =0 ;munge_pvd (dev, pvd);
lib/format_pool/format_pool.c +3 -1
@@ -308,6 +308,8 @@ struct format_type *init_format(struct cmd_context *cmd); struct format_type *init_format(struct cmd_context *cmd) #endif { + static const char pool_orphan_vg_name[] __attribute__((aligned(8))) + = FMT_POOL_ORPHAN_VG_NAME; struct format_type *fmt = dm_malloc(sizeof(*fmt)); if (!fmt) {
@@ -320,7 +322,7 @@ struct format_type *init_format(struct cmd_context *cmd) fmt->ops = &_format_pool_ops; fmt->name =FMT_POOL_NAME ; fmt->alias =NULL ; - fmt->orphan_vg_name =FMT_POOL_ORPHAN_VG_NAME ; + fmt->orphan_vg_name = pool_orphan_vg_name; fmt->features =0 ; fmt->private =NULL ;
lib/format_text/format-text.c +12 -4
@@ -1594,6 +1594,8 @@ static int _populate_pv_fields(struct lvmcache_info *info, struct physical_volume *pv, int scan_label_only) { + static const char orphan_vg_name[] __attribute__((aligned(8))) + = FMT_TEXT_ORPHAN_VG_NAME;struct data_area_list *da;/* Have we already cached vgname? */
@@ -1612,7 +1614,7 @@ static int _populate_pv_fields(struct lvmcache_info *info, pv->dev = info->dev; pv->fmt = info->fmt; pv->size = info->device_size >>SECTOR_SHIFT ; - pv->vg_name =FMT_TEXT_ORPHAN_VG_NAME ; + pv->vg_name = orphan_vg_name;memcpy (&pv->id, &info->dev->pvid,sizeof (pv->id));/* Currently only support exactly one data area */
@@ -2132,6 +2134,12 @@ static int _get_config_disk_area(struct cmd_context *cmd,struct format_type *create_text_format (struct cmd_context *cmd) { + static const char text_name[] __attribute__((aligned(8))) + =FMT_TEXT_NAME ; + static const char text_alias[] __attribute__((aligned(8))) + = FMT_TEXT_ALIAS; + static const char orphan_vg_name[] __attribute__((aligned(8))) + = ORPHAN_VG_NAME(FMT_TEXT_NAME);struct format_type *fmt;const struct config_node *cn;const struct config_value *cv;
@@ -2142,9 +2150,9 @@ struct format_type *create_text_format(struct cmd_context *cmd) fmt->cmd = cmd; fmt->ops = &_text_handler; - fmt->name =FMT_TEXT_NAME ; - fmt->alias =FMT_TEXT_ALIAS ; - fmt->orphan_vg_name =ORPHAN_VG_NAME (FMT_TEXT_NAME ); + fmt->name = text_name; + fmt->alias = text_alias; + fmt->orphan_vg_name = orphan_vg_name; fmt->features =FMT_SEGMENTS |FMT_MDAS |FMT_TAGS |FMT_PRECOMMIT |FMT_UNLIMITED_VOLS |FMT_RESIZE_PV |FMT_UNLIMITED_STRIPESIZE ;
lib/format_text/text_label.c +3 -2
@@ -253,6 +253,8 @@ static int _text_initialise_label(struct labeller *l __attribute__((unused)),static int _text_read (struct labeller *l,struct device *dev,void *buf,struct label **label) { + static const char text_orphan_vg_name[] __attribute__((aligned(8))) + =FMT_TEXT_ORPHAN_VG_NAME ;struct label_header *lh = (struct label_header *) buf;struct pv_header *pvhdr;struct lvmcache_info *info;
@@ -269,8 +271,7 @@ static int _text_read(struct labeller *l, struct device *dev, void *buf, pvhdr = (struct pv_header *) ((void *) buf +xlate32 (lh->offset_xl));if (!(info =lvmcache_add (l, (char *)pvhdr->pv_uuid, dev, -FMT_TEXT_ORPHAN_VG_NAME , -FMT_TEXT_ORPHAN_VG_NAME ,0 ))) + text_orphan_vg_name, text_orphan_vg_name,0 ))) return_0; *label = info->label;
Signature · 1 line
1.7.3.5
PATCH 10/24 Perf: speed up hash tables
In reply to Zdenek KabelacImprove considerably hash perfomance:
Remember calculated hash value for node - allows to speedup lookup of nodes with same hash & mask value.
Add statistic counters for hashes and print stats in debug mode on hash destruction - so bad perfomance of hash can be optimized.
API change:dm_hash binary functions takes void* pointer - so there
is no need to cast other pointers to char*. This is slight API change, but presents no change on user side it just allows to write code easier.
--- libdm/datastruct/hash.c | 84 ++++++++++++++++++++++++++++++----------------- libdm/libdevmapper.h | 6 ++-- 2 files changed, 57 insertions(+), 33 deletions(-)
libdm/datastruct/hash.c +54 -30
@@ -1,6 +1,6 @@/* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. -* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +* Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. * * This file is part of the device-mapper userspace tools. *
@@ -19,12 +19,18 @@ struct dm_hash_node {struct dm_hash_node *next;void *data;unsigned keylen; +unsigned long hash;char key[0 ]; };struct dm_hash_table {unsigned num_nodes; +unsigned num_hint;unsigned num_slots; +unsigned collisions; +unsigned search; +unsigned same_hash; +unsigned mask;struct dm_hash_node **slots; };
@@ -92,26 +98,26 @@ struct dm_hash_table *dm_hash_create(unsigned size_hint)unsigned new_size =16u ;struct dm_hash_table *hc =dm_zalloc (sizeof (*hc)); -if (!hc) - return_0; +if (!hc) { +log_error ("Failed to allocate memory for hash." ); +return 0 ; + } + hc->num_hint = size_hint;/* round size hint up to a power of two */ while (new_size < size_hint) new_size = new_size <<1 ; hc->num_slots = new_size; + hc->mask = new_size -1 ; len =sizeof (*(hc->slots)) * new_size; -if (!(hc->slots =dm_malloc (len))) { - stack; - goto bad; +if (!(hc->slots =dm_zalloc (len))) { +dm_free (hc); +log_error ("Failed to allocate slots for hash." ); +return 0 ; } -memset (hc->slots,0 , len); -return hc; - bad: -dm_free (hc->slots); -dm_free (hc); -return 0 ; +return hc; }static void _free_nodes (struct dm_hash_table *t)
@@ -119,6 +125,13 @@ static void _free_nodes(struct dm_hash_table *t)struct dm_hash_node *c, *n;unsigned i; +log_debug ("Released hash - used:%d size:%d hint:%d (c:%d s:%d h:%d)" , + t->num_nodes, t->num_slots, t->num_hint, + t->collisions, t->search, t->same_hash); + +if (!t->num_nodes) +return ; +for (i =0 ; i < t->num_slots; i++)for (c = t->slots[i]; c; c = n) { n = c->next;
@@ -133,45 +146,58 @@ void dm_hash_destroy(struct dm_hash_table *t)dm_free (t); } -static struct dm_hash_node **_find (struct dm_hash_table *t,const char *key, -uint32_t len) +static struct dm_hash_node **_findh (struct dm_hash_table *t,const void *key, +uint32_t len,unsigned long hash) { -unsigned h =_hash (key, len) & (t->num_slots -1 );struct dm_hash_node **c; +unsigned h = hash & t->mask;for (c = &t->slots[h]; *c; c = &((*c)->next)) { -if ((*c)->keylen != len) -continue ; - -if (!memcmp (key, (*c)->key, len)) -break ; +if ((*c)->keylen == len && (*c)->hash == hash) { +if (!memcmp (key, (*c)->key, len)) { + ++t->search; +break ; + }else + ++t->same_hash; + } + ++t->collisions; }return c; } -void *dm_hash_lookup_binary (struct dm_hash_table *t,const char *key, -uint32_t len) +static struct dm_hash_node **_find (struct dm_hash_table *t,const void *key, +uint32_t len) +{ +return _findh (t, key, len,_hash (key, len)); +} + +void *dm_hash_lookup_binary (struct dm_hash_table *t,const void *key, +uint32_t len) {struct dm_hash_node **c =_find (t, key, len);return *c ? (*c)->data :0 ; } -int dm_hash_insert_binary (struct dm_hash_table *t,const char *key, +int dm_hash_insert_binary (struct dm_hash_table *t,const void *key,uint32_t len,void *data) { -struct dm_hash_node **c =_find (t, key, len); +unsigned long hash =_hash (key, len); +struct dm_hash_node **c =_findh (t, key, len, hash);if (*c) (*c)->data = data;else {struct dm_hash_node *n =_create_node (key, len); -if (!n) +if (!n) { +log_error ("Failed to allocate new hash node." );return 0 ; + } n->data = data; + n->hash = hash; n->next =0 ; *c = n; t->num_nodes++;
@@ -180,7 +206,7 @@ int dm_hash_insert_binary(struct dm_hash_table *t, const char *key,return 1 ; } -void dm_hash_remove_binary (struct dm_hash_table *t,const char *key, +void dm_hash_remove_binary (struct dm_hash_table *t,const void *key,uint32_t len) {struct dm_hash_node **c =_find (t, key, len);
@@ -229,7 +255,7 @@ void dm_hash_wipe(struct dm_hash_table *t) {_free_nodes (t);memset (t->slots,0 ,sizeof (struct dm_hash_node *) * t->num_slots); - t->num_nodes =0u ; + t->num_nodes = t->collisions = t->search = t->same_hash =0u ; } char *dm_hash_get_key(struct dm_hash_table *t __attribute__((unused)),
@@ -262,7 +288,5 @@ struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t)struct dm_hash_node *dm_hash_get_next (struct dm_hash_table *t,struct dm_hash_node *n) { -unsigned h =_hash (n->key, n->keylen) & (t->num_slots -1 ); - -return n->next ? n->next :_next_slot (t, h +1 ); +return n->next ? n->next :_next_slot (t, (n->hash & t->mask) +1 ); }
libdm/libdevmapper.h +3 -3
@@ -707,10 +707,10 @@ void *dm_hash_lookup(struct dm_hash_table *t, const char *key);int dm_hash_insert (struct dm_hash_table *t,const char *key,void *data);void dm_hash_remove (struct dm_hash_table *t,const char *key); -void *dm_hash_lookup_binary (struct dm_hash_table *t,const char *key,uint32_t len); -int dm_hash_insert_binary (struct dm_hash_table *t,const char *key,uint32_t len, +void *dm_hash_lookup_binary (struct dm_hash_table *t,const void *key,uint32_t len); +int dm_hash_insert_binary (struct dm_hash_table *t,const void *key,uint32_t len,void *data); -void dm_hash_remove_binary (struct dm_hash_table *t,const char *key,uint32_t len); +void dm_hash_remove_binary (struct dm_hash_table *t,const void *key,uint32_t len);unsigned dm_hash_get_num_entries (struct dm_hash_table *t);void dm_hash_iter (struct dm_hash_table *t,dm_hash_iterate_fn f);
Signature · 1 line
1.7.3.5
PATCH 11/24 Perf: New HASH function
In reply to Zdenek KabelacProviding 2 new hash function for selection.
Performance of my modified Bob Jenkins hash function (completely free code) is reasonably good and in my test is seems to be equal with larger but slightly more advanced SuperFastHash (LGPL).
Our current hash is producing a lot of hash collisions (i.e. a lot of strings are hashed to same number) and also requires extra derefernce during hash calculation.
--- libdm/datastruct/hash.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 104 insertions(+), 0 deletions(-)
libdm/datastruct/hash.c +104 -0
@@ -34,6 +34,7 @@ struct dm_hash_table {struct dm_hash_node **slots; }; +#if 0 /* Permutation of the Integers 0 through 255 */ static unsigned char _nums[] = { 1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
@@ -61,6 +62,7 @@ static unsigned char _nums[] = {163 ,200 ,222 ,235 ,248 ,243 ,219 ,10 ,152 ,131 ,123 ,229 ,203 ,76 ,120 ,209 }; +#endif static struct dm_hash_node *_create_node (const char *str,unsigned len) {
@@ -74,6 +76,7 @@ static struct dm_hash_node *_create_node(const char *str, unsigned len)return n; } +#if 0 static unsigned long _hash (const char *str,unsigned len) {unsigned long h =0 , g;
@@ -91,6 +94,107 @@ static unsigned long _hash(const char *str, unsigned len)return h; } +#endif + +#if 1 +/* +* Adapted Bob Jenkins hash to read by 2 bytes if possible. +* https://secure.wikimedia.org/wikipedia/en/wiki/Jenkins_hash_function +* +* reduces amount of hash collisions +*/ +static unsigned long _hash (const char *str,unsigned len) +{ +const uint16_t *str16 = (const uint16_t *)str; +uint32_t hash =0 , i; +int sz = len /2 ; + +//if ((int)str & 1) abort(); // catch odd addresses +for (i =0 ; i < sz; ++i) { + hash += str16[i]; + hash += (hash <<10 ); + hash ^= (hash >>6 ); + } + +if (len &1 ) { + hash += str[len -1 ]; + hash += (hash <<10 ); + hash ^= (hash >>6 ); + } + + hash += (hash <<3 ); + hash ^= (hash >>11 ); + hash += (hash <<15 ); + +return hash; +} +#endif + +#if 0 +/* +* SuperFastHash +* http://www.azillionmonkeys.com/qed/hash.html +*/ +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits (d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits (d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif + +static unsigned long _hash (const char *data,unsigned len) +{ +unsigned long hash = len, tmp; +int rem; + +if (len <=0 || data ==NULL )return 0 ; + + rem = len &3 ; + len >>=2 ; + +/* Main loop */ +for (;len >0 ; len--) { + hash +=get16bits (data); + tmp = (get16bits (data+2 ) <<11 ) ^ hash; + hash = (hash <<16 ) ^ tmp; + data +=2 *sizeof (uint16_t ); + hash += hash >>11 ; + } + +/* Handle end cases */ +switch (rem) { +case 3 : + hash +=get16bits (data); + hash ^= hash <<16 ; + hash ^= data[sizeof (uint16_t )] <<18 ; + hash += hash >>11 ; +break ; +case 2 : + hash +=get16bits (data); + hash ^= hash <<11 ; + hash += hash >>17 ; +break ; +case 1 : + hash += *data; + hash ^= hash <<10 ; + hash += hash >>1 ; + } + +/* Force "avalanching" of final 127 bits */ + hash ^= hash <<3 ; + hash += hash >>5 ; + hash ^= hash <<4 ; + hash += hash >>17 ; + hash ^= hash <<25 ; + hash += hash >>6 ; + +return hash; +} +#endif struct dm_hash_table *dm_hash_create (unsigned size_hint) {
Signature · 1 line
1.7.3.5
PATCH 11/24 Perf: New HASH function
Quoted 1 line · Zdenek Kabelac
Providing 2 new hash function for selection.
My experience is that Bob Jenkins's LOOKUP3 is the best available hash by far, for use in tables. It's not very complicated and comes with well-optimised C implementation. Shows both excellent distribution and speed.
Yours,
Petr
PATCH 12/24 Perf: Increase hash sizes
In reply to Zdenek KabelacModify size of created hash tables in a way, it could be uniquely identified in debug code - as hash will be rouned up to nearest power of two - so in most updated lines it presents no functional change.
There is one major increase of hass size for lv_hash from 128 to 1024 entries. (With ideal hash - in case of 10000 LVs - 10 LVs would ocuppy one slot - which should be still pretty fast).
--- daemons/clvmd/lvm-functions.c | 2 +- lib/cache/lvmcache.c | 8 ++++---- lib/device/dev-cache.c | 2 +- lib/filters/filter-persistent.c | 2 +- lib/format1/import-export.c | 2 +- lib/format1/import-extents.c | 2 +- lib/format_text/export.c | 2 +- lib/format_text/import_vsn1.c | 4 ++-- lib/log/log.c | 2 +- libdm/libdm-deptree.c | 4 ++-- 10 files changed, 15 insertions(+), 15 deletions(-)
daemons/clvmd/lvm-functions.c +1 -1
@@ -197,7 +197,7 @@ static int get_current_lock(char *resource)void init_lvhash () {/* Create hash table for keeping LV locks & status */ - lv_hash =dm_hash_create (100 ); + lv_hash =dm_hash_create (1024 );pthread_mutex_init (&lv_hash_lock,NULL );pthread_mutex_init (&lvm_lock,NULL ); }
lib/cache/lvmcache.c +4 -4
@@ -48,16 +48,16 @@ int lvmcache_init(void)dm_list_init (&_vginfos); -if (!(_vgname_hash =dm_hash_create (128 ))) +if (!(_vgname_hash =dm_hash_create (110 )))return 0 ; -if (!(_vgid_hash =dm_hash_create (128 ))) +if (!(_vgid_hash =dm_hash_create (111 )))return 0 ; -if (!(_pvid_hash =dm_hash_create (128 ))) +if (!(_pvid_hash =dm_hash_create (112 )))return 0 ; -if (!(_lock_hash =dm_hash_create (128 ))) +if (!(_lock_hash =dm_hash_create (113 )))return 0 ;/*
lib/device/dev-cache.c +1 -1
@@ -604,7 +604,7 @@ int dev_cache_init(struct cmd_context *cmd)if (!(_cache.mem =dm_pool_create ("dev_cache" ,10 *1024 ))) return_0; -if (!(_cache.names =dm_hash_create (128 ))) { +if (!(_cache.names =dm_hash_create (120 ))) {dm_pool_destroy (_cache.mem); _cache.mem =0 ; return_0;
lib/filters/filter-persistent.c +1 -1
@@ -45,7 +45,7 @@ static int _init_hash(struct pfilter *pf)if (pf->devices)dm_hash_destroy (pf->devices); -if (!(pf->devices =dm_hash_create (128 ))) +if (!(pf->devices =dm_hash_create (500 ))) return_0;return 1 ;
lib/format1/import-export.c +1 -1
@@ -499,7 +499,7 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,if (!_check_vg_name (vg->name)) return_0; -if (!(lvd_hash =dm_hash_create (32 ))) +if (!(lvd_hash =dm_hash_create (30 ))) return_0;/*
lib/format1/import-extents.c +1 -1
@@ -45,7 +45,7 @@ struct lv_map {static struct dm_hash_table *_create_lv_maps (struct dm_pool *mem,struct volume_group *vg) { -struct dm_hash_table *maps =dm_hash_create (32 ); +struct dm_hash_table *maps =dm_hash_create (31 );struct lv_list *ll;struct lv_map *lvm;
lib/format_text/export.c +1 -1
@@ -663,7 +663,7 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)if (!(f->mem =dm_pool_create ("text pv_names" ,512 ))) return_0; -if (!(f->pv_names =dm_hash_create (128 ))) +if (!(f->pv_names =dm_hash_create (100 ))) return_0; dm_list_iterate_items(pvl, &vg->pvs) {
lib/format_text/import_vsn1.c +2 -2
@@ -756,7 +756,7 @@ static struct volume_group *_read_vg(struct format_instance *fid,* The pv hash memorises the pv section names -> pv * structures. */ -if (!(pv_hash =dm_hash_create (32 ))) { +if (!(pv_hash =dm_hash_create (61 ))) {log_error ("Couldn't create hash table." ); goto bad; }
@@ -784,7 +784,7 @@ static struct volume_group *_read_vg(struct format_instance *fid,* The lv hash memorises the lv section names -> lv * structures. */ -if (!(lv_hash =dm_hash_create (32 ))) { +if (!(lv_hash =dm_hash_create (999 ))) {log_error ("Couldn't create hash table." ); goto bad; }
lib/log/log.c +1 -1
@@ -242,7 +242,7 @@ void print_log(int level, const char *file, int line, int dm_errno,if (log_once) {if (!_duplicated) - _duplicated =dm_hash_create (128 ); + _duplicated =dm_hash_create (101 );if (_duplicated) {if (dm_hash_lookup (_duplicated, message)) level = _LOG_NOTICE;
libdm/libdm-deptree.c +2 -2
@@ -214,14 +214,14 @@ struct dm_tree *dm_tree_create(void)return NULL ; } -if (!(dtree->devs =dm_hash_create (8 ))) { +if (!(dtree->devs =dm_hash_create (28 ))) {log_error ("dtree hash creation failed" );dm_pool_destroy (dtree->mem);dm_free (dtree);return NULL ; } -if (!(dtree->uuids =dm_hash_create (32 ))) { +if (!(dtree->uuids =dm_hash_create (63 ))) {log_error ("dtree uuid hash creation failed" );dm_hash_destroy (dtree->devs);dm_pool_destroy (dtree->mem);
Signature · 1 line
1.7.3.5
PATCH 12/24 Perf: Increase hash sizes
Quoted 2 lines · Zdenek Kabelac
Modify size of created hash tables in a way, it could be uniquely identified in debug code - as hash will be rouned up to nearest power
code obfuscation :) can we better add new has function or macro which takes some identifier? (similar to pool create)
Why do you need such hacks?
Quoted 5 lines
of two - so in most updated lines it presents no functional change.
There is one major increase of hass size for
lv_hashfrom 128 to 1024 entries. (With ideal hash - in case of 10000 LVs - 10 LVs would ocuppy one slot - which should be still pretty fast).
Ack that part. Except that if I want 1024 I really do not want to push 999 there and believe it will be rounded :)
m.
PATCH 12/24 Perf: Increase hash sizes
Dne 30.1.2011 21:35, Milan Broz napsal(a):
Quoted 8 lines · Zdenek Kabelac
Quoted 2 lines
Modify size of created hash tables in a way, it could be uniquely identified in debug code - as hash will be rouned up to nearest power
code obfuscation :) can we better add new has function or macro which takes some identifier? (similar to pool create)
Why do you need such hacks?
Well I've been thinking about few solutions - for this - so take this just as an initial 'startup' - whether we want to extend API
with some new function with string parameter for hash description - or as some 'debug - like' version, which is compiled only with some debug option enabled.
Meanwhile - this was rather very easy 'quick and see' - as we don't have named hashes, like we have for pools.
This hash part needs some polishing.
Zdenek
PATCH 13/24 Memory unlock allows 1 page difference
In reply to Zdenek KabelacAs the kernel seems to be doing weird things during mlock -> munlock - allow 1 page locking difference without warning - and log just debug message for a 1 page difference.
Do not scary users too often.
--- lib/mm/memlock.c | 12 +++++++++--- 1 files changed, 9 insertions(+), 3 deletions(-)
lib/mm/memlock.c +9 -3
@@ -320,9 +320,15 @@ static void _unlock_mem(struct cmd_context *cmd)log_sys_error ("close" , _procselfmaps);dm_free (_maps_buffer); _maps_buffer =NULL ; -if (_mstats < unlock_mstats) -log_error (INTERNAL_ERROR "Maps lock %ld < unlock %ld" , - (long )_mstats, (long )unlock_mstats); +if (_mstats < unlock_mstats) { +if ((_mstats +4096 ) < unlock_mstats) +log_error (INTERNAL_ERROR +"Maps lock %ld < unlock %ld" , + (long )_mstats, (long )unlock_mstats); +else +log_debug ("Maps lock %ld < unlock %ld, 1 page difference!" , + (long )_mstats, (long )unlock_mstats); + } }if (setpriority (PRIO_PROCESS ,0 , _priority))
Signature · 1 line
1.7.3.5
PATCH 14/24 Critical section
In reply to Zdenek KabelacNew function to mark the critical section is introduced.
Inside the critical section - memory is always locked. When the critical section is left, memory stays locked until memory lock is decremeneted - during VG unlock.
memlock_reset() is needed to reset locking numbers after fork (polldaemon).
--- daemons/clvmd/lvm-functions.c | 10 +++--- lib/activate/activate.c | 16 +++++----- lib/activate/fs.c | 4 +- lib/cache/lvmcache.c | 6 ++-- lib/device/dev-io.c | 2 +- lib/format_text/format-text.c | 2 +- lib/locking/locking.c | 14 ++++++++- lib/log/log.c | 6 ++-- lib/metadata/metadata.c | 12 ++++---- lib/metadata/mirror.c | 2 +- lib/mm/memlock.c | 60 +++++++++++++++++++++++++++++++--------- lib/mm/memlock.h | 6 +++- 12 files changed, 93 insertions(+), 47 deletions(-)
daemons/clvmd/lvm-functions.c +5 -5
@@ -479,8 +479,8 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource) {int status =0 ; -DEBUGLOG ("do_lock_lv: resource '%s', cmd = %s, flags = %s, memlock = %d\n" , - resource,decode_locking_cmd (command),decode_flags (lock_flags),memlock ()); +DEBUGLOG ("do_lock_lv: resource '%s', cmd = %s, flags = %s, critical_section = %d\n" , + resource,decode_locking_cmd (command),decode_flags (lock_flags),critical_section ());if (!cmd->config_valid ||config_files_changed (cmd)) {/* Reinitialise various settings inc. logging, filters */
@@ -541,7 +541,7 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)dm_pool_empty (cmd->mem);pthread_mutex_unlock (&lvm_lock); -DEBUGLOG ("Command return is %d, memlock is %d\n" , status,memlock ()); +DEBUGLOG ("Command return is %d, critical_section is %d\n" , status,critical_section ());return status; }
@@ -689,8 +689,8 @@ void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource)if (strncmp (resource,"P_#" ,3 ) && !strncmp (resource,"P_" ,2 )) lock_cmd |=LCK_CACHE ; -DEBUGLOG ("do_lock_vg: resource '%s', cmd = %s, flags = %s, memlock = %d\n" , - resource,decode_full_locking_cmd (lock_cmd),decode_flags (lock_flags),memlock ()); +DEBUGLOG ("do_lock_vg: resource '%s', cmd = %s, flags = %s, critical_section = %d\n" , + resource,decode_full_locking_cmd (lock_cmd),decode_flags (lock_flags),critical_section ());/* P_#global causes a full cache refresh */ if (!strcmp (resource,"P_" VG_GLOBAL )) {
lib/activate/activate.c +8 -8
@@ -1027,7 +1027,7 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,if (!error_if_not_suspended) { r =1 ;if (info.suspended) -memlock_inc (cmd); +critical_section_inc (cmd); } goto out; }
@@ -1049,14 +1049,14 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,/* FIXME Consider aborting here */ stack; -memlock_inc (cmd); +critical_section_inc (cmd);if (!origin_only && (lv_is_origin (lv_pre) ||lv_is_cow (lv_pre))) lockfs =1 ;if (!_lv_suspend_lv (lv, origin_only, lockfs, flush_required)) { -memlock_dec (cmd); +critical_section_dec (cmd);fs_unlock (); goto out; }
@@ -1123,7 +1123,7 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,if (!_lv_activate_lv (lv, origin_only)) goto_out; -memlock_dec (cmd); +critical_section_dec (cmd);if (!monitor_dev_for_events (cmd, lv, origin_only,1 )) stack;
@@ -1214,9 +1214,9 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)if (!monitor_dev_for_events (cmd, lv,0 ,0 )) stack; -memlock_inc (cmd); +critical_section_inc (cmd); r =_lv_deactivate (lv); -memlock_dec (cmd); +critical_section_dec (cmd);if (!lv_info (cmd, lv,0 , &info,0 ,0 ) || info.exists) r =0 ;
@@ -1311,10 +1311,10 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,if (exclusive) lv->status |=ACTIVATE_EXCL ; -memlock_inc (cmd); +critical_section_inc (cmd);if (!(r =_lv_activate_lv (lv,0 ))) stack; -memlock_dec (cmd); +critical_section_dec (cmd);if (r && !monitor_dev_for_events (cmd, lv,0 ,1 )) stack;
lib/activate/fs.c +2 -2
@@ -411,7 +411,7 @@ static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name, const char *lv_name, const char *dev, const char *old_lv_name, int check_udev) { - if (memlock()) { + if (critical_section()) { if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev, old_lv_name, check_udev)) return_0;
@@ -457,7 +457,7 @@ int fs_rename_lv(struct logical_volume *lv, const char *dev,void fs_unlock (void ) { -if (!memlock ()) { +if (!critical_section ()) {log_debug ("Syncing device names" );/* Wait for all processed udev devices */ if (!dm_udev_wait (_fs_cookie))
lib/cache/lvmcache.c +3 -3
@@ -649,7 +649,7 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)* Note that we do not clear the PRECOMMITTED flag. */ if ((precommitted && !vginfo->precommitted) || - (!precommitted && vginfo->precommitted && !memlock ())) + (!precommitted && vginfo->precommitted && !critical_section ()))return NULL ; if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt,
@@ -783,7 +783,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, const struct id *pvid, } } -if (memlock () || (scan_done_once && *scan_done_once)) +if (critical_section () || (scan_done_once && *scan_done_once))return NULL ;lvmcache_label_scan (cmd,2 );
@@ -1229,7 +1229,7 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info,/* If PV without mdas is already in a real VG, don't make it orphan */ if (is_orphan_vg (vgname) && info->vginfo &&mdas_empty_or_ignored (&info->mdas) && - !is_orphan_vg (info->vginfo->vgname) &&memlock ()) + !is_orphan_vg (info->vginfo->vgname) &&critical_section ())return 1 ;/* If moving PV from orphan to real VG, always mark it valid */
lib/device/dev-io.c +1 -1
@@ -399,7 +399,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)dev_close_immediate (dev); } -if (memlock ()) +if (critical_section ())/* FIXME Make this log_error */ log_verbose ("dev_open(%s) called while suspended" ,dev_name (dev));
lib/format_text/format-text.c +1 -1
@@ -1603,7 +1603,7 @@ static int _populate_pv_fields(struct lvmcache_info *info,return 1 ;/* Perform full scan (just the first time) and try again */ -if (!scan_label_only && !memlock () && !full_scan_done ()) { +if (!scan_label_only && !critical_section () && !full_scan_done ()) {lvmcache_label_scan (info->fmt->cmd,2 );if (_get_pv_if_in_vg (info, pv))
lib/locking/locking.c +12 -2
@@ -167,7 +167,7 @@ static void _lock_memory(struct cmd_context *cmd, lv_operation_t lv_op)return ;if (lv_op ==LV_SUSPEND ) -memlock_inc (cmd); +critical_section_inc (cmd); }static void _unlock_memory (struct cmd_context *cmd,lv_operation_t lv_op)
@@ -176,7 +176,7 @@ static void _unlock_memory(struct cmd_context *cmd, lv_operation_t lv_op)return ;if (lv_op ==LV_RESUME ) -memlock_dec (cmd); +critical_section_dec (cmd); }void reset_locking (void )
@@ -191,6 +191,8 @@ void reset_locking(void)if (was_locked)_unblock_signals (); + +memlock_reset (); }static void _update_vg_lock_count (const char *resource,uint32_t flags)
@@ -358,6 +360,7 @@ static int _lock_vol(struct cmd_context *cmd, const char *resource, uint32_t flags, lv_operation_t lv_op) { int ret = 0; +int locked;_block_signals (flags);_lock_memory (cmd, lv_op);
@@ -392,7 +395,14 @@ static int _lock_vol(struct cmd_context *cmd, const char *resource,dev_reset_error_count (cmd); } + locked = _vg_lock_count;_update_vg_lock_count (resource, flags); +if (locked != _vg_lock_count) { +if (locked < _vg_lock_count) +memlock_inc (cmd); +else +memlock_dec (cmd); + } }else stack;
lib/log/log.c +3 -3
@@ -336,7 +336,7 @@ void print_log(int level, const char *file, int line, int dm_errno,if (level >debug_level ())return ; -if (_log_to_file && (_log_while_suspended || !memlock ())) { +if (_log_to_file && (_log_while_suspended || !critical_section ())) {fprintf (_log_file,"%s:%d %s%s" , file, line,log_command_name (), _msg_prefix);
@@ -348,14 +348,14 @@ void print_log(int level, const char *file, int line, int dm_errno,fflush (_log_file); } -if (_syslog && (_log_while_suspended || !memlock ())) { +if (_syslog && (_log_while_suspended || !critical_section ())) {va_start (ap, format);vsyslog (level, trformat, ap);va_end (ap); }/* FIXME This code is unfinished - pre-extend & condense. */ -if (!_already_logging && _log_direct &&memlock ()) { +if (!_already_logging && _log_direct &&critical_section ()) { _already_logging =1 ;memset (&buf,' ' ,sizeof (buf)); bufused =0 ;
lib/metadata/metadata.c +6 -6
@@ -2792,7 +2792,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,lvmcache_label_scan (cmd,0 );if (!(fmt =fmt_from_vgname (vgname, vgid,1 ))) {/* Independent MDAs aren't supported under low memory */ -if (!cmd->independent_metadata_areas &&memlock ()) +if (!cmd->independent_metadata_areas &&critical_section ()) return_NULL;lvmcache_label_scan (cmd,2 );if (!(fmt =fmt_from_vgname (vgname, vgid,0 )))
@@ -2921,7 +2921,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,log_debug ("Cached VG %s had incorrect PV list" , vgname); -if (memlock ()) +if (critical_section ()) inconsistent =1 ;else {free_vg (correct_vg);
@@ -2952,7 +2952,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, inconsistent =0 ;/* Independent MDAs aren't supported under low memory */ -if (!cmd->independent_metadata_areas &&memlock ()) +if (!cmd->independent_metadata_areas &&critical_section ()) return_NULL;lvmcache_label_scan (cmd,2 );if (!(fmt =fmt_from_vgname (vgname, vgid,0 )))
@@ -3212,7 +3212,7 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd, }/* Mustn't scan if memory locked: ensure cache gets pre-populated! */ -if (memlock ()) +if (critical_section ()) return_NULL;/* FIXME Need a genuine read by ID here - don't vg_read_internal by name! */
@@ -3891,10 +3891,10 @@ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname)lvmcache_label_scan (cmd,0 );if (!fmt_from_vgname (vgname,NULL ,1 )) {/* Independent MDAs aren't supported under low memory */ -if (!cmd->independent_metadata_areas &&memlock ()) { +if (!cmd->independent_metadata_areas &&critical_section ()) {/* * FIXME: Disallow calling this function if -* memlock() is true. +* critical_section() is true. */ unlock_vg (cmd, vgname);return FAILED_LOCKING ;
lib/metadata/mirror.c +1 -1
@@ -974,7 +974,7 @@ static int _remove_mirror_images(struct logical_volume *lv,/* FIXME: second suspend should not be needed * Explicitly suspend temporary LV -* This balance memlock_inc() calls with memlock_dec() in resume +* This balance critical_section_inc() calls with critical_section_dec() in resume * (both localy and in cluster) and also properly propagates precommited * metadata into dm table on other nodes. * (visible flag set causes the suspend is not properly propagated?)
lib/mm/memlock.c +46 -14
95 lines not on this page · raw message
lib/mm/memlock.h +5 -1
@@ -18,11 +18,15 @@struct cmd_context ; +void critical_section_inc (struct cmd_context *cmd); +void critical_section_dec (struct cmd_context *cmd); +int critical_section (void ); + +void memlock_reset (void );void memlock_inc (struct cmd_context *cmd);void memlock_dec (struct cmd_context *cmd);void memlock_inc_daemon (struct cmd_context *cmd);void memlock_dec_daemon (struct cmd_context *cmd); -int memlock (void );void memlock_init (struct cmd_context *cmd);#endif
Signature · 1 line
1.7.3.5
PATCH 15/24 Remove fs_unlock after failed suspend
In reply to Zdenek KabelacExplicit fs_unlock() after failed suspend is not need - as it will happen automatically with nearest lv_info() or vg_unlock().
--- lib/activate/activate.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
lib/activate/activate.c +0 -1
@@ -1057,7 +1057,6 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,if (!_lv_suspend_lv (lv, origin_only, lockfs, flush_required)) {critical_section_dec (cmd); -fs_unlock (); goto out; }
Signature · 1 line
1.7.3.5
PATCH 16/24 Man pages reformating
In reply to Zdenek KabelacUpdate format of few more man pages.
--- man/fsadm.8.in | 80 ++++++++++++++++++++++++------------------- man/lvreduce.8.in | 65 ++++++++++++++++++---------------- man/lvremove.8.in | 17 ++++----- man/lvrename.8.in | 37 ++++++-------------- man/lvresize.8.in | 99 +++++++++++++++++++++++++++-------------------------- 5 files changed, 148 insertions(+), 150 deletions(-)
man/fsadm.8.in +45 -35
@@ -1,64 +1,74 @@ .TH "FSADM" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\"" .SH "NAME" fsadm \- utility to resize or check filesystem on a device -.SH "SYNOPSIS" +.SH SYNOPSIS .B fsadm -.RI [options]\ check\ device - +.RI [ options ] +.B check +.I device +.sp .B fsadm -.RI [options]\ resize\ device\ [new_size[BKMGTEP]] - -.SH "DESCRIPTION" -\fBfsadm\fR utility resizes or checks the filesystem on a device. -It tries to use the same API for \fBext2/ext3/ext4\fR, -\fBReiserFS\fR and \fBXFS\fR filesystem. -.SH "OPTIONS" +.RI [ options ] +.B resize +.I device +.RI [ new_size [ BKMGTEP ]] +.sp +.SH DESCRIPTION +.B fsadm +utility resizes or checks the filesystem on a device. +It tries to use the same API for +.IR ext2 , ext3 , ext4 , ReiserFS +and \fIXFS\fP filesystem. +.SH OPTIONS .TP -\fB\-h \-\-help\fR -\(em print help message +.BR \-h ", " \-\-help +Display the help text. .TP -\fB\-v \-\-verbose\fR -\(em be more verbose +.BR \-v ", " \-\-verbose +Be more verbose. .TP -\fB\-e \-\-ext\-offline\fR -\(em unmount ext2/ext3/ext4 filesystem before doing resize +.BR \-e ", " \-\-ext\-offline +Unmount ext2/ext3/ext4 filesystem before doing resize. .TP -\fB\-f \-\-force\fR -\(em bypass some sanity checks +.BR \-f ", " \-\-force +Bypass some sanity checks. .TP -\fB\-n \-\-dry\-run\fR -\(em print commands without running them +.BR \-n ", " \-\-dry\-run +Print commands without running them. .TP -\fB\-y \-\-yes\fR -\(em answer "yes" at any prompts +.BR \-y ", " \-\-yes +Answer "yes" at any prompts. .TP -\fBnew_size\fR -\(em Absolute number of filesystem blocks to be in the filesystem, +.I new_size +Absolute number of filesystem blocks to be in the filesystem, or an absolute size using a suffix (in powers of 1024). If new_size is not supplied, the whole device is used. -.SH "DIAGNOSTICS" +.SH DIAGNOSTICS On successful completion, the status code is 0. A status code of 2 indicates the operation was interrupted by the user. A status code of 3 indicates the requested check operation could not be performed -because the filesystem is mounted and does not support an online fsck. +because the filesystem is mounted and does not support an online +.BR fsck (8). A status code of 1 is used for other failures. -.SH "EXAMPLES" -"fsadm \-e \-y resize /dev/vg/test 1000M" tries to resize the filesystem -on logical volume /dev/vg/test. If /dev/vg/test contains ext2/ext3/ext4 +.SH EXAMPLES +Resize the filesystem on logical volume /dev/vg/test to 1000 megabytes. +If /dev/vg/test contains ext2/ext3/ext4 filesystem it will be unmounted prior the resize. All [y|n] questions will be answered 'y'. -.SH "ENVIRONMENT VARIABLES" +.sp +.B fsadm \-e \-y resize /dev/vg/test 1000M +.SH ENVIRONMENT VARIABLES .TP -\fBTMPDIR\fP -Where the temporary directory should be created. -.TP -.BR -.SH "SEE ALSO" +.B TMPDIR +The temporary directory name for mount points. Defaults to "/tmp". + +.SH SEE ALSO .BR lvm (8), .BR lvresize (8), .BR lvm.conf (5), +.BR fsck (8), .BR tune2fs (8), .BR resize2fs (8), .BR reiserfstune (8),
man/lvreduce.8.in +34 -31
110 lines not on this page · raw message
man/lvremove.8.in +8 -9
@@ -3,11 +3,10 @@ lvremove \- remove a logical volume .SH SYNOPSIS .B lvremove -[\-A|\-\-autobackup y|n] [\-d|\-\-debug] [\-f|\-\-force] -[\-h|\-?|\-\-help] -[\-\-noudevsync] -[\-t|\-\-test] -[\-v|\-\-verbose] LogicalVolumePath [LogicalVolumePath...] +.RB [ \-f | \-\-force ] +.RB [ \-\-noudevsync ] +.IR LogicalVolume { Name | Path } +.RI [ LogicalVolume { Name | Path }...] .SH DESCRIPTION \fBlvremove\fP removes one or more logical volumes. Confirmation will be requested before deactivating any active logical
@@ -21,10 +20,10 @@ issued from one node can do this. .SH OPTIONS See \fBlvm\fP(8) for common options. .TP -.I \-f, \-\-force +.BR \-f ", " \-\-force Remove active logical volumes without confirmation. .TP -.I \-\-noudevsync +.B \-\-noudevsync Disable udev synchronisation. The process will not wait for notification from udev. It will continue irrespective of any possible udev processing
@@ -34,11 +33,11 @@ or has rules that ignore the devices LVM2 creates. Remove the active logical volume lvol1 in volume group vg00 without asking for confirmation: .sp -\ \fBlvremove -f vg00/lvol1\fP +.B lvremove -f vg00/lvol1 .sp Remove all logical volumes in volume group vg00: .sp -\ \fBlvremove vg00\fP +.B lvremove vg00 .SH SEE ALSO .BR lvcreate (8), .BR lvdisplay (8),
man/lvrename.8.in +11 -26
@@ -3,16 +3,10 @@ lvrename \- rename a logical volume .SH SYNOPSIS .B lvrename -.RB [ \-A | \-\-autobackup " {" y | n }] -.RB [ \-d | \-\-debug ] .RB [ \-f | \-\-force ] -.RB [ \-h | \-\-help ] .RB [ \-\-noudevsync ] -.RB [ \-t | \-\-test ] -.RB [ \-v | \-\-verbose ] -.RB [ \-\-version ] -.TP -.IR "OldLogicalVolumePath NewLogicalVolume" { Path | Name } +.IR OldLogicalVolume { Name | Path } +.IR NewLogicalVolume { Name | Path } .TP .I VolumeGroupName OldLogicalVolumeName NewLogicalVolumeName .SH DESCRIPTION
@@ -22,7 +16,7 @@ renames an existing logical volume from to .IR NewLogicalVolume { Name | Path }. .SH OPTIONS -See \fBlvm\fP for common options. +See \fBlvm\fP(8) for common options. .TP .BR \-\-noudevsync Disable udev synchronisation. The
@@ -31,23 +25,14 @@ It will continue irrespective of any possible udev processing in the background. You should only use this if udev is not running or has rules that ignore the devices LVM2 creates. .SH EXAMPLE -To rename -.B lvold -in volume group -.B vg02 -to -.BR lvnew : -.nf - -\ lvrename /dev/vg02/lvold /dev/vg02/lvnew - -.fi -An alternate syntax to rename this logical volume is -.nf - -\ lvrename vg02 lvold lvnew - -.fi +To rename lvold in volume group vg02 to lvnew: +.sp +.B lvrename /dev/vg02/lvold vg02/lvnew +.sp +An alternate syntax to rename this logical volume is: +.sp +.B lvrename vg02 lvold lvnew +.sp .SH SEE ALSO .BR lvm (8), .BR lvchange (8),
man/lvresize.8.in +50 -49
141 lines not on this page · raw message
Signature · 1 line
1.7.3.5
PATCH 16/24 Man pages reformating
Quoted 1 line · Zdenek Kabelac
Update format of few more man pages.
If it makes the format consistent, then ACK. (I did not read if there are some addditions though:-)
Milan
PATCH 17/24 Void* arithmetic replaced with char*
In reply to Zdenek Kabelac--- daemons/clvmd/clvmd.c | 2 +- lib/format_text/text_label.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
daemons/clvmd/clvmd.c +1 -1
@@ -1867,7 +1867,7 @@ static int send_message(void *buf, int msglen, const char *csid, int fd,break ; } - len =write (fd, buf + ptr, msglen - ptr); + len =write (fd, (char *)buf + ptr, msglen - ptr);if (len <=0 ) {if (errno ==EINTR )
lib/format_text/text_label.c +2 -2
@@ -52,7 +52,7 @@ static int _text_write(struct label *label, void *buf)strncpy ((char *)lh->type, label->type,sizeof (label->type)); - pvhdr = (struct pv_header *) ((void *) buf +xlate32 (lh->offset_xl)); + pvhdr = (struct pv_header *) ((char *) buf +xlate32 (lh->offset_xl)); info = (struct lvmcache_info *) label->info; pvhdr->device_size_xl =xlate64 (info->device_size);memcpy (pvhdr->pv_uuid, &info->dev->pvid,sizeof (struct id ));
@@ -268,7 +268,7 @@ static int _text_read(struct labeller *l, struct device *dev, void *buf,char *creation_host;struct mda_header *mdah; - pvhdr = (struct pv_header *) ((void *) buf +xlate32 (lh->offset_xl)); + pvhdr = (struct pv_header *) ((char *) buf +xlate32 (lh->offset_xl));if (!(info =lvmcache_add (l, (char *)pvhdr->pv_uuid, dev, text_orphan_vg_name, text_orphan_vg_name,0 )))
Signature · 1 line
1.7.3.5
PATCH 18/24 API change - support more const arg
In reply to Zdenek KabelacAs dm_report_field_string doesn't modify content of data pointer, it could be also marked as const.
It's slight API change - but doesn't require any change on user side and supports wide range of arguments without const casting. (i.e. we may use as paramater const lv struct this way: &lv->name)
--- libdm/libdevmapper.h | 2 +- libdm/libdm-report.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
libdm/libdevmapper.h +1 -1
@@ -1117,7 +1117,7 @@ int dm_report_set_output_field_name_prefix(struct dm_report *rh,* They take care of allocating copies of the data. */ int dm_report_field_string (struct dm_report *rh,struct dm_report_field *field, -const char **data); +const char *const *data);int dm_report_field_int32 (struct dm_report *rh,struct dm_report_field *field,const int32_t *data); int dm_report_field_uint32(struct dm_report *rh, struct dm_report_field *field,
libdm/libdm-report.c +1 -1
@@ -102,7 +102,7 @@ static const struct dm_report_object_type *_find_type(struct dm_report *rh,*/ int dm_report_field_string (struct dm_report *rh, -struct dm_report_field *field,const char **data) +struct dm_report_field *field,const char *const *data) {char *repstr;
Signature · 1 line
1.7.3.5
PATCH 19/24 Use cleaner const * pointer
In reply to Zdenek KabelacNow it's warning free -
Const cast in _string_disp() is not even needed,
but it's more readable conversion.
--- lib/report/report.c | 8 +++----- 1 files changed, 3 insertions(+), 5 deletions(-)
lib/report/report.c +3 -5
@@ -44,7 +44,7 @@ static int _string_disp(struct dm_report *rh, struct dm_pool *mem __attribute__(struct dm_report_field *field, const void *data, void *private __attribute__((unused))) { -return dm_report_field_string (rh, field, (const char **) data); +return dm_report_field_string (rh, field, (const char *const *) data); } static int _dev_name_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
@@ -307,10 +307,8 @@ static int _lvname_disp(struct dm_report *rh, struct dm_pool *mem,char *repstr, *lvname;size_t len; -if (lv_is_visible (lv)) { - repstr = lv->name; -return dm_report_field_string (rh, field, (const char **) &repstr); - } +if (lv_is_visible (lv)) +return dm_report_field_string (rh, field, &lv->name); len =strlen (lv->name) +3 ;if (!(repstr =dm_pool_zalloc (mem, len))) {
Signature · 1 line
1.7.3.5
PATCH 20/24 Const fixing
In reply to Zdenek KabelacFixing some of the remaining const warnings - major change:
int vg_extend(struct volume_group *vg, int pv_count, const char *const *pv_names,
Change is needed - as lvm2api seems to expect const behaviour here. So vg_extend() is doing local strdup for unescaping.
skip_dev_dir return const char* from const char* vg_name.
Rest of the patch is cleanup of related warnings.
--- daemons/clvmd/clvmd.c | 2 +- daemons/clvmd/clvmd.h | 2 +- lib/activate/activate.c | 4 ++-- lib/activate/activate.h | 2 +- lib/filters/filter-regex.c | 2 +- lib/metadata/lv.h | 2 +- lib/metadata/lv_manip.c | 3 ++- lib/metadata/metadata-exported.h | 8 ++++---- lib/metadata/metadata.c | 27 ++++++++++++++++----------- lib/metadata/mirror.c | 18 +++++++++--------- lib/report/properties.c | 3 +-- lib/report/report.c | 6 +++--- liblvm/lvm_vg.c | 4 ++-- tools/lvcreate.c | 2 +- tools/reporter.c | 4 ++-- tools/toollib.c | 10 +++++----- tools/toollib.h | 4 ++-- tools/vgcfgrestore.c | 2 +- tools/vgcreate.c | 2 +- tools/vgextend.c | 4 ++-- tools/vgmerge.c | 2 +- tools/vgreduce.c | 2 +- tools/vgrename.c | 2 +- tools/vgsplit.c | 2 +- 24 files changed, 62 insertions(+), 57 deletions(-)
daemons/clvmd/clvmd.c +1 -1
@@ -2091,7 +2091,7 @@ error:return -1 ; } -void process_message (struct local_client *client,const char *buf,int len, +void process_message (struct local_client *client,char *buf,int len,const char *csid) {struct clvm_header *inheader;
daemons/clvmd/clvmd.h +1 -1
@@ -112,7 +112,7 @@ extern void cmd_client_cleanup(struct local_client *client);extern int add_client (struct local_client *new_client);extern void clvmd_cluster_init_completed (void ); -extern void process_message (struct local_client *client,const char *buf, +extern void process_message (struct local_client *client,char *buf,int len,const char *csid);extern void debuglog (const char *fmt, ... ) __attribute__ ((format (printf,1 ,2 )));
lib/activate/activate.c +2 -2
@@ -162,7 +162,7 @@ int lv_snapshot_percent(const struct logical_volume *lv, percent_t *percent) {return 0 ; } -int lv_mirror_percent (struct cmd_context *cmd,struct logical_volume *lv, +int lv_mirror_percent (struct cmd_context *cmd,const struct logical_volume *lv,int wait,percent_t *percent,uint32_t *event_nr) {return 0 ;
@@ -553,7 +553,7 @@ int lv_snapshot_percent(const struct logical_volume *lv, percent_t *percent) }/* FIXME Merge with snapshot_percent */ -int lv_mirror_percent (struct cmd_context *cmd,struct logical_volume *lv, +int lv_mirror_percent (struct cmd_context *cmd,const struct logical_volume *lv,int wait,percent_t *percent,uint32_t *event_nr) {int r;
lib/activate/activate.h +1 -1
@@ -84,7 +84,7 @@ int lv_check_transient(struct logical_volume *lv);* Returns 1 if percent has been set, else 0. */ int lv_snapshot_percent (const struct logical_volume *lv,percent_t *percent); -int lv_mirror_percent (struct cmd_context *cmd,struct logical_volume *lv, +int lv_mirror_percent (struct cmd_context *cmd,const struct logical_volume *lv,int wait,percent_t *percent,uint32_t *event_nr);/*
lib/filters/filter-regex.c +1 -1
@@ -135,7 +135,7 @@ static int _build_matcher(struct rfilter *rf, const struct config_value *val)/* * build the matcher. */ -if (!(rf->engine =dm_regex_create (rf->mem, (const char **) regex, +if (!(rf->engine =dm_regex_create (rf->mem, (const char *const *) regex, count))) goto_out; r =1 ;
lib/metadata/lv.h +1 -1
@@ -23,7 +23,7 @@ struct replicator_device;struct logical_volume {union lvid lvid; -char *name; +const char *name;struct volume_group *vg;
lib/metadata/lv_manip.c +2 -1
@@ -1897,7 +1897,8 @@ static int _rename_sub_lv(struct cmd_context *cmd,struct logical_volume *lv, const char *lv_name_old, const char *lv_name_new) { - char *suffix, *new_name; + const char *suffix; +char *new_name;size_t len;/*
lib/metadata/metadata-exported.h +4 -4
@@ -410,9 +410,9 @@ void vg_remove_pvs(struct volume_group *vg);int vg_remove (struct volume_group *vg);int vg_rename (struct cmd_context *cmd,struct volume_group *vg,const char *new_name); -int vg_extend (struct volume_group *vg,int pv_count,char **pv_names, +int vg_extend (struct volume_group *vg,int pv_count,const char *const *pv_names,struct pvcreate_params *pp); -int vg_reduce (struct volume_group *vg,char *pv_name); +int vg_reduce (struct volume_group *vg,const char *pv_name);int vg_change_tag (struct volume_group *vg,const char *tag,int add_tag);int vg_split_mdas (struct cmd_context *cmd,struct volume_group *vg_from,struct volume_group *vg_to);
@@ -698,7 +698,7 @@ struct logical_volume *find_pvmove_lv_from_pvname(struct cmd_context *cmd, uint32_t lv_type);const char *get_pvmove_pvname_from_lv (struct logical_volume *lv);const char *get_pvmove_pvname_from_lv_mirr (struct logical_volume *lv_mirr); -percent_t copy_percent (struct logical_volume *lv_mirr); +percent_t copy_percent (const struct logical_volume *lv_mirr);struct dm_list *lvs_using_lv (struct cmd_context *cmd,struct volume_group *vg,struct logical_volume *lv);
@@ -721,7 +721,7 @@ int lv_has_unknown_segments(const struct logical_volume *lv);int vg_has_unknown_segments (const struct volume_group *vg);struct vgcreate_params { -char *vg_name; +const char *vg_name;uint32_t extent_size;size_t max_pv;size_t max_lv;
lib/metadata/metadata.c +16 -11
@@ -662,33 +662,38 @@ static int vg_extend_single_pv(struct volume_group *vg, char *pv_name,* - pp: parameters to pass to implicit pvcreate; if NULL, do not pvcreate * */ -int vg_extend (struct volume_group *vg,int pv_count,char **pv_names, +int vg_extend (struct volume_group *vg,int pv_count,const char *const *pv_names,struct pvcreate_params *pp) {int i; +char *pv_name;if (_vg_bad_status_bits (vg,RESIZEABLE_VG ))return 0 ;/* attach each pv */ for (i =0 ; i < pv_count; i++) { -unescape_colons_and_at_signs (pv_names[i],NULL ,NULL ); -if (!vg_extend_single_pv (vg, pv_names[i], pp)) - goto bad; +if (!(pv_name =dm_strdup (pv_names[i]))) { +log_error ("Failed to duplicate pv name %s." , pv_names[i]); +return 0 ; + } +unescape_colons_and_at_signs (pv_name,NULL ,NULL ); +if (!vg_extend_single_pv (vg, pv_name, pp)) { +log_error ("Unable to add physical volume '%s' to " +"volume group '%s'." , pv_name, vg->name); +dm_free (pv_name); +return 0 ; + } +dm_free (pv_name); }/* FIXME Decide whether to initialise and add new mdahs to format instance */ return 1 ; - - bad: -log_error ("Unable to add physical volume '%s' to " -"volume group '%s'." , pv_names[i], vg->name); -return 0 ; }/* FIXME: use this inside vgreduce_single? */ -int vg_reduce (struct volume_group *vg,char *pv_name) +int vg_reduce (struct volume_group *vg,const char *pv_name) {struct physical_volume *pv;struct pv_list *pvl;
@@ -1875,7 +1880,7 @@ int vgs_are_compatible(struct cmd_context *cmd __attribute__((unused)), {struct lv_list *lvl1, *lvl2;struct pv_list *pvl; -char *name1, *name2; +const char *name1, *name2;if (lvs_in_vg_activated (vg_from)) { log_error("Logical volumes in \"%s\" must be inactive",
lib/metadata/mirror.c +9 -9
@@ -1514,7 +1514,7 @@ struct dm_list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,return lvs; } -percent_t copy_percent (struct logical_volume *lv_mirr) +percent_t copy_percent (const struct logical_volume *lv_mirr) {uint32_t numerator =0u , denominator =0u ;struct lv_segment *seg;
@@ -1727,8 +1727,8 @@ static struct logical_volume *_set_up_mirror_log(struct cmd_context *cmd, int in_sync) {struct logical_volume *log_lv; -const char *suffix, *c; -char *lv_name; +const char *suffix, *lv_name; +char *tmp_name;size_t len;struct lv_segment *seg;
@@ -1747,21 +1747,21 @@ static struct logical_volume *_set_up_mirror_log(struct cmd_context *cmd, strstr(seg_lv(seg, 0)->name, MIRROR_SYNC_LAYER)) { lv_name = lv->name; suffix ="_mlogtmp_%d" ; - } else if ((c = strstr(lv->name, MIRROR_SYNC_LAYER))) { - len = c - lv->name +1 ; -if (!(lv_name =alloca (len)) || - !dm_snprintf (lv_name, len,"%s" , lv->name)) { + } else if ((lv_name = strstr(lv->name, MIRROR_SYNC_LAYER))) { + len = lv_name - lv->name +1 ; +if (!(tmp_name =alloca (len)) || + !dm_snprintf (tmp_name, len,"%s" , lv->name)) {log_error ("mirror log name allocation failed" );return 0 ; } + lv_name = tmp_name; suffix ="_mlog" ; } else { lv_name = lv->name; suffix ="_mlog" ; } -if (!(log_lv =_create_mirror_log (lv, ah, alloc, - (const char *) lv_name, suffix))) { +if (!(log_lv =_create_mirror_log (lv, ah, alloc, lv_name, suffix))) {log_error ("Failed to create mirror log." );return NULL ; }
lib/report/properties.c +1 -2
@@ -88,8 +88,7 @@ static int _not_implemented_set(void *obj, struct lvm_property_type *prop)static percent_t _copy_percent (const struct logical_volume *lv) {percent_t perc; -if (!lv_mirror_percent (lv->vg->cmd, (struct logical_volume *) lv, -0 , &perc,NULL )) +if (!lv_mirror_percent (lv->vg->cmd, lv,0 , &perc,NULL )) perc =PERCENT_INVALID ;return perc; }
lib/report/report.c +3 -3
@@ -613,7 +613,7 @@ static int _uuid_disp(struct dm_report *rh __attribute__((unused)), struct dm_po {char *repstr =NULL ; -if (!(repstr =id_format_and_copy (mem, (struct id *)data))) +if (!(repstr =id_format_and_copy (mem, data))) return_0;dm_report_field_set_value (field, repstr,NULL );
@@ -851,7 +851,7 @@ static int _copypercent_disp(struct dm_report *rh __attribute__((unused)),struct dm_report_field *field, const void *data, void *private __attribute__((unused))) { -struct logical_volume *lv = (struct logical_volume *) data; +const struct logical_volume *lv = (const struct logical_volume *) data;percent_t percent;uint64_t *sortval;char *repstr;
@@ -897,7 +897,7 @@ static struct format_instance _dummy_fid = {static struct volume_group _dummy_vg = { .fid = &_dummy_fid, - .name = (char *)"" , + .name ="" , .system_id = (char *)"" , .pvs = { &(_dummy_vg.pvs), &(_dummy_vg.pvs) }, .lvs = { &(_dummy_vg.lvs), &(_dummy_vg.lvs) },
liblvm/lvm_vg.c +2 -2
@@ -79,7 +79,7 @@ int lvm_vg_extend(vg_t vg, const char *device) }pvcreate_params_set_defaults (&pp); -if (!vg_extend (vg,1 , (char **) &device, &pp)) { +if (!vg_extend (vg,1 , &device, &pp)) {unlock_vg (vg->cmd,VG_ORPHANS );return -1 ; }
@@ -98,7 +98,7 @@ int lvm_vg_reduce(vg_t vg, const char *device)if (!vg_check_write_mode (vg))return -1 ; -if (!vg_reduce (vg, (char *)device)) +if (!vg_reduce (vg, device))return -1 ;return 0 ; }
tools/lvcreate.c +1 -1
@@ -31,7 +31,7 @@ static int _lvcreate_name_params(struct lvcreate_params *lp, {int argc = *pargc;char **argv = *pargv, *ptr; -char *vg_name; +const char *vg_name; lp->lv_name =arg_str_value (cmd, name_ARG,NULL );
tools/reporter.c +2 -2
@@ -61,7 +61,7 @@ static int _pvsegs_sub_single(struct cmd_context *cmd,struct volume_group _free_vg = { .cmd = cmd, - .name = (char *)"" , + .name ="" , };if (!(_free_vg.vgmem =dm_pool_create ("_free_vg" ,10240 )))
@@ -69,7 +69,7 @@ static int _pvsegs_sub_single(struct cmd_context *cmd,struct logical_volume _free_logical_volume = { .vg = vg ?: &_free_vg, - .name = (char *)"" , + .name ="" , .snapshot =NULL , .status =VISIBLE_LV , .major =-1 ,
tools/toollib.c +5 -5
@@ -28,7 +28,7 @@ const char *command_name(struct cmd_context *cmd)/* * Strip dev_dir if present */ -char *skip_dev_dir (struct cmd_context *cmd,const char *vg_name, +const char *skip_dev_dir (struct cmd_context *cmd,const char *vg_name,unsigned *dev_dir_found) {const char *dmdir =dm_dir ();
@@ -54,7 +54,7 @@ char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name, *layer) {log_error ("skip_dev_dir: Couldn't split up device name %s" , vg_name); -return (char *) vg_name; +return vg_name; } vglv_sz =strlen (vgname) +strlen (lvname) +2 ; if (!(vglv = dm_pool_alloc(cmd->mem, vglv_sz)) ||
@@ -62,7 +62,7 @@ char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name, *lvname ? "/" : "", lvname) < 0) {log_error ("vg/lv string alloc failed" ); -return (char *) vg_name; +return vg_name; }return vglv; }
@@ -76,7 +76,7 @@ char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name, }else if (dev_dir_found) *dev_dir_found =0 ; -return (char *) vg_name; +return vg_name; }/*
@@ -898,7 +898,7 @@ const char *extract_vgname(struct cmd_context *cmd, const char *lv_name)*/ char *default_vgname (struct cmd_context *cmd) { -char *vg_path; +const char *vg_path;/* Take default VG from environment? */ vg_path =getenv ("LVM_VG_NAME" );
tools/toollib.h +2 -2
@@ -84,8 +84,8 @@ int process_each_lv_in_vg(struct cmd_context *cmd,char *default_vgname (struct cmd_context *cmd);const char *extract_vgname (struct cmd_context *cmd,const char *lv_name); -char *skip_dev_dir (struct cmd_context *cmd,const char *vg_name, -unsigned *dev_dir_found); +const char *skip_dev_dir (struct cmd_context *cmd,const char *vg_name, +unsigned *dev_dir_found);/* * Builds a list of pv's from the names in argv. Used in
tools/vgcfgrestore.c +1 -1
@@ -17,7 +17,7 @@int vgcfgrestore (struct cmd_context *cmd,int argc,char **argv) { -char *vg_name =NULL ; +const char *vg_name =NULL ;if (argc ==1 ) { vg_name =skip_dev_dir (cmd, argv[0 ],NULL );
tools/vgcreate.c +1 -1
@@ -74,7 +74,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv) }/* attach the pv's */ -if (!vg_extend (vg, argc, argv, &pp)) +if (!vg_extend (vg, argc, (const char *const *)argv, &pp)) goto_bad;if (vp_new.max_lv != vg->max_lv)
tools/vgextend.c +2 -2
@@ -40,7 +40,7 @@ static int _restore_pv(struct volume_group *vg, char *pv_name)int vgextend (struct cmd_context *cmd,int argc,char **argv) { -char *vg_name; +const char *vg_name;struct volume_group *vg =NULL ;int r =ECMD_FAILED ;struct pvcreate_params pp;
@@ -107,7 +107,7 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv) }/* extend vg */ -if (!vg_extend (vg, argc, argv, &pp)) +if (!vg_extend (vg, argc, (const char *const *)argv, &pp)) goto_bad; if (arg_count(cmd, metadataignore_ARG) &&
tools/vgmerge.c +1 -1
@@ -163,7 +163,7 @@ bad:int vgmerge (struct cmd_context *cmd,int argc,char **argv) { -char *vg_name_to, *vg_name_from; +const char *vg_name_to, *vg_name_from;int opt =0 ;int ret =0 , ret_max =0 ;
tools/vgreduce.c +1 -1
@@ -457,7 +457,7 @@ bad:int vgreduce (struct cmd_context *cmd,int argc,char **argv) {struct volume_group *vg; -char *vg_name; +const char *vg_name;int ret =ECMD_FAILED ;int fixed =1 ;int repairing =arg_count (cmd, removemissing_ARG);
tools/vgrename.c +1 -1
@@ -63,7 +63,7 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,int found_id =0 ;struct dm_list *vgids;struct str_list *sl; -char *vg_name_new; +const char *vg_name_new;const char *vgid =NULL , *vg_name, *vg_name_old;char old_path[NAME_LEN ], new_path[NAME_LEN ];struct volume_group *vg =NULL ;
tools/vgsplit.c +1 -1
@@ -281,7 +281,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv) {struct vgcreate_params vp_new;struct vgcreate_params vp_def; -char *vg_name_from, *vg_name_to; +const char *vg_name_from, *vg_name_to;struct volume_group *vg_to =NULL , *vg_from =NULL ;int opt;int existing_vg =0 ;
Signature · 1 line
1.7.3.5
PATCH 20/24 Const fixing
Quoted 8 lines · Zdenek Kabelac
Fixing some of the remaining const warnings - major change:
int vg_extend(struct
volume_group*vg, intpv_count, const char *const*pv_names,Change is needed - as lvm2api seems to expect const behaviour here. So
vg_extend()is doing local strdup for unescaping.
skip_dev_dirreturn const char* from const char*vg_name.
Only C language allows us to have properly defined const variables :-)
<add mornfall's signature here>
If it helps something, ACK.
Milan
PATCH 21/24 Testing: remove -q from grep
In reply to Zdenek Kabelacto avoid problems with pipe breaking
--- test/t-mirror-names.sh | 2 +- test/t-mirror-vgreduce-removemissing.sh | 2 +- test/t-pvcreate-operation.sh | 2 +- test/t-snapshot-merge.sh | 9 +++++---- test/t-vgcreate-usage.sh | 2 +- test/t-vgextend-usage.sh | 2 +- 6 files changed, 10 insertions(+), 9 deletions(-)
test/t-mirror-names.sh +1 -1
@@ -27,7 +27,7 @@ lv_devices_() { sed 's/ //g' | sed 's/,/ /g') for d in $devs; do - (echo $devices | grep -q $d) || return 1 + (echo $devices | grep $d >/dev/null) || return 1 devices=$(echo $devices | sed "s/$d//") done
test/t-mirror-vgreduce-removemissing.sh +1 -1
@@ -65,7 +65,7 @@ lv_is_linear_() { echo "Check if $1 is linear LV (i.e. not a mirror)" lvs -o stripes,attr --noheadings $vg/$1 | sed 's/ //g' - lvs -o stripes,attr --noheadings $vg/$1 | sed 's/ //g' | grep -q '^1-' + lvs -o stripes,attr --noheadings $vg/$1 | sed 's/ //g' | grep '^1-' >/dev/null } rest_pvs_()
test/t-pvcreate-operation.sh +1 -1
@@ -82,7 +82,7 @@ for i in 0 1 2 3 do # pvcreate (lvm2) succeeds writing LVM label at sector $i pvcreate --labelsector $i $dev1 - dd if=$dev1 bs=512 skip=$i count=1 2>/dev/null | strings | grep -q LABELONE; + dd if=$dev1 bs=512 skip=$i count=1 2>/dev/null | strings | grep LABELONE >/dev/null pvremove -f $dev1 done
test/t-snapshot-merge.sh +5 -4
@@ -47,7 +47,7 @@ aux prepare_vg 1 100 # test full merge of a single LV setup_merge $vg $lv1 # now that snapshot LV is created: test if snapshot-merge target is available -$(dmsetup targets | grep -q snapshot-merge) || exit 200 +$(dmsetup targets | grep snapshot-merge >/dev/null) || exit 200 lvs -a # make sure lvconvert --merge requires explicit LV listing not lvconvert --merge 2>err
@@ -73,11 +73,12 @@ lvconvert --merge $vg/$(snap_lv_name_ $lv1) lvchange --refresh $vg/$lv1 umount test_mnt rm -r test_mnt -dmsetup table ${vg}-${lv1} | grep -q " snapshot-origin " +dmsetup table ${vg}-${lv1} | grep " snapshot-origin " + # -- refresh LV to start merge (now that FS is unmounted), # an active merge uses the 'snapshot-merge' target lvchange --refresh $vg/$lv1 -dmsetup table ${vg}-${lv1} | grep -q " snapshot-merge " +dmsetup table ${vg}-${lv1} | grep " snapshot-merge " # -- don't care if merge is still active; lvremove at this point # may test stopping an active merge lvremove -f $vg/$lv1
@@ -96,7 +97,7 @@ lvconvert --merge $vg/$(snap_lv_name_ $lv1) lvchange --refresh $vg/$lv1 umount test_mnt rm -r test_mnt -dmsetup table ${vg}-${lv1} | grep -q " snapshot-origin " +dmsetup table ${vg}-${lv1} | grep " snapshot-origin " >/dev/null lvremove -f $vg/$lv1
test/t-vgcreate-usage.sh +1 -1
@@ -102,7 +102,7 @@ for i in 0 1 2 3 do # vgcreate (lvm2) succeeds writing LVM label at sector $i vgcreate -c n --labelsector $i $vg $dev1 - dd if=$dev1 bs=512 skip=$i count=1 2>/dev/null | strings | grep -q LABELONE; + dd if=$dev1 bs=512 skip=$i count=1 2>/dev/null | strings | grep LABELONE >/dev/null vgremove -f $vg pvremove -f $dev1 done
test/t-vgextend-usage.sh +1 -1
@@ -46,7 +46,7 @@ for i in 0 1 2 3 do # vgcreate (lvm2) succeeds writing LVM label at sector $i vgextend --labelsector $i $vg $dev1 - dd if=$dev1 bs=512 skip=$i count=1 2>/dev/null | strings | grep -q LABELONE; + dd if=$dev1 bs=512 skip=$i count=1 2>/dev/null | strings | grep LABELONE >/dev/null vgreduce $vg $dev1 pvremove -f $dev1 done
Signature · 1 line
1.7.3.5
PATCH 21/24 Testing: remove -q from grep
Quoted 1 line · Zdenek Kabelac
to avoid problems with pipe breaking
yes, calling pipe fitter is quite expensive;-)
ACK.
Milan
PATCH 22/24 Testing: Try to prioritize locking process
In reply to Zdenek KabelacThis is rather 'hotfix' - it will run lvm command with lower prioritu - thus flock process should exit sooner before it's checked by 'ps' for it's existance.
Think about better way how to test this.
--- test/t-lock-blocking.sh | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
test/t-lock-blocking.sh +5 -5
@@ -20,17 +20,17 @@ vgcreate $vg $dev1 $dev2 # if wait_for_locks set, vgremove should wait for orphan lock # flock process should have exited by the time first vgremove completes -flock -w 5 $TESTDIR/var/lock/lvm/P_orphans -c "sleep 10" & +flock -w 4 $TESTDIR/var/lock/lvm/P_orphans -c "sleep 6" & flock_pid=`jobs -p` -vgremove --config 'global { wait_for_locks = 1 }' $vg -not vgremove --config 'global { wait_for_locks = 1 }' $vg +nice vgremove -vvvv --config 'global { wait_for_locks = 1 }' $vg +nice not vgremove -vvvv --config 'global { wait_for_locks = 1 }' $vg not ps $flock_pid # finished # if wait_for_locks not set, vgremove should fail on non-blocking lock # we must wait for flock process at the end - vgremove won't wait vgcreate $vg $dev1 $dev2 -flock -w 5 $TESTDIR/var/lock/lvm/P_orphans -c "sleep 10" & +flock -w 4 $TESTDIR/var/lock/lvm/P_orphans -c "sleep 6" & flock_pid=`jobs -p` -not vgremove --config 'global { wait_for_locks = 0 }' $vg +nice not vgremove --config 'global { wait_for_locks = 0 }' $vg ps $flock_pid # still running kill $flock_pid
Signature · 1 line
1.7.3.5
PATCH 23/24 Extend lvm2api with lvm_lv_rename
In reply to Zdenek KabelacAdd support for LV rename
Now useful now mainly for testing various combination of ops stacking. (following patch).
--- liblvm/lvm2app.h | 16 ++++++++++++++++ liblvm/lvm_lv.c | 10 ++++++++++ 2 files changed, 26 insertions(+), 0 deletions(-)
liblvm/lvm2app.h +16 -0
@@ -1321,6 +1321,22 @@ int lvm_lv_remove_tag(lv_t lv, const char *tag);*/ struct dm_list *lvm_lv_get_tags (const lv_t lv); +/** +* Rename logical volume to new_name. +* +* \memberof lv_t +* +* \param lv +* Logical volume handle. +* +* \param new_name +* New name of logical volume. +* +* \return +* 0 (success) or -1 (failure). +* +*/ +int lvm_lv_rename (lv_t lv,const char *new_name);/** * Resize logical volume to new_size bytes.
liblvm/lvm_lv.c +10 -0
@@ -282,6 +282,16 @@ lv_t lvm_lv_from_uuid(vg_t vg, const char *uuid) }return NULL ; } + +int lvm_lv_rename (lv_t lv,const char *new_name) +{ +if (!lv_rename (lv->vg->cmd, lv, new_name)) { +log_verbose ("LV Rename failed." ); +return -1 ; + } +return 0 ; +} +int lvm_lv_resize (const lv_t lv,uint64_t new_size) {/* FIXME: add lv resize code here */
Signature · 1 line
1.7.3.5
PATCH 24/24 Testing lvm_lv_rename
In reply to Zdenek KabelacTest stacking of rename operation within one udev transaction.
--- test/api/Makefile.in | 2 +- test/api/lvtest.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/api/lvtest.sh | 21 ++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletions(-) create mode 100644 test/api/lvtest.c create mode 100644 test/api/lvtest.sh
test/api/Makefile.in +1 -1
@@ -24,7 +24,7 @@ test_SOURCES = test.c wrapper_SOURCES = test.c INCLUDES += -I../../include -UNIT = vgtest.t percent.t +UNIT = vgtest.t percent.t lvtest.t LVMLIBS = @LVM2APP_LIB@ -ldevmapper DEPLIBS = $(top_builddir)/liblvm/liblvm2app.so $(top_builddir)/libdm/libdevmapper.so
test/api/lvtest.c new file +64 -0
64 lines not on this page · raw message
test/api/lvtest.sh new file +21 -0
@@ -0,0 +1,21 @@ +# +# Copyright (C) 2011 Red Hat, Inc. All rights reserved. +# +# This file is part of LVM2. +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions +# of the GNU General Public License v.2. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +. lib/test + +aux prepare_vg 1 + +lvcreate -n test -l 5 $vg +aux apitest lvtest $vg + +check lv_field $vg/test lv_name test
Signature · 1 line
1.7.3.5