1/*****************************************************************************
2
3Copyright (c) 2010, 2019, Oracle and/or its affiliates. All Rights Reserved.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is also distributed with certain software (including but not
10limited to OpenSSL) that is licensed under separate terms, as designated in a
11particular file or component or in included license documentation. The authors
12of MySQL hereby grant you an additional permission to link the program and
13your derivative works with the separately licensed software that they have
14included with MySQL.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19for more details.
20
21You should have received a copy of the GNU General Public License along with
22this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24
25*****************************************************************************/
26
27/** @file include/os0file.ic
28 The interface to the operating system file io
29
30 Created 2/20/2010 Jimmy Yang
31 *******************************************************/
32
33#include "univ.i"
34
35#ifdef UNIV_PFS_IO
36/** NOTE! Please use the corresponding macro os_file_create_simple(),
37not directly this function!
38A performance schema instrumented wrapper function for
39os_file_create_simple() which opens or creates a file.
40@param[in]	key		Performance Schema Key
41@param[in]	name		name of the file or path as a null-terminated
42                                string
43@param[in]	create_mode	create mode
44@param[in]	access_type	OS_FILE_READ_ONLY or OS_FILE_READ_WRITE
45@param[in]	read_only	if true read only mode checks are enforced
46@param[out]	success		true if succeeded
47@param[in]	src_file	file name where func invoked
48@param[in]	src_line	line where the func invoked
49@return own: handle to the file, not defined if error, error number
50can be retrieved with os_file_get_last_error */
51UNIV_INLINE
52pfs_os_file_t pfs_os_file_create_simple_func(
53    mysql_pfs_key_t key, const char *name, ulint create_mode, ulint access_type,
54    bool read_only, bool *success, const char *src_file, uint src_line) {
55  PSI_file_locker_state state;
56  struct PSI_file_locker *locker = nullptr;
57  pfs_os_file_t file;
58
59  /* register a file open or creation depending on "create_mode" */
60  register_pfs_file_open_begin(
61      &state, locker, key,
62      (create_mode == OS_FILE_CREATE) ? PSI_FILE_CREATE : PSI_FILE_OPEN, name,
63      src_file, src_line);
64
65  file.m_file = os_file_create_simple_func(name, create_mode, access_type,
66                                           read_only, success);
67  file.m_psi = nullptr;
68
69  /* Regsiter psi value for the file */
70  register_pfs_file_open_end(locker, file,
71                             (*success == TRUE ? success : nullptr));
72
73  return (file);
74}
75
76/** NOTE! Please use the corresponding macro
77os_file_create_simple_no_error_handling(), not directly this function!
78A performance schema instrumented wrapper function for
79os_file_create_simple_no_error_handling(). Add instrumentation to
80monitor file creation/open.
81@param[in]	key		Performance Schema Key
82@param[in]	name		name of the file or path as a null-terminated
83                                string
84@param[in]	create_mode	create mode
85@param[in]	access_type	OS_FILE_READ_ONLY, OS_FILE_READ_WRITE, or
86                                OS_FILE_READ_ALLOW_DELETE; the last option is
87                                used by a backup program reading the file
88@param[in]	read_only	if true read only mode checks are enforced
89@param[out]	success		true if succeeded
90@param[in]	src_file	file name where func invoked
91@param[in]	src_line	line where the func invoked
92@return own: handle to the file, not defined if error, error number
93can be retrieved with os_file_get_last_error */
94UNIV_INLINE
95pfs_os_file_t pfs_os_file_create_simple_no_error_handling_func(
96    mysql_pfs_key_t key, const char *name, ulint create_mode, ulint access_type,
97    bool read_only, bool *success, const char *src_file, uint src_line) {
98  PSI_file_locker_state state;
99  struct PSI_file_locker *locker = nullptr;
100  pfs_os_file_t file;
101
102  /* register a file open or creation depending on "create_mode" */
103  register_pfs_file_open_begin(
104      &state, locker, key,
105      create_mode == OS_FILE_CREATE ? PSI_FILE_CREATE : PSI_FILE_OPEN, name,
106      src_file, src_line);
107
108  file = os_file_create_simple_no_error_handling_func(
109      name, create_mode, access_type, read_only, success);
110
111  file.m_psi = nullptr;
112  register_pfs_file_open_end(locker, file,
113                             (*success == TRUE ? success : nullptr));
114
115  return (file);
116}
117
118/** NOTE! Please use the corresponding macro os_file_create(), not directly
119this function!
120A performance schema wrapper function for os_file_create().
121Add instrumentation to monitor file creation/open.
122@param[in]	key		Performance Schema Key
123@param[in]	name		name of the file or path as a null-terminated
124                                string
125@param[in]	create_mode	create mode
126@param[in]	purpose		OS_FILE_AIO, if asynchronous, non-buffered I/O
127                                is desired, OS_FILE_NORMAL, if any normal file;
128                                NOTE that it also depends on type, os_aio_..
129                                and srv_.. variables whether we really us
130                                async I/O or unbuffered I/O: look in the
131                                function source code for the exact rules
132@param[in]	type		OS_DATA_FILE or OS_LOG_FILE
133@param[in]	read_only	if true read only mode checks are enforced
134@param[out]	success		true if succeeded
135@param[in]	src_file	file name where func invoked
136@param[in]	src_line	line where the func invoked
137@return own: handle to the file, not defined if error, error number
138can be retrieved with os_file_get_last_error */
139UNIV_INLINE
140pfs_os_file_t pfs_os_file_create_func(mysql_pfs_key_t key, const char *name,
141                                      ulint create_mode, ulint purpose,
142                                      ulint type, bool read_only, bool *success,
143                                      const char *src_file, uint src_line) {
144  PSI_file_locker_state state;
145  struct PSI_file_locker *locker = nullptr;
146  pfs_os_file_t file;
147
148  /* register a file open or creation depending on "create_mode" */
149  register_pfs_file_open_begin(
150      &state, locker, key,
151      create_mode == OS_FILE_CREATE ? PSI_FILE_CREATE : PSI_FILE_OPEN, name,
152      src_file, src_line);
153
154  file =
155      os_file_create_func(name, create_mode, purpose, type, read_only, success);
156
157  file.m_psi = nullptr;
158  register_pfs_file_open_end(locker, file,
159                             (*success == TRUE ? success : nullptr));
160
161  return (file);
162}
163/**
164NOTE! Please use the corresponding macro os_file_close(), not directly
165this function!
166A performance schema instrumented wrapper function for os_file_close().
167@param[in]	file		handle to a file
168@param[in]	src_file	file name where func invoked
169@param[in]	src_line	line where the func invoked
170@return true if success */
171UNIV_INLINE
172bool pfs_os_file_close_func(pfs_os_file_t file, const char *src_file,
173                            uint src_line) {
174  PSI_file_locker_state state;
175  struct PSI_file_locker *locker = nullptr;
176
177  /* register the file close */
178  register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CLOSE, src_file,
179                             src_line);
180
181  bool result = os_file_close_func(file.m_file);
182
183  register_pfs_file_io_end(locker, 0);
184
185  return (result);
186}
187
188#ifndef UNIV_HOTBACKUP
189/** NOTE! Please use the corresponding macro os_aio(), not directly this
190function!
191Performance schema wrapper function of os_aio() which requests
192an asynchronous i/o operation.
193@param[in]	type		IO request context
194@param[in]	aio_mode	IO mode
195@param[in]	name		Name of the file or path as NUL terminated
196                                string
197@param[in]	file		Open file handle
198@param[out]	buf		buffer where to read
199@param[in]	offset		file offset where to read
200@param[in]	n		number of bytes to read
201@param[in]	read_only	if true read only mode checks are enforced
202@param[in,out]	m1		Message for the AIO handler, (can be used to
203                                identify a completed AIO operation); ignored
204                                if mode is OS_AIO_SYNC
205@param[in,out]	m2		message for the AIO handler (can be used to
206                                identify a completed AIO operation); ignored
207                                if mode is OS_AIO_SYNC
208@param[in]	src_file	file name where func invoked
209@param[in]	src_line	line where the func invoked
210@return DB_SUCCESS if request was queued successfully, false if fail */
211UNIV_INLINE
212dberr_t pfs_os_aio_func(IORequest &type, AIO_mode aio_mode, const char *name,
213                        pfs_os_file_t file, void *buf, os_offset_t offset,
214                        ulint n, bool read_only, fil_node_t *m1, void *m2,
215                        const char *src_file, uint src_line) {
216  PSI_file_locker_state state;
217  struct PSI_file_locker *locker = nullptr;
218
219  ut_ad(type.validate());
220
221  /* Register the read or write I/O depending on "type" */
222  register_pfs_file_io_begin(&state, locker, file, n,
223                             type.is_write() ? PSI_FILE_WRITE : PSI_FILE_READ,
224                             src_file, src_line);
225
226  dberr_t result = os_aio_func(type, aio_mode, name, file, buf, offset, n,
227                               read_only, m1, m2);
228
229  register_pfs_file_io_end(locker, n);
230
231  return (result);
232}
233#endif /* UNIV_HOTBACKUP */
234
235/** NOTE! Please use the corresponding macro os_file_read(), not directly
236this function!
237This is the performance schema instrumented wrapper function for
238os_file_read() which requests a synchronous read operation.
239@param[in, out]	type		IO request context
240@param[in]  file_name file name
241@param[in]	file		Open file handle
242@param[out]	buf		buffer where to read
243@param[in]	offset		file offset where to read
244@param[in]	n		number of bytes to read
245@param[in]	src_file	file name where func invoked
246@param[in]	src_line	line where the func invoked
247@return DB_SUCCESS if request was successful */
248UNIV_INLINE
249dberr_t pfs_os_file_read_func(IORequest &type, const char *file_name,
250                              pfs_os_file_t file, void *buf, os_offset_t offset,
251                              ulint n, const char *src_file, uint src_line) {
252  PSI_file_locker_state state;
253  struct PSI_file_locker *locker = nullptr;
254
255  ut_ad(type.validate());
256
257  register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_READ, src_file,
258                             src_line);
259
260  dberr_t result;
261
262  result = os_file_read_func(type, file_name, file.m_file, buf, offset, n);
263
264  register_pfs_file_io_end(locker, n);
265
266  return (result);
267}
268
269/** NOTE! Please use the corresponding macro os_file_read_first_page(),
270not directly this function!
271This is the performance schema instrumented wrapper function for
272os_file_read() which requests a synchronous read operation.
273@param[in, out]	type		IO request context
274@param[in]  file_name file name
275@param[in]	file		Open file handle
276@param[out]	buf		buffer where to read
277@param[in]	n		number of bytes to read
278@param[in]	src_file	file name where func invoked
279@param[in]	src_line	line where the func invoked
280@return DB_SUCCESS if request was successful */
281UNIV_INLINE
282dberr_t pfs_os_file_read_first_page_func(IORequest &type, const char *file_name,
283                                         pfs_os_file_t file, void *buf, ulint n,
284                                         const char *src_file, uint src_line) {
285  PSI_file_locker_state state;
286  struct PSI_file_locker *locker = nullptr;
287
288  ut_ad(type.validate());
289
290  register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_READ, src_file,
291                             src_line);
292
293  dberr_t result;
294
295  result = os_file_read_first_page_func(type, file_name, file.m_file, buf, n);
296
297  register_pfs_file_io_end(locker, n);
298
299  return (result);
300}
301
302/** Copy data from one file to another file. Data is read/written
303at current file offset.
304@param[in]	src		file handle to copy from
305@param[in]	src_offset	offset to copy from
306@param[in]	dest		file handle to copy to
307@param[in]	dest_offset	offset to copy to
308@param[in]	size		number of bytes to copy
309@param[in]	src_file	file name where func invoked
310@param[in]	src_line	line where the func invoked
311@return DB_SUCCESS if successful */
312UNIV_INLINE
313dberr_t pfs_os_file_copy_func(pfs_os_file_t src, os_offset_t src_offset,
314                              pfs_os_file_t dest, os_offset_t dest_offset,
315                              uint size, const char *src_file, uint src_line) {
316  dberr_t result;
317
318  PSI_file_locker_state state_read;
319  PSI_file_locker_state state_write;
320
321  struct PSI_file_locker *locker_read = nullptr;
322  struct PSI_file_locker *locker_write = nullptr;
323
324  register_pfs_file_io_begin(&state_read, locker_read, src, size, PSI_FILE_READ,
325                             src_file, src_line);
326
327  register_pfs_file_io_begin(&state_write, locker_write, dest, size,
328                             PSI_FILE_WRITE, src_file, src_line);
329
330  result =
331      os_file_copy_func(src.m_file, src_offset, dest.m_file, dest_offset, size);
332
333  register_pfs_file_io_end(locker_write, size);
334  register_pfs_file_io_end(locker_read, size);
335
336  return (result);
337}
338
339/** NOTE! Please use the corresponding macro os_file_read_no_error_handling(),
340not directly this function!
341This is the performance schema instrumented wrapper function for
342os_file_read_no_error_handling_func() which requests a synchronous
343read operation.
344@param[in, out]	type		IO request context
345@param[in]  file_name file name
346@param[in]	file		Open file handle
347@param[out]	buf		buffer where to read
348@param[in]	offset		file offset where to read
349@param[in]	n		number of bytes to read
350@param[out]	o		number of bytes actually read
351@param[in]	src_file	file name where func invoked
352@param[in]	src_line	line where the func invoked
353@return DB_SUCCESS if request was successful */
354UNIV_INLINE
355dberr_t pfs_os_file_read_no_error_handling_func(IORequest &type,
356                                                const char *file_name,
357                                                pfs_os_file_t file, void *buf,
358                                                os_offset_t offset, ulint n,
359                                                ulint *o, const char *src_file,
360                                                uint src_line) {
361  PSI_file_locker_state state;
362  struct PSI_file_locker *locker = nullptr;
363
364  register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_READ, src_file,
365                             src_line);
366
367  dberr_t result = os_file_read_no_error_handling_func(
368      type, file_name, file.m_file, buf, offset, n, o);
369
370  register_pfs_file_io_end(locker, n);
371
372  return (result);
373}
374
375/** NOTE! Please use the corresponding macro
376os_file_read_no_error_handling_int_fd(), not directly this function!
377This is the performance schema instrumented wrapper function for
378os_file_read_no_error_handling_int_fd_func() which requests a
379synchronous  read operation.
380@param[in, out] type            IO request context
381@param[in]      file_name       file name
382@param[in]      file            Open file handle
383@param[out]     buf             buffer where to read
384@param[in]      offset          file offset where to read
385@param[in]      n               number of bytes to read
386@param[out]     o               number of bytes actually read
387@param[in]      src_file        file name where func invoked
388@param[in]      src_line        line where the func invoked
389@return DB_SUCCESS if request was successful */
390
391UNIV_INLINE
392dberr_t pfs_os_file_read_no_error_handling_int_fd_func(
393    IORequest &type, const char *file_name, int file, void *buf,
394    os_offset_t offset, ulint n, ulint *o, const char *src_file,
395    ulint src_line) {
396  PSI_file_locker_state state;
397  struct PSI_file_locker *locker = nullptr;
398
399  locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file,
400                                                            PSI_FILE_READ);
401  if (locker != nullptr) {
402    PSI_FILE_CALL(start_file_wait)(locker, n, __FILE__, __LINE__);
403  }
404  dberr_t result = os_file_read_no_error_handling_func(
405      type, file_name, OS_FILE_FROM_FD(file), buf, offset, n, o);
406
407  if (locker != nullptr) {
408    PSI_FILE_CALL(end_file_wait)(locker, n);
409  }
410
411  return (result);
412}
413
414/** NOTE! Please use the corresponding macro os_file_write(), not directly
415this function!
416This is the performance schema instrumented wrapper function for
417os_file_write() which requests a synchronous write operation.
418@param[in, out]	type		IO request context
419@param[in]	name		Name of the file or path as NUL terminated
420                                string
421@param[in]	file		Open file handle
422@param[out]	buf		buffer where to read
423@param[in]	offset		file offset where to read
424@param[in]	n		number of bytes to read
425@param[in]	src_file	file name where func invoked
426@param[in]	src_line	line where the func invoked
427@return DB_SUCCESS if request was successful */
428UNIV_INLINE
429dberr_t pfs_os_file_write_func(IORequest &type, const char *name,
430                               pfs_os_file_t file, const void *buf,
431                               os_offset_t offset, ulint n,
432                               const char *src_file, uint src_line) {
433  PSI_file_locker_state state;
434  struct PSI_file_locker *locker = nullptr;
435
436  register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_WRITE, src_file,
437                             src_line);
438
439  dberr_t result;
440
441  result = os_file_write_func(type, name, file.m_file, buf, offset, n);
442
443  register_pfs_file_io_end(locker, n);
444
445  return (result);
446}
447
448/** NOTE! Please use the corresponding macro os_file_write(), not
449directly this function!
450This is the performance schema instrumented wrapper function for
451os_file_write() which requests a synchronous write operation.
452@param[in, out] type            IO request context
453@param[in]      name            Name of the file or path as NUL terminated
454                                string
455@param[in]      file            Open file handle
456@param[out]     buf             buffer where to read
457@param[in]      offset          file offset where to read
458@param[in]      n               number of bytes to read
459@param[in]      src_file        file name where func invoked
460@param[in]      src_line        line where the func invoked
461@return DB_SUCCESS if request was successful */
462UNIV_INLINE
463dberr_t pfs_os_file_write_int_fd_func(IORequest &type, const char *name,
464                                      int file, const void *buf,
465                                      os_offset_t offset, ulint n,
466                                      const char *src_file, ulint src_line) {
467  PSI_file_locker_state state;
468  struct PSI_file_locker *locker = nullptr;
469
470  locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file,
471                                                            PSI_FILE_WRITE);
472  if (locker != nullptr) {
473    PSI_FILE_CALL(start_file_wait)(locker, n, __FILE__, __LINE__);
474  }
475  dberr_t result =
476      os_file_write_func(type, name, OS_FILE_FROM_FD(file), buf, offset, n);
477
478  if (locker != nullptr) {
479    PSI_FILE_CALL(end_file_wait)(locker, n);
480  }
481
482  return (result);
483}
484
485/** NOTE! Please use the corresponding macro os_file_flush(),
486 not directly
487this function!
488This is the performance schema instrumented wrapper function for
489os_file_flush() which flushes the write buffers of a given file to the disk.
490Flushes the write buffers of a given file to the disk.
491@param[in]	file		Open file handle
492@param[in]	src_file	file name where func invoked
493@param[in]	src_line	line where the func invoked
494@return true if success */
495UNIV_INLINE
496bool pfs_os_file_flush_func(pfs_os_file_t file, const char *src_file,
497                            uint src_line) {
498  PSI_file_locker_state state;
499  struct PSI_file_locker *locker = nullptr;
500
501  register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_SYNC, src_file,
502                             src_line);
503
504  bool result = os_file_flush_func(file.m_file);
505
506  register_pfs_file_io_end(locker, 0);
507
508  return (result);
509}
510
511/** NOTE! Please use the corresponding macro os_file_rename(), not directly
512this function!
513This is the performance schema instrumented wrapper function for
514os_file_rename()
515@param[in]	key		Performance Schema Key
516@param[in]	oldpath		old file path as a null-terminated string
517@param[in]	newpath		new file path
518@param[in]	src_file	file name where func invoked
519@param[in]	src_line	line where the func invoked
520@return true if success */
521UNIV_INLINE
522bool pfs_os_file_rename_func(mysql_pfs_key_t key, const char *oldpath,
523                             const char *newpath, const char *src_file,
524                             uint src_line)
525
526{
527  PSI_file_locker_state state;
528  struct PSI_file_locker *locker = nullptr;
529
530  register_pfs_file_rename_begin(&state, locker, key, PSI_FILE_RENAME, oldpath,
531                                 newpath, src_file, src_line);
532
533  bool result = os_file_rename_func(oldpath, newpath);
534
535  register_pfs_file_rename_end(locker, oldpath, newpath, !result);
536
537  return (result);
538}
539
540/** NOTE! Please use the corresponding macro os_file_delete(), not directly
541this function!
542This is the performance schema instrumented wrapper function for
543os_file_delete()
544@param[in]	key		Performance Schema Key
545@param[in]	name		old file path as a null-terminated string
546@param[in]	src_file	file name where func invoked
547@param[in]	src_line	line where the func invoked
548@return true if success */
549UNIV_INLINE
550bool pfs_os_file_delete_func(mysql_pfs_key_t key, const char *name,
551                             const char *src_file, uint src_line) {
552  PSI_file_locker_state state;
553  struct PSI_file_locker *locker = nullptr;
554
555  register_pfs_file_close_begin(&state, locker, key, PSI_FILE_DELETE, name,
556                                src_file, src_line);
557
558  bool result = os_file_delete_func(name);
559
560  register_pfs_file_close_end(locker, 0);
561
562  return (result);
563}
564
565/**
566NOTE! Please use the corresponding macro os_file_delete_if_exists(), not
567directly this function!
568This is the performance schema instrumented wrapper function for
569os_file_delete_if_exists()
570@param[in]	key		Performance Schema Key
571@param[in]	name		old file path as a null-terminated string
572@param[in]	exist		indicate if file pre-exist
573@param[in]	src_file	file name where func invoked
574@param[in]	src_line	line where the func invoked
575@return true if success */
576UNIV_INLINE
577bool pfs_os_file_delete_if_exists_func(mysql_pfs_key_t key, const char *name,
578                                       bool *exist, const char *src_file,
579                                       uint src_line) {
580  PSI_file_locker_state state;
581  struct PSI_file_locker *locker = nullptr;
582
583  register_pfs_file_close_begin(&state, locker, key, PSI_FILE_DELETE, name,
584                                src_file, src_line);
585
586  bool result = os_file_delete_if_exists_func(name, exist);
587
588  register_pfs_file_close_end(locker, 0);
589
590  return (result);
591}
592#endif /* UNIV_PFS_IO */
593