summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQi Wu <qi.wu@scaleflux.com>2020-07-03 20:34:46 +0300
committerMonty <monty@mariadb.org>2020-07-03 22:42:10 +0300
commit70684afef2ce6d797f78db192c4472260cd22660 (patch)
tree9be4b019515faa8a27d168cd25f85de04028cd62
parent7a4afad969e5cb903cdf82386398a75710f5ed80 (diff)
downloadmariadb-git-70684afef2ce6d797f78db192c4472260cd22660.tar.gz
Atomic write support for ScaleFlux NVMe SSD's
-rw-r--r--mysys/my_atomic_writes.c114
1 files changed, 112 insertions, 2 deletions
diff --git a/mysys/my_atomic_writes.c b/mysys/my_atomic_writes.c
index b383af11ba8..34207a6fd07 100644
--- a/mysys/my_atomic_writes.c
+++ b/mysys/my_atomic_writes.c
@@ -19,7 +19,8 @@ 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;
+my_bool has_shannon_atomic_write= 0, has_fusion_io_atomic_write= 0,
+ has_sfx_atomic_write= 0;
#include <sys/ioctl.h>
@@ -255,6 +256,109 @@ 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
+
+struct sfx_dev
+{
+ char dev_name[32];
+ dev_t st_dev;
+ int atomic_size;
+};
+
+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.
+ @return TRUE Card exists
+*/
+
+static my_bool test_if_sfx_card_exists()
+{
+ uint sfx_found_devices = 0;
+ uint dev_num;
+
+ for (dev_num = 0; dev_num < SFX_MAX_DEVICES; dev_num++)
+ {
+ struct stat stat_buff;
+
+ sprintf(sfx_devices[sfx_found_devices].dev_name, "/dev/sfdv%dn1",
+ dev_num);
+ if (lstat(sfx_devices[sfx_found_devices].dev_name,
+ &stat_buff) < 0)
+ break;
+
+ sfx_devices[sfx_found_devices].st_dev= stat_buff.st_rdev;
+ /*
+ 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;
+ if (++sfx_found_devices == SFX_MAX_DEVICES)
+ goto end;
+ }
+end:
+ sfx_devices[sfx_found_devices].st_dev= 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 fd= open(dev->dev_name, 0);
+ if (fd < 0)
+ {
+ perror("open() failed!");
+ dev->atomic_size= 0; /* Don't try again */
+ return FALSE;
+ }
+
+ dev->atomic_size= ioctl(fd, SFX_GET_ATOMIC_SIZE);
+ close(fd);
+ }
+
+ return (page_size <= dev->atomic_size);
+}
+
+
+/**
+ Check if a file is on a ScaleFlux device and that it supports atomic_write
+ @param[in] file OS file handle
+ @param[in] page_size page size
+ @return TRUE Atomic write supported
+
+ @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.
+ We update the atomic size on first access.
+*/
+
+static my_bool sfx_has_atomic_write(File file, int page_size)
+{
+ struct sfx_dev *dev;
+ struct stat stat_buff;
+
+ if (fstat(file, &stat_buff) < 0)
+ {
+ return 0;
+ }
+
+ for (dev = sfx_devices; dev->st_dev; dev++)
+ {
+ if (stat_buff.st_dev == dev->st_dev)
+ return sfx_dev_has_atomic_write(dev, page_size);
+ }
+ return 0;
+}
+/***********************************************************************
Generic atomic write code
************************************************************************/
@@ -266,7 +370,8 @@ static my_bool shannon_has_atomic_write(File file, int page_size)
void my_init_atomic_write(void)
{
if ((has_shannon_atomic_write= test_if_shannon_card_exists()) ||
- (has_fusion_io_atomic_write= test_if_fusion_io_card_exists()))
+ (has_fusion_io_atomic_write= test_if_fusion_io_card_exists()) ||
+ (has_sfx_atomic_write= test_if_sfx_card_exists()))
my_may_have_atomic_write= 1;
#ifdef TEST_SHANNON
printf("%s(): has_shannon_atomic_write=%d, my_may_have_atomic_write=%d\n",
@@ -294,6 +399,7 @@ my_bool my_test_if_atomic_write(File handle, int page_size)
#endif
if (!my_may_have_atomic_write)
return 0;
+
if (has_shannon_atomic_write &&
shannon_has_atomic_write(handle, page_size))
return 1;
@@ -302,6 +408,10 @@ my_bool my_test_if_atomic_write(File handle, int page_size)
fusion_io_has_atomic_write(handle, page_size))
return 1;
+ if (has_sfx_atomic_write &&
+ sfx_has_atomic_write(handle, page_size))
+ return 1;
+
return 0;
}