Commit 4b0070f6 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-26029: Implement my_test_if_thinly_provisioned() for ScaleFlux

This is based on code that was contributed by Ning Zheng and Ray Kuan
from ScaleFlux.
parent 30edd554
......@@ -183,11 +183,12 @@ extern BOOL my_obtain_privilege(LPCSTR lpPrivilege);
#endif
void my_init_atomic_write(void);
#define my_test_if_thinly_provisioned(A) 0
#ifdef __linux__
my_bool my_test_if_atomic_write(File handle, int pagesize);
my_bool my_test_if_thinly_provisioned(File handle);
#else
# define my_test_if_atomic_write(A, B) 0
# define my_test_if_thinly_provisioned(A) 0
#endif /* __linux__ */
extern my_bool my_may_have_atomic_write;
......
......@@ -19,8 +19,9 @@ my_bool my_may_have_atomic_write= IF_WIN(1,0);
#ifdef __linux__
my_bool has_shannon_atomic_write= 0, has_fusion_io_atomic_write= 0,
has_sfx_atomic_write= 0;
my_bool has_shannon_atomic_write, has_fusion_io_atomic_write,
has_sfx_atomic_write;
my_bool has_sfx_card;
#include <sys/ioctl.h>
......@@ -225,7 +226,7 @@ static my_bool shannon_dev_has_atomic_write(struct shannon_dev *dev,
@return TRUE Atomic write supported
@notes
This is called only at first open of a file. In this case it's doesn't
This is called only at first open of a file. In this case it doesn't
matter so much that we loop over all cards.
We update the atomic size on first access.
*/
......@@ -264,15 +265,26 @@ static my_bool shannon_has_atomic_write(File file, int page_size)
ScaleFlux
************************************************************************/
#define SFX_GET_ATOMIC_SIZE _IO('N', 0x244)
#define SFX_MAX_DEVICES 32
#define SFX_NO_ATOMIC_SIZE_YET -2
#define SFX_GET_ATOMIC_SIZE _IOR('N', 0x243, int)
#define SFX_MAX_DEVICES (32)
#define SFX_UNKNOWN_ATOMIC_WRITE_YET (-2)
#define SFX_MAX_ATOMIC_SIZE (256 * 1024)
#define SFX_GET_SPACE_RATIO _IO('N', 0x244)
#define SFX_UNKNOWN_PUNCH_HOLE_YET (-3)
/**
Threshold for logical_space / physical_space
No less than the threshold means we can disable hole punching
*/
#define SFX_DISABLE_PUNCH_HOLE_RATIO (2)
struct sfx_dev
{
char dev_name[32];
dev_t st_dev;
int atomic_size;
int atomic_write;
int disable_punch_hole;
};
static struct sfx_dev sfx_devices[SFX_MAX_DEVICES + 1];
......@@ -280,7 +292,8 @@ static struct sfx_dev sfx_devices[SFX_MAX_DEVICES + 1];
/**
Check if the system has a ScaleFlux card
If card exists, record device numbers to allow us to later check if
a given file is on this device.
a given file is on this device
Variables for atomic_write and disable_punch_hole will be initialized
@return TRUE Card exists
*/
......@@ -303,38 +316,41 @@ static my_bool test_if_sfx_card_exists()
The atomic size will be checked on first access. This is needed
as a normal user can't open the /dev/sfdvXn1 file
*/
sfx_devices[sfx_found_devices].atomic_size = SFX_NO_ATOMIC_SIZE_YET;
sfx_devices[sfx_found_devices].atomic_write= SFX_UNKNOWN_ATOMIC_WRITE_YET;
sfx_devices[sfx_found_devices].disable_punch_hole=
SFX_UNKNOWN_PUNCH_HOLE_YET;
if (++sfx_found_devices == SFX_MAX_DEVICES)
goto end;
}
end:
sfx_devices[sfx_found_devices].st_dev= 0;
has_sfx_card = (sfx_found_devices > 0);
return sfx_found_devices > 0;
}
static my_bool sfx_dev_has_atomic_write(struct sfx_dev *dev,
int page_size)
{
if (dev->atomic_size == SFX_NO_ATOMIC_SIZE_YET)
int result= -1, max_atomic_size= SFX_MAX_ATOMIC_SIZE;
if (dev->atomic_write == SFX_UNKNOWN_ATOMIC_WRITE_YET)
{
int fd= open(dev->dev_name, 0);
if (fd < 0)
{
fprintf(stderr, "Unable to determine if atomic writes are supported:"
" open(\"%s\"): %m\n", dev->dev_name);
dev->atomic_size= 0; /* Don't try again */
}
else
{
dev->atomic_size= ioctl(fd, SFX_GET_ATOMIC_SIZE);
result= ioctl(fd, SFX_GET_ATOMIC_SIZE, &max_atomic_size);
close(fd);
}
dev->atomic_write= result == 0 && page_size <= max_atomic_size;
}
return (page_size <= dev->atomic_size);
return dev->atomic_write;
}
/**
Check if a file is on a ScaleFlux device and that it supports atomic_write
@param[in] file OS file handle
......@@ -342,7 +358,7 @@ static my_bool sfx_dev_has_atomic_write(struct sfx_dev *dev,
@return TRUE Atomic write supported
@notes
This is called only at first open of a file. In this case it's doesn't
This is called only at first open of a file. In this case it doesn't
matter so much that we loop over all cards.
We update the atomic size on first access.
*/
......@@ -358,12 +374,63 @@ static my_bool sfx_has_atomic_write(File file, int page_size)
return sfx_dev_has_atomic_write(dev, page_size);
return 0;
}
static my_bool sfx_dev_could_disable_punch_hole(struct sfx_dev *dev, File file)
{
int result = 0;
if (dev->disable_punch_hole == SFX_UNKNOWN_PUNCH_HOLE_YET)
{
int fd= open(dev->dev_name, 0);
if (fd < 0)
{
fprintf(stderr, "Unable to determine if thin provisioning is used:"
" open(\"%s\"): %m\n", dev->dev_name);
dev->disable_punch_hole= 0; /* Don't try again */
return FALSE;
}
/*
Ratio left-shifts 8 (multiplies 256) inside the ioctl;
will also add 1 to guarantee a round-up integer.
*/
result= ioctl(fd, SFX_GET_SPACE_RATIO);
result+= 1;
dev->disable_punch_hole= (result >= (((double)SFX_DISABLE_PUNCH_HOLE_RATIO) * 256));
}
return dev->disable_punch_hole;
}
/**
Check if a file is on a ScaleFlux device and whether it is possible to
disable hole punch.
@param[in] file OS file handle
@return TRUE Could disable hole punch
@notes
This is called only at first open of a file. In this case it's doesn't
matter so much that we loop over all cards
*/
static my_bool sfx_could_disable_punch_hole(File file)
{
struct sfx_dev *dev;
struct stat stat_buff;
if (fstat(file, &stat_buff) == 0)
for (dev = sfx_devices; dev->st_dev; dev++)
if (SAME_DEV(stat_buff.st_dev, dev->st_dev))
return sfx_dev_could_disable_punch_hole(dev, file);
return 0;
}
/***********************************************************************
Generic atomic write code
************************************************************************/
/*
Initialize automic write sub systems.
/**
Initialize the atomic write subsystem.
Checks if we have any devices that supports atomic write
*/
......@@ -418,6 +485,22 @@ my_bool my_test_if_atomic_write(File handle, int page_size)
return 0;
}
/**
Check if a file resides on thinly provisioned storage.
@return FALSE File cannot disable hole punch
TRUE File could disable hole punch
*/
my_bool my_test_if_thinly_provisioned(File handle)
{
if (has_sfx_card && sfx_could_disable_punch_hole(handle))
return 1;
return 0;
}
#ifdef TEST_SHANNON
int main()
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment