Skip to content

Commit 70684af

Browse files
Qi Wumontywi
authored andcommitted
Atomic write support for ScaleFlux NVMe SSD's
1 parent 7a4afad commit 70684af

File tree

1 file changed

+112
-2
lines changed

1 file changed

+112
-2
lines changed

mysys/my_atomic_writes.c

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ my_bool my_may_have_atomic_write= IF_WIN(1,0);
1919

2020
#ifdef __linux__
2121

22-
my_bool has_shannon_atomic_write= 0, has_fusion_io_atomic_write= 0;
22+
my_bool has_shannon_atomic_write= 0, has_fusion_io_atomic_write= 0,
23+
has_sfx_atomic_write= 0;
2324

2425
#include <sys/ioctl.h>
2526

@@ -254,6 +255,109 @@ static my_bool shannon_has_atomic_write(File file, int page_size)
254255
}
255256

256257

258+
/***********************************************************************
259+
ScaleFlux
260+
************************************************************************/
261+
262+
#define SFX_GET_ATOMIC_SIZE _IO('N', 0x244)
263+
#define SFX_MAX_DEVICES 32
264+
#define SFX_NO_ATOMIC_SIZE_YET -2
265+
266+
struct sfx_dev
267+
{
268+
char dev_name[32];
269+
dev_t st_dev;
270+
int atomic_size;
271+
};
272+
273+
static struct sfx_dev sfx_devices[SFX_MAX_DEVICES + 1];
274+
275+
/**
276+
Check if the system has a ScaleFlux card
277+
If card exists, record device numbers to allow us to later check if
278+
a given file is on this device.
279+
@return TRUE Card exists
280+
*/
281+
282+
static my_bool test_if_sfx_card_exists()
283+
{
284+
uint sfx_found_devices = 0;
285+
uint dev_num;
286+
287+
for (dev_num = 0; dev_num < SFX_MAX_DEVICES; dev_num++)
288+
{
289+
struct stat stat_buff;
290+
291+
sprintf(sfx_devices[sfx_found_devices].dev_name, "/dev/sfdv%dn1",
292+
dev_num);
293+
if (lstat(sfx_devices[sfx_found_devices].dev_name,
294+
&stat_buff) < 0)
295+
break;
296+
297+
sfx_devices[sfx_found_devices].st_dev= stat_buff.st_rdev;
298+
/*
299+
The atomic size will be checked on first access. This is needed
300+
as a normal user can't open the /dev/sfdvXn1 file
301+
*/
302+
sfx_devices[sfx_found_devices].atomic_size = SFX_NO_ATOMIC_SIZE_YET;
303+
if (++sfx_found_devices == SFX_MAX_DEVICES)
304+
goto end;
305+
}
306+
end:
307+
sfx_devices[sfx_found_devices].st_dev= 0;
308+
return sfx_found_devices > 0;
309+
}
310+
311+
static my_bool sfx_dev_has_atomic_write(struct sfx_dev *dev,
312+
int page_size)
313+
{
314+
if (dev->atomic_size == SFX_NO_ATOMIC_SIZE_YET)
315+
{
316+
int fd= open(dev->dev_name, 0);
317+
if (fd < 0)
318+
{
319+
perror("open() failed!");
320+
dev->atomic_size= 0; /* Don't try again */
321+
return FALSE;
322+
}
323+
324+
dev->atomic_size= ioctl(fd, SFX_GET_ATOMIC_SIZE);
325+
close(fd);
326+
}
327+
328+
return (page_size <= dev->atomic_size);
329+
}
330+
331+
332+
/**
333+
Check if a file is on a ScaleFlux device and that it supports atomic_write
334+
@param[in] file OS file handle
335+
@param[in] page_size page size
336+
@return TRUE Atomic write supported
337+
338+
@notes
339+
This is called only at first open of a file. In this case it's doesn't
340+
matter so much that we loop over all cards.
341+
We update the atomic size on first access.
342+
*/
343+
344+
static my_bool sfx_has_atomic_write(File file, int page_size)
345+
{
346+
struct sfx_dev *dev;
347+
struct stat stat_buff;
348+
349+
if (fstat(file, &stat_buff) < 0)
350+
{
351+
return 0;
352+
}
353+
354+
for (dev = sfx_devices; dev->st_dev; dev++)
355+
{
356+
if (stat_buff.st_dev == dev->st_dev)
357+
return sfx_dev_has_atomic_write(dev, page_size);
358+
}
359+
return 0;
360+
}
257361
/***********************************************************************
258362
Generic atomic write code
259363
************************************************************************/
@@ -266,7 +370,8 @@ static my_bool shannon_has_atomic_write(File file, int page_size)
266370
void my_init_atomic_write(void)
267371
{
268372
if ((has_shannon_atomic_write= test_if_shannon_card_exists()) ||
269-
(has_fusion_io_atomic_write= test_if_fusion_io_card_exists()))
373+
(has_fusion_io_atomic_write= test_if_fusion_io_card_exists()) ||
374+
(has_sfx_atomic_write= test_if_sfx_card_exists()))
270375
my_may_have_atomic_write= 1;
271376
#ifdef TEST_SHANNON
272377
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)
294399
#endif
295400
if (!my_may_have_atomic_write)
296401
return 0;
402+
297403
if (has_shannon_atomic_write &&
298404
shannon_has_atomic_write(handle, page_size))
299405
return 1;
@@ -302,6 +408,10 @@ my_bool my_test_if_atomic_write(File handle, int page_size)
302408
fusion_io_has_atomic_write(handle, page_size))
303409
return 1;
304410

411+
if (has_sfx_atomic_write &&
412+
sfx_has_atomic_write(handle, page_size))
413+
return 1;
414+
305415
return 0;
306416
}
307417

0 commit comments

Comments
 (0)