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