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); ...@@ -183,11 +183,12 @@ extern BOOL my_obtain_privilege(LPCSTR lpPrivilege);
#endif #endif
void my_init_atomic_write(void); void my_init_atomic_write(void);
#define my_test_if_thinly_provisioned(A) 0
#ifdef __linux__ #ifdef __linux__
my_bool my_test_if_atomic_write(File handle, int pagesize); my_bool my_test_if_atomic_write(File handle, int pagesize);
my_bool my_test_if_thinly_provisioned(File handle);
#else #else
# define my_test_if_atomic_write(A, B) 0 # define my_test_if_atomic_write(A, B) 0
# define my_test_if_thinly_provisioned(A) 0
#endif /* __linux__ */ #endif /* __linux__ */
extern my_bool my_may_have_atomic_write; extern my_bool my_may_have_atomic_write;
......
...@@ -19,8 +19,9 @@ my_bool my_may_have_atomic_write= IF_WIN(1,0); ...@@ -19,8 +19,9 @@ my_bool my_may_have_atomic_write= IF_WIN(1,0);
#ifdef __linux__ #ifdef __linux__
my_bool has_shannon_atomic_write= 0, has_fusion_io_atomic_write= 0, my_bool has_shannon_atomic_write, has_fusion_io_atomic_write,
has_sfx_atomic_write= 0; has_sfx_atomic_write;
my_bool has_sfx_card;
#include <sys/ioctl.h> #include <sys/ioctl.h>
...@@ -225,7 +226,7 @@ static my_bool shannon_dev_has_atomic_write(struct shannon_dev *dev, ...@@ -225,7 +226,7 @@ static my_bool shannon_dev_has_atomic_write(struct shannon_dev *dev,
@return TRUE Atomic write supported @return TRUE Atomic write supported
@notes @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. matter so much that we loop over all cards.
We update the atomic size on first access. We update the atomic size on first access.
*/ */
...@@ -264,15 +265,26 @@ static my_bool shannon_has_atomic_write(File file, int page_size) ...@@ -264,15 +265,26 @@ static my_bool shannon_has_atomic_write(File file, int page_size)
ScaleFlux ScaleFlux
************************************************************************/ ************************************************************************/
#define SFX_GET_ATOMIC_SIZE _IO('N', 0x244) #define SFX_GET_ATOMIC_SIZE _IOR('N', 0x243, int)
#define SFX_MAX_DEVICES 32 #define SFX_MAX_DEVICES (32)
#define SFX_NO_ATOMIC_SIZE_YET -2 #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 struct sfx_dev
{ {
char dev_name[32]; char dev_name[32];
dev_t st_dev; dev_t st_dev;
int atomic_size; int atomic_write;
int disable_punch_hole;
}; };
static struct sfx_dev sfx_devices[SFX_MAX_DEVICES + 1]; static struct sfx_dev sfx_devices[SFX_MAX_DEVICES + 1];
...@@ -280,7 +292,8 @@ 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 Check if the system has a ScaleFlux card
If card exists, record device numbers to allow us to later check if 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 @return TRUE Card exists
*/ */
...@@ -303,38 +316,41 @@ static my_bool test_if_sfx_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 The atomic size will be checked on first access. This is needed
as a normal user can't open the /dev/sfdvXn1 file 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) if (++sfx_found_devices == SFX_MAX_DEVICES)
goto end; goto end;
} }
end: end:
sfx_devices[sfx_found_devices].st_dev= 0; sfx_devices[sfx_found_devices].st_dev= 0;
has_sfx_card = (sfx_found_devices > 0);
return sfx_found_devices > 0; return sfx_found_devices > 0;
} }
static my_bool sfx_dev_has_atomic_write(struct sfx_dev *dev, static my_bool sfx_dev_has_atomic_write(struct sfx_dev *dev,
int page_size) 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); int fd= open(dev->dev_name, 0);
if (fd < 0) if (fd < 0)
{
fprintf(stderr, "Unable to determine if atomic writes are supported:" fprintf(stderr, "Unable to determine if atomic writes are supported:"
" open(\"%s\"): %m\n", dev->dev_name); " open(\"%s\"): %m\n", dev->dev_name);
dev->atomic_size= 0; /* Don't try again */
}
else else
{ {
dev->atomic_size= ioctl(fd, SFX_GET_ATOMIC_SIZE); result= ioctl(fd, SFX_GET_ATOMIC_SIZE, &max_atomic_size);
close(fd); 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 Check if a file is on a ScaleFlux device and that it supports atomic_write
@param[in] file OS file handle @param[in] file OS file handle
...@@ -342,7 +358,7 @@ static my_bool sfx_dev_has_atomic_write(struct sfx_dev *dev, ...@@ -342,7 +358,7 @@ static my_bool sfx_dev_has_atomic_write(struct sfx_dev *dev,
@return TRUE Atomic write supported @return TRUE Atomic write supported
@notes @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. matter so much that we loop over all cards.
We update the atomic size on first access. We update the atomic size on first access.
*/ */
...@@ -358,12 +374,63 @@ static my_bool sfx_has_atomic_write(File file, int page_size) ...@@ -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 sfx_dev_has_atomic_write(dev, page_size);
return 0; 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 Generic atomic write code
************************************************************************/ ************************************************************************/
/* /**
Initialize automic write sub systems. Initialize the atomic write subsystem.
Checks if we have any devices that supports atomic write 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) ...@@ -418,6 +485,22 @@ my_bool my_test_if_atomic_write(File handle, int page_size)
return 0; 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 #ifdef TEST_SHANNON
int main() 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