~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/os/os0file.c

Merge initial InnoDB+ import.

This was applied by generating a patch between MySQL 5.1.50 InnoDB plugin and
the just-merged innodb+ from mysql-trunk revision-id: vasil.dimov@oracle.com-20100422110752-1zowoqxel5xx3z2e

Then, some manual merge resolving and it worked. This should make it much
easier to merge the rest of InnoDB 1.1 and 1.2 from the mysql tree using
my bzr-reapply script.

This takes us to InnoDB 1.1.1(ish).

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
*******************************************************/
33
33
 
34
34
#include "os0file.h"
 
35
 
 
36
#ifdef UNIV_NONINL
 
37
#include "os0file.ic"
 
38
#endif
 
39
 
35
40
#include "ut0mem.h"
36
41
#include "srv0srv.h"
37
42
#include "srv0start.h"
52
57
# endif /* __WIN__ */
53
58
#endif /* !UNIV_HOTBACKUP */
54
59
 
 
60
#if defined(LINUX_NATIVE_AIO)
 
61
#include <libaio.h>
 
62
#endif
 
63
 
55
64
/* This specifies the file permissions InnoDB uses when it creates files in
56
65
Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to
57
66
my_umask */
73
82
/* We do not call os_file_flush in every os_file_write. */
74
83
#endif /* UNIV_DO_FLUSH */
75
84
 
76
 
#ifdef UNIV_HOTBACKUP
77
 
# define os_aio_use_native_aio  FALSE
78
 
#else /* UNIV_HOTBACKUP */
 
85
#ifndef UNIV_HOTBACKUP
79
86
/* We use these mutexes to protect lseek + file i/o operation, if the
80
87
OS does not provide an atomic pread or pwrite, or similar */
81
88
#define OS_FILE_N_SEEK_MUTEXES  16
84
91
/* In simulated aio, merge at most this many consecutive i/os */
85
92
#define OS_AIO_MERGE_N_CONSECUTIVE      64
86
93
 
87
 
/** If this flag is TRUE, then we will use the native aio of the
88
 
OS (provided we compiled Innobase with it in), otherwise we will
89
 
use simulated aio we build below with threads */
90
 
 
91
 
UNIV_INTERN ibool       os_aio_use_native_aio   = FALSE;
 
94
/**********************************************************************
 
95
 
 
96
InnoDB AIO Implementation:
 
97
=========================
 
98
 
 
99
We support native AIO for windows and linux. For rest of the platforms
 
100
we simulate AIO by special io-threads servicing the IO-requests.
 
101
 
 
102
Simulated AIO:
 
103
==============
 
104
 
 
105
In platforms where we 'simulate' AIO following is a rough explanation
 
106
of the high level design.
 
107
There are four io-threads (for ibuf, log, read, write).
 
108
All synchronous IO requests are serviced by the calling thread using
 
109
os_file_write/os_file_read. The Asynchronous requests are queued up
 
110
in an array (there are four such arrays) by the calling thread. 
 
111
Later these requests are picked up by the io-thread and are serviced
 
112
synchronously.
 
113
 
 
114
Windows native AIO:
 
115
==================
 
116
 
 
117
If srv_use_native_aio is not set then windows follow the same
 
118
code as simulated AIO. If the flag is set then native AIO interface
 
119
is used. On windows, one of the limitation is that if a file is opened
 
120
for AIO no synchronous IO can be done on it. Therefore we have an
 
121
extra fifth array to queue up synchronous IO requests.
 
122
There are innodb_file_io_threads helper threads. These threads work
 
123
on the four arrays mentioned above in Simulated AIO. No thread is
 
124
required for the sync array.
 
125
If a synchronous IO request is made, it is first queued in the sync
 
126
array. Then the calling thread itself waits on the request, thus
 
127
making the call synchronous.
 
128
If an AIO request is made the calling thread not only queues it in the
 
129
array but also submits the requests. The helper thread then collects
 
130
the completed IO request and calls completion routine on it.
 
131
 
 
132
Linux native AIO:
 
133
=================
 
134
 
 
135
If we have libaio installed on the system and innodb_use_native_aio
 
136
is set to TRUE we follow the code path of native AIO, otherwise we
 
137
do simulated AIO.
 
138
There are innodb_file_io_threads helper threads. These threads work
 
139
on the four arrays mentioned above in Simulated AIO.
 
140
If a synchronous IO request is made, it is handled by calling
 
141
os_file_write/os_file_read.
 
142
If an AIO request is made the calling thread not only queues it in the
 
143
array but also submits the requests. The helper thread then collects
 
144
the completed IO request and calls completion routine on it.
 
145
 
 
146
**********************************************************************/
92
147
 
93
148
/** Flag: enable debug printout for asynchronous i/o */
94
149
UNIV_INTERN ibool       os_aio_print_debug      = FALSE;
95
150
 
 
151
#ifdef UNIV_PFS_IO
 
152
/* Keys to register InnoDB I/O with performance schema */
 
153
UNIV_INTERN mysql_pfs_key_t  innodb_file_data_key;
 
154
UNIV_INTERN mysql_pfs_key_t  innodb_file_log_key;
 
155
UNIV_INTERN mysql_pfs_key_t  innodb_file_temp_key;
 
156
#endif /* UNIV_PFS_IO */
 
157
 
96
158
/** The asynchronous i/o array slot structure */
97
159
typedef struct os_aio_slot_struct       os_aio_slot_t;
98
160
 
127
189
                                        OVERLAPPED struct */
128
190
        OVERLAPPED      control;        /*!< Windows control block for the
129
191
                                        aio request */
 
192
#elif defined(LINUX_NATIVE_AIO)
 
193
        struct iocb     control;        /* Linux control block for aio */
 
194
        int             n_bytes;        /* bytes written/read. */
 
195
        int             ret;            /* AIO return code */
130
196
#endif
131
197
};
132
198
 
152
218
                                array of pending aio requests. A
153
219
                                thread can wait separately for any one
154
220
                                of the segments. */
 
221
        ulint           cur_seg;/*!< We reserve IO requests in round
 
222
                                robin fashion to different segments.
 
223
                                This points to the segment that is to
 
224
                                be used to service next IO request. */
155
225
        ulint           n_reserved;
156
226
                                /*!< Number of reserved slots in the
157
227
                                aio array outside the ibuf segment */
165
235
                                WaitForMultipleObjects; used only in
166
236
                                Windows */
167
237
#endif
 
238
 
 
239
#if defined(LINUX_NATIVE_AIO)
 
240
        io_context_t*           aio_ctx;
 
241
                                /* completion queue for IO. There is 
 
242
                                one such queue per segment. Each thread
 
243
                                will work on one ctx exclusively. */
 
244
        struct io_event*        aio_events;
 
245
                                /* The array to collect completed IOs.
 
246
                                There is one such event for each
 
247
                                possible pending IO. The size of the
 
248
                                array is equal to n_slots. */
 
249
#endif
168
250
};
169
251
 
 
252
#if defined(LINUX_NATIVE_AIO)
 
253
/** timeout for each io_getevents() call = 500ms. */
 
254
#define OS_AIO_REAP_TIMEOUT     (500000000UL)
 
255
 
 
256
/** time to sleep, in microseconds if io_setup() returns EAGAIN. */
 
257
#define OS_AIO_IO_SETUP_RETRY_SLEEP     (500000UL)
 
258
 
 
259
/** number of attempts before giving up on io_setup(). */
 
