mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-06 17:18:29 +03:00
Add "devices/issue_discards" to lvm.conf.
Issue discards on lvremove if enabled and both storage and kernel have support.
This commit is contained in:
parent
116362d11b
commit
fdc8670327
@ -1,5 +1,7 @@
|
||||
Version 2.02.85 -
|
||||
===================================
|
||||
Add "devices/issue_discards" to lvm.conf.
|
||||
Issue discards on lvremove if enabled and both storage and kernel have support.
|
||||
Fix incorrect tests for dm_snprintf() failure.
|
||||
Fix some unmatching sign comparation gcc warnings in the code.
|
||||
Allow lv_extend() to work on zero length intrinsically layered LVs.
|
||||
|
@ -151,6 +151,14 @@ devices {
|
||||
# Example: Ignore devices smaller than 2MB (i.e. floppy drives).
|
||||
# pv_min_size = 2048
|
||||
pv_min_size = 512
|
||||
|
||||
# Issue discards to an LV's underlying PV(s) when the LV is removed.
|
||||
# Discards inform the storage that a region is no longer in use. If set
|
||||
# to 1, discards will only be issued if both the storage and kernel provide
|
||||
# support. Not all storage will support or benefit from discards but SSDs
|
||||
# or thinly provisioned LUNs generally do.
|
||||
# 1 enables; 0 disables.
|
||||
issue_discards = 0
|
||||
}
|
||||
|
||||
# This section allows you to configure the way in which LVM selects
|
||||
|
@ -37,6 +37,7 @@
|
||||
#define DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID 1
|
||||
#define DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION 1
|
||||
#define DEFAULT_DATA_ALIGNMENT_DETECTION 1
|
||||
#define DEFAULT_ISSUE_DISCARDS 0
|
||||
|
||||
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
|
||||
#define DEFAULT_FALLBACK_TO_LOCAL_LOCKING 1
|
||||
|
@ -36,6 +36,9 @@
|
||||
# ifndef BLKGETSIZE64 /* fs.h out-of-date */
|
||||
# define BLKGETSIZE64 _IOR(0x12, 114, size_t)
|
||||
# endif /* BLKGETSIZE64 */
|
||||
# ifndef BLKDISCARD
|
||||
# define BLKDISCARD _IO(0x12,119)
|
||||
# endif
|
||||
#else
|
||||
# include <sys/disk.h>
|
||||
# define BLKBSZGET DKIOCGETBLOCKSIZE
|
||||
@ -301,6 +304,33 @@ static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64_t size_bytes)
|
||||
{
|
||||
uint64_t discard_range[2];
|
||||
|
||||
if (!dev_open(dev))
|
||||
return_0;
|
||||
|
||||
discard_range[0] = offset_bytes;
|
||||
discard_range[1] = size_bytes;
|
||||
|
||||
log_debug("Discarding %" PRIu64 " bytes offset %" PRIu64 " bytes on %s.",
|
||||
size_bytes, offset_bytes, dev_name(dev));
|
||||
if (ioctl(dev->fd, BLKDISCARD, &discard_range) < 0) {
|
||||
log_error("%s: BLKDISCARD ioctl at offset %" PRIu64 " size %" PRIu64 " failed: %s.",
|
||||
dev_name(dev), offset_bytes, size_bytes, strerror(errno));
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
/* It doesn't matter if discard failed, so return success. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
* Public functions
|
||||
*---------------------------------------------------------------*/
|
||||
@ -329,6 +359,17 @@ int dev_get_read_ahead(struct device *dev, uint32_t *read_ahead)
|
||||
return _dev_read_ahead_dev(dev, read_ahead);
|
||||
}
|
||||
|
||||
int dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64_t size_bytes)
|
||||
{
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
||||
if (dev->flags & DEV_REGULAR)
|
||||
return 1;
|
||||
|
||||
return _dev_discard_blocks(dev, offset_bytes, size_bytes);
|
||||
}
|
||||
|
||||
/* FIXME Unused
|
||||
int dev_get_sectsize(struct device *dev, uint32_t *size)
|
||||
{
|
||||
|
@ -455,6 +455,20 @@ unsigned long dev_optimal_io_size(const char *sysfs_dir,
|
||||
sysfs_dir, dev);
|
||||
}
|
||||
|
||||
unsigned long dev_discard_max_bytes(const char *sysfs_dir,
|
||||
struct device *dev)
|
||||
{
|
||||
return _dev_topology_attribute("queue/discard_max_bytes",
|
||||
sysfs_dir, dev);
|
||||
}
|
||||
|
||||
unsigned long dev_discard_granularity(const char *sysfs_dir,
|
||||
struct device *dev)
|
||||
{
|
||||
return _dev_topology_attribute("queue/discard_granularity",
|
||||
sysfs_dir, dev);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int get_primary_dev(const char *sysfs_dir,
|
||||
@ -481,4 +495,16 @@ unsigned long dev_optimal_io_size(const char *sysfs_dir,
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
unsigned long dev_discard_max_bytes(const char *sysfs_dir,
|
||||
struct device *dev)
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
unsigned long dev_discard_granularity(const char *sysfs_dir,
|
||||
struct device *dev)
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -68,6 +68,7 @@ struct device_area {
|
||||
int dev_get_size(const struct device *dev, uint64_t *size);
|
||||
int dev_get_sectsize(struct device *dev, uint32_t *size);
|
||||
int dev_get_read_ahead(struct device *dev, uint32_t *read_ahead);
|
||||
int dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64_t size_bytes);
|
||||
|
||||
/* Use quiet version if device number could change e.g. when opening LV */
|
||||
int dev_open(struct device *dev);
|
||||
@ -115,4 +116,10 @@ unsigned long dev_minimum_io_size(const char *sysfs_dir,
|
||||
unsigned long dev_optimal_io_size(const char *sysfs_dir,
|
||||
struct device *dev);
|
||||
|
||||
unsigned long dev_discard_max_bytes(const char *sysfs_dir,
|
||||
struct device *dev);
|
||||
|
||||
unsigned long dev_discard_granularity(const char *sysfs_dir,
|
||||
struct device *dev);
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "archiver.h"
|
||||
#include "locking.h"
|
||||
#include "lvmcache.h"
|
||||
#include "defaults.h"
|
||||
|
||||
static struct pv_segment *_alloc_pv_segment(struct dm_pool *mem,
|
||||
struct physical_volume *pv,
|
||||
@ -190,12 +191,38 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv,
|
||||
|
||||
int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction)
|
||||
{
|
||||
uint64_t discard_offset;
|
||||
uint64_t pe_start = peg->pv->pe_start;
|
||||
uint64_t discard_area_reduction = area_reduction;
|
||||
|
||||
if (!peg->lvseg) {
|
||||
log_error("release_pv_segment with unallocated segment: "
|
||||
"%s PE %" PRIu32, pv_dev_name(peg->pv), peg->pe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only issue discards if enabled in lvm.conf and both
|
||||
* the device and kernel (>= 2.6.35) supports discards.
|
||||
*/
|
||||
if (find_config_tree_bool(peg->pv->fmt->cmd,
|
||||
"devices/issue_discards", DEFAULT_ISSUE_DISCARDS) &&
|
||||
dev_discard_max_bytes(peg->pv->fmt->cmd->sysfs_dir, peg->pv->dev) &&
|
||||
dev_discard_granularity(peg->pv->fmt->cmd->sysfs_dir, peg->pv->dev)) {
|
||||
if (!pe_start) {
|
||||
/* skip the first extent */
|
||||
pe_start = peg->pv->vg->extent_size;
|
||||
discard_area_reduction--;
|
||||
}
|
||||
discard_offset = peg->pe + peg->lvseg->area_len - area_reduction;
|
||||
discard_offset = (discard_offset * peg->pv->vg->extent_size) + pe_start;
|
||||
log_debug("Discarding %" PRIu32 " extents offset %" PRIu64 " sectors on %s.",
|
||||
discard_area_reduction, discard_offset, dev_name(peg->pv->dev));
|
||||
if (!dev_discard_blocks(peg->pv->dev, discard_offset << SECTOR_SHIFT,
|
||||
discard_area_reduction * peg->pv->vg->extent_size * SECTOR_SIZE))
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (peg->lvseg->area_len == area_reduction) {
|
||||
peg->pv->pe_alloc_count -= area_reduction;
|
||||
peg->lvseg->lv->vg->free_count += area_reduction;
|
||||
|
@ -180,6 +180,13 @@ ignore devices smaller than 2MB (i.e. floppy drives):
|
||||
.IP
|
||||
pv_min_size = 2048
|
||||
.IP
|
||||
\fBissue_discards\fP \(em
|
||||
Issue discards to an LV's underlying PV(s) when the LV is removed. Discards
|
||||
inform the storage that a region is no longer in use. If set to 1, discards will
|
||||
only be issued if both the storage and kernel provide support. Not all storage
|
||||
will support or benefit from discards but SSDs or thinly provisioned LUNs
|
||||
generally do.
|
||||
.IP
|
||||
.TP
|
||||
\fBallocation\fP \(em Space allocation policies
|
||||
.IP
|
||||
|
Loading…
Reference in New Issue
Block a user