1
0
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:
Mike Snitzer 2011-04-12 21:59:01 +00:00
parent 116362d11b
commit fdc8670327
8 changed files with 119 additions and 0 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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