260
#define OS_AIO_IO_SETUP_RETRY_ATTEMPTS  5
 
261
#endif
 
262
 
170
263
/** Array of events used in simulated aio */
171
264
static os_event_t*      os_aio_segment_wait_events      = NULL;
172
265
 
185
278
/** If the following is TRUE, read i/o handler threads try to
186
279
wait until a batch of new read requests have been posted */
187
280
static ibool    os_aio_recommend_sleep_for_read_threads = FALSE;
188
 
#endif /* UNIV_HOTBACKUP */
 
281
#endif /* !UNIV_HOTBACKUP */
189
282
 
190
283
UNIV_INTERN ulint       os_n_file_reads         = 0;
191
284
UNIV_INTERN ulint       os_bytes_read_since_printout = 0;
391
484
 
392
485
        fflush(stderr);
393
486
 
394
 
        if (err == ENOSPC) {
 
487
        switch (err) {
 
488
        case ENOSPC:
395
489
                return(OS_FILE_DISK_FULL);
396
 
        } else if (err == ENOENT) {
 
490
        case ENOENT:
397
491
                return(OS_FILE_NOT_FOUND);
398
 
        } else if (err == EEXIST) {
 
492
        case EEXIST:
399
493
                return(OS_FILE_ALREADY_EXISTS);
400
 
        } else if (err == EXDEV || err == ENOTDIR || err == EISDIR) {
 
494
        case EXDEV:
 
495
        case ENOTDIR:
 
496
        case EISDIR:
401
497
                return(OS_FILE_PATH_ERROR);
402
 
        } else {
403
 
                return(100 + err);
 
498
        case EAGAIN:
 
499
                if (srv_use_native_aio) {
 
500
                        return(OS_FILE_AIO_RESOURCES_RESERVED);
 
501
                }
 
502
                break;
 
503
        case EINTR:
 
504
                if (srv_use_native_aio) {
 
505
                        return(OS_FILE_AIO_INTERRUPTED);
 
506
                }
 
507
                break;
404
508
        }
 
509
        return(100 + err);
405
510
#endif
406
511
}
407
512
 
451
556
        } else if (err == OS_FILE_AIO_RESOURCES_RESERVED) {
452
557
 
453
558
                return(TRUE);
 
559
        } else if (err == OS_FILE_AIO_INTERRUPTED) {
 
560
 
 
561
                return(TRUE);
454
562
        } else if (err == OS_FILE_ALREADY_EXISTS
455
563
                   || err == OS_FILE_PATH_ERROR) {
456
564
 
926
1034
}
927
1035
 
928
1036
/****************************************************************//**
 
1037
NOTE! Use the corresponding macro os_file_create_simple(), not directly
 
1038
this function!
929
1039
A simple function to open or create a file.
930
1040
@return own: handle to the file, not defined if error, error number
931
1041
can be retrieved with os_file_get_last_error */
932
1042
UNIV_INTERN
933
1043
os_file_t
934
 
