mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-10-30 20:23:49 +03:00 
			
		
		
		
	The new label_scan() function reads a large buffer of data from the start of the disk, and saves it so that multiple structs can be read from it. Previously, only the label_header was read from this buffer, and the code which needed data structures that immediately followed the label_header would read those from disk separately. This created a large number of small, unnecessary disk reads. In each place that the two read paths (label_scan and vg_read) need to read data from disk, first check if that data is already available from the label_read_data buffer, and if so just copy it from the buffer instead of reading from disk. Code changes ------------ - passing the label_read_data struct down through both read paths to make it available. - before every disk read, first check if the location and size of the desired piece of data exists fully in the label_read_data buffer, and if so copy it from there. Otherwise, use the existing code to read the data from disk. - adding some log_error messages on existing error paths that were already being updated for the reasons above. - using similar naming for parallel functions on the two parallel read paths that are being updated above. label_scan path calls: read_metadata_location_summary, text_read_metadata_summary vg_read path calls: read_metadata_location_vg, text_read_metadata_file Previously, those functions were named: label_scan path calls: vgname_from_mda, text_vgsummary_import vg_read path calls: _find_vg_rlocn, text_vg_import_fd I/O changes ----------- In the label_scan path, the following data is either copied from label_read_data or read from disk for each PV: - label_header and pv_header - mda_header (in _raw_read_mda_header) - vg metadata name (in read_metadata_location_summary) - vg metadata (in config_file_read_fd) Total of 4 reads per PV in the label_scan path. In the vg_read path, the following data is either copied from label_read_data or read from disk for each PV: - mda_header (in _raw_read_mda_header) - vg metadata name (in read_metadata_location_vg) - vg metadata (in config_file_read_fd) Total of 3 reads per PV in the vg_read path. For a common read/reporting command, each PV will be: - read by the command's initial lvmcache_label_scan() - read by lvmcache_label_rescan_vg() at the start of vg_read() - read by vg_read() Previously, this would cause 11 synchronous disk reads per PV: 4 from lvmcache_label_scan(), 4 from lvmcache_label_rescan_vg() and 3 from vg_read(). With this commit's optimization, there are now 2 async disk reads per PV: 1 from lvmcache_label_scan() and 1 from lvmcache_label_rescan_vg(). When a second mda is used on a PV, it is located at the end of the PV. This second mda and copy of metadata will not be found in the label_read_data buffer, and will always require separate disk reads.
		
			
				
	
	
		
			128 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
 | |
|  * Copyright (C) 2004-2007 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 Lesser General Public License v.2.1.
 | |
|  *
 | |
|  * You should have received a copy of the GNU Lesser General Public License
 | |
|  * along with this program; if not, write to the Free Software Foundation,
 | |
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | |
|  */
 | |
| 
 | |
| #ifndef _LVM_LABEL_H
 | |
| #define _LVM_LABEL_H
 | |
| 
 | |
| #include "uuid.h"
 | |
| #include "device.h"
 | |
| #include "toolcontext.h"
 | |
| 
 | |
| #define LABEL_ID "LABELONE"
 | |
| #define LABEL_SIZE SECTOR_SIZE	/* Think very carefully before changing this */
 | |
| #define LABEL_SCAN_SECTORS 4L
 | |
| #define LABEL_SCAN_SIZE (LABEL_SCAN_SECTORS << SECTOR_SHIFT)
 | |
| 
 | |
| struct labeller;
 | |
| 
 | |
| void allow_reads_with_lvmetad(void);
 | |
| 
 | |
| struct label_read_data {
 | |
| 	struct dev_async_io *aio;
 | |
| 	char *buf; /* points to aio->buf */
 | |
| 	struct device *dev;
 | |
| 	struct dm_list list;
 | |
| 	int buf_len; /* same as aio->buf_len */
 | |
| 	int result; /* same as aio->result */
 | |
| 	int try_sync;
 | |
| 	int process_done;
 | |
| };
 | |
| 
 | |
| /* On disk - 32 bytes */
 | |
| struct label_header {
 | |
| 	int8_t id[8];		/* LABELONE */
 | |
| 	uint64_t sector_xl;	/* Sector number of this label */
 | |
| 	uint32_t crc_xl;	/* From next field to end of sector */
 | |
| 	uint32_t offset_xl;	/* Offset from start of struct to contents */
 | |
| 	int8_t type[8];		/* LVM2 001 */
 | |
| } __attribute__ ((packed));
 | |
| 
 | |
| /* In core */
 | |
| struct label {
 | |
| 	char type[8];
 | |
| 	uint64_t sector;
 | |
| 	struct labeller *labeller;
 | |
| 	struct device *dev;
 | |
| 	void *info;
 | |
| };
 | |
| 
 | |
| struct labeller;
 | |
| 
 | |
| struct label_ops {
 | |
| 	/*
 | |
| 	 * Is the device labelled with this format ?
 | |
| 	 */
 | |
| 	int (*can_handle) (struct labeller * l, void *buf, uint64_t sector);
 | |
| 
 | |
| 	/*
 | |
| 	 * Write a label to a volume.
 | |
| 	 */
 | |
| 	int (*write) (struct label * label, void *buf);
 | |
| 
 | |
| 	/*
 | |
| 	 * Read a label from a volume.
 | |
| 	 */
 | |
| 	int (*read) (struct labeller * l, struct device * dev,
 | |
| 		     void *label_buf,
 | |
| 		     struct label_read_data *ld, struct label ** label);
 | |
| 
 | |
| 	/*
 | |
| 	 * Additional consistency checks for the paranoid.
 | |
| 	 */
 | |
| 	int (*verify) (struct labeller * l, void *buf, uint64_t sector);
 | |
| 
 | |
| 	/*
 | |
| 	 * Populate label_type etc.
 | |
| 	 */
 | |
| 	int (*initialise_label) (struct labeller * l, struct label * label);
 | |
| 
 | |
| 	/*
 | |
| 	 * Destroy a previously read label.
 | |
| 	 */
 | |
| 	void (*destroy_label) (struct labeller * l, struct label * label);
 | |
| 
 | |
| 	/*
 | |
| 	 * Destructor.
 | |
| 	 */
 | |
| 	void (*destroy) (struct labeller * l);
 | |
| };
 | |
| 
 | |
| struct labeller {
 | |
| 	struct label_ops *ops;
 | |
| 	const struct format_type *fmt;
 | |
| };
 | |
| 
 | |
| int label_init(void);
 | |
| void label_exit(void);
 | |
| 
 | |
| int label_register_handler(struct labeller *handler);
 | |
| 
 | |
| struct labeller *label_get_handler(const char *name);
 | |
| 
 | |
| int label_remove(struct device *dev);
 | |
| int label_read(struct device *dev, struct label **label, uint64_t scan_sector);
 | |
| int label_write(struct device *dev, struct label *label);
 | |
| int label_verify(struct device *dev);
 | |
| struct label *label_create(struct labeller *labeller);
 | |
| void label_destroy(struct label *label);
 | |
| 
 | |
| int label_scan_force(struct cmd_context *cmd);
 | |
| int label_scan(struct cmd_context *cmd);
 | |
| int label_scan_devs(struct cmd_context *cmd, struct dm_list *devs);
 | |
| struct label_read_data *get_label_read_data(struct cmd_context *cmd, struct device *dev);
 | |
| void label_scan_destroy(struct cmd_context *cmd);
 | |
| 
 | |
| #endif
 |