os_file_create_simple(
935
 
/*==================*/
 
1044
os_file_create_simple_func(
 
1045
/*=======================*/
936
1046
        const char*     name,   /*!< in: name of the file or path as a
937
1047
                                null-terminated string */
938
1048
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file is
1067
1177
}
1068
1178
 
1069
1179
/****************************************************************//**
 
1180
NOTE! Use the corresponding macro
 
1181
os_file_create_simple_no_error_handling(), not directly this function!
1070
1182
A simple function to open or create a file.
1071
1183
@return own: handle to the file, not defined if error, error number
1072
1184
can be retrieved with os_file_get_last_error */
1073
1185
UNIV_INTERN
1074
1186
os_file_t
1075
 
os_file_create_simple_no_error_handling(
1076
 
/*====================================*/
 
1187
os_file_create_simple_no_error_handling_func(
 
1188
/*=========================================*/
1077
1189
        const char*     name,   /*!< in: name of the file or path as a
1078
1190
                                null-terminated string */
1079
1191
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
1226
1338
}
1227
1339
 
1228
1340
/****************************************************************//**
 
1341
NOTE! Use the corresponding macro os_file_create(), not directly
 
1342
this function!
1229
1343
Opens an existing file or creates a new.
1230
1344
@return own: handle to the file, not defined if error, error number
1231
1345
can be retrieved with os_file_get_last_error */
1232
1346
UNIV_INTERN
1233
1347
os_file_t
1234
 
os_file_create(
1235
 
/*===========*/
 
1348
os_file_create_func(
 
1349
/*================*/
1236
1350
        const char*     name,   /*!< in: name of the file or path as a
1237
1351
                                null-terminated string */
1238
1352
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
1282
1396
                buffering of writes in the OS */
1283
1397
                attributes = 0;
1284
1398
#ifdef WIN_ASYNC_IO
1285
 
                if (os_aio_use_native_aio) {
 
1399
                if (srv_use_native_aio) {
1286
1400
                        attributes = attributes | FILE_FLAG_OVERLAPPED;
1287
1401
                }
1288
1402
#endif
1345
1459
 
1346
1460
                /* When srv_file_per_table is on, file creation failure may not
1347
1461
                be critical to the whole instance. Do not crash the server in
1348
 
                case of unknown errors.
1349
 
                Please note "srv_file_per_table" is a global variable with
1350
 
                no explicit synchronization protection. It could be
1351
 
                changed during this execution path. It might not have the
1352
 
                same value as the one when building the table definition */
 
1462
                case of unknown errors. */
1353
1463
                if (srv_file_per_table) {
1354
1464
                        retry = os_file_handle_error_no_exit(name,
1355
1465
                                                create_mode == OS_FILE_CREATE ?
1436
1546
 
1437
1547
                /* When srv_file_per_table is on, file creation failure may not
1438
1548
                be critical to the whole instance. Do not crash the server in
1439
 
                case of unknown errors.
1440
 
                Please note "srv_file_per_table" is a global variable with
1441
 
                no explicit synchronization protection. It could be
1442
 
                changed during this execution path. It might not have the
1443
 
                same value as the one when building the table definition */
 
1549
                case of unknown errors. */
1444
1550
                if (srv_file_per_table) {
1445
1551
                        retry = os_file_handle_error_no_exit(name,
1446
1552
                                                create_mode == OS_FILE_CREATE ?
1625
1731
}
1626
1732
 
1627
1733
/***********************************************************************//**
 
1734
NOTE! Use the corresponding macro os_file_rename(), not directly this function!
1628
1735
Renames a file (can also move it to another directory). It is safest that the
1629
1736
file is closed before calling this function.
1630
1737
@return TRUE if success */
1631
1738
UNIV_INTERN
1632
1739
ibool
1633
 
os_file_rename(
1634
 
/*===========*/
 
1740
os_file_rename_func(
 
1741
/*================*/
1635
1742
        const char*     oldpath,/*!< in: old file path as a null-terminated
1636
1743
                                string */
1637
1744
        const char*     newpath)/*!< in: new file path */
1664
1771
}
1665
1772
 
1666
1773
/***********************************************************************//**
 
1774
NOTE! Use the corresponding macro os_file_close(), not directly this function!
1667
1775
Closes a file handle. In case of error, error number can be retrieved with
1668
1776
os_file_get_last_error.
1669
1777
@return TRUE if success */
1670
1778
UNIV_INTERN
1671
1779
ibool
1672
 
os_file_close(
1673
 
/*==========*/
 
1780
os_file_close_func(
 
1781
/*===============*/
1674
1782
        os_file_t       file)   /*!< in, own: handle to a file */
1675
1783
{
1676
1784
#ifdef __WIN__
1966
2074
#endif /* !__WIN__ */
1967
2075
 
1968
2076
/***********************************************************************//**
 
2077
NOTE! Use the corresponding macro os_file_flush(), not directly this function!
1969
2078
Flushes the write buffers of a given file to the disk.
1970
2079
@return TRUE if success */
1971
2080
UNIV_INTERN
1972
2081
ibool
1973
 
os_file_flush(
1974
 
/*==========*/
 
2082
os_file_flush_func(
 
2083
/*===============*/
1975
2084
        os_file_t       file)   /*!< in, own: handle to a file */
1976
2085
{
1977
2086
#ifdef __WIN__
2278
2387
#endif
2279
2388
 
2280
2389
/*******************************************************************//**
 
2390
NOTE! Use the corresponding macro os_file_read(), not directly this
 
2391
function!
2281
2392
Requests a synchronous positioned read operation.
2282
2393
@return TRUE if request was successful, FALSE if fail */
2283
2394
UNIV_INTERN
2284
2395
ibool
2285
 
os_file_read(
2286
 
/*=========*/
 
2396
os_file_read_func(
 
2397
/*==============*/
2287
2398
        os_file_t       file,   /*!< in: handle to a file */
2288
2399
        void*           buf,    /*!< in: buffer where to read */
2289
2400
        ulint           offset, /*!< in: least significant 32 bits of file
2401
2512
}
2402
2513
 
2403
2514
/*******************************************************************//**
 
2515
NOTE! Use the corresponding macro os_file_read_no_error_handling(),
 
2516
not directly this function!
2404
2517
Requests a synchronous positioned read operation. This function does not do
2405
2518
any error handling. In case of error it returns FALSE.
2406
2519
@return TRUE if request was successful, FALSE if fail */
2407
2520
UNIV_INTERN
2408
2521
ibool
2409
 
os_file_read_no_error_handling(
2410
 
/*===========================*/
 
2522
os_file_read_no_error_handling_func(
 
2523
/*================================*/
2411
2524
        os_file_t       file,   /*!< in: handle to a file */
2412
2525
        void*           buf,    /*!< in: buffer where to read */
2413
2526
        ulint           offset, /*!< in: least significant 32 bits of file
2529
2642
}
2530
2643
 
2531
2644
/*******************************************************************//**
 
2645
NOTE! Use the corresponding macro os_file_write(), not directly
 
2646
this function!
2532
2647
Requests a synchronous write operation.
2533
2648
@return TRUE if request was successful, FALSE if fail */
2534
2649
UNIV_INTERN
2535
2650
ibool
2536
 
os_file_write(
2537
 
/*==========*/
 
2651
os_file_write_func(
 
2652
/*===============*/
2538
2653
        const char*     name,   /*!< in: name of the file or path as a
2539
2654
                                null-terminated string */
2540
2655
        os_file_t       file,   /*!< in: handle to a file */
2993
3108
        return((array->slots) + index);
2994
3109
}
2995
3110
 
2996
 
/************************************************************************//**
2997
 
Creates an aio wait array.
2998
 
@return own: aio array */
 
3111
#if defined(LINUX_NATIVE_AIO)
 
3112
/******************************************************************//**
 
3113
Creates an io_context for native linux AIO.
 
3114
@return TRUE on success. */
 
3115
static
 
3116
ibool
 
3117
os_aio_linux_create_io_ctx(
 
3118
/*=======================*/
 
3119
        ulint           max_events,     /*!< in: number of events. */
 
3120
        io_context_t*   io_ctx)         /*!< out: io_ctx to initialize. */
 
3121
{
 
3122
        int     ret;
 
3123
        ulint   retries = 0;
 
3124
 
 
3125
retry:
 
3126
        memset(io_ctx, 0x0, sizeof(*io_ctx));
 
3127
 
 
3128
        /* Initialize the io_ctx. Tell it how many pending
 
3129
        IO requests this context will handle. */
 
3130
 
 
3131
        ret = io_setup(max_events, io_ctx);
 
3132
        if (ret == 0) {
 
3133
#if defined(UNIV_AIO_DEBUG)
 
3134
                fprintf(stderr,
 
3135
                        "InnoDB: Linux native AIO:"
 
3136
                        " initialized io_ctx for segment\n");
 
3137
#endif
 
3138
                /* Success. Return now. */
 
3139
                return(TRUE);
 
3140
        }
 
3141
 
 
3142
        /* If we hit EAGAIN we'll make a few attempts before failing. */
 
3143
 
 
3144
        switch (ret) {
 
3145
        case -EAGAIN:
 
3146
                if (retries == 0) {
 
3147
                        /* First time around. */
 
3148
                        ut_print_timestamp(stderr);
 
3149
                        fprintf(stderr,
 
3150
                                "  InnoDB: Warning: io_setup() failed"
 
3151
                                " with EAGAIN. Will make %d attempts"
 
3152
                                " before giving up.\n",
 
3153
                                OS_AIO_IO_SETUP_RETRY_ATTEMPTS);
 
3154
                }
 
3155
 
 
3156
                if (retries < OS_AIO_IO_SETUP_RETRY_ATTEMPTS) {
 
3157
                        ++retries;
 
3158
                        fprintf(stderr,
 
3159
                                "InnoDB: Warning: io_setup() attempt"
 
3160
                                " %lu failed.\n",
 
3161
                                retries);
 
3162
                        os_thread_sleep(OS_AIO_IO_SETUP_RETRY_SLEEP);
 
3163
                        goto retry;
 
3164
                }
 
3165
 
 
3166
                /* Have tried enough. Better call it a day. */
 
3167
                ut_print_timestamp(stderr);
 
3168
                fprintf(stderr,
 
3169
                        "  InnoDB: Error: io_setup() failed"
 
3170
                        " with EAGAIN after %d attempts.\n",
 
3171
                        OS_AIO_IO_SETUP_RETRY_ATTEMPTS);
 
3172
                break;
 
3173
 
 
3174
        case -ENOSYS:
 
3175
                ut_print_timestamp(stderr);
 
3176
                fprintf(stderr,
 
3177
                        "  InnoDB: Error: Linux Native AIO interface"
 
3178
                        " is not supported on this platform. Please"
 
3179
                        " check your OS documentation and install"
 
3180
                        " appropriate binary of InnoDB.\n");
 
3181
 
 
3182
                break;
 
3183
 
 
3184
        default:
 
3185
                ut_print_timestamp(stderr);
 
3186
                fprintf(stderr,
 
3187
                        "  InnoDB: Error: Linux Native AIO setup"
 
3188
                        " returned following error[%d]\n", -ret);
 
3189
                break;
 
3190
        }
 
3191
 
 
3192
        fprintf(stderr,
 
3193
                "InnoDB: You can disable Linux Native AIO by"
 
3194
                " setting innodb_native_aio = off in my.cnf\n");
 
3195
        return(FALSE);
 
3196
}
 
3197
#endif /* LINUX_NATIVE_AIO */
 
3198
 
 
3199
/******************************************************************//**
 
3200
Creates an aio wait array. Note that we return NULL in case of failure.
 
3201
We don't care about freeing memory here because we assume that a
 
3202
failure will result in server refusing to start up.
 
3203
@return own: aio array, NULL on failure */
2999
3204
static
3000
3205
os_aio_array_t*
3001
3206
os_aio_array_create(
3002
3207
/*================*/
3003
 
        ulint   n,              /*!< in: maximum number of pending aio operations
3004
 
                                allowed; n must be divisible by n_segments */
 
3208
        ulint   n,              /*!< in: maximum number of pending aio
 
3209
                                operations allowed; n must be
 
3210
                                divisible by n_segments */
3005
3211
        ulint   n_segments)     /*!< in: number of segments in the aio array */
3006
3212
{
3007
3213
        os_aio_array_t* array;
3009
3215
        os_aio_slot_t*  slot;
3010
3216
#ifdef WIN_ASYNC_IO
3011
3217
        OVERLAPPED*     over;
 
3218
#elif defined(LINUX_NATIVE_AIO)
 
3219
        struct io_event*        io_event = NULL;
3012
3220
#endif
3013
3221
        ut_a(n > 0);
3014
3222
        ut_a(n_segments > 0);
3024
3232
        array->n_slots          = n;
3025
3233
        array->n_segments       = n_segments;
3026
3234
        array->n_reserved       = 0;
 
3235
        array->cur_seg          = 0;
3027
3236
        array->slots            = ut_malloc(n * sizeof(os_aio_slot_t));
3028
3237
#ifdef __WIN__
3029
3238
        array->native_events    = ut_malloc(n * sizeof(os_native_event_t));
3030
3239
#endif
 
3240
 
 
3241
#if defined(LINUX_NATIVE_AIO)
 
3242
        /* If we are not using native aio interface then skip this
 
3243
        part of initialization. */
 
3244
        if (!srv_use_native_aio) {
 
3245
                goto skip_native_aio;
 
3246
        }
 
3247
 
 
3248
        /* Initialize the io_context array. One io_context
 
3249
        per segment in the array. */
 
3250
 
 
3251
        array->aio_ctx = ut_malloc(n_segments *
 
3252
                                   sizeof(*array->aio_ctx));
 
3253
        for (i = 0; i < n_segments; ++i) {
 
3254
                if (!os_aio_linux_create_io_ctx(n/n_segments,
 
3255
                                           &array->aio_ctx[i])) {
 
3256
                        /* If something bad happened during aio setup
 
3257
                        we should call it a day and return right away.
 
3258
                        We don't care about any leaks because a failure
 
3259
                        to initialize the io subsystem means that the
 
3260
                        server (or atleast the innodb storage engine)
 
3261
                        is not going to startup. */
 
3262
                        return(NULL);
 
3263
                }
 
3264
        }
 
3265
 
 
3266
        /* Initialize the event array. One event per slot. */
 
3267
        io_event = ut_malloc(n * sizeof(*io_event));
 
3268
        memset(io_event, 0x0, sizeof(*io_event) * n);
 
3269
        array->aio_events = io_event;
 
3270
 
 
3271
skip_native_aio:
 
3272
#endif /* LINUX_NATIVE_AIO */
3031
3273
        for (i = 0; i < n; i++) {
3032
3274
                slot = os_aio_array_get_nth_slot(array, i);
3033
3275
 
3041
3283
                over->hEvent = slot->event->handle;
3042
3284
 
3043
3285
                *((array->native_events) + i) = over->hEvent;
 
3286
 
 
3287
#elif defined(LINUX_NATIVE_AIO)
 
3288
 
 
3289
                memset(&slot->control, 0x0, sizeof(slot->control));
 
3290
                slot->n_bytes = 0;
 
3291
                slot->ret = 0;
3044
3292
#endif
3045
3293
        }
3046
3294
 
3083
3331
segment in these arrays. This function also creates the sync array.
3084
3332
No i/o handler thread needs to be created for that */
3085
3333
UNIV_INTERN
3086
 
void
 
3334
ibool
3087
3335
os_aio_init(
3088
3336
/*========*/
3089
3337
        ulint   n_per_seg,      /*<! in: maximum number of pending aio
3108
3356
        /* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */
3109
3357
 
3110
3358
        os_aio_ibuf_array = os_aio_array_create(n_per_seg, 1);
 
3359
        if (os_aio_ibuf_array == NULL) {
 
3360
                goto err_exit;
 
3361
        }
3111
3362
 
3112
3363
        srv_io_thread_function[0] = "insert buffer thread";
3113
3364
 
3114
3365
        os_aio_log_array = os_aio_array_create(n_per_seg, 1);
 
3366
        if (os_aio_log_array == NULL) {
 
3367
                goto err_exit;
 
3368
        }
3115
3369
 
3116
3370
        srv_io_thread_function[1] = "log thread";
3117
3371
 
3118
3372
        os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
3119
3373
                                                n_read_segs);
 
3374
        if (os_aio_read_array == NULL) {
 
3375
                goto err_exit;
 
3376
        }
 
3377
 
3120
3378
        for (i = 2; i < 2 + n_read_segs; i++) {
3121
3379
                ut_a(i < SRV_MAX_N_IO_THREADS);
3122
3380
                srv_io_thread_function[i] = "read thread";
3124
3382
 
3125
3383
        os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg,
3126
3384
                                                 n_write_segs);
 
3385
        if (os_aio_write_array == NULL) {
 
3386
                goto err_exit;
 
3387
        }
 
3388
 
3127
3389
        for (i = 2 + n_read_segs; i < n_segments; i++) {
3128
3390
                ut_a(i < SRV_MAX_N_IO_THREADS);
3129
3391
                srv_io_thread_function[i] = "write thread";
3130
3392
        }
3131
3393
 
3132
3394
        os_aio_sync_array = os_aio_array_create(n_slots_sync, 1);
 
3395
        if (os_aio_sync_array == NULL) {
 
3396
                goto err_exit;
 
3397
        }
 
3398
 
3133
3399
 
3134
3400
        os_aio_n_segments = n_segments;
3135
3401
 
3143
3409
 
3144
3410
        os_last_printout = time(NULL);
3145
3411
 
 
3412
        return(TRUE);
 
3413
 
 
3414
err_exit:
 
3415
        return(FALSE);
 
3416
 
3146
3417
}
3147
3418
 
3148
3419
/***********************************************************************
3209
3480
        os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
3210
3481
        os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
3211
3482
        os_aio_array_wake_win_aio_at_shutdown(os_aio_log_array);
 
3483
 
 
3484
#elif defined(LINUX_NATIVE_AIO)
 
3485
 
 
3486
        /* When using native AIO interface the io helper threads
 
3487
        wait on io_getevents with a timeout value of 500ms. At
 
3488
        each wake up these threads check the server status.
 
3489
        No need to do anything to wake them up. */
 
3490
 
 
3491
        if (srv_use_native_aio) {
 
3492
                return;
 
3493
        }
 
3494
        /* Fall through to simulated AIO handler wakeup if we are
 
3495
        not using native AIO. */
3212
3496
#endif
3213
3497
        /* This loop wakes up all simulated ai/o threads */
3214
3498
 
3326
3610
                                offset */
3327
3611
        ulint           len)    /*!< in: length of the block to read or write */
3328
3612
{
3329
 
        os_aio_slot_t*  slot;
 
3613
        os_aio_slot_t*  slot = NULL;
3330
3614
#ifdef WIN_ASYNC_IO
3331
3615
        OVERLAPPED*     control;
 
3616
 
 
3617
#elif defined(LINUX_NATIVE_AIO)
 
3618
 
 
3619
        struct iocb*    iocb;
 
3620
        off_t           aio_offset;
 
3621
 
3332
3622
#endif
3333
3623
        ulint           i;
 
3624
        ulint           counter;
3334
3625
        ulint           slots_per_seg;
3335
3626
        ulint           local_seg;
3336
3627
 
3349
3640
        if (array->n_reserved == array->n_slots) {
3350
3641
                os_mutex_exit(array->mutex);
3351
3642
 
3352
 
                if (!os_aio_use_native_aio) {
 
3643
                if (!srv_use_native_aio) {
3353
3644
                        /* If the handler threads are suspended, wake them
3354
3645
                        so that we get more slots */
3355
3646
 
3361
3652
                goto loop;
3362
3653
        }
3363
3654
 
3364
 
        /* First try to find a slot in the preferred local segment */
3365
 
        for (i = local_seg * slots_per_seg; i < array->n_slots; i++) {
3366
 
                slot = os_aio_array_get_nth_slot(array, i);
3367
 
 
3368
 
                if (slot->reserved == FALSE) {
3369
 
                        goto found;
3370
 
                }
3371
 
        }
3372
 
 
3373
 
        /* Fall back to a full scan. We are guaranteed to find a slot */
3374
 
        for (i = 0;; i++) {
3375
 
                slot = os_aio_array_get_nth_slot(array, i);
3376
 
 
3377
 
                if (slot->reserved == FALSE) {
3378
 
                        goto found;
3379
 
                }
3380
 
        }
 
3655
        /* We start our search for an available slot from our preferred
 
3656
        local segment and do a full scan of the array. We are
 
3657
        guaranteed to find a slot in full scan. */
 
3658
        for (i = local_seg * slots_per_seg, counter = 0;
 
3659
             counter < array->n_slots; i++, counter++) {
 
3660
 
 
3661
                i %= array->n_slots;
 
3662
                slot = os_aio_array_get_nth_slot(array, i);
 
3663
 
 
3664
                if (slot->reserved == FALSE) {
 
3665
                        goto found;
 
3666
                }
 
3667
        }
 
3668
 
 
3669
        /* We MUST always be able to get hold of a reserved slot. */
 
3670
        ut_error;
3381
3671
 
3382
3672
found:
3383
3673
        ut_a(slot->reserved == FALSE);
3409
3699
        control->Offset = (DWORD)offset;
3410
3700
        control->OffsetHigh = (DWORD)offset_high;
3411
3701
        os_event_reset(slot->event);
3412
 
#endif
3413
 
 
 
3702
 
 
3703
#elif defined(LINUX_NATIVE_AIO)
 
3704
 
 
3705
        /* If we are not using native AIO skip this part. */
 
3706
        if (!srv_use_native_aio) {
 
3707
                goto skip_native_aio;
 
3708
        }
 
3709
 
 
3710
        /* Check if we are dealing with 64 bit arch.
 
3711
        If not then make sure that offset fits in 32 bits. */
 
3712
        if (sizeof(aio_offset) == 8) {
 
3713
                aio_offset = offset_high;
 
3714
                aio_offset <<= 32;
 
3715
                aio_offset += offset;
 
3716
        } else {
 
3717
                ut_a(offset_high == 0);
 
3718
                aio_offset = offset;
 
3719
        }
 
3720
 
 
3721
        iocb = &slot->control;
 
3722
 
 
3723
        if (type == OS_FILE_READ) {
 
3724
                io_prep_pread(iocb, file, buf, len, aio_offset);
 
3725
        } else {
 
3726
                ut_a(type == OS_FILE_WRITE);
 
3727
                io_prep_pwrite(iocb, file, buf, len, aio_offset);
 
3728
        }
 
3729
 
 
3730
        iocb->data = (void*)slot;
 
3731
        slot->n_bytes = 0;
 
3732
        slot->ret = 0;
 
3733
        /*fprintf(stderr, "Filled up Linux native iocb.\n");*/
 
3734
        
 
3735
 
 
3736
skip_native_aio:
 
3737
#endif /* LINUX_NATIVE_AIO */
3414
3738
        os_mutex_exit(array->mutex);
3415
3739
 
3416
3740
        return(slot);
3445
3769
        }
3446
3770
 
3447
3771
#ifdef WIN_ASYNC_IO
 
3772
 
3448
3773
        os_event_reset(slot->event);
 
3774
 
 
3775
#elif defined(LINUX_NATIVE_AIO)
 
3776
 
 
3777
        if (srv_use_native_aio) {
 
3778
                memset(&slot->control, 0x0, sizeof(slot->control));
 
3779
                slot->n_bytes = 0;
 
3780
                slot->ret = 0;
 
3781
                /*fprintf(stderr, "Freed up Linux native slot.\n");*/
 
3782
        } else {
 
3783
                /* These fields should not be used if we are not
 
3784
                using native AIO. */
 
3785
                ut_ad(slot->n_bytes == 0);
 
3786
                ut_ad(slot->ret == 0);
 
3787
        }
 
3788
 
3449
3789
#endif
3450
3790
        os_mutex_exit(array->mutex);
3451
3791
}
3465
3805
        ulint           n;
3466
3806
        ulint           i;
3467
3807
 
3468
 
        ut_ad(!os_aio_use_native_aio);
 
3808
        ut_ad(!srv_use_native_aio);
3469
3809
 
3470
3810
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
3471
3811
 
3501
3841
{
3502
3842
        ulint   i;
3503
3843
 
3504
 
        if (os_aio_use_native_aio) {
 
3844
        if (srv_use_native_aio) {
3505
3845
                /* We do not use simulated aio: do nothing */
3506
3846
 
3507
3847
                return;
3533
3873
        os_aio_array_t* array;
3534
3874
        ulint           g;
3535
3875
 
3536
 
        if (os_aio_use_native_aio) {
 
3876
        if (srv_use_native_aio) {
3537
3877
                /* We do not use simulated aio: do nothing */
3538
3878
 
3539
3879
                return;
3552
3892
#endif /* __WIN__ */
3553
3893
}
3554
3894
 
3555
 
/*******************************************************************//**
 
3895
#if defined(LINUX_NATIVE_AIO)
 
3896
/*******************************************************************//**
 
3897
Dispatch an AIO request to the kernel.
 
3898
@return TRUE on success. */
 
3899
static
 
3900
ibool
 
3901
os_aio_linux_dispatch(
 
3902
/*==================*/
 
3903
        os_aio_array_t* array,  /*!< in: io request array. */
 
3904
        os_aio_slot_t*  slot)   /*!< in: an already reserved slot. */
 
3905
{
 
3906
        int             ret;
 
3907
        ulint           io_ctx_index;
 
3908
        struct iocb*    iocb;
 
3909
 
 
3910
        ut_ad(slot != NULL);
 
3911
        ut_ad(array);
 
3912
 
 
3913
        ut_a(slot->reserved);
 
3914
 
 
3915
        /* Find out what we are going to work with.
 
3916
        The iocb struct is directly in the slot.
 
3917
        The io_context is one per segment. */
 
3918
 
 
3919
        iocb = &slot->control;
 
3920
        io_ctx_index = (slot->pos * array->n_segments) / array->n_slots;
 
3921
 
 
3922
        ret = io_submit(array->aio_ctx[io_ctx_index], 1, &iocb);
 
3923
 
 
3924
#if defined(UNIV_AIO_DEBUG)
 
3925
        fprintf(stderr,
 
3926
                "io_submit[%c] ret[%d]: slot[%p] ctx[%p] seg[%lu]\n",
 
3927
                (slot->type == OS_FILE_WRITE) ? 'w' : 'r', ret, slot,
 
3928
                array->aio_ctx[io_ctx_index], (ulong)io_ctx_index);
 
3929
#endif
 
3930
 
 
3931
        /* io_submit returns number of successfully
 
3932
        queued requests or -errno. */
 
3933
        if (UNIV_UNLIKELY(ret != 1)) {
 
3934
                errno = -ret;
 
3935
                return(FALSE);
 
3936
        }
 
3937
 
 
3938
        return(TRUE);
 
3939
}
 
3940
#endif /* LINUX_NATIVE_AIO */
 
3941
 
 
3942
 
 
3943
/*******************************************************************//**
 
3944
NOTE! Use the corresponding macro os_aio(), not directly this function!
3556
3945
Requests an asynchronous i/o operation.
3557
3946
@return TRUE if request was queued successfully, FALSE if fail */
3558
3947
UNIV_INTERN
3559
3948
ibool
3560
 
os_aio(
3561
 
/*===*/
 
3949
os_aio_func(
 
3950
/*========*/
3562
3951
        ulint           type,   /*!< in: OS_FILE_READ or OS_FILE_WRITE */
3563
3952
        ulint           mode,   /*!< in: OS_AIO_NORMAL, ..., possibly ORed
3564
3953
                                to OS_AIO_SIMULATED_WAKE_LATER: the
3601
3990
        struct fil_node_struct * dummy_mess1;
3602
3991
        void*           dummy_mess2;
3603
3992
        ulint           dummy_type;
3604
 
#endif
3605
 
        ulint           err             = 0;
 
3993
#endif /* WIN_ASYNC_IO */
3606
3994
        ibool           retry;
3607
3995
        ulint           wake_later;
3608
3996
 
3618
4006
 
3619
4007
        if (mode == OS_AIO_SYNC
3620
4008
#ifdef WIN_ASYNC_IO
3621
 
            && !os_aio_use_native_aio
3622
 
#endif
 
4009
            && !srv_use_native_aio
 
4010
#endif /* WIN_ASYNC_IO */
3623
4011
            ) {
3624
4012
                /* This is actually an ordinary synchronous read or write:
3625
4013
                no need to use an i/o-handler thread. NOTE that if we use
3658
4046
                array = os_aio_log_array;
3659
4047
        } else if (mode == OS_AIO_SYNC) {
3660
4048
                array = os_aio_sync_array;
 
4049
 
 
4050
#if defined(LINUX_NATIVE_AIO)
 
4051
                /* In Linux native AIO we don't use sync IO array. */
 
4052
                ut_a(!srv_use_native_aio);
 
4053
#endif /* LINUX_NATIVE_AIO */
3661
4054
        } else {
3662
4055
                array = NULL; /* Eliminate compiler warning */
3663
4056
                ut_error;
3666
4059
        slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
3667
4060
                                         name, buf, offset, offset_high, n);
3668
4061
        if (type == OS_FILE_READ) {
3669
 
                if (os_aio_use_native_aio) {
3670
 
#ifdef WIN_ASYNC_IO
 
4062
                if (srv_use_native_aio) {
3671
4063
                        os_n_file_reads++;
3672
 
                        os_bytes_read_since_printout += len;
3673
 
 
 
4064
                        os_bytes_read_since_printout += n;
 
4065
#ifdef WIN_ASYNC_IO
3674
4066
                        ret = ReadFile(file, buf, (DWORD)n, &len,
3675
4067
                                       &(slot->control));
 
4068
 
 
4069
#elif defined(LINUX_NATIVE_AIO)
 
4070
                        if (!os_aio_linux_dispatch(array, slot)) {
 
4071
                                goto err_exit;
 
4072
                        }
3676
4073
#endif
3677
4074
                } else {
3678
4075
                        if (!wake_later) {
3682
4079
                        }
3683
4080
                }
3684
4081
        } else if (type == OS_FILE_WRITE) {
3685
 
                if (os_aio_use_native_aio) {
3686
 
#ifdef WIN_ASYNC_IO
 
4082
                if (srv_use_native_aio) {
3687
4083
                        os_n_file_writes++;
 
4084
#ifdef WIN_ASYNC_IO
3688
4085
                        ret = WriteFile(file, buf, (DWORD)n, &len,
3689
4086
                                        &(slot->control));
 
4087
 
 
4088
#elif defined(LINUX_NATIVE_AIO)
 
4089
                        if (!os_aio_linux_dispatch(array, slot)) {
 
4090
                                goto err_exit;
 
4091
                        }
3690
4092
#endif
3691
4093
                } else {
3692
4094
                        if (!wake_later) {
3700
4102
        }
3701
4103
 
3702
4104
#ifdef WIN_ASYNC_IO
3703
 
        if (os_aio_use_native_aio) {
 
4105
        if (srv_use_native_aio) {
3704
4106
                if ((ret && len == n)
3705
4107
                    || (!ret && GetLastError() == ERROR_IO_PENDING)) {
3706
4108
                        /* aio was queued successfully! */
3723
4125
                        return(TRUE);
3724
4126
                }
3725
4127
 
3726
 
                err = 1; /* Fall through the next if */
3727
 
        }
3728
 
#endif
3729
 
        if (err == 0) {
3730
 
                /* aio was queued successfully! */
3731
 
 
3732
 
                return(TRUE);
3733
 
        }
3734
 
 
 
4128
                goto err_exit;
 
4129
        }
 
4130
#endif /* WIN_ASYNC_IO */
 
4131
        /* aio was queued successfully! */
 
4132
        return(TRUE);
 
4133
 
 
4134
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
 
4135
err_exit:
 
4136
#endif /* LINUX_NATIVE_AIO || WIN_ASYNC_IO */
3735
4137
        os_aio_array_free_slot(array, slot);
3736
4138
 
3737
4139
        retry = os_file_handle_error(name,
3835
4237
#ifdef UNIV_DO_FLUSH
3836
4238
                if (slot->type == OS_FILE_WRITE
3837
4239
                    && !os_do_not_call_flush_at_each_write) {
3838
 
                        ut_a(TRUE == os_file_flush(slot->file));
 
4240
                        if (!os_file_flush(slot->file)) {
 
4241
                                ut_error;
 
4242
                        }
3839
4243
                }
3840
4244
#endif /* UNIV_DO_FLUSH */
3841
4245
        } else if (os_file_handle_error(slot->name, "Windows aio")) {
3852
4256
                /* retry failed read/write operation synchronously.
3853
4257
                No need to hold array->mutex. */
3854
4258
 
 
4259
#ifdef UNIV_PFS_IO
 
4260
                /* This read/write does not go through os_file_read
 
4261
                and os_file_write APIs, need to register with
 
4262
                performance schema explicitly here. */
 
4263
                struct PSI_file_locker* locker = NULL;
 
4264
                register_pfs_file_io_begin(locker, slot->file, slot->len,
 
4265
                                           (slot->type == OS_FILE_WRITE)
 
4266
                                                ? PSI_FILE_WRITE
 
4267
                                                : PSI_FILE_READ,
 
4268
                                            __FILE__, __LINE__);
 
4269
#endif
 
4270
 
3855
4271
                switch (slot->type) {
3856
4272
                case OS_FILE_WRITE:
3857
4273
                        ret = WriteFile(slot->file, slot->buf,
3869
4285
                        ut_error;
3870
4286
                }
3871
4287
 
 
4288
#ifdef UNIV_PFS_IO
 
4289
                register_pfs_file_io_end(locker, len);
 
4290
#endif
 
4291
 
3872
4292
                if (!ret && GetLastError() == ERROR_IO_PENDING) {
3873
4293
                        /* aio was queued successfully!
3874
4294
                        We want a synchronous i/o operation on a
3890
4310
}
3891
4311
#endif
3892
4312
 
 
4313
#if defined(LINUX_NATIVE_AIO)
 
4314
/******************************************************************//**
 
4315
This function is only used in Linux native asynchronous i/o. This is
 
4316
called from within the io-thread. If there are no completed IO requests
 
4317
in the slot array, the thread calls this function to collect more
 
4318
requests from the kernel.
 
4319
The io-thread waits on io_getevents(), which is a blocking call, with
 
4320
a timeout value. Unless the system is very heavy loaded, keeping the
 
4321
io-thread very busy, the io-thread will spend most of its time waiting
 
4322
in this function.
 
4323
The io-thread also exits in this function. It checks server status at
 
4324
each wakeup and that is why we use timed wait in io_getevents(). */
 
4325
static
 
4326
void
 
4327
os_aio_linux_collect(
 
4328
/*=================*/
 
4329
        os_aio_array_t* array,          /*!< in/out: slot array. */
 
4330
        ulint           segment,        /*!< in: local segment no. */
 
4331
        ulint           seg_size)       /*!< in: segment size. */
 
4332
{
 
4333
        int                     i;
 
4334
        int                     ret;
 
4335
        ulint                   start_pos;
 
4336
        ulint                   end_pos;
 
4337
        struct timespec         timeout;
 
4338
        struct io_event*        events;
 
4339
        struct io_context*      io_ctx;
 
4340
 
 
4341
        /* sanity checks. */
 
4342
        ut_ad(array != NULL);
 
4343
        ut_ad(seg_size > 0);
 
4344
        ut_ad(segment < array->n_segments);
 
4345
 
 
4346
        /* Which part of event array we are going to work on. */
 
4347
        events = &array->aio_events[segment * seg_size];
 
4348
 
 
4349
        /* Which io_context we are going to use. */
 
4350
        io_ctx = array->aio_ctx[segment];
 
4351
 
 
4352
        /* Starting point of the segment we will be working on. */
 
4353
        start_pos = segment * seg_size;
 
4354
 
 
4355
        /* End point. */
 
4356
        end_pos = start_pos + seg_size;
 
4357
 
 
4358
retry:
 
4359
 
 
4360
        /* Go down if we are in shutdown mode.
 
4361
        In case of srv_fast_shutdown == 2, there may be pending
 
4362
        IO requests but that should be OK as we essentially treat
 
4363
        that as a crash of InnoDB. */
 
4364
        if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
 
4365
                os_thread_exit(NULL);
 
4366
        }
 
4367
 
 
4368
        /* Initialize the events. The timeout value is arbitrary.
 
4369
        We probably need to experiment with it a little. */
 
4370
        memset(events, 0, sizeof(*events) * seg_size);
 
4371
        timeout.tv_sec = 0;
 
4372
        timeout.tv_nsec = OS_AIO_REAP_TIMEOUT;
 
4373
 
 
4374
        ret = io_getevents(io_ctx, 1, seg_size, events, &timeout);
 
4375
 
 
4376
        /* This error handling is for any error in collecting the
 
4377
        IO requests. The errors, if any, for any particular IO
 
4378
        request are simply passed on to the calling routine. */
 
4379
 
 
4380
        /* Not enough resources! Try again. */
 
4381
        if (ret == -EAGAIN) {
 
4382
                goto retry;
 
4383
        }
 
4384
 
 
4385
        /* Interrupted! I have tested the behaviour in case of an
 
4386
        interrupt. If we have some completed IOs available then
 
4387
        the return code will be the number of IOs. We get EINTR only
 
4388
        if there are no completed IOs and we have been interrupted. */
 
4389
        if (ret == -EINTR) {
 
4390
                goto retry;
 
4391
        }
 
4392
 
 
4393
        /* No pending request! Go back and check again. */
 
4394
        if (ret == 0) {
 
4395
                goto retry;
 
4396
        }
 
4397
 
 
4398
        /* All other errors! should cause a trap for now. */
 
4399
        if (UNIV_UNLIKELY(ret < 0)) {
 
4400
                ut_print_timestamp(stderr);
 
4401
                fprintf(stderr,
 
4402
                        "  InnoDB: unexpected ret_code[%d] from"
 
4403
                        " io_getevents()!\n", ret);
 
4404
                ut_error;
 
4405
        }
 
4406
 
 
4407
        ut_a(ret > 0);
 
4408
 
 
4409
        for (i = 0; i < ret; i++) {
 
4410
                os_aio_slot_t*  slot;
 
4411
                struct iocb*    control;
 
4412
 
 
4413
                control = (struct iocb *)events[i].obj;
 
4414
                ut_a(control != NULL);
 
4415
 
 
4416
                slot = (os_aio_slot_t *) control->data;
 
4417
 
 
4418
                /* Some sanity checks. */
 
4419
                ut_a(slot != NULL);
 
4420
                ut_a(slot->reserved);
 
4421
 
 
4422
#if defined(UNIV_AIO_DEBUG)
 
4423
                fprintf(stderr,
 
4424
                        "io_getevents[%c]: slot[%p] ctx[%p]"
 
4425
                        " seg[%lu]\n",
 
4426
                        (slot->type == OS_FILE_WRITE) ? 'w' : 'r',
 
4427
                        slot, io_ctx, segment);
 
4428
#endif
 
4429
 
 
4430
                /* We are not scribbling previous segment. */
 
4431
                ut_a(slot->pos >= start_pos);
 
4432
 
 
4433
                /* We have not overstepped to next segment. */
 
4434
                ut_a(slot->pos < end_pos);
 
4435
 
 
4436
                /* Mark this request as completed. The error handling
 
4437
                will be done in the calling function. */
 
4438
                os_mutex_enter(array->mutex);
 
4439
                slot->n_bytes = events[i].res;
 
4440
                slot->ret = events[i].res2;
 
4441
                slot->io_already_done = TRUE;
 
4442
                os_mutex_exit(array->mutex);
 
4443
        }
 
4444
 
 
4445
        return;
 
4446
}
 
4447
 
 
4448
/**********************************************************************//**
 
4449
This function is only used in Linux native asynchronous i/o.
 
4450
Waits for an aio operation to complete. This function is used to wait for
 
4451
the completed requests. The aio array of pending requests is divided
 
4452
into segments. The thread specifies which segment or slot it wants to wait
 
4453
for. NOTE: this function will also take care of freeing the aio slot,
 
4454
therefore no other thread is allowed to do the freeing!
 
4455
@return TRUE if the IO was successful */
 
4456
UNIV_INTERN
 
4457
ibool
 
4458
os_aio_linux_handle(
 
4459
/*================*/
 
4460
        ulint   global_seg,     /*!< in: segment number in the aio array
 
4461
                                to wait for; segment 0 is the ibuf
 
4462
                                i/o thread, segment 1 is log i/o thread,
 
4463
                                then follow the non-ibuf read threads,
 
4464
                                and the last are the non-ibuf write
 
4465
                                threads. */
 
4466
        fil_node_t**message1,   /*!< out: the messages passed with the */
 
4467
        void**  message2,       /*!< aio request; note that in case the
 
4468
                                aio operation failed, these output
 
4469
                                parameters are valid and can be used to
 
4470
                                restart the operation. */
 
4471
        ulint*  type)           /*!< out: OS_FILE_WRITE or ..._READ */
 
4472
{
 
4473
        ulint           segment;
 
4474
        os_aio_array_t* array;
 
4475
        os_aio_slot_t*  slot;
 
4476
        ulint           n;
 
4477
        ulint           i;
 
4478
        ibool           ret = FALSE;
 
4479
 
 
4480
        /* Should never be doing Sync IO here. */
 
4481
        ut_a(global_seg != ULINT_UNDEFINED);
 
4482
 
 
4483
        /* Find the array and the local segment. */
 
4484
        segment = os_aio_get_array_and_local_segment(&array, global_seg);
 
4485
        n = array->n_slots / array->n_segments;
 
4486
 
 
4487
        /* Loop until we have found a completed request. */
 
4488
        for (;;) {
 
4489
                os_mutex_enter(array->mutex);
 
4490
                for (i = 0; i < n; ++i) {
 
4491
                        slot = os_aio_array_get_nth_slot(
 
4492
                                        array, i + segment * n);
 
4493
                        if (slot->reserved && slot->io_already_done) {
 
4494
                                /* Something for us to work on. */
 
4495
                                goto found;
 
4496
                        }
 
4497
                }
 
4498
 
 
4499
                os_mutex_exit(array->mutex);
 
4500
 
 
4501
                /* We don't have any completed request.
 
4502
                Wait for some request. Note that we return
 
4503
                from wait iff we have found a request. */
 
4504
 
 
4505
                srv_set_io_thread_op_info(global_seg,
 
4506
                        "waiting for completed aio requests");
 
4507
                os_aio_linux_collect(array, segment, n);
 
4508
        }
 
4509
 
 
4510
found:
 
4511
        /* Note that it may be that there are more then one completed
 
4512
        IO requests. We process them one at a time. We may have a case
 
4513
        here to improve the performance slightly by dealing with all
 
4514
        requests in one sweep. */
 
4515
        srv_set_io_thread_op_info(global_seg,
 
4516
                                "processing completed aio requests");
 
4517
 
 
4518
        /* Ensure that we are scribbling only our segment. */
 
4519
        ut_a(i < n);
 
4520
 
 
4521
        ut_ad(slot != NULL);
 
4522
        ut_ad(slot->reserved);
 
4523
        ut_ad(slot->io_already_done);
 
4524
 
 
4525
        *message1 = slot->message1;
 
4526
        *message2 = slot->message2;
 
4527
 
 
4528
        *type = slot->type;
 
4529
 
 
4530
        if ((slot->ret == 0) && (slot->n_bytes == (long)slot->len)) {
 
4531
                ret = TRUE;
 
4532
 
 
4533
#ifdef UNIV_DO_FLUSH
 
4534
                if (slot->type == OS_FILE_WRITE
 
4535
                    && !os_do_not_call_flush_at_each_write)
 
4536
                    && !os_file_flush(slot->file) {
 
4537
                        ut_error;
 
4538
                }
 
4539
#endif /* UNIV_DO_FLUSH */
 
4540
        } else {
 
4541
                errno = -slot->ret;
 
4542
 
 
4543
                /* os_file_handle_error does tell us if we should retry
 
4544
                this IO. As it stands now, we don't do this retry when
 
4545
                reaping requests from a different context than
 
4546
                the dispatcher. This non-retry logic is the same for
 
4547
                windows and linux native AIO.
 
4548
                We should probably look into this to transparently
 
4549
                re-submit the IO. */
 
4550
                os_file_handle_error(slot->name, "Linux aio");
 
4551
 
 
4552
                ret = FALSE;
 
4553
        }
 
4554
 
 
4555
        os_mutex_exit(array->mutex);
 
4556
 
 
4557
        os_aio_array_free_slot(array, slot);
 
4558
 
 
4559
        return(ret);
 
4560
}
 
4561
#endif /* LINUX_NATIVE_AIO */
 
4562
 
3893
4563
/**********************************************************************//**
3894
4564
Does simulated aio. This function should be called by an i/o-handler
3895
4565
thread.
4269
4939
}
4270
4940
 
4271
4941
/**********************************************************************//**
 
4942
Prints pending IO requests per segment of an aio array.
 
4943
We probably don't need per segment statistics but they can help us
 
4944
during development phase to see if the IO requests are being
 
4945
distributed as expected. */
 
4946
static
 
4947
void
 
4948
os_aio_print_segment_info(
 
4949
/*======================*/
 
4950
        FILE*           file,   /*!< in: file where to print */
 
4951
        ulint*          n_seg,  /*!< in: pending IO array */
 
4952
        os_aio_array_t* array)  /*!< in: array to process */
 
4953
{
 
4954
        ulint   i;
 
4955
 
 
4956
        ut_ad(array);
 
4957
        ut_ad(n_seg);
 
4958
        ut_ad(array->n_segments > 0);
 
4959
 
 
4960
        if (array->n_segments == 1) {
 
4961
                return;
 
4962
        }
 
4963
 
 
4964
        fprintf(file, " [");
 
4965
        for (i = 0; i < array->n_segments; i++) {
 
4966
                if (i != 0) {
 
4967
                        fprintf(file, ", ");
 
4968
                }
 
4969
 
 
4970
                fprintf(file, "%lu", n_seg[i]);
 
4971
        }
 
4972
        fprintf(file, "] ");
 
4973
}
 
4974
 
 
4975
/**********************************************************************//**
4272
4976
Prints info of the aio arrays. */
4273
4977
UNIV_INTERN
4274
4978
void
4279
4983
        os_aio_array_t* array;
4280
4984
        os_aio_slot_t*  slot;
4281
4985
        ulint           n_reserved;
 
4986
        ulint           n_res_seg[SRV_MAX_N_IO_THREADS];
4282
4987
        time_t          current_time;
4283
4988
        double          time_elapsed;
4284
4989
        double          avg_bytes_read;
4311
5016
 
4312
5017
        n_reserved = 0;
4313
5018
 
 
5019
        memset(n_res_seg, 0x0, sizeof(n_res_seg));
 
5020
 
4314
5021
        for (i = 0; i < array->n_slots; i++) {
 
5022
                ulint   seg_no;
 
5023
 
4315
5024
                slot = os_aio_array_get_nth_slot(array, i);
4316
5025
 
 
5026
                seg_no = (i * array->n_segments) / array->n_slots;
4317
5027
                if (slot->reserved) {
4318
5028
                        n_reserved++;
 
5029
                        n_res_seg[seg_no]++;
4319
5030
#if 0
4320
5031
                        fprintf(stderr, "Reserved slot, messages %p %p\n",
4321
5032
                                (void*) slot->message1,
4329
5040
 
4330
5041
        fprintf(file, " %lu", (ulong) n_reserved);
4331
5042
 
 
5043
        os_aio_print_segment_info(file, n_res_seg, array);
 
5044
 
4332
5045
        os_mutex_exit(array->mutex);
4333
5046
 
4334
5047
        if (array == os_aio_read_array) {